From 80c41ddd8f11b8094018296d9820c2b6c119ac12 Mon Sep 17 00:00:00 2001 From: Erik Scholz Date: Sat, 1 Mar 2025 12:57:22 +0100 Subject: [PATCH 01/87] CUDA: compress mode option and default to size (#12029) cuda 12.8 added the option to specify stronger compression for binaries, so we now default to "size". --- ggml/CMakeLists.txt | 3 +++ ggml/src/ggml-cuda/CMakeLists.txt | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/ggml/CMakeLists.txt b/ggml/CMakeLists.txt index 610010da8..9e7db3560 100644 --- a/ggml/CMakeLists.txt +++ b/ggml/CMakeLists.txt @@ -155,6 +155,9 @@ option(GGML_CUDA_NO_VMM "ggml: do not try to use CUDA VMM" option(GGML_CUDA_FA "ggml: compile ggml FlashAttention CUDA kernels" ON) option(GGML_CUDA_FA_ALL_QUANTS "ggml: compile all quants for FlashAttention" OFF) option(GGML_CUDA_GRAPHS "ggml: use CUDA graphs (llama.cpp only)" ${GGML_CUDA_GRAPHS_DEFAULT}) +set (GGML_CUDA_COMPRESSION_MODE "size" CACHE STRING + "ggml: cuda link binary compression mode; requires cuda 12.8+") +set_property(CACHE GGML_CUDA_COMPRESSION_MODE PROPERTY STRINGS "none;speed;balance;size") option(GGML_HIP "ggml: use HIP" OFF) option(GGML_HIP_GRAPHS "ggml: use HIP graph, experimental, slow" OFF) diff --git a/ggml/src/ggml-cuda/CMakeLists.txt b/ggml/src/ggml-cuda/CMakeLists.txt index 96bd5a0be..8623214c7 100644 --- a/ggml/src/ggml-cuda/CMakeLists.txt +++ b/ggml/src/ggml-cuda/CMakeLists.txt @@ -102,6 +102,15 @@ if (CUDAToolkit_FOUND) set(CUDA_FLAGS -use_fast_math) + if (CUDAToolkit_VERSION VERSION_GREATER_EQUAL "12.8") + # Options are: + # - none (not recommended) + # - speed (nvcc's default) + # - balance + # - size + list(APPEND CUDA_FLAGS -compress-mode=${GGML_CUDA_COMPRESSION_MODE}) + endif() + if (GGML_FATAL_WARNINGS) list(APPEND CUDA_FLAGS -Werror all-warnings) endif() From 45a8e7674548fca9b4ff6d8de97b73bf60f83d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigbj=C3=B8rn=20Skj=C3=A6ret?= Date: Sat, 1 Mar 2025 13:56:45 +0100 Subject: [PATCH 02/87] common : add --system-prompt parameter, replace behavior of -p in conversation mode (#12131) * Add --system-prompt parameter * use user defined system prompt * clarify Co-authored-by: Xuan-Son Nguyen * add warning * clarify Co-authored-by: Xuan-Son Nguyen --------- Co-authored-by: Xuan-Son Nguyen --- common/arg.cpp | 11 ++++++++--- common/common.h | 1 + examples/main/main.cpp | 6 +++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/common/arg.cpp b/common/arg.cpp index 3c169b5b5..5924c68c7 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -813,13 +813,18 @@ common_params_context common_params_parser_init(common_params & params, llama_ex ).set_env("LLAMA_ARG_FLASH_ATTN")); add_opt(common_arg( {"-p", "--prompt"}, "PROMPT", - ex == LLAMA_EXAMPLE_MAIN - ? "prompt to start generation with\nif -cnv is set, this will be used as system prompt" - : "prompt to start generation with", + "prompt to start generation with; for system message, use -sys", [](common_params & params, const std::string & value) { params.prompt = value; } ).set_excludes({LLAMA_EXAMPLE_SERVER})); + add_opt(common_arg( + {"-sys", "--system-prompt"}, "PROMPT", + "system prompt to use with model (if applicable, depending on chat template)", + [](common_params & params, const std::string & value) { + params.system_prompt = value; + } + ).set_examples({LLAMA_EXAMPLE_MAIN})); add_opt(common_arg( {"--no-perf"}, string_format("disable internal libllama performance timings (default: %s)", params.no_perf ? "true" : "false"), diff --git a/common/common.h b/common/common.h index efe8e7f79..5973677e8 100644 --- a/common/common.h +++ b/common/common.h @@ -261,6 +261,7 @@ struct common_params { std::string hf_repo = ""; // HF repo // NOLINT std::string hf_file = ""; // HF file // NOLINT std::string prompt = ""; // NOLINT + std::string system_prompt = ""; // NOLINT std::string prompt_file = ""; // store the external prompt file name // NOLINT std::string path_prompt_cache = ""; // path to file for saving/loading prompt eval state // NOLINT std::string input_prefix = ""; // string to prefix user inputs with // NOLINT diff --git a/examples/main/main.cpp b/examples/main/main.cpp index cf8659b03..a6dfdb4d4 100644 --- a/examples/main/main.cpp +++ b/examples/main/main.cpp @@ -219,6 +219,10 @@ int main(int argc, char ** argv) { // print chat template example in conversation mode if (params.conversation_mode) { if (params.enable_chat_template) { + if (!params.prompt.empty()) { + LOG_WRN("*** User-specified prompt in conversation mode will be ignored, did you mean to set --system-prompt (-sys) instead?\n"); + } + LOG_INF("%s: chat template example:\n%s\n", __func__, common_chat_format_example(chat_templates.get(), params.use_jinja).c_str()); } else { LOG_INF("%s: in-suffix/prefix is specified, chat template will be disabled\n", __func__); @@ -276,7 +280,7 @@ int main(int argc, char ** argv) { { auto prompt = (params.conversation_mode && params.enable_chat_template) // format the system prompt in conversation mode (fallback to default if empty) - ? chat_add_and_format("system", params.prompt.empty() ? DEFAULT_SYSTEM_MESSAGE : params.prompt) + ? chat_add_and_format("system", params.system_prompt.empty() ? DEFAULT_SYSTEM_MESSAGE : params.system_prompt) // otherwise use the prompt as is : params.prompt; if (params.interactive_first || !params.prompt.empty() || session_tokens.empty()) { From 1782cdfed60952f9ff333fc2ab5245f2be702453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigbj=C3=B8rn=20Skj=C3=A6ret?= Date: Sat, 1 Mar 2025 15:22:27 +0100 Subject: [PATCH 03/87] main: update outdated system prompt message (followup to #12131) (#12132) * Update outdated message * wording Co-authored-by: Xuan-Son Nguyen --------- Co-authored-by: Xuan-Son Nguyen --- examples/main/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/main/main.cpp b/examples/main/main.cpp index a6dfdb4d4..7896dd26e 100644 --- a/examples/main/main.cpp +++ b/examples/main/main.cpp @@ -480,8 +480,8 @@ int main(int argc, char ** argv) { LOG_INF( " - Press Ctrl+C to interject at any time.\n"); #endif LOG_INF( "%s", control_message); - if (params.conversation_mode && params.enable_chat_template && params.prompt.empty()) { - LOG_INF( " - Using default system message. To change it, set a different value via -p PROMPT or -f FILE argument.\n"); + if (params.conversation_mode && params.enable_chat_template && params.system_prompt.empty()) { + LOG_INF( " - Not using system message. To change it, set a different value via -sys PROMPT\n"); } LOG_INF("\n"); From 14dec0c2f29ae56917907dbf2eed6b19438d0a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigbj=C3=B8rn=20Skj=C3=A6ret?= Date: Sun, 2 Mar 2025 14:53:48 +0100 Subject: [PATCH 04/87] main: use jinja chat template system prompt by default (#12118) * Use jinja chat template system prompt by default * faster conditional order * remove nested ternary --------- Co-authored-by: Xuan Son Nguyen --- examples/main/main.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/examples/main/main.cpp b/examples/main/main.cpp index 7896dd26e..acf79a892 100644 --- a/examples/main/main.cpp +++ b/examples/main/main.cpp @@ -31,8 +31,6 @@ #pragma warning(disable: 4244 4267) // possible loss of data #endif -static const char * DEFAULT_SYSTEM_MESSAGE = "You are a helpful assistant"; - static llama_context ** g_ctx; static llama_model ** g_model; static common_sampler ** g_smpl; @@ -267,6 +265,7 @@ int main(int argc, char ** argv) { std::vector embd_inp; + bool waiting_for_first_input = params.conversation_mode && params.enable_chat_template && params.system_prompt.empty(); auto chat_add_and_format = [&chat_msgs, &chat_templates](const std::string & role, const std::string & content) { common_chat_msg new_msg; new_msg.role = role; @@ -278,11 +277,20 @@ int main(int argc, char ** argv) { }; { - auto prompt = (params.conversation_mode && params.enable_chat_template) - // format the system prompt in conversation mode (fallback to default if empty) - ? chat_add_and_format("system", params.system_prompt.empty() ? DEFAULT_SYSTEM_MESSAGE : params.system_prompt) + std::string prompt; + + if (params.conversation_mode && params.enable_chat_template) { + // format the system prompt in conversation mode (will use template default if empty) + prompt = params.system_prompt; + + if (!prompt.empty()) { + prompt = chat_add_and_format("system", prompt); + } + } else { // otherwise use the prompt as is - : params.prompt; + prompt = params.prompt; + } + if (params.interactive_first || !params.prompt.empty() || session_tokens.empty()) { LOG_DBG("tokenize the prompt\n"); embd_inp = common_tokenize(ctx, prompt, true, true); @@ -296,7 +304,7 @@ int main(int argc, char ** argv) { } // Should not run without any tokens - if (embd_inp.empty()) { + if (!params.conversation_mode && embd_inp.empty()) { if (add_bos) { embd_inp.push_back(llama_vocab_bos(vocab)); LOG_WRN("embd_inp was considered empty and bos was added: %s\n", string_from(ctx, embd_inp).c_str()); @@ -777,7 +785,7 @@ int main(int argc, char ** argv) { } // deal with end of generation tokens in interactive mode - if (llama_vocab_is_eog(vocab, common_sampler_last(smpl))) { + if (!waiting_for_first_input && llama_vocab_is_eog(vocab, common_sampler_last(smpl))) { LOG_DBG("found an EOG token\n"); if (params.interactive) { @@ -797,12 +805,12 @@ int main(int argc, char ** argv) { } // if current token is not EOG, we add it to current assistant message - if (params.conversation_mode) { + if (params.conversation_mode && !waiting_for_first_input) { const auto id = common_sampler_last(smpl); assistant_ss << common_token_to_piece(ctx, id, false); } - if (n_past > 0 && is_interacting) { + if ((n_past > 0 || waiting_for_first_input) && is_interacting) { LOG_DBG("waiting for user input\n"); if (params.conversation_mode) { @@ -892,11 +900,12 @@ int main(int argc, char ** argv) { input_echo = false; // do not echo this again } - if (n_past > 0) { + if (n_past > 0 || waiting_for_first_input) { if (is_interacting) { common_sampler_reset(smpl); } is_interacting = false; + waiting_for_first_input = false; } } From cc473cac7cea1484c1f870231073b0bf0352c6f9 Mon Sep 17 00:00:00 2001 From: Diego Devesa Date: Sun, 2 Mar 2025 22:11:00 +0100 Subject: [PATCH 05/87] ggml-backend : keep paths in native string type when possible (#12144) --- ggml/src/ggml-backend-reg.cpp | 104 ++++++++++++++++------------------ 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/ggml/src/ggml-backend-reg.cpp b/ggml/src/ggml-backend-reg.cpp index 955ed505f..23ddf41d4 100644 --- a/ggml/src/ggml-backend-reg.cpp +++ b/ggml/src/ggml-backend-reg.cpp @@ -2,10 +2,8 @@ #include "ggml-backend.h" #include "ggml-impl.h" #include -#include #include #include -#include #include #include #include @@ -72,14 +70,15 @@ # pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -static std::wstring utf8_to_utf16(const std::string & str) { - std::wstring_convert> converter; - return converter.from_bytes(str); -} +namespace fs = std::filesystem; -static std::string utf16_to_utf8(const std::wstring & str) { - std::wstring_convert> converter; - return converter.to_bytes(str); +static std::string path_str(const fs::path & path) { + std::string u8path; + try { + u8path = path.u8string(); + } catch (...) { + } + return u8path; } #if defined(__clang__) @@ -96,12 +95,12 @@ struct dl_handle_deleter { } }; -static dl_handle * dl_load_library(const std::wstring & path) { +static dl_handle * dl_load_library(const fs::path & path) { // suppress error dialogs for missing DLLs DWORD old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); SetErrorMode(old_mode | SEM_FAILCRITICALERRORS); - HMODULE handle = LoadLibraryW(path.c_str()); + HMODULE handle = LoadLibraryW(path.wstring().c_str()); SetErrorMode(old_mode); @@ -129,8 +128,8 @@ struct dl_handle_deleter { } }; -static void * dl_load_library(const std::wstring & path) { - dl_handle * handle = dlopen(utf16_to_utf8(path).c_str(), RTLD_NOW | RTLD_LOCAL); +static void * dl_load_library(const fs::path & path) { + dl_handle * handle = dlopen(path.string().c_str(), RTLD_NOW | RTLD_LOCAL); return handle; } @@ -217,11 +216,11 @@ struct ggml_backend_registry { devices.push_back(device); } - ggml_backend_reg_t load_backend(const std::wstring & path, bool silent) { + ggml_backend_reg_t load_backend(const fs::path & path, bool silent) { dl_handle_ptr handle { dl_load_library(path) }; if (!handle) { if (!silent) { - GGML_LOG_ERROR("%s: failed to load %s\n", __func__, utf16_to_utf8(path).c_str()); + GGML_LOG_ERROR("%s: failed to load %s\n", __func__, path_str(path).c_str()); } return nullptr; } @@ -229,7 +228,7 @@ struct ggml_backend_registry { auto score_fn = (ggml_backend_score_t) dl_get_sym(handle.get(), "ggml_backend_score"); if (score_fn && score_fn() == 0) { if (!silent) { - GGML_LOG_INFO("%s: backend %s is not supported on this system\n", __func__, utf16_to_utf8(path).c_str()); + GGML_LOG_INFO("%s: backend %s is not supported on this system\n", __func__, path_str(path).c_str()); } return nullptr; } @@ -237,7 +236,7 @@ struct ggml_backend_registry { auto backend_init_fn = (ggml_backend_init_t) dl_get_sym(handle.get(), "ggml_backend_init"); if (!backend_init_fn) { if (!silent) { - GGML_LOG_ERROR("%s: failed to find ggml_backend_init in %s\n", __func__, utf16_to_utf8(path).c_str()); + GGML_LOG_ERROR("%s: failed to find ggml_backend_init in %s\n", __func__, path_str(path).c_str()); } return nullptr; } @@ -246,16 +245,17 @@ struct ggml_backend_registry { if (!reg || reg->api_version != GGML_BACKEND_API_VERSION) { if (!silent) { if (!reg) { - GGML_LOG_ERROR("%s: failed to initialize backend from %s: ggml_backend_init returned NULL\n", __func__, utf16_to_utf8(path).c_str()); + GGML_LOG_ERROR("%s: failed to initialize backend from %s: ggml_backend_init returned NULL\n", + __func__, path_str(path).c_str()); } else { GGML_LOG_ERROR("%s: failed to initialize backend from %s: incompatible API version (backend: %d, current: %d)\n", - __func__, utf16_to_utf8(path).c_str(), reg->api_version, GGML_BACKEND_API_VERSION); + __func__, path_str(path).c_str(), reg->api_version, GGML_BACKEND_API_VERSION); } } return nullptr; } - GGML_LOG_INFO("%s: loaded %s backend from %s\n", __func__, ggml_backend_reg_name(reg), utf16_to_utf8(path).c_str()); + GGML_LOG_INFO("%s: loaded %s backend from %s\n", __func__, ggml_backend_reg_name(reg), path_str(path).c_str()); register_backend(reg, std::move(handle)); @@ -391,14 +391,14 @@ ggml_backend_t ggml_backend_init_best(void) { // Dynamic loading ggml_backend_reg_t ggml_backend_load(const char * path) { - return get_reg().load_backend(utf8_to_utf16(path), false); + return get_reg().load_backend(path, false); } void ggml_backend_unload(ggml_backend_reg_t reg) { get_reg().unload_backend(reg, true); } -static std::wstring get_executable_path() { +static fs::path get_executable_path() { #if defined(__APPLE__) // get executable path std::vector path; @@ -416,7 +416,7 @@ static std::wstring get_executable_path() { if (last_slash != std::string::npos) { base_path = base_path.substr(0, last_slash); } - return utf8_to_utf16(base_path + "/"); + return base_path + "/"; #elif defined(__linux__) || defined(__FreeBSD__) std::string base_path = "."; std::vector path(1024); @@ -442,7 +442,7 @@ static std::wstring get_executable_path() { path.resize(path.size() * 2); } - return utf8_to_utf16(base_path + "/"); + return base_path + "/"; #elif defined(_WIN32) std::vector path(MAX_PATH); DWORD len = GetModuleFileNameW(NULL, path.data(), path.size()); @@ -461,74 +461,69 @@ static std::wstring get_executable_path() { #endif } -static std::wstring backend_filename_prefix() { +static fs::path backend_filename_prefix() { #ifdef _WIN32 - return L"ggml-"; + return fs::u8path("ggml-"); #else - return L"libggml-"; + return fs::u8path("libggml-"); #endif } -static std::wstring backend_filename_suffix() { +static fs::path backend_filename_extension() { #ifdef _WIN32 - return L".dll"; + return fs::u8path(".dll"); #else - return L".so"; -#endif -} - -static std::wstring path_separator() { -#ifdef _WIN32 - return L"\\"; -#else - return L"/"; + return fs::u8path(".so"); #endif } static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, const char * user_search_path) { // enumerate all the files that match [lib]ggml-name-*.[so|dll] in the search paths - // TODO: search system paths - std::wstring file_prefix = backend_filename_prefix() + utf8_to_utf16(name) + L"-"; - std::vector search_paths; + const fs::path name_path = fs::u8path(name); + const fs::path file_prefix = backend_filename_prefix().native() + name_path.native() + fs::u8path("-").native(); + const fs::path file_extension = backend_filename_extension(); + + std::vector search_paths; if (user_search_path == nullptr) { - search_paths.push_back(L"." + path_separator()); + // default search paths: executable directory, current directory search_paths.push_back(get_executable_path()); + search_paths.push_back(fs::current_path()); } else { - search_paths.push_back(utf8_to_utf16(user_search_path) + path_separator()); + search_paths.push_back(user_search_path); } int best_score = 0; - std::wstring best_path; + fs::path best_path; - namespace fs = std::filesystem; for (const auto & search_path : search_paths) { if (!fs::exists(search_path)) { + GGML_LOG_DEBUG("%s: search path %s does not exist\n", __func__, path_str(search_path).c_str()); continue; } fs::directory_iterator dir_it(search_path, fs::directory_options::skip_permission_denied); for (const auto & entry : dir_it) { if (entry.is_regular_file()) { - std::wstring filename = entry.path().filename().wstring(); - std::wstring ext = entry.path().extension().wstring(); - if (filename.find(file_prefix) == 0 && ext == backend_filename_suffix()) { - dl_handle_ptr handle { dl_load_library(entry.path().wstring()) }; + auto filename = entry.path().filename().native(); + auto ext = entry.path().extension().native(); + if (filename.find(file_prefix) == 0 && ext == file_extension) { + dl_handle_ptr handle { dl_load_library(entry) }; if (!handle && !silent) { - GGML_LOG_ERROR("%s: failed to load %s\n", __func__, utf16_to_utf8(entry.path().wstring()).c_str()); + GGML_LOG_ERROR("%s: failed to load %s\n", __func__, path_str(entry.path()).c_str()); } if (handle) { auto score_fn = (ggml_backend_score_t) dl_get_sym(handle.get(), "ggml_backend_score"); if (score_fn) { int s = score_fn(); #ifndef NDEBUG - GGML_LOG_DEBUG("%s: %s score: %d\n", __func__, utf16_to_utf8(entry.path().wstring()).c_str(), s); + GGML_LOG_DEBUG("%s: %s score: %d\n", __func__, path_str(entry.path()).c_str(), s); #endif if (s > best_score) { best_score = s; - best_path = entry.path().wstring(); + best_path = entry.path(); } } else { if (!silent) { - GGML_LOG_INFO("%s: failed to find ggml_backend_score in %s\n", __func__, utf16_to_utf8(entry.path().wstring()).c_str()); + GGML_LOG_INFO("%s: failed to find ggml_backend_score in %s\n", __func__, path_str(entry.path()).c_str()); } } } @@ -540,7 +535,8 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, if (best_score == 0) { // try to load the base backend for (const auto & search_path : search_paths) { - std::wstring path = search_path + backend_filename_prefix() + utf8_to_utf16(name) + backend_filename_suffix(); + fs::path filename = backend_filename_prefix().native() + name_path.native() + backend_filename_extension().native(); + fs::path path = search_path.native() + filename.native(); if (fs::exists(path)) { return get_reg().load_backend(path, silent); } From ece9745bb8079b9f4af45df29b67ad0c6e50584d Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Mon, 3 Mar 2025 15:37:22 +0530 Subject: [PATCH 06/87] SYCL: Move CPY kernels to a separate file and add few missing kernels (#12133) * SYCL: refactor and move cpy kernels to a separate file * Add few missing cpy kernels * refactor and add debug logs --- ggml/src/ggml-sycl/backend.hpp | 1 + ggml/src/ggml-sycl/common.hpp | 1 + ggml/src/ggml-sycl/cpy.cpp | 701 +++++++++++++++++++++++++++++++ ggml/src/ggml-sycl/cpy.hpp | 11 + ggml/src/ggml-sycl/ggml-sycl.cpp | 491 ++-------------------- 5 files changed, 739 insertions(+), 466 deletions(-) create mode 100644 ggml/src/ggml-sycl/cpy.cpp create mode 100644 ggml/src/ggml-sycl/cpy.hpp diff --git a/ggml/src/ggml-sycl/backend.hpp b/ggml/src/ggml-sycl/backend.hpp index b1df4e5db..577ff51fd 100644 --- a/ggml/src/ggml-sycl/backend.hpp +++ b/ggml/src/ggml-sycl/backend.hpp @@ -29,6 +29,7 @@ #include "wkv6.hpp" #include "outprod.hpp" #include "element_wise.hpp" +#include "cpy.hpp" #include "gla.hpp" #endif // GGML_SYCL_BACKEND_HPP diff --git a/ggml/src/ggml-sycl/common.hpp b/ggml/src/ggml-sycl/common.hpp index 7c503a1b1..a92988b7d 100644 --- a/ggml/src/ggml-sycl/common.hpp +++ b/ggml/src/ggml-sycl/common.hpp @@ -34,6 +34,7 @@ #pragma clang diagnostic ignored "-Wnested-anon-types" #include "ggml-common.h" #pragma clang diagnostic pop +#include "ggml-impl.h" void* ggml_sycl_host_malloc(size_t size); void ggml_sycl_host_free(void* ptr); diff --git a/ggml/src/ggml-sycl/cpy.cpp b/ggml/src/ggml-sycl/cpy.cpp new file mode 100644 index 000000000..5a2314589 --- /dev/null +++ b/ggml/src/ggml-sycl/cpy.cpp @@ -0,0 +1,701 @@ +#include "cpy.hpp" + +#include + +#include "dequantize.hpp" + +static __dpct_inline__ int best_index_int8(int n, const int8_t * val, float x) { + if (x <= val[0]) { + return 0; + } + if (x >= val[n - 1]) { + return n - 1; + } + int ml = 0, mu = n - 1; + while (mu - ml > 1) { + int mav = (ml + mu) / 2; + if (x < val[mav]) { + mu = mav; + } else { + ml = mav; + } + } + return x - val[mu - 1] < val[mu] - x ? mu - 1 : mu; +} + +static void cpy_1_f32_f32(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + float * dsti = (float *) cdsti; + + *dsti = *xi; +} + +static void cpy_1_f32_f16(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + sycl::half * dsti = (sycl::half *) cdsti; + + *dsti = sycl::vec(*xi).convert()[0]; +} + +static void cpy_1_f16_f16(const char * cxi, char * cdsti) { + const sycl::half * xi = (const sycl::half *) cxi; + sycl::half * dsti = (sycl::half *) cdsti; + + *dsti = *xi; +} + +static void cpy_1_f16_f32(const char * cxi, char * cdsti) { + const sycl::half * xi = (const sycl::half *) cxi; + float * dsti = (float *) cdsti; + + *dsti = *xi; +} + +static void cpy_1_i16_i16(const char * cxi, char * cdsti) { + const int16_t * xi = (const int16_t *) cxi; + int16_t * dsti = (int16_t *) cdsti; + + *dsti = *xi; +} + +static void cpy_1_i32_i32(const char * cxi, char * cdsti) { + const int32_t * xi = (const int32_t *) cxi; + int32_t * dsti = (int32_t *) cdsti; + + *dsti = *xi; +} + +template +static void cpy_f32_f16(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, const int ne02, + const int nb00, const int nb01, const int nb02, const int nb03, const int ne10, const int ne11, + const int ne12, const int nb10, const int nb11, const int nb12, const int nb13, + const sycl::nd_item<3> & item_ct1) { + const int i = item_ct1.get_local_range(2) * item_ct1.get_group(2) + item_ct1.get_local_id(2); + + if (i >= ne) { + return; + } + + // determine indices i02/i12, i01/i11, i00/i10 as a function of index i of flattened tensor + // then combine those indices with the corresponding byte offsets to get the total offsets + const int i03 = i / (ne00 * ne01 * ne02); + const int i02 = (i - i03 * ne00 * ne01 * ne02) / (ne00 * ne01); + const int i01 = (i - i03 * ne00 * ne01 * ne02 - i02 * ne01 * ne00) / ne00; + const int i00 = i - i03 * ne00 * ne01 * ne02 - i02 * ne01 * ne00 - i01 * ne00; + const int x_offset = i00 * nb00 + i01 * nb01 + i02 * nb02 + i03 * nb03; + + const int i13 = i / (ne10 * ne11 * ne12); + const int i12 = (i - i13 * ne10 * ne11 * ne12) / (ne10 * ne11); + const int i11 = (i - i13 * ne10 * ne11 * ne12 - i12 * ne10 * ne11) / ne10; + const int i10 = i - i13 * ne10 * ne11 * ne12 - i12 * ne10 * ne11 - i11 * ne10; + const int dst_offset = i10 * nb10 + i11 * nb11 + i12 * nb12 + i13 * nb13; + + cpy_1(cx + x_offset, cdst + dst_offset); +} + +static void cpy_blck_f32_q8_0(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + block_q8_0 * dsti = (block_q8_0 *) cdsti; + + float amax = 0.0f; // absolute max + + for (int j = 0; j < QK8_0; j++) { + const float v = xi[j]; + amax = sycl::fmax(amax, sycl::fabs((float) v)); + } + + const float d = amax / ((1 << 7) - 1); + const float id = d ? 1.0f / d : 0.0f; + + dsti->d = d; + + for (int j = 0; j < QK8_0; ++j) { + const float x0 = xi[j] * id; + + dsti->qs[j] = sycl::round((float) x0); + } +} + +static void cpy_blck_q8_0_f32(const char * cxi, char * cdsti) { + float * cdstf = (float *) (cdsti); + + for (int j = 0; j < QK8_0; j += 2) { + dfloat2 dq; + dequantize_q8_0(cxi, 0, j, dq); + *(cdstf + j) = dq.x(); + *(cdstf + j + 1) = dq.y(); + } +} + +static void cpy_blck_f32_q4_0(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + block_q4_0 * dsti = (block_q4_0 *) cdsti; + + float amax = 0.0f; + float vmax = 0.0f; + + for (int j = 0; j < QK4_0; ++j) { + const float v = xi[j]; + if (amax < sycl::fabs((float) v)) { + amax = sycl::fabs((float) v); + vmax = v; + } + } + + const float d = vmax / -8; + const float id = d ? 1.0f / d : 0.0f; + + dsti->d = d; + + for (int j = 0; j < QK4_0 / 2; ++j) { + const float x0 = xi[0 + j] * id; + const float x1 = xi[QK4_0 / 2 + j] * id; + + const uint8_t xi0 = dpct::min(15, (int8_t) (x0 + 8.5f)); + const uint8_t xi1 = dpct::min(15, (int8_t) (x1 + 8.5f)); + + dsti->qs[j] = xi0; + dsti->qs[j] |= xi1 << 4; + } +} + +static void cpy_blck_f32_q4_1(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + block_q4_1 * dsti = (block_q4_1 *) cdsti; + + float vmin = FLT_MAX; + float vmax = -FLT_MAX; + + for (int j = 0; j < QK4_1; ++j) { + const float v = xi[j]; + + if (v < vmin) { + vmin = v; + } + if (v > vmax) { + vmax = v; + } + } + + const float d = (vmax - vmin) / ((1 << 4) - 1); + const float id = d ? 1.0f / d : 0.0f; + + dsti->dm.x() = d; + dsti->dm.y() = vmin; + + for (int j = 0; j < QK4_1 / 2; ++j) { + const float x0 = (xi[0 + j] - vmin) * id; + const float x1 = (xi[QK4_1 / 2 + j] - vmin) * id; + + const uint8_t xi0 = dpct::min(15, (int8_t) (x0 + 0.5f)); + const uint8_t xi1 = dpct::min(15, (int8_t) (x1 + 0.5f)); + + dsti->qs[j] = xi0; + dsti->qs[j] |= xi1 << 4; + } +} + +static void cpy_blck_f32_q5_0(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + block_q5_0 * dsti = (block_q5_0 *) cdsti; + + float amax = 0.0f; + float vmax = 0.0f; + + for (int j = 0; j < QK5_0; ++j) { + const float v = xi[j]; + if (amax < sycl::fabs((float) v)) { + amax = sycl::fabs((float) v); + vmax = v; + } + } + + const float d = vmax / -16; + const float id = d ? 1.0f / d : 0.0f; + + dsti->d = d; + + uint32_t qh = 0; + for (int j = 0; j < QK5_0 / 2; ++j) { + const float x0 = xi[0 + j] * id; + const float x1 = xi[QK5_0 / 2 + j] * id; + + const uint8_t xi0 = dpct::min(31, (int8_t) (x0 + 16.5f)); + const uint8_t xi1 = dpct::min(31, (int8_t) (x1 + 16.5f)); + + dsti->qs[j] = (xi0 & 0xf) | ((xi1 & 0xf) << 4); + qh |= ((xi0 & 0x10u) >> 4) << (j + 0); + qh |= ((xi1 & 0x10u) >> 4) << (j + QK5_0 / 2); + } + memcpy(dsti->qh, &qh, sizeof(qh)); +} + +static void cpy_blck_f32_q5_1(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + block_q5_1 * dsti = (block_q5_1 *) cdsti; + + float min = xi[0]; + float max = xi[0]; + + for (int j = 1; j < QK5_1; ++j) { + const float v = xi[j]; + min = v < min ? v : min; + max = v > max ? v : max; + } + + const float d = (max - min) / 31; + const float id = d ? 1.0f / d : 0.0f; + + dsti->dm.x() = d; + dsti->dm.y() = min; + + uint32_t qh = 0; + for (int j = 0; j < QK5_1 / 2; ++j) { + const float x0 = (xi[0 + j] - min) * id; + const float x1 = (xi[QK5_1 / 2 + j] - min) * id; + + const uint8_t xi0 = (uint8_t) (x0 + 0.5f); + const uint8_t xi1 = (uint8_t) (x1 + 0.5f); + + dsti->qs[j] = (xi0 & 0xf) | ((xi1 & 0xf) << 4); + qh |= ((xi0 & 0x10u) >> 4) << (j + 0); + qh |= ((xi1 & 0x10u) >> 4) << (j + QK5_1 / 2); + } + memcpy(dsti->qh, &qh, sizeof(qh)); +} + +static void cpy_blck_f32_iq4_nl(const char * cxi, char * cdsti) { + const float * xi = (const float *) cxi; + block_iq4_nl * dsti = (block_iq4_nl *) cdsti; + + float amax = 0.0f; + float vmax = 0.0f; + + for (int j = 0; j < QK4_NL; ++j) { + const float v = xi[j]; + if (amax < sycl::fabs((float) v)) { + amax = sycl::fabs((float) v); + vmax = v; + } + } + + float d = vmax / kvalues_iq4nl[0]; + const float id = d ? 1.0f / d : 0.0f; + + float sumqx = 0, sumq2 = 0; + for (int j = 0; j < QK4_NL / 2; ++j) { + const float x0 = xi[0 + j] * id; + const float x1 = xi[QK4_NL / 2 + j] * id; + const uint8_t xi0 = best_index_int8(16, kvalues_iq4nl, x0); + const uint8_t xi1 = best_index_int8(16, kvalues_iq4nl, x1); + dsti->qs[j] = xi0 | (xi1 << 4); + const float v0 = kvalues_iq4nl[xi0]; + const float v1 = kvalues_iq4nl[xi1]; + const float w0 = xi[0 + j] * xi[0 + j]; + const float w1 = xi[QK4_NL / 2 + j] * xi[QK4_NL / 2 + j]; + sumqx += w0 * v0 * xi[j] + w1 * v1 * xi[QK4_NL / 2 + j]; + sumq2 += w0 * v0 * v0 + w1 * v1 * v1; + } + + dsti->d = sumq2 > 0 ? sumqx / sumq2 : d; +} + +template static void cpy_blck_q_f32(const char * cxi, char * cdsti) { + float * cdstf = (float *) (cdsti); + + for (int j = 0; j < qk / 2; j++) { + dfloat2 dq; + dequant(cxi, 0, j, dq); + *(cdstf + j) = dq.x(); + *(cdstf + j + qk / 2) = dq.y(); + } +} + +template +static void cpy_f32_q(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, const int ne02, + const int nb00, const int nb01, const int nb02, const int nb03, const int ne10, const int ne11, + const int ne12, const int nb10, const int nb11, const int nb12, const int nb13, + const sycl::nd_item<3> & item_ct1) { + const int i = (item_ct1.get_local_range(2) * item_ct1.get_group(2) + item_ct1.get_local_id(2)) * qk; + + if (i >= ne) { + return; + } + + const int i03 = i / (ne00 * ne01 * ne02); + const int i02 = (i - i03 * ne00 * ne01 * ne02) / (ne00 * ne01); + const int i01 = (i - i03 * ne00 * ne01 * ne02 - i02 * ne01 * ne00) / ne00; + const int i00 = i - i03 * ne00 * ne01 * ne02 - i02 * ne01 * ne00 - i01 * ne00; + const int x_offset = i00 * nb00 + i01 * nb01 + i02 * nb02 + i03 * nb03; + + const int i13 = i / (ne10 * ne11 * ne12); + const int i12 = (i - i13 * ne10 * ne11 * ne12) / (ne10 * ne11); + const int i11 = (i - i13 * ne10 * ne11 * ne12 - i12 * ne10 * ne11) / ne10; + const int i10 = i - i13 * ne10 * ne11 * ne12 - i12 * ne10 * ne11 - i11 * ne10; + const int dst_offset = (i10 / qk) * nb10 + i11 * nb11 + i12 * nb12 + i13 * nb13; + + cpy_blck(cx + x_offset, cdst + dst_offset); +} + +template +static void cpy_q_f32(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, const int ne02, + const int nb00, const int nb01, const int nb02, const int nb03, const int ne10, const int ne11, + const int ne12, const int nb10, const int nb11, const int nb12, const int nb13, + const sycl::nd_item<3> & item_ct1) { + const int i = (item_ct1.get_local_range(2) * item_ct1.get_group(2) + item_ct1.get_local_id(2)) * qk; + + if (i >= ne) { + return; + } + + const int i03 = i / (ne00 * ne01 * ne02); + const int i02 = (i - i03 * ne00 * ne01 * ne02) / (ne00 * ne01); + const int i01 = (i - i03 * ne00 * ne01 * ne02 - i02 * ne01 * ne00) / ne00; + const int i00 = i - i03 * ne00 * ne01 * ne02 - i02 * ne01 * ne00 - i01 * ne00; + const int x_offset = (i00 / qk) * nb00 + i01 * nb01 + i02 * nb02 + i03 * nb03; + + const int i13 = i / (ne10 * ne11 * ne12); + const int i12 = (i - i13 * ne10 * ne11 * ne12) / (ne10 * ne11); + const int i11 = (i - i13 * ne10 * ne11 * ne12 - i12 * ne10 * ne11) / ne10; + const int i10 = i - i13 * ne10 * ne11 * ne12 - i12 * ne10 * ne11 - i11 * ne10; + const int dst_offset = i10 * nb10 + i11 * nb11 + i12 * nb12 + i13 * nb13; + + cpy_blck(cx + x_offset, cdst + dst_offset); +} + +static void ggml_cpy_f16_f32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; + { + dpct::has_capability_or_fail(stream->get_device(), { sycl::aspect::fp16 }); + + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), + sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, + nb10, nb11, nb12, nb13, item_ct1); + }); + } +} + +static void ggml_cpy_f32_f32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; + { + dpct::has_capability_or_fail(stream->get_device(), { sycl::aspect::fp16 }); + + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), + sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, + nb10, nb11, nb12, nb13, item_ct1); + }); + } +} + +static void ggml_cpy_f32_f16_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; + { + dpct::has_capability_or_fail(stream->get_device(), { sycl::aspect::fp16 }); + + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), + sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, + nb10, nb11, nb12, nb13, item_ct1); + }); + } +} + +static void ggml_cpy_f32_q8_0_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + GGML_ASSERT(ne % QK8_0 == 0); + const int num_blocks = ne / QK8_0; + stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_q(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, + ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1); + }); +} + +static void ggml_cpy_q8_0_f32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = ne; + stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), + [=](sycl::nd_item<3> item_ct1) { + cpy_q_f32(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, + ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1); + }); +} + +static void ggml_cpy_f32_q4_0_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + GGML_ASSERT(ne % QK4_0 == 0); + const int num_blocks = ne / QK4_0; + stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_q(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, + ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1); + }); +} + +static void ggml_cpy_q4_0_f32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = ne; + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), [=](sycl::nd_item<3> item_ct1) { + cpy_q_f32, QK4_0>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, + nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, + item_ct1); + }); +} + +static void ggml_cpy_f32_q4_1_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + GGML_ASSERT(ne % QK4_1 == 0); + const int num_blocks = ne / QK4_1; + stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_q(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, + ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1); + }); +} + +static void ggml_cpy_q4_1_f32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = ne; + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), [=](sycl::nd_item<3> item_ct1) { + cpy_q_f32, QK4_1>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, + nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, + item_ct1); + }); +} + +static void ggml_cpy_f32_q5_0_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + GGML_ASSERT(ne % QK5_0 == 0); + const int num_blocks = ne / QK5_0; + stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_q(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, + ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1); + }); +} + +static void ggml_cpy_q5_0_f32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = ne; + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), [=](sycl::nd_item<3> item_ct1) { + cpy_q_f32, QK5_0>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, + nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, + item_ct1); + }); +} + +static void ggml_cpy_f32_q5_1_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + GGML_ASSERT(ne % QK5_1 == 0); + const int num_blocks = ne / QK5_1; + stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_q(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, + ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1); + }); +} + +static void ggml_cpy_q5_1_f32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = ne; + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), [=](sycl::nd_item<3> item_ct1) { + cpy_q_f32, QK5_1>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, + nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, + item_ct1); + }); +} + +static void ggml_cpy_f32_iq4_nl_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + GGML_ASSERT(ne % QK4_NL == 0); + const int num_blocks = ne / QK4_NL; + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), sycl::range<3>(1, 1, 1)), [=](sycl::nd_item<3> item_ct1) { + cpy_f32_q(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, + ne12, nb10, nb11, nb12, nb13, item_ct1); + }); +} + +static void ggml_cpy_f16_f16_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; + { + dpct::has_capability_or_fail(stream->get_device(), { sycl::aspect::fp16 }); + + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), + sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, + nb10, nb11, nb12, nb13, item_ct1); + }); + } +} + +static void ggml_cpy_i16_i16_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; + { + // dpct::has_capability_or_fail(stream->get_device(), + // {sycl::aspect::fp16}); + + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), + sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, + nb10, nb11, nb12, nb13, item_ct1); + }); + } +} + +static void ggml_cpy_i32_i32_sycl(const char * cx, char * cdst, const int ne, const int ne00, const int ne01, + const int ne02, const int nb00, const int nb01, const int nb02, const int nb03, + const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, + const int nb12, const int nb13, queue_ptr stream) { + const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; + { + // dpct::has_capability_or_fail(stream->get_device(), + // {sycl::aspect::fp16}); + + stream->parallel_for( + sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), + sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), + [=](sycl::nd_item<3> item_ct1) { + cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, + nb10, nb11, nb12, nb13, item_ct1); + }); + } +} + +void ggml_sycl_cpy(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1) try { + const int64_t ne = ggml_nelements(src0); + GGML_ASSERT(ne == ggml_nelements(src1)); + + GGML_ASSERT(ggml_nbytes(src0) <= INT_MAX); + GGML_ASSERT(ggml_nbytes(src1) <= INT_MAX); + + GGML_TENSOR_BINARY_OP_LOCALS01; + + SYCL_CHECK(ggml_sycl_set_device(ctx.device)); + queue_ptr main_stream = ctx.stream(); + + char * src0_ddc = (char *) src0->data; + char * src1_ddc = (char *) src1->data; + GGML_SYCL_DEBUG("[SYCL] %s: Tensor supplied: %s to %s\n", __func__, ggml_type_name(src0->type), + ggml_type_name(src1->type)); + + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32) { + ggml_cpy_f32_f32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F16) { + ggml_cpy_f32_f16_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q8_0) { + ggml_cpy_f32_q8_0_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_0) { + ggml_cpy_f32_q4_0_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_1) { + ggml_cpy_f32_q4_1_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F32) { + ggml_cpy_f16_f32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F16) { + ggml_cpy_f16_f16_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_I16 && src1->type == GGML_TYPE_I16) { + ggml_cpy_i16_i16_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_I32 && src1->type == GGML_TYPE_I32) { + ggml_cpy_i32_i32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_Q4_0 && src1->type == GGML_TYPE_F32) { + ggml_cpy_q4_0_f32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_Q4_1 && src1->type == GGML_TYPE_F32) { + ggml_cpy_q4_1_f32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_Q8_0 && src1->type == GGML_TYPE_F32) { + ggml_cpy_q8_0_f32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q5_0) { + ggml_cpy_f32_q5_0_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_Q5_0 && src1->type == GGML_TYPE_F32) { + ggml_cpy_q5_0_f32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q5_1) { + ggml_cpy_f32_q5_1_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_Q5_1 && src1->type == GGML_TYPE_F32) { + ggml_cpy_q5_1_f32_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, + nb11, nb12, nb13, main_stream); + } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_IQ4_NL) { + ggml_cpy_f32_iq4_nl_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, + nb10, nb11, nb12, nb13, main_stream); + } else { + GGML_LOG_ERROR("%s: unsupported type combination (%s to %s)\n", __func__, ggml_type_name(src0->type), + ggml_type_name(src1->type)); + GGML_ABORT("fatal error"); + } +} catch (const sycl::exception & exc) { + std::cerr << exc.what() << "Exception caught at file:" << __FILE__ << ", line:" << __LINE__ << std::endl; + std::exit(1); +} + +void ggml_sycl_dup(ggml_backend_sycl_context & ctx, ggml_tensor * dst) { + // TODO: why do we pass dst as src1 here? + GGML_SYCL_DEBUG("[SYCL] call %s\n", __func__); + ggml_sycl_cpy(ctx, dst->src[0], dst); + GGML_SYCL_DEBUG("[SYCL] call %s done\n", __func__); +} diff --git a/ggml/src/ggml-sycl/cpy.hpp b/ggml/src/ggml-sycl/cpy.hpp new file mode 100644 index 000000000..0a0f561d2 --- /dev/null +++ b/ggml/src/ggml-sycl/cpy.hpp @@ -0,0 +1,11 @@ +#ifndef GGML_SYCL_CPY_HPP +#define GGML_SYCL_CPY_HPP + +#include "common.hpp" + +typedef void (*cpy_kernel_t)(const char * cx, char * cdst); + +void ggml_sycl_cpy(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1); +void ggml_sycl_dup(ggml_backend_sycl_context & ctx, ggml_tensor * dst); + +#endif // GGML_SYCL_CPY_HPP diff --git a/ggml/src/ggml-sycl/ggml-sycl.cpp b/ggml/src/ggml-sycl/ggml-sycl.cpp index d804e6606..e7304947f 100644 --- a/ggml/src/ggml-sycl/ggml-sycl.cpp +++ b/ggml/src/ggml-sycl/ggml-sycl.cpp @@ -1285,8 +1285,6 @@ std::unique_ptr ggml_backend_sycl_context::new_pool_for_device(q // struct ggml_sycl_pool_vmm : public ggml_sycl_pool /// kernels - -typedef void (*cpy_kernel_t)(const char * cx, char * cdst); typedef void (*ggml_sycl_op_mul_mat_t)( ggml_backend_sycl_context & ctx, const ggml_tensor *src0, const ggml_tensor *src1, ggml_tensor *dst, @@ -1468,193 +1466,6 @@ static void mul_mat_vec_nc_f16_f32( // nc == non-contiguous } } -static void cpy_1_f32_f32(const char * cxi, char * cdsti) { - const float * xi = (const float *) cxi; - float * dsti = (float *) cdsti; - - *dsti = *xi; -} - -static void cpy_1_f32_f16(const char * cxi, char * cdsti) { - const float * xi = (const float *) cxi; - sycl::half *dsti = (sycl::half *)cdsti; - - *dsti = sycl::vec(*xi) - .convert()[0]; -} - -static void cpy_1_f16_f16(const char * cxi, char * cdsti) { - const sycl::half *xi = (const sycl::half *)cxi; - sycl::half *dsti = (sycl::half *)cdsti; - - *dsti = *xi; -} - -static void cpy_1_f16_f32(const char * cxi, char * cdsti) { - const sycl::half *xi = (const sycl::half *)cxi; - float * dsti = (float *) cdsti; - - *dsti = *xi; -} - -static void cpy_1_i16_i16(const char * cxi, char * cdsti) { - const int16_t *xi = (const int16_t *)cxi; - int16_t *dsti = (int16_t *)cdsti; - - *dsti = *xi; -} - -static void cpy_1_i32_i32(const char * cxi, char * cdsti) { - const int32_t *xi = (const int32_t *)cxi; - int32_t *dsti = (int32_t *)cdsti; - - *dsti = *xi; -} - -template -static void cpy_f32_f16(const char * cx, char * cdst, const int ne, - const int ne00, const int ne01, const int ne02, const int nb00, const int nb01, const int nb02, - const int nb03, const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, - const int nb12, const int nb13, const sycl::nd_item<3> &item_ct1) { - const int i = item_ct1.get_local_range(2) * item_ct1.get_group(2) + - item_ct1.get_local_id(2); - - if (i >= ne) { - return; - } - - // determine indices i02/i12, i01/i11, i00/i10 as a function of index i of flattened tensor - // then combine those indices with the corresponding byte offsets to get the total offsets - const int i03 = i/(ne00 * ne01 * ne02); - const int i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01); - const int i01 = (i - i03*ne00*ne01*ne02 - i02*ne01*ne00) / ne00; - const int i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00; - const int x_offset = i00*nb00 + i01*nb01 + i02*nb02 + i03 * nb03; - - const int i13 = i/(ne10 * ne11 * ne12); - const int i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11); - const int i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10; - const int i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10; - const int dst_offset = i10*nb10 + i11*nb11 + i12*nb12 + i13 * nb13; - - cpy_1(cx + x_offset, cdst + dst_offset); -} - -static void cpy_blck_f32_q8_0(const char * cxi, char * cdsti) { - const float * xi = (const float *) cxi; - block_q8_0 * dsti = (block_q8_0 *) cdsti; - - float amax = 0.0f; // absolute max - - for (int j = 0; j < QK8_0; j++) { - const float v = xi[j]; - amax = sycl::fmax(amax, sycl::fabs((float)v)); - } - - const float d = amax / ((1 << 7) - 1); - const float id = d ? 1.0f/d : 0.0f; - - dsti->d = d; - - for (int j = 0; j < QK8_0; ++j) { - const float x0 = xi[j]*id; - - dsti->qs[j] = sycl::round((float)x0); - } -} - -static void cpy_blck_f32_q4_0(const char * cxi, char * cdsti) { - const float * xi = (const float *) cxi; - block_q4_0 * dsti = (block_q4_0 *) cdsti; - - float amax = 0.0f; - float vmax = 0.0f; - - for (int j = 0; j < QK4_0; ++j) { - const float v = xi[j]; - if (amax < sycl::fabs((float)v)) { - amax = sycl::fabs((float)v); - vmax = v; - } - } - - const float d = vmax / -8; - const float id = d ? 1.0f/d : 0.0f; - - dsti->d = d; - - for (int j = 0; j < QK4_0/2; ++j) { - const float x0 = xi[0 + j]*id; - const float x1 = xi[QK4_0/2 + j]*id; - - const uint8_t xi0 = dpct::min(15, (int8_t)(x0 + 8.5f)); - const uint8_t xi1 = dpct::min(15, (int8_t)(x1 + 8.5f)); - - dsti->qs[j] = xi0; - dsti->qs[j] |= xi1 << 4; - } -} - -static void cpy_blck_f32_q4_1(const char * cxi, char * cdsti) { - const float * xi = (const float *) cxi; - block_q4_1 * dsti = (block_q4_1 *) cdsti; - - float vmin = FLT_MAX; - float vmax = -FLT_MAX; - - for (int j = 0; j < QK4_1; ++j) { - const float v = xi[j]; - - if (v < vmin) vmin = v; - if (v > vmax) vmax = v; - } - - const float d = (vmax - vmin) / ((1 << 4) - 1); - const float id = d ? 1.0f/d : 0.0f; - - dsti->dm.x() = d; - dsti->dm.y() = vmin; - - for (int j = 0; j < QK4_1/2; ++j) { - const float x0 = (xi[0 + j] - vmin)*id; - const float x1 = (xi[QK4_1/2 + j] - vmin)*id; - - const uint8_t xi0 = dpct::min(15, (int8_t)(x0 + 0.5f)); - const uint8_t xi1 = dpct::min(15, (int8_t)(x1 + 0.5f)); - - dsti->qs[j] = xi0; - dsti->qs[j] |= xi1 << 4; - } -} - -template -static void cpy_f32_q(const char * cx, char * cdst, const int ne, - const int ne00, const int ne01, const int ne02, const int nb00, const int nb01, const int nb02, - const int nb03, const int ne10, const int ne11, const int ne12, const int nb10, const int nb11, - const int nb12, const int nb13, const sycl::nd_item<3> &item_ct1) { - const int i = (item_ct1.get_local_range(2) * item_ct1.get_group(2) + - item_ct1.get_local_id(2)) * - qk; - - if (i >= ne) { - return; - } - - const int i03 = i/(ne00 * ne01 * ne02); - const int i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01); - const int i01 = (i - i03*ne00*ne01*ne02 - i02*ne01*ne00) / ne00; - const int i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00; - const int x_offset = i00*nb00 + i01*nb01 + i02*nb02 + i03 * nb03; - - const int i13 = i/(ne10 * ne11 * ne12); - const int i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11); - const int i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10; - const int i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10; - const int dst_offset = (i10/qk)*nb10 + i11*nb11 + i12*nb12 + i13*nb13; - - cpy_blck(cx + x_offset, cdst + dst_offset); -} - static void k_sum_rows_f32(const float * x, float * dst, const int ncols, const sycl::nd_item<3> &item_ct1) { const int row = item_ct1.get_group(1); @@ -1903,231 +1714,7 @@ static void ggml_mul_mat_vec_nc_f16_f32_sycl( } } -static void -ggml_cpy_f16_f32_sycl(const char *cx, char *cdst, const int ne, const int ne00, - const int ne01, const int ne02, const int nb00, - const int nb01, const int nb02, const int nb03, - const int ne10, const int ne11, const int ne12, - const int nb10, const int nb11, const int nb12, - const int nb13, queue_ptr stream) { - const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; - { - dpct::has_capability_or_fail(stream->get_device(), - {sycl::aspect::fp16}); - - stream->parallel_for( - sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, - nb01, nb02, nb03, ne10, ne11, ne12, - nb10, nb11, nb12, nb13, item_ct1); - }); - } -} - -static void ggml_cpy_f32_f32_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; - { - dpct::has_capability_or_fail(stream->get_device(), - {sycl::aspect::fp16}); - - stream->parallel_for( - sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); - } -} - -static void ggml_cpy_f32_f16_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; - { - dpct::has_capability_or_fail(stream->get_device(), - {sycl::aspect::fp16}); - - stream->parallel_for( - sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); - } -} - -static void ggml_cpy_f32_q8_0_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - GGML_ASSERT(ne % QK8_0 == 0); - const int num_blocks = ne / QK8_0; - stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), - sycl::range<3>(1, 1, 1)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_q( - cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); -} - -static void ggml_cpy_f32_q4_0_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - GGML_ASSERT(ne % QK4_0 == 0); - const int num_blocks = ne / QK4_0; - stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), - sycl::range<3>(1, 1, 1)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_q( - cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); -} - -static void ggml_cpy_f32_q4_1_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - GGML_ASSERT(ne % QK4_1 == 0); - const int num_blocks = ne / QK4_1; - stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks), - sycl::range<3>(1, 1, 1)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_q( - cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); -} - -static void ggml_cpy_f16_f16_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; - { - dpct::has_capability_or_fail(stream->get_device(), - {sycl::aspect::fp16}); - - stream->parallel_for( - sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); - } -} - -static void ggml_cpy_i16_i16_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; - { - // dpct::has_capability_or_fail(stream->get_device(), - // {sycl::aspect::fp16}); - - stream->parallel_for( - sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); - } -} - -static void ggml_cpy_i32_i32_sycl(const char *cx, char *cdst, const int ne, - const int ne00, const int ne01, - const int ne02, const int nb00, - const int nb01, const int nb02, - const int nb03, const int ne10, - const int ne11, const int ne12, - const int nb10, const int nb11, - const int nb12, const int nb13, - queue_ptr stream) { - - const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE; - { - // dpct::has_capability_or_fail(stream->get_device(), - // {sycl::aspect::fp16}); - - stream->parallel_for( - sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), - sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)), - [=](sycl::nd_item<3> item_ct1) { - cpy_f32_f16(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, - nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, - item_ct1); - }); - } -} static void scale_f32_sycl(const float *x, float *dst, const float scale, const int k, queue_ptr stream) { @@ -3645,58 +3232,6 @@ static void ggml_sycl_clamp(ggml_backend_sycl_context & ctx, ggml_tensor * dst) ggml_sycl_op_flatten(ctx, dst->src[0], dst->src[1], dst, ggml_sycl_op_clamp); } -static void ggml_sycl_cpy(ggml_backend_sycl_context & ctx, const ggml_tensor *src0, const ggml_tensor *src1, - ggml_tensor *dst) try { - const int64_t ne = ggml_nelements(src0); - GGML_ASSERT(ne == ggml_nelements(src1)); - - GGML_ASSERT(ggml_nbytes(src0) <= INT_MAX); - GGML_ASSERT(ggml_nbytes(src1) <= INT_MAX); - - GGML_TENSOR_BINARY_OP_LOCALS01; - - SYCL_CHECK(ggml_sycl_set_device(ctx.device)); - queue_ptr main_stream = ctx.stream(); - - char * src0_ddc = (char *) src0->data; - char * src1_ddc = (char *) src1->data; - - if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32) { - ggml_cpy_f32_f32_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F16) { - ggml_cpy_f32_f16_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q8_0) { - ggml_cpy_f32_q8_0_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_0) { - ggml_cpy_f32_q4_0_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_1) { - ggml_cpy_f32_q4_1_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F32) { - ggml_cpy_f16_f32_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F16) { - ggml_cpy_f16_f16_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_I16 && src1->type == GGML_TYPE_I16) { - ggml_cpy_i16_i16_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else if (src0->type == GGML_TYPE_I32 && src1->type == GGML_TYPE_I32) { - ggml_cpy_i32_i32_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream); - } else { - GGML_LOG_ERROR("%s: unsupported type combination (%s to %s)\n", __func__, - ggml_type_name(src0->type), ggml_type_name(src1->type)); - GGML_ABORT("fatal error"); - } - GGML_UNUSED(dst); -} -catch (sycl::exception const &exc) { - std::cerr << exc.what() << "Exception caught at file:" << __FILE__ - << ", line:" << __LINE__ << std::endl; - std::exit(1); -} - -static void ggml_sycl_dup(ggml_backend_sycl_context & ctx, ggml_tensor * dst) { - // TODO: why do we pass dst as src1 here? - ggml_sycl_cpy(ctx, dst->src[0], dst, nullptr); -} - static void ggml_sycl_diag_mask_inf(ggml_backend_sycl_context & ctx, ggml_tensor * dst) { ggml_sycl_op_flatten(ctx, dst->src[0], dst->src[1], dst, ggml_sycl_op_diag_mask_inf); } @@ -3893,7 +3428,7 @@ bool ggml_sycl_compute_forward(ggml_backend_sycl_context & ctx, struct ggml_tens ggml_sycl_clamp(ctx, dst); break; case GGML_OP_CPY: - ggml_sycl_cpy(ctx, dst->src[0], dst->src[1], dst); + ggml_sycl_cpy(ctx, dst->src[0], dst->src[1]); break; case GGML_OP_CONT: ggml_sycl_dup(ctx, dst); @@ -4407,6 +3942,30 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) { return true; } + if (src0_type == GGML_TYPE_Q8_0 && src1_type == GGML_TYPE_F32) { + return true; + } + if (src0_type == GGML_TYPE_Q4_0 && src1_type == GGML_TYPE_F32) { + return true; + } + if (src0_type == GGML_TYPE_Q4_1 && src1_type == GGML_TYPE_F32) { + return true; + } + if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q5_0) { + return true; + } + if (src0_type == GGML_TYPE_Q5_0 && src1_type == GGML_TYPE_F32) { + return true; + } + if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q5_1) { + return true; + } + if (src0_type == GGML_TYPE_Q5_1 && src1_type == GGML_TYPE_F32) { + return true; + } + if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_IQ4_NL) { + return true; + } return false; } break; case GGML_OP_CONCAT: From 7b69003af74924ac04d97313c2e57c45ba56b616 Mon Sep 17 00:00:00 2001 From: Xuan-Son Nguyen Date: Mon, 3 Mar 2025 11:42:45 +0100 Subject: [PATCH 07/87] webui : add ?m=... and ?q=... params (#12148) * webui : add ?m=... and ?q=... params * also clear prefilledMessage variable * better approach * fix comment * test: bump timeout on GITHUB_ACTION --- examples/server/public/index.html.gz | Bin 1260365 -> 1260534 bytes examples/server/tests/utils.py | 5 ++- .../webui/src/components/ChatScreen.tsx | 38 +++++++++++++++++- examples/server/webui/src/utils/misc.ts | 8 ++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/examples/server/public/index.html.gz b/examples/server/public/index.html.gz index dc8a4fc6f2d843a6c08664211c0680795bf22e49..c7a3c426b623c707bf17b900886abb3a3a57c8d6 100644 GIT binary patch delta 1215997 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

{x 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

c>NEBcC|GXUi4PB2fAHVZl z{wq9*=-Ck+_W}%G^FYB~5Z|+}Ga)+afB5q=f8Tj*zI^*FcZe<$;hlfvf9}65XA27X zgawlO0`dF!7rerkUmfCWw*JUrY=HvxPgnGRMg8jUco2Rhcc`EAtv5e%iR#~ZX@9ME z1=$5KN5?dfAt~(RR5qj;1um+Kl{Xr;8G-~KXguioo8)j?|_efoJA2| zkuy8jqZG#<1Rt$G^OJt@qy6t^zfArr&yWG`%8H0j;13h|{lo!I{&$BJ^XqFD@ata< zkn8L>Pmv5jgZwx(@Z+jzA`#}lOH)RV@Q|N15~c5X_nk^)uSTSQfB9d1^9BO&&DX1} zNT?cQ0vwS%YiM2|gVy_o=+jq#0nP&kvZHbZFfC-gn~)Rv4XslPtt(ze4@W6&fW0Cj z8sHSHhKO;Izci2H1y~#HlOD?VE_lF4c5tBp0m|bnAbU8Q0TJa(hbEA9a4EPD#pDx! zD}iOPti_AKm=F;ee=r(w`Nn$|EVOtPSQEV0ULgiFPs##n z&^eaXL53$?v+A{eVK4sjaKUaJ&98Qav#ek3jR9FNE0X{(f59E5YYDzswwcI_t|-h= zXP2NY2hg$u>l;H%;3bRuYf7|JLXey%mIJ`q)8@ z|EK@?|M*|g7gqk4=OfMk_g|&1YWM$8A8sE0Z%#T^!~EaA4b!~0`G33+hW6)|HLr?t z{tptv{@XOB|M8FCY(XD#A^!MkONQM<{SRv?45ptb9RMs8-Ua>m@2%Z`kaf{=8e~TwTWpPh1BTNMwH8M*Sdf}vr<7R?QRCmC^Ya&R{#yw zH}P!Tr0J@<{cDN46PXfVoQku)ZIYhf-)~w-ZF=hkBVW@C)cXi0xZ4?XPsJ)gH9G)9 zK)kX4iWOQ&coOSTmX<>t06S*r+l3V#au6$j-rS=goei0pKHo@pn(Vyq3E*V?jYf(A(+ z@%k=B$_ae~eR-4_Zoc2cB`}vty9}clj%?zq?oQapeH7{W!DiqFge%Hf%FYnoOB zzIkS<%V}0M47^M+_E;ILMA6aw*6=ucEKga&|=tjvgB!e z>va|5@qdHJhSpX*cqMZ0y<)wDOJALYoyE?4Uq9F!c8}RE@#{n1r+1V;b3>@=&uj4{ zKkqGfAI35~Tbxu_BXRcfu522`D*3Y~a=0Wa&v8@F=Uj{z=A=^x%U1Pj*RQJF+AC3; zp&al_-wtecsxW?IsnoHcN-#E2>_U(T6aNqsd4KCK@Rk-ec-0#xp0SW8llZt?hKh6B z(`DGAq{kCS*qA7ipm)BV_Tw}>ZiL%WI=WFY7&dVtC#P z?xw>Q7xE&+y??o4Vlv8WSb~q#(_Zn)PI=3HyawME*0=pCb#5jZzlMO~u}CCh@<9%q z3x9Q-zOyMP&F1|qV8#lK8a%8U#~+2xYwz+h%J$Zz&Dv9-^IyH?C%F+j_1GE;>FQmQ zY+TbFkHPR|#ha}=wq7A1N2_6r4H%-#d1Ku=p&-5MxlV$7Xj3OU3Zr?!rY?`RnMG6Y zO(wVE8Ai=LnU)*Rf6n)eQ%0pXdg2+EJAY$kw}%o~=`wRS6-0Z7y$9KA^mu`cl(XI2 zp&AN2G@Mts{lQBcHGuWyS_bBhGIekAHn$ZEQy!g8F69TG63M}5CttbSO%u6;?Y800 z31+|vl8@WaC>qhq#383WRe35^oezvZOM?VncM5W(i?@Z=_G@h{R!Ven5KVT(zki*} zJlf)@5xBzDGULyUTJE0Wa*v66aqT^6Uo=lCt|-X7$8%FtLnFu6x*4?Q;%==I5;+kY3Y3)^z? z)0Of?>GtW^LMVyXZ1Tb-eM<%hXS?WBuYdD8m-~GuKSWsDy3Odip>O=U?^sj3dvZ&> zx5wHR#@NJDpN5Cx$zdh~#x<`w7PqqnMJP5+YEf!_K4MB2!OY>W$6bHD-{b=eXI(U} z<`aH!KbGjLOX*a+7uNZDp?@kVdg*6Bkvm7ebkA~Ni`UuG)z{h1<9+O?$61b|g6(Vd z*kJbQh1PYdr42$u!z}*ArE@5s^lFF7wQ`io)w-v$cjZV4-jkFu^QO}C=sw;Fj-Rim zLbmu8lEMv=U2;$2YZC1ucQMr_eJgh*dw&u7%~`rd*p}q| zs=Mo$K}|VvYs`+rU3p`AYdpiQjDcwPKn3b9$tV9(&}WhJPo6db2Ce$EF8JxB6W37CnYc@$L>PJEECXyQeFEh+MfBcdRS6 z+wtB->bT4S%1xTKalT8pc5dw&e~+Uf8rnOwd8R`s z5~ZOJWl9Q~TE)el+Fk{`_Y;KV+$=90Ynh%Xi@aHweT;G6#{VJMIzeQ%u8v3@gVU;eY3=8(xo$g-mC<@E@Y5GnKDnT$6XW8p;#f;y%TBbiSR^TO9Kkf?S0MDVSVg*C0N-9YmKXFmo-F%)wG3M(LDBm9 z^*U|E6;=YxcYol@5e@{=@u;SVh%$dVc}E}u!-akwE8D8P*QqS7folXXz)Kt4M%%iL z)_NOl^8CgCnROn8#oA~!c`Mr2NRr|<&qVi%DbipwPabfJcfxtYEyKO9yu>0Zf4!2I znWzr?)SD5v>-`#$O=rZwH0nlZFt;qbm$*cDvKyzAqkr&14`RSi2T->Mcfv$AO}3=w zRXtYvtqOy3j@lwv@8HA3*WAMgi8(LmdyzWUwvt8!ULiDgZ~oqPqKkMKgk-T z@_39{rJl1#aQBS4!=z@T8$74@6awH^qE5=QUv7R}f>FB5cUch&sy3G?XO$VqIi~?` zW5F9&Y=4tcJ_VJ_5MusIUmV6wHpdVvKRQM0#l@O9TisSDK{(&H;bng~+_rw^ELsb&f)=O2c6m{_ZE=qY@xwJfO zm79|owjlGs%d*PmB|6hAUJg{1h@3bp$T zV6E~Y_cgW4Pq-z2`pR^gOB~ln@M%ht(LTzAX|aEGT4>}=TkvIHTtwN{LJ@*$4X~U) z*{Z$*n^(N}9jJN6Hz}M|!80@YM(V{g-QC+wsm<$2l>;?*o&rdmHW*E3xpfAsp4ws9 z@PA?u?x)aaDzfAUc!o94jRSkby0c|ow%M?j%C7t?6$BU`!pUb7BT!G@7$9krT5u)tSGIoa|qmQGecTJSD?DTyp!Yd+*&J-j2*!zU4}yE9Iek zHThW6SuMhjw-yG?n`y))F#Vc&>xGkBsa$=WMYQ&j1KpLkbMj8skIxQ1vP#<^s7xd9 z;`X(Dut(4pK#jxlNqIuB-mD_b@{CIbyk5f`yUeCd4_1CDB){`$`N{7C@5W+5On(L? zdi3~!M;99R&c)x(eXOIISoa=OB(+SE*B{l1@RkA(1+7i9&sMgBVJNZkNa#mjzMh3I zED4F5#4U)Thgwu(_E@@?6Hb;}2}wd>qG>}bZ}R-6yWS!_f`>>7gNQAMLJXP{id!2V zvS-Ynn;6L_=Tfkkm~W4v6{XXyQGZ0sKGq?lHA{2HqAa9B(K(^o6lW}-2R_d$^`Qc* zd)gQge=`2^?h7szw%*5Ujq}C2WXf8-m%K4hjPk0k74MvhjrSh*X5h+UJ015bCa$N` zBB?K_VVdJ-j@3hb0?l2yn`LqN5NVBXe6nk0E3}m|ol8c(P0prN%E9MJK7Xhr{t%y* zHBZ&XbaVA^BV#d(Bb^6RZf4q!T;)*o`>U!HxfLa|vc+@hin{mq25V$Lr&ZFQB6-2* z_x>^+Hmc-VbC+bT9&`|{_55}_S?mnuFWY{@&k zL6*a^StesrzjomblP&_@bXZsWaiH<{I-y2~K*qPl@etJwekqMMqMt@o8As5r_m6DQb)H0!s- zc}N$)-}=k>Tr4Fw+zZ>jR-f%MEyp7;glLZs_$d9%9gG-WnVaHzK*h*bt^x5*%*UG; z$=e7%_?7$^f3zni?S4Kb1kKd+5!QF(-R}>1N>7IW?7+JUgZ#ogM4FO>54CZVaa?Xh zAhOFt!~Rt52O1=C_<1+v{t>-Rq#*ut*>E#8M}n!z{gtLi%$0 z+-?-1I!(*$k^d>)C3xv$f6dHeqe)r%P-{q2S|Qehf4!z2nB7~KY{umy6Q6!~UeEg= zV@(ChtHa)T5vK}{-Y%g`zWg#G=YvqH^|IAVG88HOP{qXw*CF(uh4L~edkJd>mz%e9 z8fWcuS||g+vbiOA*<~Ruo*j-@sQ8%gqxpKP!)~?JwJhS#@_9+jbyfuKb<$q)bbW(A&__(F}HZ)vT z4)~Nwm!AszDQF*Dr;KxcV|E?4sV>8mXXWMEh6jfqDl%RUW8qY{n z0V1lKJu*=`hu5#-pIm0aNSc%Dpg(_*y3IqN!^pEH?(@9jl${SZX3SK=D+__HvK0N!^2^k;2@Lvn3rqT~vC&7X~O*V28P&bXuVUe~a3Nb)pGYas^ z%;$~ZC-A{LNm=rEJqR4|;dUv1y#!QUTH>%2eyqUox1PY1WHjM1O4wJ$Pd%=211z~w zVXM8UV8Kn5eBq&1m|P*2I<^dkLH#@p2;$05j###`{W__>60b^%e${kgedBefYACOM zc6`M$1|aKayfn9nMrQ=?C_F=Rh?nI6!!mv>jEMihd#g>mAdV=L7r-xnEWjlM==X); zEtNRXp5Hht77EPikI{s_`b}0qc;2L`OMlJmLy*5%tpb&+)KGm@U6vYmypuBZTaydi z>>bat%)YKo2f3--mPX;;#vfv-fEjR5?QZu}6HxDU^C|>xrXgVnem@yJ>lgJV0 z5pT844O})D8z${;cs`X*6cX9D2l)=7j_zjCbH@a?5k+me2cDFFfYN z`CX4wgXO@=0|w|Z^Aoc-5%j4g@Rpl_(S#<-X8DVx1XWn0jPRxT7*qyN9jFRDf`>9C zOR4~V({4M|Y_|1(LKn|hL_W_MLj>k)?Oy9AHie>dmZS!i4aos^ui{?pX~CL&&DJCr zeY)#21UyYzg{f5VuAKoj>r{q8y9=1qlG1f;Ig#rvzwP|kVU(dD66ubumZ`$;=SWGs z+-9c{DTzTh9+irY1Jo8x5AaDJyUdeVTCY1X9(%n^Izi2oqkY&{YPHMlU9(F=@FSm?;kya@chH&kI^W%(dmQ`IrjR`9GjO@jBD zEb65g0k&G5-=@u9Loc(*flEdi9b${f@Kzi%Pr{1E0K{cen^iaRO)E#vuwt6Q>AmJL zCQF}SqGx}9OA8$gxY1U*doeCqRCC(??6W+Z;|YPACmh<-dDA(l`9~rW9RfENkhl}{ zTebjyZ{VmDEf%P^dE6TKsENh11&nFz1=JAU%PeG?GgT?^L;)`!NKnqL=M4f%05xhFR zsc36Urb!b-XYNbKa%1!ZdW&2eJR;t_@DCWF_=_DatRXXYR?=W{zBe0_0$sTJ1S>#y zjW}k1GW>GZcX+6Nu_)hwMt^06WgY(Tj_pGwNM-t|z$4jo4a7`?&ro;o;cW;J`QEv# zF1FT{@f{zItD z|D@P3-7OpmnnHh#D)bMvYX8IGt|KG-ra~(Jz?Awgx{%%fWCxg$bR=0JWn28qfgb-M zz1;tbRCH40!P9^CBKHv z{`Y$Fzd%Sw5pMaHNibCXwf#ek|3i7zVt28Dc;txrH{L4w-$GW$acjH?ZmYlOb{79% zIkz0ce1GR)4rzQ5eqlC)Gb-EH9vYUTF)7Em06!?KEOD%3{1&N* zq9Hl~JV_@3QZ5iN{MyGEW*>EwlItdbm;QiJ-_|>x^H2wA*5mTF%dc`6vbX!S)-bhlC5S z832v>StBKHRRLr-P|>FZ5USma^-fZ%NUN^FKf-*>RPQRj>AB~j+`VSv;pQ*jzdxB9KG##(5}2z}br_Ac$06>9oE5P{ALq$o1y9UkXMjCzg5 zHTzLvC0&hxi5F{lSACAYjD9lX4(RswIZN;SPKSFnez24qa3OvJ0Jj7Pj2|}Y-BG5X zyzsS3?!G*75kb+ohN4}6o>s)NUj}z~^(tr2VEhOUM6N=sNrHwaMK1vl*ZE2q@<#s{}Q0!jCaU;6i* zXvE^Q*Qa?z8v22HyZ5ZEF?{0+fDQEd1}Ni8&Sj;wwx^2iowf{r$O)gRMfxic7zD!O z)fagLig65}V}xm4MZ`L2=Wui03jEr_R_Mf~VnX9qs?VnutQJa)QEg6Y3WH})+4CrI zWpiH3S3&J}MXR@2{?j>7BeKaU&RV1lJV&$SAr^B9=wiVYy|5hE&PqJj_S+Z7La)`R8FvRgQ)8(pi=W~QuW0S3tq&kv zSOGoGbGalAv1KaGMFpDdP~&urugjbw2z;0~_xY)Wa!G>Jx!0751UkR1$+ zhie_Zxya4_034SP?R9L?odF;nvIg@idX~~7 z7{rC)^@ur4QJewe{E)DG zAIDn>%fR&hS%Pc;Sm96}5(bflSmHwO)A%OFR^a~c8FWwZm}Bpg!){ldAIl$RxNqFX z+wk=H6djoq{}#IFxO+J%c}0?qWNu&cyghIH3o06V|5ak3e2k!MHn`qc>KMVh)E*6! zhjjNn%L{Fx2sWDt-CcE0ZluZwf4~!amOd2*5V9=sc`zd@snH}geQ&{m#~741NIy@t zrFE2wxW#itn1^i_{DVS#EfV?h{8hXTGLETM9}y8}Z9ZB6Dm!Igz_U@~ae6Qae3I18 zUqQ>)>*0w$oAUW%e1R9Eu=HnzU*nWCXnt4Wkqiv%49Um(oBo!&XN7NHe}oemXE!B{ z;-ju6Zs#wL_XnMRBiO97YeV(Ssub323TyWYo;)kLT2dmIG+;01_+V9PlU2+UaFd-? z_BYpbMI5q!N0z_zPi79Qak>StyCo?t7@f(*xF-$k$(W3GFgRLQJzm$b`rWNZ6s~z%mFryt=~%u z5)b>*HwHGne}Vz;U)>vVhJO8(Eb297vU>c`cqaxoYc9XCaUdP1UVZA>o-l?6lJ@>K z4KENuW&HVRLk03#p0-UzZ16mpJL(F|rXRV4tt1U|wW<-A%2klvH=yc(cAM9O`!j~Y zNS8qRCQG{MLV>Y+IimL^g>4(nr26b3U^UkYQ#r3)e;rHTFKCAi8u#rKnjzHh%0}hy z!x{oG6@CTqE*)TaC6L#x=Ih5(Qxwk>C0xJVE?^47>qtgog2c+onA2I!--*JlOs2&s z)uej7cm(KCc|5J_ck*9K@DW;;b`EaeYL^{^$TT`Xrww>NnqWu*^oe02EZ!t5qTmfZ zN&E7gfBBL;u=7;4+>^k>*e(;f^wV^c=TLk5i8NwoO8&CcK;)SN=lnS@-nr|NS_Y`M zMY0vyAm&~k7`=_86LUxKfWlHwAbDItHWO9#bj6a3?)Jh2qeNB6O~Z8yQaGWbQ*vGc zC7KV#tq-D5aMV`_4%dBBXL4Wq;PF~(Dwr(%e?etUBg2T|tPn+DC|4OyLK&|1H{5 ze?dApOKa^X42j3T$bz9=y=R)7J&6EgDof}9?&#Vy>)NupGwPr#CwD%JPeh#ZyvJ+> zLGS_r`wuT=59JO2gzkalLn&+{sP4QF(VFK*+tK~`cO$=NFTo!y;U)xy@GSD3s zhk5es#2r)aL??w*wUkn7QcPe$*4uI4A4E_Qkox>Ok9llP_4^GurC#rb+XzO7b9P9Q z!eDTfaJ6}N*tX+X4XvY-3Z{pd`+ckxLd96TVlZi(TITmLpSjs*B+vxz3j!)ue}5-Y zPN!Oe3_Nrys1Y*LHIA)&JI>XONTVNxLLE^+xOy5Pl!2GrQjJ)zV3J-D$r~8WkzIGxmkd3AU@4u<$n8!;)-EW8 zIiJy!TBII|;A$m2V69mmXR}J=fA`ocy61Nj$5~Xr{G$6;BJh6vjQaB?Rfs@z7rcCU zK8kW4W|M|`$9zOzBe%7>IEB7+Pn&nn&B6@idZb(Er~5RPaLUPSb+g`L4NA{+z_W}O zvz_C3#=X0TK#>HK*|ApFc~$8WSKhQVvB7Zdy--5xe%*cT{`~XGE(A{KMF3kM0PJhS0C#yJR8qP6 zxs#s`Utw2dr5urF{pCU8efabQVPqhoQCf$m*uT#T$-5C2^EisPz zi(2D#y@@u|g?lBg(La}<%(RGps<;ZSMc$o_y{ViCYW!)hWUce1e_v#6cYmR@pCUy8 z6t7Fyy|KI${P83_e{VmM5B8P7ZPM%*M(Mo7W`#o&3Oj_;_tVV6x+ z5PlV5RCS^O98O_jcC!kE8f{F;%d!m5ByIpY&}WVGe$*cQk!Vd$!{3}Ic(A8&S&Q+c z0V+VMkZ)`Q3gSV(6*m_Te{^rBhsJTf1EflI+mS4iIPrjS9+I6eo`<-@b=+Vzp?-Xs z;hRn<{Kr*me}NxxlikvywpX_3@!xAQ!ZEpXZblfcHp-eUzL?JFShnK^XDv<8Vjg;4 z*r{!x2ARi5E|$$WoT`Gn&{tB^uo2%W>A=gvjrT2%aGe`~IA`7V0QH#!04;CQkBGCU z#`NplDz>6Ot;(-iHR&&jz{-9u0?p1?2EP+tN@Be)e<_qY$>ufsKDUwm=wAH08=!-K zfT`^FJMtahp&?7mNWUE?5*-?aG+~e4>$Z=r>sSMS{oS=xSsw^h4b?kw~nK(56W$WT-F#oBABMKF{7?LXr0o2r&(sZs#6#Pf~Z z-|{!;e~4hh53T4{EVF2C&BEPC*sql$?eTbZLg_0wk&FuVasL%tPfy)DaC-%EWiClZ zz~mUMDtuw|3nC#(bktfJ{StT0TgjwB0+HmBnB4?BNO+w4XN1fR#TPjUm?mnQ#^La? zlqK+^Vp>lm`>YGxrZcdqugD}ptaAVgBO?;%f6E(OW$pK2(hJ`FqGA z8mDLS5h6ML1%q`VNA|$^y<;VU^HrqbIDoAf8dBw#A~_SYRd@8E)m9U+Bp(+b@rCKw z!&SGmbdkVuvQISq(a*Y9hm*H-EzPlU7haewQO+NfZaG@uZ~=46i`Q$|PdWSyK^?lK ze*wVu*$U1A=?s|wY>u(laj_UQCQ23jImGl*ieOQZxm7G{HY}%M+o-f9x&H<7fQfhx zr^f5aXr$;d?LGFMyMba-0%t!Ce}1dmNciFlOLnix^6}?G%^W9U2J4EP+>l#afS?)g zYQJcL`_5&T(PPGIleXF#5NfaMFq!jre>%4edna(=Y>6%u1hF6iK13rrzGFpD=YQk7 z^JiUxZ&gUkGSOL7P0X{~M!5uI0p;f<3_@Um1GS#~Q6%)!kp) zSyXk^ox+69rXNS(m;}MMOjhwdW&vb*6Enkx)r?d4QEEc1j+N+s*9^bPm6dz$e@7HD zlCV(_Crm*kYva}}BYUyPNlSpC*-H?bV5hHoFa-_@5IgrnCepYs?fa`wi@fQ#69uj_ z%+II&Oj@Vh@_uq~O{o3yzP84b_ty4?CAfHsUSHMK%axW}L_62xz&wuGCTU_f8Cx&` z^^Z7x%5|T3jJ7gUxMdHEDYPVxe}Fq-HVvWawdYe{FC%6M7(IY2jg9?TWauJxKp)j> z%VMyik=C8<9_ z7+<@AeTG)2l5R_Z>`e!6f0}jS4H{1@QTcb)^YPFyMX#Ms5Rl2!#U8!|Sx7U+q7v>6gI%G&V)tdC1SIqf(ca6z>n`mm;9lqe-9jMKIvJ=O|z8v zaW`Ml$z)OTTeakq%$){nLp1MnY7{Cis#mMheU{t7JY_m~1yLnn5`Pm|<3-}mKoGQX z%zTHPBYwwnfnNqhVaEDt(t@~b$OhK54$o82L*b%y?41gFx{G1jlD!A072o*d=$PAI zAO4FQLa|q&@lK;re<&t)<$~^1lS`f2HqId_0jAsdymQFHAOz_44715!EWuH*&u2*a z``yEK;@=BASWY1rR-$mYzD&v5kh#$*Ox}A%o=(WrA?Q0}L?`JUt41lfk}iFfP0R&_ zZu?>u5p<~4Cz`F?s$|)Uh?KUm4G$+BwK>r2I&)|+o>dh}e=ssh4hMqX3am6}YPkL0 zM7aUIi1AMiYmLx2`X|fnkn}FEr{kMS-C3Wew&G81sd`kU0|ym(T@`g_7`3lz7*^!b z1-No7J4}3(713#su1_j!lFzg_fM$mbOab!U&|FSi*$FN_(dURgvhPAX?`=-$}lSi3qASDJTm6%X_4 z@ROhr9&D`d9pI5$0rZk}%&dwRHg8KzXN z^a+N}e3o!P|MVxu*s3OrFqq?H`bZEroTJG~Um}=a9+fQlK?H^1l#gJ-?B@OjY~Kf9 zM!xmOe>HUk51yy+8EIaCxrml;wRu8>Iryn^+)3y7{Gc>eF2-g`#uMVW_S|yK< zd3iH)5DjVRbS##6*;*1-P!`&9Xgc>7zZ~^_R|lOnzZc ze^rvZ(ST0-KH87t2K5i+xN|uF{(U`n@~TsK zQzBCmw!eRNS+1xUi0{nRR{g9mG&oxsu#C)kNFy`k-+&KiuOfO0n=>x)q#jf&Ups1D z8w#wKY+j(i5~fGYl9qr*QV!#_Hd0&hhFahbxLZF?m(yuj{k58pi7$Z@`0@Llf9;y0 zetztZ0&dF&za4Tugm^RTjTb;)a}~CeUBO=Gk6d){3rrG+d?N#>>x0VQ-27Ik93zow zYjCbMXb2aBU!vKtBDc{iDb#?6wP{UYO9Zku>-T*6Luee&K8>@f z>(5=IwKGNo7xh*EFMll5X>KXXnNr;Btm2p)MO(=53ob!(21H7vT8 zfqZFzP1E%RUx8ztH^vrHe+l=Ff(}pzeH3|LWO=rV#~GJAPI7W3Sr{;;E|Gml=D*fs z`R0TFwTSTl%l=;d|F*yLJ5wv%?wCK8heWeURQ6%y-DznqUNrAMG!CN->xN>!G%Vr< zY=J)$KwgZO0|5>H~&x;KLf8db_h@;p4UAp(b zY|!@dXD#@**w6nTF}2Y%oWb{hg8Ox0q{fgKLEwx(3jj(n>aBJRbMx<5OW0#)cVj;ftF=7+43v#vB+H;)t6q{`~9at)72M67?_r zon)Bw)+L4?c+>f>f4y7ovjky>MB)e#pc3ct^rxmlkRm>m@wA0eamENJj&YdET>C^) zqBQ-O+t``g^u?c2u}vn(PHzAS&km`iGE4&*yhVwUNlkYPyqr^1ZH|XG|`x9j1oi>4z-*J5&XJnihnPdfvX<8T4@_Y zHc{-bCvK#4D9%@^V(sRmZfDfDUID<|xDr{@+9%b|SMgehd~uOW;)%>7-QE3^Gj1&T z-?%_G(nY#%-#1|<1}%H{@|nK`_R0Ci_b7G>A6a-1f1z{^7AX>*=cBVj6mqu#5;#c-MErw5$qN+DMRv+`f9xLpyM0c0cKg= z*C!8&v{Ev6GiC(G(5(dx9)t2T0YA5z`>k|f9~SL=+iIR%!zQda?$}CMucnCqSVdf zYh1aOM-r>NAUuWjYDUzZeeZqZ%f&6Aavdv#rO10*FmSbtr6Rf+$GUr*L5GMag}8=s1mO(lIG6DF`VxP*sZ2PMKe&8cy@ z;|yk>1>3SR63ardo(tApFA(E9MTo0IR`CX}4p1*Xi72fggOxg68LmFk#^h-wWJ5M# znUyL&0Do9wn|(ul!Ik9LM9RL*3Cj{ee~R0)!@hu%a>0wjy1l>*KkQD!vLyR5{)anV zA;0P+o79?WRQFsP;WNb|a%t zBE!zulSPk_)VIt$Ysu~m4$sJP?)&Lfs4hA_1?)U~@f~4~wGp@6Chwri)G45!G)>=~AJ{)G0Mv2qi4Fdh_wI1~g_8wtCTbe+IVIlHV)jX7^9X z2rs#=%QvY!nCzf)OEu!h%jrX@E(=&?r?}Pybxa{1D+0dPoJe zNoxMW_Yle8YAy;1Pq(0scQJlRfBY~7q!UBkCgdc`?<)0GB&#p^wSkFxI$A}WyO~kT z1W+(cpuT5oMFqji$GMf`iTw$i z1~ilWISD4hjzDHmsWqc70Kb*suAgG!_KF{$m}&5>lY&g~OJ2985B>sSf9Yy+hkYjr ze_ariKcg+7)KmzZt4kzp6=ojoH$b-|bBqb|d{#<)Bmb+uV+5 zKOvq8vd7gPHAKE6;gjJ#ajS^fXvSrl@buMgpLC?kNNG>yp8I1}+!p$@xve|nmUDE%~2*!+^; zkzRgCn;*xi&-~B4y|Y`?wFEG-kzoA9n3KRW>Vk5h#jr<{LeK*?l&f6*nuN$El-!Jj zg#P`oU7mWXrf7I@6H;Vc2QU-AWJY6h#i-Fw(wqqM{POc!JA@ClS(|(WMemtx{#cpD zakjFHII&T=Rbezke`6v8ij(z`dX{D0biGA4;5iA}vNTMFRdj1{HQwdWJCho+V438pSGB^y0|V6t@jd3Y2In}qk$HG zC?b6x%4q;#Vd^@_Wbc}uPYolnMnRxFTYLC0DIg&D%vFe-{?^~-Xd0p<19|=*)ABce zqD+!4IAuvXf1^)eaA1$Dl$pEWjX{*2IhpD03A-gI#zB z9Sn5+Dc7GJuX+pKxGnAtlIT%Bwre0$W|gkScGYDlzrG9MPiM4us$Xpk<{?My-UhE= zKhBjI&1V$ZWV+X=#f6k?0L>?UMT=g*bS*WL$h?a{e`HJp*5Kyf_-`hM8k5VMWM$hx z5{YsLdFbtU=3#&yQP_sHHYS7rJ74S)iEmP_?Gh<%QcDnywqT9KH(!onaY0Ue=An4~ zXmXBU@0j7}2HqEqDE1Wbr>fD0hkVY_W|}DiT(F-sym1lE>}>1nW(UgG*64 ztkMJlwTwsYynUW5vG1T&H-0d)hZ$)Q(`y1)e=6z&Gz|NwcQ1hksSld%&vb){>!5-H z?J^7aa)GLv>kqg_cbtUskyqeT=LAIUFmN&nxV6CwEA%`4{6TVXuX>Ifi>a)+Q?u~a z<+mDC);)Ic=d~%3rrY_z&n2;;gecRe44a|p)}nDp+H~uf{xP%&PtG-m~2Y>X=*0;(MrL#B^q9qFH!uQU-rf2$u^5TqFX{(t@7n7aQ1 zsr&u@hp7868fN_~cyG4xVdFA}M9PZ4((?UJ8T?;D?vIH38$9u^40ii+b{cL981H5n z3;0)c-s#NFd8C{GdN2$J{XO5}rT-Ff|7u+JKh-YN&bd5JjMFpfU&U(O48yHMCWUP( z*@Uw!48xuO4$5xxKLp%A;_Yw$>A$j#tEO{-C};qL6w2=#)RN+RZS= zBYc8ae1d1ZQ9NLbtny`h?=_WA{gC) ze~P{FnqPvbZ!)WW0GVI%8Ep}pUjj0Hf||YY8lMu0uEQ}+A)9@Hn4e-ZO(L^5#<6!H zDX%g8wJWbOt6ed(chW0eF`2%D{NSVNI7?)G%`cGxkaOMwaUhjz1WsTS zj%T9tb|A^}AeChxiDeqVb8e1p432S>OK%d6a~4i`UCwY0D;=myd>B=5Z=ZjZP<oy_F1eE+a3fl<0@UgNphP=r%T89-1-(W1`C^7?*3wSgk=NdoGQ3CF6Xn}Qjj!8JC z5k&UJEVdbZmRSw)reeWWI=*Q_!8J0LQAWml`qWW0V=ScS$YJ%qRnAQa)44;%y#s+6 zc*ZFr0bvy$$79`H6{~9kt}$Y^e^FTFffSKp_`mNs{%0OM9A><^jnNl|+bd|-tSq>1 z-slci`OoL&KgX#zP@^~Af5-ISZDRkwd3)0)b(L;k@VoT8j*5;#rAq7EH+SU#B%{eF zzPX`jC5RR(S_yXacfXNn4gbCO^PJOhB5p-g2;?HkVdWZrYmq=%sCid&e`^_Kk_>ZL zdDXyYcRorDD9rD$Z*(3t zw0h5%>dxqAH^kXO zeT)$Id1mhuly&rzpyU&G5F+9;&bfgwHL%QGBnymz29)Pp#kX0=e=N_O?KUC95K$AO zVorfO7}|qZ=8G`#JVs=SM{g{`Oqg{Z`GT1sH4g-(F_NL3qC?Q<9HiJFZ0zj>aU`g1 zkfgPd$XMAb`oaPhMAh3;jKa?l8kHAmkXlZxJ>6nNCvKRUapVOc7^8@0WG8hN>d#v! zJcB~Y&}?f6@3t^Fe*sPpz$qqzV&D=Dz^Z`N^HWYd>E`PDmO=u%EJmY6C$ZvN19A)X zZ1>=g1eHnR-PqW>%R_Rdhi%ea*WMIe$7s?qQ%9-`?Wm zgdrl6cP5*;wI`N$qm=BDtsT{SD{Q14Ck}+ofPZ+v5X$dGO^^>2`kr`2grp4>BOc30RS5E=~YCY@R&y~E&)pv0j1AN}h zwhQBf$wtYmco=u`B`XFQb-T*~KFAkTCSUUEF;73b%*dE$CVT zTuy`ird~w(7)!bLkmiQ6HBcCy-BNR`E*Zu9(wLKiI7dC92RpU6J|)6HSb9~|wG%4U zw@W1jSsO^^k$<4cJ8T#t_-!2$$Xn z?SGpuyZ14_YW~z5qd#~<&A+lMe%nM}Hpmz6-0~mZP;@tMJeTaDQxfxAH;E#Eujf{( z&O4v7o_+CB|FFN&!%nx5n1>|f5dvzPef>VC?Gab}%{NED$m}f%Wek#H6FiDhgGlwZ z*z8+`BmVlC<`xaL)X}^d!({d$d1J@<(SO;6*zRW*s){NM3zJICB;5)7B}B%q{xIYG ziXkV^(Z<0=3!+^aLYhuB3kaGaTqYBuY-8?W2Xllv2tg(vG$!s6X%#n`y&1M=2MG=* z84^(IzYd{kEfmU?>I+7VK!Qc~0X|tIM*$XVD02d(k|}xQfNswFBa69iIydC4rGNVP zw%C|L*w2LsP&ebGYedw)Q7m%DKrKVUGf7uplw2}23NqBy!S>RZH%DKRV0|qpVx3@_{K2- zn*nw+zl;kHcI-@*EV}EiU;2yx=zpHUAIpDi-7nd~A7wvuO6Glh+2CKcG^>gVi99jX znk&C~^!}{d_gXmEH@^FAi$8cV8D!}%I|yR_b#9`Eth<#n52VPfadTa1o`>t2f+&_5 zyWqL-7zhtztVs_3E8|@GmI$FdBSQ1cFwf1(@j`M*h$t2$6oQt;+2Ab)&VLZdBl8ev zX4!6C+-4vW$BB{vN3$tNFJq}LS(w+6vB8832P0SoHJnf&n?VK8YMH{dmRsFYf`er z11&cywnl=PNOBjIJO`04jDK6_+JdX^fxjckF18fZ!&KURX9Scn1Z_aV%lrHW5s5vN zmi%TReczN6VeP3IcIOeWd47{BLhpm4KJE_evd*rlsPA?z`L<^ta)?`~EPDUued)q) zIfr_t^v~``_vMqhV3T2fyKny4*}rs`A2Ex`U;Ou*FI3&--REcDa(^$s+q7RclPLbs zg^&Nqj|}}~4_DqVTBXD9a?$?bv&A>R3dXFMUJYc-=j!v3k`wPlky*hD&bDm=B9DaU zy8CGYQkcM#6%V~z5ZeZboG3j(Lu%r1Rs=D%=>jYqf$t->vTiklUB}G0qCwg2mM9^J z%L_wn;dF^dA-S1lLw~Ta!_DpDkjg#{Suc)ig>NC6Q@8m0l_~J_e>DXbEFGs|h-wd{^6}ZaNaVpm zd4Q>qreGALw*;9GkV#-#@JhJYZ<8>OZ-#?`j_f;s_!tUgmfDCQ;PHrWXeUt+0!bF_ z)FQbFm2g4U)K1{VuGXcsFMLXlPf<9lDNmHco1_`PEq@4KLRlgfH5u*%0nsp8>Y)|N zJ^`KL+j3|1%{v2bJET=}NkK5n5c(X2%gpSW5|&M1R?W;hP=Px5G=L)_^4Ddpe+*cu zM1{%#S}XZtCa?wU0h}gca=a}yf#Al@5P$i%U%E(Pf;#rTeWU?X8SJFH47%IiM6v+N zBpJr|_J2zb$w7~O>6?cv8R}7Zb@-YeUkC)koz z+J7dmnw0iMLb&&`HNxcC6<6T-OK#@KsI(g;%7z3CX!1Ok(Fj@%&H_)A|8-g0n}`2Z zJ$xYR;p1oze)zUM{(`Fvy62BIJn+$X9SQ66k1yVM;LE>!w&D69JARc(e<&OLw#gU& zD4jI$ugE`GrEHildnvzT+<)MQ#h0yP{eQ*29y6JL>nrb;8a-6bt4-@2@SMY|st82C^Zjr++63 z%?QhU#6=StQiPTP5{vd0pvHFv#{?GyclClmjT|24Ywd^}T*suRpMzb~6$I>flu!iHrJ#AZ69pEM(YTI)dlZG*-WLh7!a6sVZxAtRg2H%bV@FU#r67^-DNGMp zf}3b}n!8l#=K>j`KoG+YRf5e;@qdm)TX{tPw8C14a+4F0Q`{Bn1X?n`_rU-1s>?>2F< zh27vMKB2gn{Kf}E|czhXQ42l!S1@RgN2Xt57iEk#n&}-=YP|}{Praw z=$x1~oF%Ve#}G~-bZg;5a$H#5$aQ%U8nO_1Og~sDSzzQ#yn8bYoNw@`AVv)fe^(q( z*Ji-kiKtA{val_lY|W<8O~J!<?4+c5AP$wbLa1XV4py4YG>y~TnO zC-&?G$)8OWMn(rFbmym;Oo*N6v$FeZGkp!+(W>5MZ_=Z4NOz z``usT4eEEma2|5wffN78q4AfjLx1>dMe>NfP3A(y*t{V|_7@Cc@}R|kvArk1>IvYB z7r$+tBtezWNmXR%))}leEL&Uc*0m>4nIHrWF2KWjSB%WA#wcRreQmE3lsnjI2}Xj< zi556F_Qr`MAnP43wSNL6M~LT)LVh$T8yjUv{FuMkT-&(fjlD#=g`?!<80!=`{h+D% zH0c|0kbanlGuPN@8M?8OhQ-mSW+8|di;axjq3LUKYYHrwL3ltx%%9G^;d#}JIPtZM zjgd{I<{o%sfwuPz8djVAOYX|Xn4{*P^e2cMqnO6?val2FNPpvT3Iw$sH5N~^t{_l# ztMs}|5ogHaBhxGQ+qf5n)iVpqnL|olqa965IYf^Kzv{}}1sFA;vv(t$D*2Gy<-^bX zt9dsdPm%nxAs_QnvAb;=57?pR|CH_iA`AXm2TB%+8M5W7UU~#P6C_hM z3OB<|oV~nUuz&C{6O7_W$%@t`_Uu-gvy~w(JA-=$!P>)LmK?>+$$+DsReK*I&43a( z5^V>976P?LOXwD!mzS{e3=k@&)KHL|5d`}C+jL>5*r~|FXhauwEjHOspVKSM8l2d3 zUVEfurQ79|DT{?wN=*0KdCkoWNM<5rgack{lIJJz_J0bmwItG%z2HVPfxEr%%cfLu z-*3EDt&PKPAJn*g`+th|@A1F^e;x3UPJm;Gls?ZbBYsQP*b|t~u5;cHgz}S${m5Ql+mL&9lBbC0 z!q+m-GnxRnAH@i)mGyK@dvuDC=MiEbw=eq4y%hxaa84(sXYv{Yrw$cDi9DC^+`%9W zkfH;5@%&_YjZuO?=q89}yBv+CQCQeewI5ij`G0SfUKsqi?DKhzpuji4KG==It>WGI zXe&Ps6z(W<6>AGnc*g<$7CZTSTuuFct&jBEH~5RqHTVrmXMXF{hrRZNnGW>c7k=<( z{CL1a)pK+8+y@?;fBTbuKdk44_k}5d^GZ3xsPiI)5h(uvOKEI(TsLGp*^kQQnu@g} z3x9)^x=V19gMH9AoWcJfsUJtYeT&v*QzwNO7T+un=%7?78~{9?mm?@a___utu<+ z5mPc^NM<7_3=BNL@>B)4HpaJN?;74VDt~1}P_qG1Y*}1dLC6j1KG@72EYolz5psoYlv4rj-$+sXFbxDUJ{6a9W(BGjb-{}L6kf3C4gbhZaw>Ik|@hRj+ z*8~)Gu;E)$bBf|v)9g+tJZt>?G$WhA-_##*+w?QR$zSlSL8gAm-#@VTUpCm}FMqgz zMFi`O@H;l6Y&nG^C4b1}Kk@jx9O{aHiuYPb3^BtmO#cb)?Nafc10+Y5X|%zT2MRY< zd18d?9>&|$?MIQx>omyAFySJM#v&!W-D<2c5a-CFjZdo0+=3zm;dv;UWg*d0Dn@n| zGL6F5_fgIbl8jI{>Y|^7>gQ#XcCYN1AoNN&!5kq zFew!7oq;3ZD%9TJBf#f=+PZ}Q|@Uw+~jUp{zJP|fa(hi)tSFFVi| z-sIaixXZeUr`j!wi6@E*>3`6eN(TT#LDa0-2PR0}P{n~M)@p6r*i#V8zwLc1W5U?Mffgy*s-HF3vN5S|4gFc0Sz z6~X|n#YUAVOa%K0EL7eFl)@u&roWGpql;!SF`%Ml;+dF+hIDQeJbxb0R+7?VRC);S zJ&h%rPeV!&uQzGLBCN2Nt_%cl6{o}7GFho#jPe!5+x=zCUVW}n92N^V0}+RsNn#OD zqWMnLG*l>EHVah{Ag|hxiw3z-n_$C^(jDw=UaToJ2=SWXC}|BLFHSG_>Ks857-6%e zluvM}=R^t>3*S=E=6@&|t!=0+;FOxiD{;EqMLmm*l3xfCDXiL^@?E@r=Np0&D7(OW ze|e*vnYiB=WXRd-{9LfFycA_us=Pc3h6ZaT-?F`kZaE%u@&2@3CO-BKzw+|bwcA6- zS*&6YtYYBx!EgMhd;_9vuHUxjcYHa&%f3NoGUVgDx?^|B-+z7R;o6%zFw0km*`DDd zMe^+>B)J2TciD`N5tRu-GN&pp4K$40n9mV~rxnPh)o05sm!>0gmq%r>5_(8?Vu`|; z+}R$pQf-C*#6%3xHOqim>XbaSZz2Hxa^+!u4m$ac(582=HZm19S7|$kC%%jGo89RI z@xoO;pB=WP%YR$X?Ljasv=L(1?dZZywJNF-YLrWt$>iWzkU%u!2G_zboEvtngCQ|p z%=TejCuoO4bHs*E8Z1;??up}xL^{Cg=7$_9edLpG?DIahf6e*1`}4nI$@z!f70Ivp z_zO<`FXC}Oc}Wl6NbY>`uksG=dg=gGTY%Ie6!R)MgnugtcsnFQ% zvi8!=lz)KtZYn#OfNvt@Q{)(lf>KfM2o5Ya8||D}@3CYAB%NC-o-1Ai$1F0rG*M`n zZdIt5pYrP_%D#}wzOZJ1&VK8`;MZw??pFgTTWUChj^*W0fHmuCyrToN5jVaxIEL6Vf%m{W`L_}_o zj#3P>k65b>4?NeDZ>C2*0b@V%5POFM)HYC7q~4xE!HG~0}%Pl;jB2GQNlR2hL~=3GmiUY?SqCek=y`*5zieX zV$XyE$B5g`Naf9CXq9-oxq8Ey?4GC6j}#8Q0)^Y~M&ULP^T9tSf>%l(|H=pIzp&$9 zdB=aldXaqiExSMR$9~xdzkGj{5B**L;D76=wLjRUz&&YI^$rw{COrc|5hHXIj;NC) z~Cz?CRcExd%L_nCMfdPClK!*+&`O5>dMh za+P126EVXe*r$CfRs>i>_$+m$ir0Av12^oN+fYevgqn{yrI@!XB-+awX%tD%;eUZG zSl{d^G+szA@q65KjOPh~+(0-4cbuAjRPXt|P(cX~2}a57ur8?AA}&lzcqgNi!GNdX z>GM=_tmdWSV76Lgt9hZFveRaGu*a3W{LXdxo{QgW>rwVs{Oy5x{prhp%zP644H%rt@Z|^Dk^!nINnyHH^^&g41cjM6gtIt z6NU?EtK69=>hCxbfjy9gx(@&>**`zx#O=E z9HlBLB7A=n9&pd$+QKYZ_$wZqQNcDw*KCO52lM@TD#NqlhgR{!hz3jzhg=A7td6GvDF{Bp?3GT z+^sub3_9EU!kUym{-<0}&EF+oHrKap2I=hJa6MmY^v%toMCuhYEvS4UmPRLX56RFF z+%Q6Y<7uP0gA>aDZw?{FP{|gHj-b6rh?a89xv6|dD7j%*GK->_L4Qg9h9y(Ex%2qe zTv1uttb{G?cxDS0y1Zey6FLoTnqoOI)t1mDB~Y;nq1+GRLVDx+=m;-GwvL_-b4Wt1f&;M9XIQ8C9j z*J>vbiDhLo_5Os5D}Viy?j!^5&HP@fcmxAY|76f2R?^(uQIFunK^O>znQKC^S&}ed zvQ`)e!kA@CGP`<2AM+Rtf_03#TEv=)lPOG1#nET;@G$dX&=()iQyDx%E1{BLs(ly- zx%3-n+7)+uZjdoQvi^6j)t~u(`JXcA3%4S_-gy}K%=_iX7Jn+Q>bG6-#Z%uH<=-$e zWjp+Vaj0jm)^40&I$_T{qR*GO4v7#BmgT3)D}e>jj;5wn`CW{lNIQ6S z{p7^eE{@ri?|G^6?LZVYmBIpP*e;jG;-d&aa!f?&7~uJcEDc<~6cnMbA<5aUXk><3 z=Lw02SROEgsDIoD-o6;&TL7WBIGx89Su*0XIMQ%d7?B#6>lTTbWubh7q-Qfe(Tr|( zv~V3D&JB>>+9fA%b4%TK)P(j3N|i^41@{f`EVC4dFg+Yn9zZTlUivxmZj4AwvTn|C zy|PM3!=!jaU6VrzD+*0UL`tHtU2*l^i!pzm0cUr)M1L^&9^mu4)43-tURA z*8f-BP~p#uKXa~rVb|g(MqtF=7QXx~m3Jiuyg}tiso3|;zsG}q=T&{!@(;W7>pd-% zpSM$Zn2I9>l6~VLf74}u<=Gpb+k)F_h#4F1egKBqX;#E zRBcXTZRsGkVV#yQG+j87qd;o5fwat#9RELzGlzsD-$r0pb^jMKcd72q^Mm3+J)I z+94`*3p@&vA_SCxNDPn?K|U(5NMaXBtWv@TTdIFC2lYMT!m_5QmlT!F`<#FeoJK?n<@3E0l%$j-fx?DN;cZ!` zU4R!hDU$U}Vu)SbQv$x{tV%fMmDSxLVEPPE)&qSZ`pd*szbrg3#HbA6ane^YE z76kJC6p`gZ&Sq~M=I|u`ar2_*=jl@?;w4;Wk8PINciGe9eM$hsf1CsK9xxerfM)n0 zUu+y%!_pEk2VgM63=n$y*7uHD&=mXju0`85#@E%=K{dM1;+Z-~%b=9AnjF*pb z`0L+003!xBIe>cW)N$ZEe7@0xroo@XE93y4T5Es#Q;(W<>Sa^y=c0iQVa63?CBOl~ z<})3P22Uh?Rin5Y>5r*)?Z@DvpMQ@}s_?mLgm>TM3Jv@sA3I2W&4U1=foA^ve7_$d zaLDuX^Yc#aa`Y~KSPTG5z*4k;(u}4{hLL*(2$JL~(cWKWE@n7b2Q83L`^gq#N$_w?@+^|bKzb_}hT0eW4COMEWeYapQx+K9z!t_5 zYH!ESEQZimZP>MdcxI-{w#?CRUp1Bp_Y(T6G!j2&J>9W2WL)#UY0Vzh%q5VxK<)jh zcYyj_OLyTK%rF&Y3*J6U?SFNK>5he0C&O4K2FlqQK^C^6B_+?WDFb7_WG+P{@r_(d z%cToVVu-TkkNP64Jk*@6K@RtMh-X-h^U290Eb$)YIci0#BGcHE_yB9>!g#2IEQL8n z%Pg(eEwFtH9m%Hv$-a_6ufx4;4Ib|py?UJ*b(1&@yd9e;6DW$C`o(}RTQ zvdp4Df`Rg7x?eIgl7rKgkO-%O(ad3EDwbGf4G(h$=6@8V8efL4k}Dok^J|)JEU8*Q83^XWoNK3nXVfv%>}87(iOz}-g=i7n`3KRKxxn+oN&~01Sh7}L`HwkL&d*{N|vn@_)7KQsZ7O+m`1;xfS&t>W1>I>r!?vpS3NohjOQvyPx?FBsw5BHN=kLR|%=M zW|5)RZR=uBvUcuD1Ko*Tw5@Dv!`Vi zjU~epT9}<%4meE1T)j=tD`d2wtMTxe;t$G1u7B3RI>}9-K$Sjfj-m}YbEepJy0#kX ziuw*PsQy*1OA*8ErNv&`awb&&Y}|Ly59NE;rSx8|#y7c__kD+|p}cWjYTe7#_==(2 zsrn8_L;2OkFjMpCuHn3VO;&hV%PmDB%hX)?f{m$e_QU-2zj&}CVreM8GS1LBXKFy0 z8W}-Lv$qxP%>^t;fBmo0Yc7V-qu(R-oGx2p4j zrcOmKEy-I(qzLpD2QnYSa%zxZ9=xUDCIR9Hc;R5inDIxK90Upah@sNPb zj^N7ZR>GhU**?loPT2dFlGmBZ)`K36eBAB?f-p(cyarV-0j;Dl=v%II;{JY**%3gv zg$r@Und4TTV5E13=kNi&c&e9 z)`0(E>`T_Gdia59%Q8Uiu7x8B&w%YUIQ-F$9Ak;<;2-5}uH=bo#}rH@+abD26s2W5 z*cJ9a@eH*O^ls;ve5dqeZiYO=bbrlyWBEsWjQY|N*|q>#i;5ku27PGQ6STN0z&}T}o+~;ZykQ(C3h*Y+wgz8tB8rvvS zI_rzpwAWzR$zjk-S1#0x1G~KU9=x^x*Xz93cMQX<+KJsDXUXi(cGsS8>wm}GE3er^ zhkqQy{)Y!SmOF-DOvUHn85Vq0a&u%aGYqpVdhI-*iIRUj`Wszjj?mxfs()9XYTrur z+icN>WCmL&#y)4HTe@c|A>?Owjfm^QtJD9L7S@Ap`6n%PU6?w0qxv(fmtk!Fv;HVv z>tCg(WIRpoV|ZVGhp&0h*MHzKjXn6plvwl5tcMxH`Yv$4pKrP@b(B5wtB(KP8m8NS zvsTplXhqc=l^ss`7}abF1|J)P4T-22y+p{m+pWsZ zrm2Bcd46)&$oWsoUG;1TdEAmhoqMheFG|+Nk&>HBL)jCIu9O|E|FlnUTWEItjC{q9 zao_g<$W+G(R>#KuIO==gkL#5>eq6uPTk1Hy)8CKp^!MXC{r$M_Z^OPVoD9dM>oWAXUJb|h>$^L>P{;M1emLIW>4)RPoqjm}7}^1ds&=ff>KBDjjj36y zb}0R<=uShw_=E1=e{`pl_x>jX-R0hYW1w5#`~RR*b|=i7{(nbq6v{p$^4!vacRDrq zb9|Lt*{K%0uTgc+6ybqh*~9TSy{2rwANt3d=JcC>Q>ps3^Do&k8J-bcC0A{-2EKlC zrU)teZFHw^DO0qsL;c^hZQFACP5Z9e9)Hum4fXzBGnTIEesZP=271+YqMutz&+Zz- zo&G9$)m~agRe#;zv_iEz{-z~EJHBZLf9m=7IF>`ZXOD5g=1_P47#CLD=^tZK4ekD> zwTHUDX&cp!AKJd}vAp}8E#&J~#qPCKVKYi+EqQg7*vusKA>X<`wxi1xRz+B{uR7pn zkgWlI>Ab?FfHY^oHJ$Ttd?SJ*T%9_A4Q@M*fj6g?1ApV^hR6Y9Yt^~U&&{yGojSjA zP~lYCMjTa2u2Rf0w^r|N)}c!q$jdNu1p`**U$j|x?QChXB&}Ytg5!7ymFXw<`v5{? zzs%D8vh9EZ*H2flp361R-I`*c(G6wX1RDM$5cvb!>EH^O0&2hpsNu4Ho(=og0UoJ* z&oX%s)_+h4)h?BPprFeEAN)E;3SVx1$}xZr*PnBuK<563o&pw#{+z4OJPLl!&A*iU za1dzwQ(pjt6I~zz<_rozFJLiParB|yPu?ip5(~&B992s^0cz(V2sm7TFok$_>YM?h z>V4Tlq9d3EtcAimJ+&{rv3kTE(ITcKUb*dx{5yM=&I;A zSI?np|Gzz$8f>{Lr;w_1L%>3!7)%cefsSASY(Tw-oxoC}5tvfd(*w<6EzuP$4xvDw zs$ENo_K$X4@BM{WbskAng27?QQ4Yoo5{Y(?en@q{%m1nVR{bXGdIsqIF-|?0wHgNv zuzv=LQ0*^Z!%?f+UkH>9<15fj(GBfW?NMI>AXIJfDAe;dfDVd&!;z-Obp>kt_3!cA z2`9NJ;L9_OyO*FOg|0jq$GgsYmb zd}z0Tl|Us}0^INMhbO@G{{epar*^e!9DhqSj``o|uS0tT`T(M$x zquL*if#R!L@!ekas~CQV`$p<~=%2;Z`7j?#eqYZKN1ke5ERnpg>%TqM`&+$Os(4M?N-r+KUssm@)s zg^2Z+^=B#me6$mO%`cv*ew#q0YNw{^DF!((16L~gKjg|yt+Ts4l)w4-6X;CI74IiL zN1lcJiqHM?->~-#1ApK`F~JdVqqah6mE3Rze5!Tnap=|h_SH)TBnMxD z4y0DQTTX#Un5*~hC+T$+gXHnQ+Tr$czHTr5ar=M$-~ZqLRJ+^$Kkutz`~N_;P)Ro00_Yu5r={x%JAuhHa8FXg4LkYCp>2AO>v{* zV2Kai6QNw=s@~D{id>j&CHynC%Xl{8#ym{dPXyJGemb6y=22(!uADp-I@vA#+xqim z)XgWXkCxB5IeywcZ!EsG3V#;igcmtx6}**wl-8q z+HZ1m)fz6A*Qc^Bm#h8m`Dwb?PRaOlAva6A(tFCM%j@RyxxBFaReWe4BQl9`Gy0ge z(-EVF-E1QVc)iybtAG7!m#^PzcAX}t%Vv2g4fD)j*W~)qT#qGf#?P-$Sw34`wO50S zBSMX%$=PY~>T9vUDA2`JK!|o7)nM$}&)!65FAV@&6nhD8(bGJiKGBceIMl!#zc}^V zt=`bJAJ{D!lh-veEow$@hLJhY8(Q*gmc})xKX=~Tt`9+GFMsnF9(VR9eTqH|XOv9S z^;>>E`RmmCSdr}H&(rWT-5si(-@okNU%A*ESKbF~QS-8_(9EA9oKB+f_3bIc^XBc8 z1n0}k{QYXbt*3Q=U5xtiIF_IK`PrR6+4JY!$J^<=cE+>m`gXa_#&7=Qdd{ZP&C~Uo zz3kt^r>D2iv48)Ze!gC&9*DRM_WmXhu^7E?Ngp(6%Qoq&dwKsjOJjU2^!;f)G7C4l zM8KZt=5^^vBM|uGZGVK@RXEf_FAIv`ylF7qJMVStuj%WH>*Lhi>-%!_w9rmvfVce? zN7%~ac#*s%dpCvhW8+i-d6oTm?d+nWAggGRTsE`|&VTF)h3B^-tI~Rbyp-9RG3UFb zwqI(bTe0av&PbX(UD8wYwp&`yS^4(%g0su+WxBpb$3wj^PtWgb|MQUa;nA@gyWSs? z)j8U;Aj>^cA7Ikx_Q5}Pd&e!UT(e+WVVqS0PS~XG+^@i+$p%`vIbF^1%Q8Q*Xtgbl z(dB4@MSq;pRK8^P2%pf7h17ZJ=zf$Z*gEmg#9p36F}sk_Yy%$)b1cXKcIVHz?Jkz@ zQ&cTitIJ_~Xx?)yU7ybA>*e)H9Lam}es~Yt(`iGFnf89sZY!L=5|X=@Tk{k&tAcAy z?mRJ69%WWdFxTyRwZSLU;VqNs{EW!_NfXSVpMRn2YGIPTGdt;yE3)2MW8>Jy%^@-M zpr4MWE93;HjBGPoGtYd)UrX0_&2S&ow{tVE^7L5lFQOkwSS9A?%hUO(3PzsYYyQ>K z(l$F*ZR&SqR*hD(&+G)_&vj1eVO8n4h;~pNvOS3CycfOMn6Ei*j)%(h@qvr$wri8s zYk#AgGYy4@osVA7=4fA&e45UePsfkZi(Y+JjV+gk`*s_jrk@KzwB6z}Yf{^9}1_ z^m)vx$?+v#-#APzP(-bp=d<@!;lwzk+kf_LH|jTUrj@dE4SFALyIT9;@v_Tj>?M@3 zaYl6;tXBKw#Q&H@QF1_RX`pePF`C%2a*UquF>4}}KShX6Y*EjSyv9dyJbadK%kpD` zUN*(kc^?ofEatZfAFbTwqTkF&yDvZbX+PO{)N-_u#`d57xyxQddmoF2EdeyTLVrQc zmlSiH(@a#7ZEWn&l#SeLQnQJ%yk3su>ub7yBi49*NoetTd(xINJ7C)Hom1u)lOwU7 zry|!&5#3%+6Z>F3O@pj^K4`Pvtlhljy2w zZ#a`G=C4iXh{IM}n%d;~7)4p}0*mF*$L3UwM0?y7xzwmxOpl9?a~N2Q&wuH16=_NS zI+2H<88t`Y6;CcXFVC56FOu}g0`1s^CF)>I<{#78+?`Rkzle2PAv%kmkJ%-;a3?HF zUmOgvXl@_+1@oxhUykCo&1)lTM=x2eUsw|^VPpkqoPA{2e2KP+y?hPcjs2T*+^q7E zZ0VxjpBgsV=Fjygc3<<$+keNXTs1G_&*Q|^FAZ)#$Jdfxcdy0MX%mk8QRNy zoTCZJ*#W=vk8t+B@EdHe%T3t)vyv09D9H*tuz~k2 zetl`r+?S_9?ticK&DN(>;+w2K>y=aGeS%Lbe8`S;AG@AYCa;T+y%`a8e>fpqK5zG`V70(Y8G_ygeQ8619(Ou`Y7|Fs_fN{WDiqjta@Wu zRLn;9s?kovQltar(oP~xGt`5#G`X}cbT@kn)_<9T>IL|f4_uhYon5POP-#vB^&okUdTZV}_?;>!^_9HuNKD9Mboz(MM6Dp%l0&w|>sYS!(i*Nn2 z7i^srkY9#_UerxcdERRolE_5i0v)Fbet#mNwrvLam^bh_yO5Gm8810XCbVg<-iOi7 zPOhvtBBDKPIs4}u*^fsK#qH|k@F!2#;yG0-lVFtzXZR3La5OfR{whWl7Miy89M~lE zxh|DrI>po-l0x!WAHy~)T=UWha90FmOV`zzcA;~1y%c)|%_(>k&QBEQ@FTz4@_+Ri zV3A%cCHu+?QxUcWdAZXIS%ZW(`^vxECc)9lx5~zN$e1?gYV{)CFhQp~8?E?jYA`NE zO&b>Z%V()?KjB6^q}1f*?co(7R;780s6s=~mv&;`PGU*9reg~J1i^p=EwB2i7GjiC z>dIICUMb`km$joQax9!&Czng0Hh)`gT2a{VLl92=nNRBrTak)vY(3YFk3`_L__8{8 zMCU90+PpC=)5&#$MKNS?3GbDN-a0LCm6!*Sz8YG#Wl1u*Dfcn|%wBlH)>23N%*Y zs8WPFMHzw5%9CtlBu}zP@Sgoa` zA2f^Fa;7WjYu>(eQeLD{U+akj|BJPJMPP&w0J6Wbwh1zkTU zB~8|p93yul)FFLd=WP4@yJnMQfmzb+&h8X;_qy}!B2Nd^2gSxGx*0 zr5|!J#PaslO<}S?NPpS(p^7Kp!yk490K_m(O>vXVYIp^ys#D~Ke~B>L#I>~ zcphZc3k&cX$Vg-z^v!>xwUoaH92aMYt}hSWZ00~0{IR)W`F~g;4QgET!4xvnz4v&* ziq{8+X==wWZRa4aoWv(>KB33*UeOru7=!x9!Nb>{T7<(o_- zMA!R|E{C56Q^$;S6dC@sRyD)6PPsOw#o-#6;E*l0OrPzi%eaSHQ?_Zqbb-BMQk-2q zzSM92)*llF6o2h{w^O~&tzEt>-5Lq_Yhx5`sWAyj+%&%IY~#u&mI&$YAKM0Ra7d4A z^|9af_S`JGWy(`5$(vZ0#z*|Td~Yk=q4Zb+ezO!!nAHQP*ar+<&@h)mI*#80 zxyY`5n(A9&9zyp#AE88#Zx*Z1IxHG2)uj=Ks#jQu?*=9(Wgn8kR_sc-=;9-fJq_V7 zOYT^8yre_;Y)!&^8jD<>27EMYbym5eRjpheEq}>mU5sWsx!a7Nv@&$;R3teYGZlb!^`b;$FdU%VJ5-%vI zPk($-PHiA9u9RcfBi=>WN1rZArHEO-6OJ7tA+3phK^$@_%O{xD5B${L%osD@T^DnR z*dI&N8pfHH2ra!!cEaU`(#TT5wKN{yo{=9fs+>JBEYR7J%S`pxU}9{s-)T509UUEd zB$THnHqYS`@l*L!+>Xe^D()}F!-~(&2!D1?f4?3@nFHq={4~5j?+@~@%h!^P(B>w1 z^Zno-xt$G2^p<_yr~Qe=`u8GFPfoora&F>-L|E&TlT+`b$4nb&F>^7tP!|X7rLQAl z`E0ALWvw_1qG6_4(cruzz~M z!AaEv+F0*fJ#?ZzM-}rbt8HzDW9eC$)pWzJ*#iWsn6GTXmA-u z!6JV!Oy#AuprB>e+xy0>5{Wbxgnw$0nOiQUC2{bKmxI`6QdIwba2^za+GLXJ=fkwx z&l0b&p`A9hZ!?}~0>{>O=%bM*^Ia}gi(t<4``3OSusvm&c~nOX+i(nNB2r-YaRVpW zL$2hG6w&&Ujzutja_$|FaGmHGfuf9D3Ky-gTc!+8fo%#_D_z$Qw8GFRNq^C#Mw8CK z`Eo8_Z?OHbyqBN?l7BxGNaRhN1!L9u{n&mf0iS^N9MVO7kc$UBG_!4r_t)9la{yC7 ztiPnS6Mt20O?N`Pd(*z=qt%Y%%lhO#r_MD0B~LnmX0K)=c2*-+U^OS{UF#KvE~|xp z;Hb&UKQ-suzsJMvSxp)F<77#{UAlj9QcJgi^nD?be5+AyvnLg-^ocmfBA+LsU4}M< z$?n%wKB^S za$H*)o2A@OMu{E8m$ouHZ9Go1FDPP@S_}5--l9l%u9~LywZaHWc}6|XU_*aH+2`*- zdx_HxEIXTnZz~m89+nbh#7woYzAFo%QIWKeZf0W8!MaK7zT0$sGwmykUbw&GA|cu( zUpy3oZIIe~5UnX2;5i;HJF_wf{W1?|=v#(Iq;FZ`M^Ft}2?w&kACkC@1J&S_u|trv z;Dry%va3>y$NN3L+A#X;7{!0vDOHNSo+=5m2q7O?LJ6-`k)Ki{q6}Fns=Sut_^ht> zh50!vM$W5#>t&tyni;WM_x&7K;|xad@c4AO7`etZ^z%lzMn8Qy;$7p7?9B4yMWq4P zG#OWPmbJp+gp2fjpp?km$iP>3P6>CxAX`!S)|@iAuJh7@Bt1JLNkV@Oc*!ML#4WLK z32J`{VgL`k9U?=|Use^RN@(m_!EB0(E^PAC^Go2OH9qC_=ptK=p?Rf=eTA0Z z!`(Pm3o~rZ6^$PrMwZ{lii)_0Kgka=W0YHL%X^q7WL(e{_mF2gP~v0K7fWBCA5%4< zIkF>0W<&nsdm3K|y32ppRUynxoKRS*OFCg0?x>S!+iDt&UB{b!4N%0$^5K{|rpA_e z{wTV8J&qVyb+jgsN~k0J)X`e?jPMPGGxE~;p@>+Nf%INs{HQ2Y&4vZe)SCzZ@NZa8 z?7wk6@BjVRb4vH`bIMo!_cX#!Aai-z1HXFJePm?xlQU|lCMU;AW#4v zKerNp5(XXTEd+g-;3;w+6^rZ7L$seGrp15$W4Fm1V5Bqcq>B6G}o7!oD)D_CIqNUXEdx=y^+aer`c=z1Ya@8nRI%uFndUNEGZd>mIWNsk(M~e z3*HPo-)VSOE3MzsXk}k(nazWic}{gPaz=#m9E_Oa8ck+qlinL=djhu--frwPcz`86 zuduLs&S(c;!((*UN%6}r?(!#Y>hc^cM0EM#j4Xe&4LxwYRSe46G#efY^&Mw=?)Hz9 z+Hp~LLuV?w2x=a@mbkt7-0g9i`w^BmB3oidfZcUmKN-=LF5A*{+dWEj;p=O4;Rk_k zw%|$U15QINvB@r22|uN~<(cf%raQG12Vb1kk)Sz(jKPwr$CB^1gcBNNcvx8?u6E`@ zoce#`-S9E(qeo5C$9`OeNwNXp+MdL<$)ARmTyswZT##BXO}e;&R~JJHhqqU-=Mjfg z@vh2O&wJ>Ij6_Ud-v|!)n#5lo8PfMf$@zo$pEBFiwyY}8{qmNZ7OWvbYbRAEd13x5 z)}?&j9xh%V4|21OOKYu1X(!(@rz13O%#(kDh<(fz#O#FSfYjEvsXWgrbFsfgZNvNu zcdNoxkH+g;x9igtN_*FJmwYrbh^-tWWoP#}yp5!m{P**$P}{M%mu=KqXE~>r*PC|L ztp&thosm`w{N&PQ&qb_#)CA}(pkYGU8R#M^VRB3OTI zB`~^WPgy|_?Sm;FjufQ|Is1^M**B5VbziWb5|8%?D5ZA+EqK?44KEV5r=kAb@B@L~ zODnLeo3P-!hdgB1rO(l~f-KQ_&-D3bTMvaDw8DSL!mjO}5v@_}=`l%31NHJG#t&iMKpFS464|SW z!)*<52h2wVBpNPE0JxtkYv0_xX@E?sgoqy*n1|D0pMsWYN-#R%hLarP-;p^PR;pZnYA7D+)Yqk%q< zil~&?ILGLHaI=1h!id}NVoXWUJj;;OUOp1MB+qCgW^BoPbO=|uDkPRq_@(Z|`d#$? z{M24GNc5(~J8GkZHw?U3AvAxl5wX-ueI0~exn*)VbGWKJGp-p92UDRosB{}8Vp;Em zpi9)Tq4rlo_+2!T6gpE3NxWs``+6g>UegIofUxjPl~o95yD@@xF^hi>naUrniZc6U zOvso@5TQJ;q|DxmSW&`?Z*Jj_@>&pArb}Ev`VdniPuB-;5ePJtQ*laCZ7Xe+V<*d0 z2gsR+P>pRbD`i)9l&T{p*(VED=lMW;3s!e|@s?sRg;4L>DTIumk*Yj_nsw2+YR6%- zbf{@diu`2AhqGQv0+)Za$C3p*LaM9l4Fnf8#xUyn{h(g=Ru7};Hcn0)x3r?t&KO86 z`Hg6o2MLdfFEKdMDU#4Wc+O2%FtHd+kwIV&RZ_5t+PE+@j$gv854{MNtsQCS{m@f- zoG((D{9O)&#p=2J)Zed1yFK@Q<4VL)5?$XF#dsQv@Fu^|>#ct~!s8TpR6u(0qGQTnn5`AOBXXxbP;0i}sYKKh8F|jU!Z)z^z6Z=kf-8!g3R$ML7 z9t*mzriuz*%@G{zQ~)G^bMi9I8x{(Co+lM1FHfuA6#^6vI|z657-lQ$1tx1WWws6N zFs#Ih{bGc{9Uy-hqPrTaQ|CpYb^>dDcX8%O`|s8%bu1^3a(4hljdC*YZ}z!J1&P#w zrn)Z^!q(3FW?o87@^gAjm&Fa{6-8~*YyPXNT1rW$PjjLkp}Y zxGbAuQ3ig3tS=PD6A2Qi=jz&qq(Bok&oxD(6{<{=>WU1 z<{Z8}I&X)u-mQd7Z&5%?dRAdxuLwBX50b#^Za)}PH|AmUpqlbO^7DET&dC$c{E-!! zNv!A*(~y6=e@Imr>tv>n=#>&{uy8GyX8r?6F%m0?XkSfNzVu}vI*#tlS8BZpMFKA< zS6;C5sb8%!htXNc8uH2yoO2bOrY4d`^x(Ct9;Z#%vqv7=Neb_Hto==*oCo8e%TZaA z-&}DjUWH@$Rg5xEdB~9Bf+C0-agGtC5`8jZ6Zd~Jg1*yG1#h}yJiR|I%1F`6X2uwA zi~^j|x#3QbTyvN$SXC>>j1%oc_mi~ZbJ*;^@H)GVdy1BlG1ktE*fuf#k4gD}~EJc!qESNEVL`(4~-H!65u0Qaohn@diZACRv#_gw$K?`Gc5)(fCw97VG zu=IZiIu~6l_Hg%z{WRQQ%AAE{aYN;zWhjPiAj#TWY927kxRrVl)kK7g?AasKbqpBy z24(6cYWp%1Fr0d8qoW-`h{{5T_a6ZYiZXYn6Pcb3A~MH|^lCd;qldVXz7rLv6ri1f zt6#rZ26D+RdWKOCb9Kc`EwN0i2f<3x%uIiHUXG)?@g}T6+ql)xv&x6F#6Mp>mbp^M z2}>@^nCsQgTu=w{eZ*&#MtDT-AKI0;QjkQ<%4JH;x!Ni=dttSz9KNYB9DTY~yT-2r zzQCKtB26T(vT(v*YRFdkyDvp& z!ZS&qZ;LCk9J0xb`W*FU&#_FjwvJJ%f54y>)(+V#9YO-qdQUZfL9eghJv8CDRJf@_ znTKtqH-sqrn#S)GGmZpqouckN(+pZaE$g z?3+A0%St|sA$;lQCr&=~EcuzD@apQPW3ja)Z7dpO#d~q7a&ufrLHCVo_|q_?Bx`T3 zDUM+T4eBTl&mt?I*^08${zi|&ZIj{D#uGaWowsy&N9DPyp%0F$=Rm14%u9dABFdF6 zsu2F9Qp6VM$HTWQwlQB<)UgP-{yh7Vr92%!L`dv*@px9W5|tbzbfi?$6Lrn;CQpdKJcudwaDWPFP|?++ zs%mO|VUM&bNlDD8z*2P-#16Nj0#Y+s`;KW~Q9bh|8YZK95W>gK`tJ2K>{JZV{oG1dpmER3MZ&8iQ}0}*|Z2k$Ml zZ1`9qRbHT8BK4U1P8i$c^()|Y-9k;}9mmjm zu-3u{qzU_~B?wdmr`GBlyhm;X`VF1o{oPUl?Fe%1`m7=dXdRGjHOdmGA`T>q2U?Fa zdxZiW&N+!HI(>i31*2N*@0NQB8UdD!BgQ{MUq6ZXz?-LB7HQkI1HkY0_#Z<_Hm<{y zB1*vY{=|3w7P>0UPk6S1viBfpV0qiZB}>s^k6-$JO`Z5OU$ZH_w6cm>Gt&*r|H%!br;NcyCpS8J8gnTGIVsm5nw-F+D{CPC9uJ) zQ;DtlZNghl(mo};Q5Ez0vMLZlujY5IEI_*asoyr5Yobo1uuh~;i}g0xO`a#*p)%O| zG&-RMP9}e`UCCV>T{>IGQXcu~0AX;=IQzmE)}M7NDONHbej@Q>hgnjFia)9?ROMKA zh^#a}-7Rkk26a%_gzd+p9>%x% z`nZ3y$qS!9nQBwMne!s?2d>R9sN9!B#nmGNtJA+XazKN-g-BAU~Rv*f6qL>4RDxIi*wtrHgV0X+#SY>?MJwL4??G z*aZys6Bu&4Ph;IHjM5)WId8JPzS<4(ywKmkgtdBXZsWcTB(O8eb;ybuvsm zj#lfMrfJVlY>4Y7AbL{epSSC;yuN>f5ukX=%%8X5QFOqIzxLha3BJz>$& zu9m%8)=jB%=J=%hNbL$?FFaJCwQ=$F>=ZR4W;KgHUs_3+^<_xp0RGq>1&RfdHaOQf`Cbm0a9$ZK z5(Zr-#`*5flM!~Ms*@@HQq}hwE-%+jhIahS-?Qr*U0=`dC&6E~S|NY)gIfApiBOCkpwThaBp{)kp7Ia$)ENXi! zt#fgcz=K2U(kxt56cC}I-69#bgX8^yK4(uHjuYF$zLc}xwcZjZb8Mi zvBx$-PnE{VC|x|>u3-&P`-oa*jQ5z%HC$QCC=H}?)`{B6UW{iu{qy3#WYD>b&d=nN zBqk~U$PZf&71a7VHJ4~-UcEwh$J5Z12$ptatWlQBd`o7a8To%%Puxj65hYq*)L$?+ zS^2hq6c(X4Qj~O`i_V?g)b(rT{O7xS)~5jlON7J4E@_EOtUeoVEJb{QQ=kX0nY}tU zugy=XW8{$3X2SD3&K!13nt=_@Oc_J}q(AnW3wvMZ=bPkmG!iw*FH}{T5pVB9Rh3FN z1ur%E3MEpOvp|31iu?4)mOq#$3H8UL=UDPd#en^^sQJ`a$3t?zFb;V@b>cISXRtmx zZ>GZ9m{Rv)_hzJOk(W+oUlUALM-laPAJ0m|Jth}gDr2w{SCt1tjg9`y&`Pm!-f~t7 zEd^A~cupVihKJB?@K>G>7FJ0|Ona0(rIo9-#<51dh@^i+BO&}Ybxel414*qMnu{$N z0`*ekY^eG4d~*rieJX)`T|z;NU~3grJMYmr4dN%glrd$(P7!3U zj$=M>m^Xj6^1?4om7j(==$cVR5FPTD4{cCMdCL6cYGtgfSzT*yxIq2gP4p=}Dk*js zJVvgZonF4^>yP|F_{=W90?|>%&^W#<*o7wOYf%zwUdr@2Ao#ScL24igH%?8%XQ63K zMi#Z>)*@0GCF$A=*HcQ#^<{9lH@MF{9mB@s#AbhZN35tsT=;pdhg;j8DREDBIQMPg zR_x`eS+b!+o`%UXHNwNyQ)cQ62=@o)fk3+H|?zdEZ3kC@Lh~0UWbDs3Tt<@#ZJ0VXw-m(PfcH`-S`R39}>x*MO-Qha@1N zmK%RC?6`B6_Lbu8++7S*lMw9CJM=Vm0verXg(&tmiR>qSWMn^mx$RuAxAnsNWrtaaXLXRJ=>?*DSIY} zqu#ibx*I&W3NJeg-qF>iE;QBszPi|YgT_r3-cEU@Mq|-&-zw0;=$P=BB0i}6$g!WxJc2L z{HYS?e4X7hWr*qO36Zp#uKTi~)1?v!pkmhQs6*^W%tyvD4++8;w&6aYYF&qU8eZMo z_PJ@2Dxz`_d?trDuwhKa;%@0Njk)Zy6zHkpjYY@xC|AStVYBkb{yrD|6H9;6L>vs( zVUSToGZ~^xfRDf%wH)P$08{9vntZt_&kM?ua_D*y!2*rlJ66jcz=cRpZ~br;c*C|j z3bvA|VlCSx4a2K|@Sf{~H1;(kKHkQg9@e=rov0NMMqCssy9%lRk zx#mebzQ65f-fw30tw&at$ozk zjNWYeGq{s7e$p%w=_jM(CxZikTM6PvcBXs2oxk)O^d}+!-Bg^}aJQ*q;mx0Kn(RD0RP+P=2Hi&L3$U;}&87#vxpS zS6qT;oUg&T1?xh%oKKJo061I%Pk#pcsm-4V4d4?;xUq1*m;qN{e^C(1nI$DI6l^{1 zGZ-aV7BG;EtPu$k*d6`YCOwK`AkOjP3&k=xEz&X3g)rRn!zr$;{-Rqoa#XE|?HclzBy)=AgNoIfNRRM`0Um%x3mXClq+=k%O#sH&16Ja7|92_D7$NWVvIBE#mkwa>5H(LKjlo(BN{b_4AA_NzYA|(cC*uJfRjeuB|=4)?$`bZd4jy)PRMb0T)&<1Qz8t4bdmK8{cUB zw$Wcy&+*d-*(ddi;C04Is1+F?!5TQ`CmG=y#Jfh;ut>Z?21QMe=O9OtOnU-OLO3YXyD z^*PXW&48^6FkHH3+;CSmzQgs5ng}m>mCFDUXGGU1zxL*!!?Bl8Yd730XDJwl9Hr= zT@-+m2=K@K7C2BBJPY(JkC1zZaf{osK!TyMwrPM0x4IoredQi2 z!5_3$2%I0(tE8Ow7+_dnFJ$#9SauhObQf5-RwSMkczErpw_vdB0gU_kf_tyu6jtgl z^05*u%Ly9S2ojvXNcejiz$sX`+6~beZ?u1N_Os)2I2VQmumSY~+`Vrxe(_zd6Nt?& zv5gao&d;9w^2pndJQ{2s8tF+9P!rD4^c-)W8Wgs*vh?o%+zJm-dUMw{P9 zRqJ7-bMqE1u_2;lsm0{YEGVnHldP_6{;Qy{ggPYn?{9=HEpZUY|cTVkg!R&t= zC=LK{*%6TV3&0oL>9CQx>lNkI(qi?;aKy z6kfe076FL<1%oKx$h7~CIQ~K9VaC0ta2@Gy?HO~Ut72BInhiH5Q0Fco&vV${8=P9;ZH|s)7765fXTh$ptWz5%i@uug$$xpT)@lS2-8s4? z?tc96Kz{w8-20W}{Ac}I1b?p^y8nteHM)DPb^9!7|G^Fy$e*>uf58p@g@|oadF3C3 z+~Gw3hBW@`?;D%>i#BYPe;qg8{{@NsU-03s|HpR%*k?gt3!isuLvUzIU`Ig;>Qt^3 zoAqc&=Egz-f&zBO7TjbO!M%4Q91)Dq&>c&UB@7T3f9lK-e(OxJ{ugy7fSq>4^Z$IE zm$07^6o2mpu6+}m{VCpMaSRSP!M(_Rrb$NE)Q*hYXxdGXi}yNg2RJ+vqI9Fb1OqfX zum2zI51jM=x3B+K+t!h#c4v zIf|rBv1U^P6YmqD^snFf|6beYZ*t#Nt1UQ#Uny3_`Cp8Gzx&32P?iM*y5h!T{%`h& zyD$BTh5X>7Z`@{a@00$etvSAVf4=eGP4N@!GLHhe_XDEy7pn7qU;3ZhB%pcLaZC^x zF)0V?EZ75ExG}uWr~vnW+7^7Su4CsY6psD)tV6pj5IAm641OP<#-FyA>Yx!bf75or zoo-qys?zs~;wedR3f!%C&(&nCT=ZAuiR4dP<4i~4c>zK6-tpPmDH8m}Xh`9(AQ2>_ zHAN?o`F{Lo-M#nsx;wvb*!@*sfd31Vs>Hwb^iwY^0ELveN^+OW0g5iUi3ujv34oFa zZeYW!4^eeuL(S;2wV?pg;YC*wf8fr3ll3SFZtsKhOXE)A|9QXs=lwtXzdz%x%+|_3 zc-7ii!Ec-Ru}Q9-*ld)$&0%1nUCB|MKvOur2`p|e1YQkZ!P&E*DO_Cw_W4oay}?WB8d*05Myc>7KcoG`MSs@!uJ9WZiT*~&vI_bq_Ua1Y@A%zs-~TCZ zTHgw`cPxk}*iv9aJoIY|)QTycK)uJ!uwOb&a^87bYrs)tuo5~~Z_rjz5FfrM-cdvA zWtcgT*6ai&yFCPW26Fj&=@J+DB+~dH44^vkXQCe(0=H zJ%XR_{a%+%_TP98;Dnzzj>XOY#BU@S8h1&%_gBC1o1cAE0CvL{n&16|S}UB%DjtZO zpS@H?aG=@+k9QKTe||G?U7Hej2r|6N5Me)Rcok&9nPuP^tX$WuTnpXZUj2&dK%DSF z{d11y|IGPE;t7p&@BM!FF0A2$T{S^t7_6gl6%KKr4y^k+Ypt*_K!69FS%w!JBI*tz zw#Sp*XP4cD>Q6pu^@9fZ*(W>Y-L8J5=YLKDe$El1KlttVe;*|F-)o`a7wcYNW-Z*~ z`#)=@#)snb(yAYW zTbMHEygAa83JA5p3gPG3dEjH72R0pn1UJqgJ5I>5eWM}H7tC`9oFeG3j~&qsT65`<{Xr=wZ`o5O?GD-f zS3i9L?*QAm=?8%Q>2JS%F8Uoq{*Iyl#%}+fbCcNQjK8qevf>(pa>xGeF{ZxbBgLnHpFV(&iIUFFe+K_3tUvN1!Ea}I`?f638cgGoo<7xvow-BtB|RrQA+ zb+3srdPqVNS_X8#&;G()cm_hrGnt6!Eby5O@b+pIPy=|=^<3LuB^?wOoryi=zsjd6 zzW{q=k|Ywq4RD`jqsD{{gvmfah6rP`rSN8oiw+#=ya)8p`Sb?dbPhQm|1ai~@YA1_ znD6g%e-EYPF=LM&pLyRh#wdsV?c-PJw-0mj+3sKWZGI^D|F*0#j@`b5y6U|3!d0@% zaor1&2A3-dTXD|&W;QB-u~g*aT9<^$v%Y^a&?daNyv5fX*Nun30Y60t^S{d95@8sJ zzp~$Ls5Xp_CE@bripH5e^6VpsLE&q_)nR!sfB%^8K|`cdu57CgKv+`TN8C!>z{=w`7(x+b zf5iXMHE5w+q0~LLAxH+Si3ldq^ahS|Y>zATi)lxi$V@uJwa`EHZ;}t-T&C4oHu+DV z_$SX?-r>Lftuv1tu(p~|po@6kHz@UxtBCV<*AtXe#%&P?<~CvMGGI!xWJ<)5$^>#P zQa-(sH;8h+L`1m0{!rCm1^W8Emop(B|oE16Yf8MB*#wNiyC z+kkat#Vxyo&1KcMUnPqUTK${WKHo54)P0=N|450a3pA8|bl%_nuPE_!06maYf57Uj zT>>23d9arX3%H0GY!HGr1$SGKPEz3$Umq~N%F}1REL;PCqfuK|&)?I+$^MdDPf8hZ)QGcx07h@ql zPa_MSOsSXfQJ&z5`6>-S9);Y_qXDa09Zf4;7IeyTQD zfPjE}WoV!Rb}O|Mta>Tbq9ez8g}9O@S9~qjawFG%t<@SQuTz7t#i*9@lVJz(e4+;Y zkSyBDBtV)#VY6qsW^tgiG80v;D|&LqSI90~ay8WQE_ZT0)hnyZG7TP=leH-AC$qpX z3|TO4!8iDFzzqzUFm})me~j#~jTaDoVeo;=ZJK29vdCZ>$MGV`t{Gb5&XI;j#h~>P zs&h2{Cqd$W=}!YdJBdCah@7A;W&TY7Ksqi3L?0caiL;Z5t>Q?G%DM}plPHXmRz9;O z!t^FOiS7h|FgZCnga4DO2JZgh9JK_n8mm|G&d(FjCs}k4u-O6Ne-&~gq`SlNtoP5b|=A<;wJO%no7Tt}(6!zrT&se4nB9Z!G>p!373PeVTC?Kfy$)i@B zEDvSKdwH80mTKtqR z?Ia@qxh`<*F9QC<#sd2!VM91lZbV z`zKjTe@S+sEGKYn?5+t-s;-}n#N4jAE69`w!^>R-$-L&vW`^ z-@k13IX_HJvOYhLUpfi*e=R%ue_)-@JF9wgo?Dv&zMfB10FLiNw|xNs7UUwZv^5{h41{p2L& zFU@|Ej9+^Fe$wOL^plYEzcf3$Z%p+`&rW*$n|_j!BV z^&k0l<{$X=?H9kUx&KJMD}R#jH~AO&Uj7pk{x`He^P%m}yqTRJ-kv{cdv+5*`I_YE zfAvF%S0_jLrPbw=m;BJ`^2uR->Gf9AcMZ#prZBrpiUJh9j5qANZn{vh)mC5R#Yx#dkx+h<@S^lF874jz2o_sJLP8|Q7Y@ZSQAku|4k-L|htr0GN zQ+Bb{sMpdunfiZw{Ok(&GrzFa*w?pktniO#;%c^#DzbvFUe2#$T8*UO)TH^ctPa`QUi)erL=N5lJM#4UL^w@3Z! zGX7u8wgyBQQU4;|cXo}=KE`=n4eH~6)Wu}xeK2e!h+W5iubbm}ZEk)MUyQbXJSvy@f2Ms{_~g81{fdpclc0B#&vl7p&wqGD zqmlQYvK9W%^<1le@#^}gowfFV+;4mT&Ci#S2Fggh|7{-rRR$Sww)_7DhtB+K+}{%G z?7v&zd7W_1>#=`d1;mK_YPQ3Fpe!w+{euD5r->V0{}Rj0?!U&`)5J}$x(227tuJTZ z{Kw-t%bNBA>)FOTKj;2i|DvDso>dcA8@v7~C&`CcKUwoq`%RLc+mEKn9?t&AAM5x( ztHTcUZ|cffKXz8F`?DYJaFJ*?69~8{{PZDt8{?DDcj4?m{(b$4K4mk1{#;)yRwu-r zFJ(Sz9O_*6*^UbFU&r@hoiBef(C&xRo?f#1DT^P5UOwt?`nm7>Wz|2+wr70_PIms& zZ$10jj_>pPWi{$yp7`NEq@Vp5zzB@F8vFTuohGh5xpw2zZnl2&X{U#wiM;yv{(1Gj zvS z|5EHfwE34<|3#aBi1qsqZT^k>q0PT>zi9JMT=qkof64YA+WZ@Lou(21=j_9Y;GAZ@ z)BH4*{Lg&(oc@`wf8yN_i*A47ztjFF{yQCg;=j}BmyZ8Z?8BFTj{l+9zjXW$**<*f z_;1|nd;C8X`}g>ND0bv~{9m&D{XPDlxcy7A|Iu!&zghMVYtBzUB>RU!PwP(|{bAfc z6#DU-W&gyVTsi+cK68KKz2EWJmt_BwPEUWa>>mz2XMeHmCx_0EzX|t~LzjkMEc-Wh z|HZO@Vz0jm_fIT;@+H~-s53?Vi)H_i^6+n#{llSyUxfRILoeN5Ec=H}XMeNopIH4D z;r@xO*e}WcS3a`BZy@eAI|F3S3Cc!3|HlhDR;7R(CxBA~hWMlJID_*9w<^7Im&LIWEPs>y+?VCu zO#vTjeYJlP?4rY;W0jv=`x}&?7V4i^=X}re@g>^_xdeb=cvg;3=P$ZFIBE8N1K@v$ zW&cmqdi1Zt?T8V)cQZ98=#Mv4E!Utj{Sd%T5myqQsx~0 zcci&^?oV<)7xg8i_cQ%NO@DLpNg1!_cFYek{jX&D-DWQ5cm2$tFR}dqk`I!T>Xzic zBeX{#4d?o||DRa@|B3Z~Up~(I@-HO$U*+|i{|gYKvpnEG<>#~B`?()1ILqPqJum0> zKcDS6Kl_}Y&vy6E_YdLjf5~>f1>R@BKl%Tm&;NP5-oLE(d)|ZcOMkY1+lA}5UHH=K zKgV;{pYq@AA1FWN`Yab8`uzNq&(F_s{X>3>{CB^2{v1U9yWII)3K;(H(CDA?cCP1B z|Ce(;=~>>t<#GM2|139>{-xkq;&=O@t&DY^ckho8(O^RV4i^7E{e5rNGN1dL>sjU2 z^L{M^xa;|Xcn(CsfPeCI)Z6pfP#)Mm^LgLVE*aKl@4y~FZ?he+Cx$y+b{k>1lDB{Z z7~bYx;OLA1_y9N&BdmM`oR$$wJ^{|kNH(7X=PG3(IqDq4=paLrzCG_|?(EGO6Vd4+ zjGm+NGk@1P9%C?JPkS2AZa|4{%AVj^o8Z}-?Z5M5QJJzE(0_lWMg8_k|B~k^=G|}jQ&n<_220Z_?4~*ztZjF*YXOd+dt{8zWmjW)4jrrvGc_U>M38U!k%2Yo0@xp1Y1eXj}F zXlLMYX3{gG{cKI-CdO_-hC@n*gGET9oYD)rEeQA01Aj%l??_u`2|g~uR-)Gq^AJW1 zTHk$|uZo_0B%}w%Zr>q=iH|3c5fG_OKwgp9W!UgK3S9!&C$@tO@cW=#bQ$;^Om_lx zSD{z+%w)f1qwaQrDLTAoFdZbmo;4jWwdG@-?vZtYF68XN3psH?svG5jJVH98qTJ27 z3Os|ye1G*CJLh&s>GjIcxG58MAsuycH?5bWVjEOkU^MP#bn{1@XCr+o0u`b*2{b=MiN>_nJg2B7f-mV&3=Lol#K(B5E^+8?{nena7P@ zDS^A)3B%eXukPXnZ7xH!y&*&AaT+3OYDJU8lZe~3gOBCPQ<$~D1)if2gf41E=&*s} z`Eo~(5ZKnip%xfynSCJgR9|4aq(mYkCkwZ&VMm4O((cL1RtagLlQ=T3XPxk24$J{} zVt>EaRt|VFoMMdqr00^ibEBewU#Ehtb=#o-y8aMuNG;_n}6dN@@RGkrFuQhdK~$e-A{>EZampyF}FI* zO$mCB)v=(8m(-444g$bLNV<%JqKuyXbWx_k??+EtWO%Z-jfO=_4nsYQE~OyqsUTd{ zPOuBf-ehkFHM**rxr$*MYk%gC z9Nea;kPNu2X;~}9IzG(IKwvDr^KFtf8+Z*3v(77|-i24cdO22``E~<^9lZ{O3nmAR z5<8XbM@!iy1@nQb_M4Vl;t=|eY|qdgd2m8?P!L8C8S&mo%S|pX2#FQoD}38s8uj9s zxpN7xlx(L}w_v5VB5X)m4q}(FpMOH#15gtw@4BhpKqZdWJd7HF-rvUSvawYppc1Y2 z8rMjnSPA@1v%Cse_>`tkoHx>puK=ETes_cTK*rv-F1KEiI;J1r1LB32C@a6KcOk!< z;qCAH-jflI!jDEkW-L;6L1~_nHM$s6`8j*O3}9bhzEd#<%}K?gC$CE#5R`&8sc%EId1|4&$pz z=_^XN8rw$`_@u7q&q zg8+MrH{Vw{d%KI0y?Soyt{MB4epXPO%X}BP7S}pc0wZ_Akcaua=eq0lMK~)Dt(2k;ul11I zdvM%a{CIap8M7`gW-1iSFr!E+`95w-=O5H=&<|@wkm-_m7hdpt7z6+P#N@4OTr zDfuL!Drbzf)S&zeNmf{A*S-=K7W`PXj_TmySXewDaPo!(s>-Czu=y|G#SxYV=iHXW1%Db$(gxIZ%s8XC$hMhBo zxsy@xh^R1YjsUafTs)kiQv}b(U1`101RJ z%C%IO5xe5ro9UJf3-cIY7`&?Rc|te{S!ns-TW?TVW+3O~rXdoZ&aLq6%(a~{5pK2%-yhQ*^7Rb8Tz#bu?F zu%WH3o`mfQ`1ndGCRyB*z?k1Kb+6^CT{aklq__7Q$zLi%Q+MjUr){T9PcmE4*QW3{ z-En`Z%l(!s_|p_6rXUV}Eg-l->!6fQIkS&KSA&oHhUZbnQuhOMT_SPuyYg)LM4@pj zc|IipJB(%#unQpwcQCdfJ{VWkK8r~R292}B071taCsYy^M^Ft$_WKd9|9CmS*+Dw1-gkI>puf=O&cRtT~9x5|vIhZ316liRF zZHx0AUWstP>4&JjSNL-GD$CEFXkCzl`WkML$N4n1=9t^oH=zHEk_U&WmAG2oq`y1x6DFfQ{2u4jLE zx9~ScQ`UpmpSxv%8GWSJ^7f8Mx_v%o zrq&w-iczDU(T+frh|h>!c-NP~2vM`QacbYu6ap6!y$VBWWf(*=B~acAyVvR?Rv&(| zWEe4DED@7bPxUtC0_63m!<62b8NJSVpShSK-61aDJlxsytYRjY&Y*?#IqZLipnZFL z#tV2*wtORw@u}m`F{toyy&o3f#>F&lrBnB9aSqzRJ~M~&W#5B1Xv(HBFAD{Ih`bqR z>WE*~df?T&lyu_A(yL((YD-S2ATA4nt_xIb zA!Q%odMZ;j)LR?OX&zPb%nAo%zL%a+=0!CUt{eGyQ%a^3lHnFz+3|nwtZy#@1s!** z%w*hk8nAdkRI(QZ$;P|1O|UMG^6-ujnkOOL@UdTxH+XUx1Hgau3T z4eI5f8F4TLxhluamAtPvix4XZE9k)HFmCOFT|tjxTgY(V=XafqhzHC0ONxB$<@269 zPk|RhNpY2O=OI=(u|2p<#d8{DIOJOU$cc|ed{UHiWO#a8g{*&g<5^$QlHFyvwpaSa zvdQTZ)I)4S6dy-0O^7{4;}Ge?&;lf?ukImk+${6@e#?#J1w877lv6%)BGfTNhl8CrFEoERiQ_a-Lt1<6CYug+~y z70;0~!q*jEY6Z`$7byoF=1(5i`mJ|yI%^M5E2f8oscnXQtFzf)h}|^d?M+Q4OSaEp zhV4wj=+UDsVzKGfG$tr70zV9-Yb#1zmPIm22vmPsJQ2FOE7mGlsj269^Q1Fy)_^65 zFRt4k`tt@YrOGXvsCKa`9|%S0KaXs#Ju+)9yRDVy^&)hB=>n zgPM1kO5YHh*$uzIYih~M!C++0@b+6!+nl3vMto*a(-vL57AFeM(* z`8^^WI@}jDC|EBUN8O(7d(4TVTow9FyY0t}Z}EtEH+YEWY8r2qdr=K&c5c&Vi;#%) zgie`MvewVJPIj(oNUC~4ue%G}L>@(H6M)5U@7sLweGPq^QMwBYTrWdJ`w9KrQgVNb zmg(58rfNLZcC<7iIZs_8ve3|U>s6l?Bzgv{vY;q+sFtlt8zm%@%Iz=Oz2|dVToScF zvP(Oq!kR1G)pQl-hL7pt$^qfmb^woozbMI=Y^9>EWthJt?b3E_Oe=;p<6gL|7xzJ< znhQhEYaC*en=U$xIwzD#XE~K?on$81>cH=? zjZx`+l`R)8))xe)`~@XN&1P5NnZfYhP&-`wVS8-wu7ngi=%Te6UR5j4ceBXV9f)v_ zWiEf@Kv~uy<*8EGt}LfBejHv|`VqE|79K+(bYFD=17E(R<*-c|8w{mP9*uv4*z~KH z;l5{jAFM?@Ij$%xj~N=IzSYPw}Z%Ct!B^Q`Ie z1Qzb@@N&@F57efpWd5%8wGDp?1-^BO{ssPzQ6OSeq-CJ*KvfdU*nJ)H7Swh^|{AlKAU+2(b=S5>_>l9f@*wR3lTA{ zZ9@tC8}f0(&Z!qk39ki{gl?zVSU(hv?#s?cId7p_Gf0(ZcW*8{9q{UV7NWPIsWi2A z2kL_@ydt!&5Oo?p?Ve$%o(IL)t_AB`uD&4ewNZm1xrt9*eB&lWAtiFYI^DNTe0f6< z{h*x&8|O9f@ySRktF3*@Bc7^cbtjM#v(XR}(pB3SEu7_mh5Q96pyk80G zR^dHpfGr-=p+8e(b_$)Q@fGNhYu*%+4o8#Vm>veUR$Et2T2~f*RVGlw+55Y5oo~ro%N}yS5(W(y*SLSB{a~aGW<{$<85n~= zAoIXr5!0lUqOd6T zi(SXkKiGAp00Q)zT|WoM0L%zE?FddRGgU za+8UzbI`Y@Pwy)k#=QgiIk9#5!_#5R=sjuqa_eAspe_!P_HBwcm>uJ8S;j{}vAgi( zHo;HQs!D%l-$6w&=BwDgzS;(@qhq&(ywNQI6+n{QFh|Fcdp)wg%N$~WTbKS`3G5I* zYvs`7yp`2@=p&qlP#&#Pjb|`(;`u8CUP}2&Z&SxY*4t9a_;MAa?XBHCF_=i`Sd*7o zbatCIR`_^;x(#N<&jl9o7(ck_tz2I`bVBPoR@r}EZPXmNm6yn6`UVmd3oXvW3-RPL zEWN@h70~pN+`+E2h<(1ehboE#Y-Kirrej zNe*Rnhhbfx?6L<8Seg25+4bX@kWSc}wtat&P-eaI$9R>8iOzdPE+wZzlqk~7E3C96 z1nf{$B-@(1`<5ASHX0*k!HfV#T|apLiYcZ4v{?E^~+|wiiwO52Psc77}G=~ zQ1*%)JYOMN#|i#9XzSg-SEIbM_ov$_8Y>0QOSzBDc>V(7UnB!IuvVahIz$S}YVaWN z1|_EQ2Mv|jE3?!pmhyL}y#jx8M(Cqp5|PkQFnLe=a@TivdlbVeXwUw5!nozXtODeS zZLMjPhDbJ^Z`wiX1C1F9>E0`JbY?Sqom55jv)f`ZOzp?g&hp^p0We0{#36fUty!PO z<0{#igV`zr=#JHhy&s^Ku0$J; z)-@&s>!9;!x!$zPwjLQCI7<=0=)NtqLJeBD5bmSEd;V>8t@;Y}a85~kJoHPIM5LY$ zRlMgEZYDKXI~h^GXc}=(Ve+`g!0IS5>&l^+mtZFAH1NHT8cNi!t;^PV2PXZ10k01}M=r zmbB1$k#I>TA|t&mB3UQ?Aqsxh)5YZ;=(-)-7}_JbI~=p+KlK+0Gm|dB(l$;QYz>U@ zIG%0AX;m7rqCdU{JeRv*-|@~E9m7%FOKm~~pRa95JmetKN(VZJ7)vFCHP?W+mHu!Q z2GbgM#=(E)wt3w5ONBVL17AH=GO?#h-K$l-Bh&I;SLYH?MO_KqIqnQhq!Q>Ewf5EB zyeO4W1;FTOJ!cKVcRTVr&Flk-p2IGg=|*2Y)eJ;MB)oaR{0MD_IB~ogH~BL4c7^E( zxsB!*Ya1^ow26rncnuzm8#i7bddY$aY6mW5;mm)0u4}r$=xP9m);AACHFLoQYzM^i z=3QrXQ0VSSnL9c@TaOEFU@l;e>ymy}@t#@^Ozt|@pbbKu;qHw~rc+aw+YP)+6h5->uk&8RZR6h4pASUxm8SMPmG z?%dWr7Wa86Qe+#DIl>avZ5zfFs!pe$6mJ!wcqJ4hY!>S{@~3s&`xJ?j=uR(Ih~*nc zs?FmikRuhfyxx(F@A`+tjuLav%JFI&)fRuE2MF@K5H~-h0jshh&TK&vwhZDFs}sSr zE8AM6!`_tEdlCS^y}1v2&W%!)6xn)9=E?bb%D^4%{g zHybw-MP&1AskX-x)o>lE6aRnt z9J3=CbaOkBTV*@w9KRvA4SI(hckbb5_vKxOF0&2-Kmtu&9~y&X;(nd(*|I|FqbubTGyR?#H@8+EW7PwzT#bHSZ&#S;RlayQ?6aO88VTdnHMybV1jT+-l z=Tkn#vW%ork87e^7e^i*fx8L1gH11146Y9IL`pgq$7mlxN>z7p|A6ud{w=$yw zS0rds*bTUsi^vjbBGp*QXlTK%AtbsOvw0~vyu6h`v)w6)+MxIG+_)#awRa7j=i(O3 z9!XK=f)xXU6r(G*T&<$}!c)xf<|s$l-_#Ve`Bf2iS5=`VONEMs2tCsFN|B;ERK_EOkyVW zhTcplBKz%ri^Rjzrigzw@rb+N&;%nPH5`cS3!zK8;z6SudNuD{03l>fl#_BatV216 z0^i{5KrsLIiyi0e==A*ll^xGzAO?TKjzj0e@HJp#prv33JOu7n=Cw)=s1Vj#RSirw z2Y^ukQs=Iv`(%-EhAQ*6ajzq3)@`PYW;^nzvs|C6=i^Diel#mJ5^5AoLJYW9F1VDt*tT7} z$*`}67*YxyxA?cPTtK$$JZOCUYCoAcQ;y2IwKEW z?wtB%NK}947^868zPXhlu;&({_$%=Mkv(7Ct#jPIR37r>2&Hi*td zEU)9Pb3;PXJ+MW;B&b#DrYkh#Gs2{ozvs7|=C?b8=Tp!m;vKnD6;_Tnn~Lv-ZVX+$ zA6MOMLe6rKN!5=eG<=A>ns>BAB%Xc(m|oa*b_$cW#M+AQ(imOwt8%rnhU^j8jNdDl z^q7BhAFyj0k+&4#ft$yM;A7tNHE|E|MrqQ+eR_l~;yiC^O;=rPW-jslQijWIaC#BA zj2j-+Bwi}a5}ZX89yOfwB6Ubld|rkMZidOvE#g(npt<`ID@wMLF+fDvh(^GgYwWXT z?FOkm3BBys6uN{eoT)7*F!CkjU!zjr%SV4Fmrf9|Xa00gpvEd`uy67Ozjek?M#dy3`LaOGqFnM!xBq_zZf7rVQ#0x^Hd zScUIS)EleEY?|M!&l=U|m+TK)$`6F4`lF5V0W<7_KucX4nl`=nimH-zB|D_&y3`}` zmU}8OY3oj)c|UFi0P~aAiQ_e8*nmCYc(iAJR6wqlPTXzwklGaiJV$wRE%Y)TF?`y~2tR*ScXC^N$-Uk04d?CE6@#p!aAaPZ5O;Ei5VcZd z)=7#Hen?drLiH_Pyx!e!)@Yjm=TNJp;=oh4kjO2{E_T0HaS}4yOqV!6f7CT^JMW5t7X0Dyj9F{Kaf|Kf8FOYm8p=Z8^n6_r|yKQi13W zLtH{U!6mw{nOH!X7$e^HY#Rcu}pITiOkKZYt|FJ={zj@`apQRk`-FaE$5oU{cuI$Lk9z zZrkzB`1KOswfU}LRlyY7^h#@zj5|BNtV<2Z=M9x<*1>gi>0CoZCi8#j@JBtw@3xq( zv)}lanFUJuQf4R!BrfZGBq^m06nDPHbu5igd)OA09W-rYlEJ?$fr-aLO_-`TuT)uq zIIhiywav_gOpCcH29_HbCm*DXCIx+fXe^7G)P?XWz3Pc!jvKEJnBDJUNE?rrSZYoS zqc`R(6WA4PY&gf zm(_cum4Ir!Y)L5oxOmdrmZc6KQy})5k0Ni9(VW>>4?a))rS6l5;!w}}>s&6$=*qw-wGk0<9`Z)_#sc=BFJLxxIP_mNXxC z{yjJy?t5Te^h|%N2m8eP=bh<}Ma$xDEv_r1MYZ}mZdT{vni!UQ5XgwzmgTSOeQX91 zN}G#!T|CfRD&dn~pS{)-*vL5<8#jFlY_bY=_GO@P+tlmz&q-KzGZyz4ohg(+7^_tf|%JrdEGFt%IuM*WGyy_0$xEH(*0L zee%gcW)Hbd@t#5z!p?bPiRFphVVYR#?|B0TL<=q@N2RjkpIA(_I!dp;&Md_(YE$Nt%_xt2W z-K?v(>05g4pGSDt&a8cSc~Y`2g8DL;Vji!IwQ~-QDzhJVq*z-)jFxoTEOrMoH+bdp zSOAfs81Yhb;I!sJw>?_&QV%ajeQ+FhEnYTTaTI@7^eEQr5;7Dn7K>{jpYrG9?A=?P za#((|)eoA&**E5P%Od~5KG`eBQ?KFirlEGYLQMMelz8lRpweZvR+m=30;zm)J5vFp z2HiGUYV^{q;T1>4OH!^E(3zsuYY&Zl!pS*?Tkhn#6;u&(2jsy;)jnm>g%s>EF#tlV zO4@(=I^NVhJSdx#CNtSC)T;HCM7w@oDS?B)({yR1f>VLPK2a$pba(YQuR#zxtyJ+M5%wLu&2>$k?1zwj3c`|Duqxf#l~SagmNC1#V=r&cD>~63@6@0R*WvSxxRGCFft=B7FWSt)N_#{F z@8%_r`|z@?->>C$xV`VuMJV2VoZ5MxJ5_RsPp5@+&x<29dOKMH7nM6W{Q2QMH_?BC zinSGMsHwAc;@!eI`?s(TD+begXO5Or8;^{>T;J<`vkOJTTk86&TBob^UJ4z{UX9z> zOW3hotncYq++-%AuW!sy>u}H1>EqPyE()Va+skd~SYZ?`nML2d8!0=v(dM+wwQV&z z*W;c)JbRJ3=Zn!u)W#fzCPW?)9LNJFpG}4!){P4 z+0-&rm>WfJ()}j8QirOzE^?NF#d5Pu*9)aQ%W}EfTsHdtnP$(1>sIeq^v;s)g?<{F zyRnm=+i<)+B+;yIiV>I?GNoOOm7L0r{W}T5HNpBduwCyC$x8k|Ah8#H^0!{rDxdvH|-tR zGwp2*_(|xrr2B>Tp56i=+xLE%Mj^ru+oort?PPBJ;l0s+_JY#=)iy-*W-sGu2 zc?*I14ef0$NQfehE`DflML1vN4gldjy-J`dzoEU)mw%u3rm0;fnAlwaIK6NXz`^_` z27Y0_6;L7!+*mMioF%v7W{GY<_nj=dT)`A55c4GfU9wxO_8ZPxY=LhxurQHWp)2(g z7a(T=^~`K?d{v5J!5)90yqH*a-xA}|oVf!+S#GNXE&}F6%LstBzPH=aHtdiI zTt8AFXF^3)p_FeO%b{2HtS50q?d|TW;#;`Wvnl}f`mkez!tZMPEmiL!p#IXp;bIWr|gQ= z#v|pbz|mRlMiMd#EPu8;5#+&4p@554Pee)tfH6oU;0VQ#@K%n{bu#F5i;DSJD6qUN z0z>Ss;=-E<7)z7y>k zzd`jyf8!6I#tVOz7?5e^L#ln)@0q3&J2jY?sxp{41VSeC6EzV??l%P z<}+ojN^sC_LP288Hx=vxVIr^HFw@6Y6*^7^U2#_E%$exm4(;}%DGSArDg~OzNRiHR zttdolN6S#$(#U%_e9^`t6O5qCVgZp4LX0xvfU;E1);73QS7t9?H;{e zFKn?uFhXhqI#YHoF$8#RJHw+B=xmTWLTu3_)E7&Rn@Y-=(CN^mtsfGcFfBj%b@4YV z_d}z{GiNVy!iP}uKL4`T@WoYs%Ac^{Y$k~vZ8_D-MO^^l7(6W8h@fi<`IH#|2Y%pj z3lY;cEHHm56gmJ`Qnsd1wKt<{wXC9jVdB6L6i$F91qp$B7rQ``N}l!Hv|Hl?vW7M$ z@zq2eAhCC0ROB}vCYsgr5yY`A;6{W%-37jBfkR`O4a$|$L{O9zMF6heZU#77uGFar zbmZkJg<5nf0~VbKNy7yIR0}-i->l=t>hNx+w&H&?$T6hKLIg!CFaSXnD>NijRJL1# z$6Zo8O9{Kz6=1Wrn$O#1XH#5tgzT932SS0*Jjyp)I8ocXncDuU-`_0TM4(KpGf7*Z z4tb@d4Si;U?(Cny)+F3)p^6X}O~@TAV?>!1a&J*c>_DVD(2>B=rX&b1b`TOaxHZKA z$)JCvLwVxRkSe&q(+Apuy;;ISJxFdb6~6!)jH)7#Fn|;^1&f5T>hP=xO@umO3e}}1 zW=QJs%!a%<6XaYBI@JJAOt^Bm1%UwyMOqa4y7WxZWisOqkf@Fc0zlzqpw$$`6O!XS zkz+G!@+*@_s24&|6Ncz_WctibPn0v^+{b@(>p^sNy{z4dz|@)*c6=bhLKQ$4sG4+C ze2?!HF+3XGAImThdk9{%Ap-tS%A$RWIP+B;3yK@W6Gey%4MFuP!C-EuYYz3;UQRSF zK#@6`q3Q<{`#!NEBu_K(JP_h}K99_qO(w@&Q2nxaED*SD<-%DA9r|V7G-S6qTit&Z z)%Y$-?~NAv@zMtkdQ!`V+J~W4C#HbiT7jG)j`1>_dkeqpSN13S70(RX7?hGn%5>tK z&vQLA8PyF4k%rXLmWB6o6fX20bZsJgF)I{GCtS@4V1*I-Cei9l2RYD-K3xo9u(X;^ zgR+?^MeA5~5>R`8djlT#yZvLSnv;K0U@w8#Or)^tp`B8wJN3K02}-F0JE_Q^B$|cw zE9Kn%LOGMV(t(R5#AmHT7fb9!aJmXneYI4;i#o_|(M~kYeB)BjP6Zh+0IY0z%Y=7N z*SwqMOD?{Gv0GF7e0wWQ8B}IfHV6uZBsBhIu`Q7J1iGToT?O&VvkKB_2j^P)JEnb1=nxNUn1!#Vi5Uk$y$?O)2#lOzrT@ z?U6j5=lY#_Qhyb|HbWv*Me3+}utz2+0_KW&PX&!9dqrdE@jZ0bB~-AE3V-E`nF3vp z2UX`uUZ$dw>-BovzHb1+&OCpEoS%<_u8J)PF$tLkpc%lqt%^S7?V*tqXLdUNY8MF) z^tm2<^H(zLRPmQ<$z|#*mHUf@RfPJhCDtaR2+w_4#yg`nbJgWXr!bFlpA{B1MWHYq zR0M)5pi+li604w)s-QIj@N_zLN=LcvLo7^D0?0C{yRZPN2g*|rTtk0XDoeq1yGn({ zLoBc;096P0lt%5#J5y{*K)E?` zqEfayRSZPXT}821B~X8XQuT_X90@>$@yQSvVEDW+r2{Jd-+Fvxf%J>a0APAtTn!GC zsvw81SB5B(k=iSQI;DZYQ~^=$!{>fj=_z%1Z>h^x%)~3@iXc#%KKB#b39#~ z{r~P`16{04ELZ<&t9sRU3X`4A?=lOf>pdZahwS{DYd*Pena+Rt56M?$bN{Uf{#T!m zpacvkurC+1ZH_^vGj~}kvzOWPr81fe&~vFY00xkIl8*NvRtwcbSEW1^g#aSW>z?G+ z4wO?mNQwWAb=#p+z2ijCV<`I0x_B1?D%2#DbSZG-7}qFMD-i1)hd@^dLV>i1c^J*@ zy%~l6fpLgQv;*%wO5yPAS$EhE@w8r1p#a0pv*U~)hrOJ#b6sJh9 z=usO@Q4s&SF3Ez5gd%{x5WkFa`@-E-3o80)4!^c@NQHm>)dxk;7{UsQAeJS>MF6X! zjL|FaR0xXB23@vCor*+QiaSgTe`wEOzmtS`gBib3X{AK1NF4hDyN+L)${?+=`;h z1q!)M%S=Ipd?pqu?6C@|Gw&;9D}p8#yu#R|9ZnT;&j=bxDsUnLXT8Fi_#tfZLRe#xpKq2Gx#Sqf^D?adhK<+e`=>ML0SC&~LvHuA|GIl#{(k=rjehxi zHft4Tf3VLWobt`_c-ntwg{TJo?0+FsAnkwV{Rg{+opYSP+{~J8Mu>agS>6>TG|6FC zrsFe@M^V#w6rRST$UTV50hDhXhJ{@=F1#t0IY17>0*@#CWN8|I^N_3dWPFb&@6wD5 zr;(ZIenKp$T?VOXoaq-r_z1>%o%zZT&9Ct&X#6%^Y31EWy_D^}NP~sbOyS*uLiT@C zwa9+T7yxSweDrBAVIPRoJ!o(Gk{f@xV5@6yT`FMS5<7j=B|efK_6RU%h+Ugr9Bh*} zwGJo<#O|t4&9+*J@seuTMF28G>|F`$@RaW`XIPM{B;VwlDPOH()^bhX0;-@5@rMOB zeF>Wa?2=9>0cmix$I9W}km)!~&de4?WOfCwCwy zd#@Bg#*lysY=@)Zo)e!Wda>An>4UMEM*fv}o!fp=r-W~QehIx_t{H@kpT|jmxu1_2 z3y^X`^hA-8bP4d^WZa%~KtSZkN%%{v_wVSVJxJ;Xsg zuJ*xg=XS5lOL7Z@BvyOeq`tUt41eu70TkD#u}$EMJRVm9FRry7m8uvpS`{->zpg;8>VZ&l z$@twoo&qe|l8{P8zFf3aDFZbMp}?*C^+K+G-DjSGoYA zPIgg&WfFE4bqI>PzAp03g?h1z4W8zka^DH{d-J4Tw7h4SGkI-61i?SQRIXHF3R;IX z-Pv&Oo-+Yf8&D|QCE=KhLd*{*V@EwNfUx$3ssffxyd`!)6+r6HK%wg1xAT>9domUs z{I<6>?h)z%0sEIA@DXJTT=xAGmc#`&=>JETknj;%0neA}@DZFE3+gxnps>dOS?V~% zfcZD6V*||fQ24}o|7(|^@ev&X@3+435efnu-!PT%i}KYCL)F9rif*9Z)l>x&Ydh7i zw*8ZrX$l*IoTy#rn~P<@7_ak~<)|v42qkp7b?mlKE>HDcj&gu32AcVHI`I3$^*W z)Trb(CtjNMSKa#S^W6L&D0 z>ff!eR)y6>R=W?d!%XSP3``;c@R9dJc;aE`?5h2JS}Zf#AJV$Q(AmRFC;6GqmwziM zoBt|5uMRfms}(0ARQimk6Om|lP7V+myn?0=yxr@A69YU`zVq}<`OecbCzA7JJZ7-%6CrpMfpzYjvvZ*PB#n#d2CFkV}VRd^Rzb%0Dt~ok?GIh=kzL>PUiIU z^qhX4p3~3MGnM?Ihl`m?p6TJ+OeKGa;+abRq-*E=&-8FR=l??w&-wol#oV0#Io*3E zh<_!5!52e3vA>x&dETcMcqWK{p@I*? z7ehR?1Kc-5OzMr&e38Wy|9h;y7~(1I=9?j&(so~D@su|AW`g*ab7t|)5KnpKzZl|) z|1E?svUuWu;WtA(QNijLLp-M)zR2P!Et(19U&>Jpz8K=ET*~T;A%7<2A}HTvF)0(Z z_+p5sw3YY85Kn3KZ?bqw+qNwU&Pnb&4Is-K6@kK%$k+_IW<`PeXhC^uf!PE~_0xCs zXh6oQ1~TS>5v)(=4t!nnSmBEz27jc85fG}GDt=Alhwbl(;$|8TbPd$Z%rN}shZE%W z`b-sb0ua>5_@tGZw14%onJX?Ta?&EKmUZ|GTRgGEDFR}3=Rm%YTHslvPv{z^lz%mx?1|_E<->-QDq(Z2E=2ajT0{1g-0=E$5pLqid1$XNHACY=dX zvmm7J6bEJfUl6jxUl7B8LnN!fz<;toQan?!Gj;l&^Es2QCI*`iAxjgAHpY-4`<-@# zlx@DrSRIf@4}TK{%T2!{gztZLyr<*nl6=hjb@`OPPs)FfXSz0?%B>@R*XDWf`i!6R zGyMzMiEhP&BA%$-J1L(d_yhU-KVMJ&WWV-PIU-Vy&CV=N^gimFB(mOVq<)dWz4=1|i+?|4F#aKfe@Ni&hXh7HWN`7leEcSX z#o~ty{`&n0;SU+C{*b_*?OSxP`XPV84+;E31`j{W@%M78_)lqI_P?112Hf>4oVk*c zjsxreOEj?i3k`f_u2ub^ff>#)3xHG*X#gCd0*JNvPUXsU4;PzO8`o{BSS%h}z10{i z0Dt+iQ4Omvf^%_Ki#y}++jo|#*}283du!RZknIk!t$Pu2kX|GOZf*~Z+g{xT#hn)K zH(5Wc??=%bL-~oYxD`iWFSoh5t>dy!P-`ruW8f-F&EiZo^A9%7Z7m@@^qA_l*29Y> z1a)83Z-$;*jUbB|<92mo;Oxx4@7gkmwtu^P&pr#FjO*%sTfYloIfxv!W>?G0;bPG{ z+BY`sakw>gax&ZcoLq9+Jg@LV8yYvlP!~cWbW-3tyJ*1AbQKl`T*Hb))vEfeUPki$ zpz=@h-ObCD7tbw2%eu1^HvlWN2)B|cM$|Rc627P;m5mBscpu**Z7x=4`r((Goqq^V z@9Q?^-e-nIyL0}0b}Dy^8k*MGckPPWAlmY3G96J5-0X01hy1_zOW<+A|rdA_<= zNq9Rg1h2DoUbojoUdqi%9zy@RY_&_~4L7>RetdP;k@)tz{T^jX+bj9|6_pBL_v_T! zJUdr^X7aUJTdh!S>ezjl%Nq4(4eX;6a!&wO=2ezfKxPYz7Narqfp>HW5 zs~XncAL*>uuPSTWkILkh!NWPOm`l5tduOpk1i)Arf)sS

E5NN(^{Fb)>X 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�}76MVf%Y-O5@{O`dE^K;EhX;7Zo)j^O4 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

3^?bENQp}hHAc)yIuA8CV?(B^AchJc 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 |d!vQYMl*!P!aMveCy! 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

0Kt9*mB=|8? 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

@1aJ&#Ws| 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�&cEy<4$-!f8w`vzm&z@dS$0d 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

%F;v;HCVg}eL^r-8&)erGe0a2P3$-s+nAh< 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%0DJEB_7l*DtyPNP$+Qa-+3Ezps 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

SN_%g#coly9XtJZ%4 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 >eHv2%DfLV&+CfOB51EJx5l_U#Z{Ueo=g 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 diff --git a/examples/server/tests/utils.py b/examples/server/tests/utils.py index a82504235..f32a439f6 100644 --- a/examples/server/tests/utils.py +++ b/examples/server/tests/utils.py @@ -26,7 +26,10 @@ from re import RegexFlag import wget -DEFAULT_HTTP_TIMEOUT = 12 if "LLAMA_SANITIZE" not in os.environ else 30 +DEFAULT_HTTP_TIMEOUT = 12 + +if "LLAMA_SANITIZE" in os.environ or "GITHUB_ACTION" in os.environ: + DEFAULT_HTTP_TIMEOUT = 30 class ServerResponse: diff --git a/examples/server/webui/src/components/ChatScreen.tsx b/examples/server/webui/src/components/ChatScreen.tsx index d7a246cf6..79de30532 100644 --- a/examples/server/webui/src/components/ChatScreen.tsx +++ b/examples/server/webui/src/components/ChatScreen.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'; import { CallbackGeneratedChunk, useAppContext } from '../utils/app.context'; import ChatMessage from './ChatMessage'; import { CanvasType, Message, PendingMessage } from '../utils/types'; -import { classNames, throttle } from '../utils/misc'; +import { classNames, cleanCurrentUrl, throttle } from '../utils/misc'; import CanvasPyInterpreter from './CanvasPyInterpreter'; import StorageUtils from '../utils/storage'; import { useVSCodeContext } from '../utils/llama-vscode'; @@ -18,6 +18,24 @@ export interface MessageDisplay { isPending?: boolean; } +/** + * If the current URL contains "?m=...", prefill the message input with the value. + * If the current URL contains "?q=...", prefill and SEND the message. + */ +const prefilledMsg = { + content() { + const url = new URL(window.location.href); + return url.searchParams.get('m') ?? url.searchParams.get('q') ?? ''; + }, + shouldSend() { + const url = new URL(window.location.href); + return url.searchParams.has('q'); + }, + clear() { + cleanCurrentUrl(['m', 'q']); + }, +}; + function getListMessageDisplay( msgs: Readonly, leafNodeId: Message['id'] @@ -81,7 +99,7 @@ export default function ChatScreen() { canvasData, replaceMessageAndGenerate, } = useAppContext(); - const [inputMsg, setInputMsg] = useState(''); + const [inputMsg, setInputMsg] = useState(prefilledMsg.content()); const inputRef = useRef(null); const { extraContext, clearExtraContext } = useVSCodeContext( @@ -172,6 +190,22 @@ export default function ChatScreen() { const hasCanvas = !!canvasData; + useEffect(() => { + if (prefilledMsg.shouldSend()) { + // send the prefilled message if needed + sendNewMessage(); + } else { + // otherwise, focus on the input and move the cursor to the end + if (inputRef.current) { + inputRef.current.focus(); + inputRef.current.selectionStart = inputRef.current.value.length; + } + } + prefilledMsg.clear(); + // no need to keep track of sendNewMessage + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [inputRef]); + // due to some timing issues of StorageUtils.appendMsg(), we need to make sure the pendingMsg is not duplicated upon rendering (i.e. appears once in the saved conversation and once in the pendingMsg) const pendingMsgDisplay: MessageDisplay[] = pendingMsg && messages.at(-1)?.msg.id !== pendingMsg.id diff --git a/examples/server/webui/src/utils/misc.ts b/examples/server/webui/src/utils/misc.ts index d46322862..87f55b2af 100644 --- a/examples/server/webui/src/utils/misc.ts +++ b/examples/server/webui/src/utils/misc.ts @@ -118,3 +118,11 @@ export const throttle = ( }, delay); }; }; + +export const cleanCurrentUrl = (removeQueryParams: string[]) => { + const url = new URL(window.location.href); + removeQueryParams.forEach((param) => { + url.searchParams.delete(param); + }); + window.history.replaceState({}, '', url.toString()); +}; From c950a1f69269bff416d74349a82d78181ce6f0f8 Mon Sep 17 00:00:00 2001 From: Eric Curtin Date: Mon, 3 Mar 2025 12:44:56 +0000 Subject: [PATCH 08/87] Adding UTF-8 support to llama.cpp (#12111) For emojis, non-alpha characters, etc. Signed-off-by: Eric Curtin --- examples/run/linenoise.cpp/linenoise.cpp | 1119 +++++++++++++++++----- examples/run/linenoise.cpp/linenoise.h | 61 +- 2 files changed, 917 insertions(+), 263 deletions(-) diff --git a/examples/run/linenoise.cpp/linenoise.cpp b/examples/run/linenoise.cpp/linenoise.cpp index a68f12a1a..9cb939900 100644 --- a/examples/run/linenoise.cpp/linenoise.cpp +++ b/examples/run/linenoise.cpp/linenoise.cpp @@ -75,7 +75,7 @@ * * DSR (Device Status Report) * Sequence: ESC [ 6 n - * Effect: reports the current cusor position as ESC [ n ; m R + * Effect: reports the current cursor position as ESC [ n ; m R * where n is the row and m is the column * * When multi line mode is enabled, we also use an additional escape @@ -107,6 +107,7 @@ # include # include +# include # include # include # include @@ -205,9 +206,9 @@ class File { int fd = -1; }; -__attribute__((format(printf, 1, 2))) -/* Debugging function. */ #if 0 +/* Debugging function. */ +__attribute__((format(printf, 1, 2))) static void lndebug(const char *fmt, ...) { static File file; if (file.file == nullptr) { @@ -222,11 +223,469 @@ static void lndebug(const char *fmt, ...) { fflush(file.file); } } -#else -static void lndebug(const char *, ...) { -} #endif +/* ========================== Encoding functions ============================= */ + +/* Get length of previous UTF8 codepoint */ +static size_t prevUtf8CodePointLen(const char * buf, int pos) { + int end = pos--; + while (pos >= 0 && ((unsigned char) buf[pos] & 0xC0) == 0x80) { + pos--; + } + return end - pos; +} + +/* Convert UTF8 to Unicode code point */ +static size_t utf8BytesToCodePoint(const char * buf, size_t len, int * cp) { + if (len) { + unsigned char byte = buf[0]; + if ((byte & 0x80) == 0) { + *cp = byte; + return 1; + } else if ((byte & 0xE0) == 0xC0) { + if (len >= 2) { + *cp = (((unsigned long) (buf[0] & 0x1F)) << 6) | ((unsigned long) (buf[1] & 0x3F)); + return 2; + } + } else if ((byte & 0xF0) == 0xE0) { + if (len >= 3) { + *cp = (((unsigned long) (buf[0] & 0x0F)) << 12) | (((unsigned long) (buf[1] & 0x3F)) << 6) | + ((unsigned long) (buf[2] & 0x3F)); + return 3; + } + } else if ((byte & 0xF8) == 0xF0) { + if (len >= 4) { + *cp = (((unsigned long) (buf[0] & 0x07)) << 18) | (((unsigned long) (buf[1] & 0x3F)) << 12) | + (((unsigned long) (buf[2] & 0x3F)) << 6) | ((unsigned long) (buf[3] & 0x3F)); + return 4; + } + } + } + return 0; +} + +/* Check if the code is a wide character */ +static const unsigned long wideCharTable[][2] = { + /* BEGIN: WIDE CHAR TABLE */ + { 0x1100, 0x115F }, + { 0x231A, 0x231B }, + { 0x2329, 0x232A }, + { 0x23E9, 0x23EC }, + { 0x23F0, 0x23F0 }, + { 0x23F3, 0x23F3 }, + { 0x25FD, 0x25FE }, + { 0x2614, 0x2615 }, + { 0x2630, 0x2637 }, + { 0x2648, 0x2653 }, + { 0x267F, 0x267F }, + { 0x268A, 0x268F }, + { 0x2693, 0x2693 }, + { 0x26A1, 0x26A1 }, + { 0x26AA, 0x26AB }, + { 0x26BD, 0x26BE }, + { 0x26C4, 0x26C5 }, + { 0x26CE, 0x26CE }, + { 0x26D4, 0x26D4 }, + { 0x26EA, 0x26EA }, + { 0x26F2, 0x26F3 }, + { 0x26F5, 0x26F5 }, + { 0x26FA, 0x26FA }, + { 0x26FD, 0x26FD }, + { 0x2705, 0x2705 }, + { 0x270A, 0x270B }, + { 0x2728, 0x2728 }, + { 0x274C, 0x274C }, + { 0x274E, 0x274E }, + { 0x2753, 0x2755 }, + { 0x2757, 0x2757 }, + { 0x2795, 0x2797 }, + { 0x27B0, 0x27B0 }, + { 0x27BF, 0x27BF }, + { 0x2B1B, 0x2B1C }, + { 0x2B50, 0x2B50 }, + { 0x2B55, 0x2B55 }, + { 0x2E80, 0x2E99 }, + { 0x2E9B, 0x2EF3 }, + { 0x2F00, 0x2FD5 }, + { 0x2FF0, 0x303E }, + { 0x3041, 0x3096 }, + { 0x3099, 0x30FF }, + { 0x3105, 0x312F }, + { 0x3131, 0x318E }, + { 0x3190, 0x31E5 }, + { 0x31EF, 0x321E }, + { 0x3220, 0x3247 }, + { 0x3250, 0xA48C }, + { 0xA490, 0xA4C6 }, + { 0xA960, 0xA97C }, + { 0xAC00, 0xD7A3 }, + { 0xF900, 0xFAFF }, + { 0xFE10, 0xFE19 }, + { 0xFE30, 0xFE52 }, + { 0xFE54, 0xFE66 }, + { 0xFE68, 0xFE6B }, + { 0xFF01, 0xFF60 }, + { 0xFFE0, 0xFFE6 }, + { 0x16FE0, 0x16FE4 }, + { 0x16FF0, 0x16FF1 }, + { 0x17000, 0x187F7 }, + { 0x18800, 0x18CD5 }, + { 0x18CFF, 0x18D08 }, + { 0x1AFF0, 0x1AFF3 }, + { 0x1AFF5, 0x1AFFB }, + { 0x1AFFD, 0x1AFFE }, + { 0x1B000, 0x1B122 }, + { 0x1B132, 0x1B132 }, + { 0x1B150, 0x1B152 }, + { 0x1B155, 0x1B155 }, + { 0x1B164, 0x1B167 }, + { 0x1B170, 0x1B2FB }, + { 0x1D300, 0x1D356 }, + { 0x1D360, 0x1D376 }, + { 0x1F004, 0x1F004 }, + { 0x1F0CF, 0x1F0CF }, + { 0x1F18E, 0x1F18E }, + { 0x1F191, 0x1F19A }, + { 0x1F200, 0x1F202 }, + { 0x1F210, 0x1F23B }, + { 0x1F240, 0x1F248 }, + { 0x1F250, 0x1F251 }, + { 0x1F260, 0x1F265 }, + { 0x1F300, 0x1F320 }, + { 0x1F32D, 0x1F335 }, + { 0x1F337, 0x1F37C }, + { 0x1F37E, 0x1F393 }, + { 0x1F3A0, 0x1F3CA }, + { 0x1F3CF, 0x1F3D3 }, + { 0x1F3E0, 0x1F3F0 }, + { 0x1F3F4, 0x1F3F4 }, + { 0x1F3F8, 0x1F43E }, + { 0x1F440, 0x1F440 }, + { 0x1F442, 0x1F4FC }, + { 0x1F4FF, 0x1F53D }, + { 0x1F54B, 0x1F54E }, + { 0x1F550, 0x1F567 }, + { 0x1F57A, 0x1F57A }, + { 0x1F595, 0x1F596 }, + { 0x1F5A4, 0x1F5A4 }, + { 0x1F5FB, 0x1F64F }, + { 0x1F680, 0x1F6C5 }, + { 0x1F6CC, 0x1F6CC }, + { 0x1F6D0, 0x1F6D2 }, + { 0x1F6D5, 0x1F6D7 }, + { 0x1F6DC, 0x1F6DF }, + { 0x1F6EB, 0x1F6EC }, + { 0x1F6F4, 0x1F6FC }, + { 0x1F7E0, 0x1F7EB }, + { 0x1F7F0, 0x1F7F0 }, + { 0x1F90C, 0x1F93A }, + { 0x1F93C, 0x1F945 }, + { 0x1F947, 0x1F9FF }, + { 0x1FA70, 0x1FA7C }, + { 0x1FA80, 0x1FA89 }, + { 0x1FA8F, 0x1FAC6 }, + { 0x1FACE, 0x1FADC }, + { 0x1FADF, 0x1FAE9 }, + { 0x1FAF0, 0x1FAF8 }, + { 0x20000, 0x2FFFD }, + { 0x30000, 0x3FFFD } + /* END: WIDE CHAR TABLE */ +}; + +static const size_t wideCharTableSize = sizeof(wideCharTable) / sizeof(wideCharTable[0]); + +static bool isWideChar(unsigned long cp) { + for (size_t i = 0; i < wideCharTableSize; i++) { + auto first_code = wideCharTable[i][0]; + auto last_code = wideCharTable[i][1]; + if (first_code > cp) { + return false; + } + if (first_code <= cp && cp <= last_code) { + return true; + } + } + return false; +} + +/* Check if the code is a combining character */ +static const unsigned long combiningCharTable[] = { + /* BEGIN: COMBINING CHAR TABLE */ + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, + 0x030D, 0x030E, 0x030F, 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 0x0318, 0x0319, + 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, + 0x0327, 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, 0x0330, 0x0331, 0x0332, 0x0333, + 0x0334, 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, 0x0340, + 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, + 0x034E, 0x034F, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035A, + 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, + 0x059E, 0x059F, 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA, + 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BF, 0x05C1, 0x05C2, 0x05C4, 0x05C5, 0x05C7, 0x0610, + 0x0611, 0x0612, 0x0613, 0x0614, 0x0615, 0x0616, 0x0617, 0x0618, 0x0619, 0x061A, 0x064B, 0x064C, 0x064D, + 0x064E, 0x064F, 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0656, 0x0657, 0x0658, 0x0659, 0x065A, + 0x065B, 0x065C, 0x065D, 0x065E, 0x065F, 0x0670, 0x06D6, 0x06D7, 0x06D8, 0x06D9, 0x06DA, 0x06DB, 0x06DC, + 0x06DF, 0x06E0, 0x06E1, 0x06E2, 0x06E3, 0x06E4, 0x06E7, 0x06E8, 0x06EA, 0x06EB, 0x06EC, 0x06ED, 0x0711, + 0x0730, 0x0731, 0x0732, 0x0733, 0x0734, 0x0735, 0x0736, 0x0737, 0x0738, 0x0739, 0x073A, 0x073B, 0x073C, + 0x073D, 0x073E, 0x073F, 0x0740, 0x0741, 0x0742, 0x0743, 0x0744, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749, + 0x074A, 0x07A6, 0x07A7, 0x07A8, 0x07A9, 0x07AA, 0x07AB, 0x07AC, 0x07AD, 0x07AE, 0x07AF, 0x07B0, 0x07EB, + 0x07EC, 0x07ED, 0x07EE, 0x07EF, 0x07F0, 0x07F1, 0x07F2, 0x07F3, 0x07FD, 0x0816, 0x0817, 0x0818, 0x0819, + 0x081B, 0x081C, 0x081D, 0x081E, 0x081F, 0x0820, 0x0821, 0x0822, 0x0823, 0x0825, 0x0826, 0x0827, 0x0829, + 0x082A, 0x082B, 0x082C, 0x082D, 0x0859, 0x085A, 0x085B, 0x0897, 0x0898, 0x0899, 0x089A, 0x089B, 0x089C, + 0x089D, 0x089E, 0x089F, 0x08CA, 0x08CB, 0x08CC, 0x08CD, 0x08CE, 0x08CF, 0x08D0, 0x08D1, 0x08D2, 0x08D3, + 0x08D4, 0x08D5, 0x08D6, 0x08D7, 0x08D8, 0x08D9, 0x08DA, 0x08DB, 0x08DC, 0x08DD, 0x08DE, 0x08DF, 0x08E0, + 0x08E1, 0x08E3, 0x08E4, 0x08E5, 0x08E6, 0x08E7, 0x08E8, 0x08E9, 0x08EA, 0x08EB, 0x08EC, 0x08ED, 0x08EE, + 0x08EF, 0x08F0, 0x08F1, 0x08F2, 0x08F3, 0x08F4, 0x08F5, 0x08F6, 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, + 0x08FC, 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, 0x093A, 0x093C, 0x0941, 0x0942, 0x0943, 0x0944, + 0x0945, 0x0946, 0x0947, 0x0948, 0x094D, 0x0951, 0x0952, 0x0953, 0x0954, 0x0955, 0x0956, 0x0957, 0x0962, + 0x0963, 0x0981, 0x09BC, 0x09C1, 0x09C2, 0x09C3, 0x09C4, 0x09CD, 0x09E2, 0x09E3, 0x09FE, 0x0A01, 0x0A02, + 0x0A3C, 0x0A41, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4C, 0x0A4D, 0x0A51, 0x0A70, 0x0A71, 0x0A75, 0x0A81, + 0x0A82, 0x0ABC, 0x0AC1, 0x0AC2, 0x0AC3, 0x0AC4, 0x0AC5, 0x0AC7, 0x0AC8, 0x0ACD, 0x0AE2, 0x0AE3, 0x0AFA, + 0x0AFB, 0x0AFC, 0x0AFD, 0x0AFE, 0x0AFF, 0x0B01, 0x0B3C, 0x0B3F, 0x0B41, 0x0B42, 0x0B43, 0x0B44, 0x0B4D, + 0x0B55, 0x0B56, 0x0B62, 0x0B63, 0x0B82, 0x0BC0, 0x0BCD, 0x0C00, 0x0C04, 0x0C3C, 0x0C3E, 0x0C3F, 0x0C40, + 0x0C46, 0x0C47, 0x0C48, 0x0C4A, 0x0C4B, 0x0C4C, 0x0C4D, 0x0C55, 0x0C56, 0x0C62, 0x0C63, 0x0C81, 0x0CBC, + 0x0CBF, 0x0CC6, 0x0CCC, 0x0CCD, 0x0CE2, 0x0CE3, 0x0D00, 0x0D01, 0x0D3B, 0x0D3C, 0x0D41, 0x0D42, 0x0D43, + 0x0D44, 0x0D4D, 0x0D62, 0x0D63, 0x0D81, 0x0DCA, 0x0DD2, 0x0DD3, 0x0DD4, 0x0DD6, 0x0E31, 0x0E34, 0x0E35, + 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, + 0x0EB1, 0x0EB4, 0x0EB5, 0x0EB6, 0x0EB7, 0x0EB8, 0x0EB9, 0x0EBA, 0x0EBB, 0x0EBC, 0x0EC8, 0x0EC9, 0x0ECA, + 0x0ECB, 0x0ECC, 0x0ECD, 0x0ECE, 0x0F18, 0x0F19, 0x0F35, 0x0F37, 0x0F39, 0x0F71, 0x0F72, 0x0F73, 0x0F74, + 0x0F75, 0x0F76, 0x0F77, 0x0F78, 0x0F79, 0x0F7A, 0x0F7B, 0x0F7C, 0x0F7D, 0x0F7E, 0x0F80, 0x0F81, 0x0F82, + 0x0F83, 0x0F84, 0x0F86, 0x0F87, 0x0F8D, 0x0F8E, 0x0F8F, 0x0F90, 0x0F91, 0x0F92, 0x0F93, 0x0F94, 0x0F95, + 0x0F96, 0x0F97, 0x0F99, 0x0F9A, 0x0F9B, 0x0F9C, 0x0F9D, 0x0F9E, 0x0F9F, 0x0FA0, 0x0FA1, 0x0FA2, 0x0FA3, + 0x0FA4, 0x0FA5, 0x0FA6, 0x0FA7, 0x0FA8, 0x0FA9, 0x0FAA, 0x0FAB, 0x0FAC, 0x0FAD, 0x0FAE, 0x0FAF, 0x0FB0, + 0x0FB1, 0x0FB2, 0x0FB3, 0x0FB4, 0x0FB5, 0x0FB6, 0x0FB7, 0x0FB8, 0x0FB9, 0x0FBA, 0x0FBB, 0x0FBC, 0x0FC6, + 0x102D, 0x102E, 0x102F, 0x1030, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, 0x1039, 0x103A, 0x103D, + 0x103E, 0x1058, 0x1059, 0x105E, 0x105F, 0x1060, 0x1071, 0x1072, 0x1073, 0x1074, 0x1082, 0x1085, 0x1086, + 0x108D, 0x109D, 0x135D, 0x135E, 0x135F, 0x1712, 0x1713, 0x1714, 0x1732, 0x1733, 0x1752, 0x1753, 0x1772, + 0x1773, 0x17B4, 0x17B5, 0x17B7, 0x17B8, 0x17B9, 0x17BA, 0x17BB, 0x17BC, 0x17BD, 0x17C6, 0x17C9, 0x17CA, + 0x17CB, 0x17CC, 0x17CD, 0x17CE, 0x17CF, 0x17D0, 0x17D1, 0x17D2, 0x17D3, 0x17DD, 0x180B, 0x180C, 0x180D, + 0x180F, 0x1885, 0x1886, 0x18A9, 0x1920, 0x1921, 0x1922, 0x1927, 0x1928, 0x1932, 0x1939, 0x193A, 0x193B, + 0x1A17, 0x1A18, 0x1A1B, 0x1A56, 0x1A58, 0x1A59, 0x1A5A, 0x1A5B, 0x1A5C, 0x1A5D, 0x1A5E, 0x1A60, 0x1A62, + 0x1A65, 0x1A66, 0x1A67, 0x1A68, 0x1A69, 0x1A6A, 0x1A6B, 0x1A6C, 0x1A73, 0x1A74, 0x1A75, 0x1A76, 0x1A77, + 0x1A78, 0x1A79, 0x1A7A, 0x1A7B, 0x1A7C, 0x1A7F, 0x1AB0, 0x1AB1, 0x1AB2, 0x1AB3, 0x1AB4, 0x1AB5, 0x1AB6, + 0x1AB7, 0x1AB8, 0x1AB9, 0x1ABA, 0x1ABB, 0x1ABC, 0x1ABD, 0x1ABF, 0x1AC0, 0x1AC1, 0x1AC2, 0x1AC3, 0x1AC4, + 0x1AC5, 0x1AC6, 0x1AC7, 0x1AC8, 0x1AC9, 0x1ACA, 0x1ACB, 0x1ACC, 0x1ACD, 0x1ACE, 0x1B00, 0x1B01, 0x1B02, + 0x1B03, 0x1B34, 0x1B36, 0x1B37, 0x1B38, 0x1B39, 0x1B3A, 0x1B3C, 0x1B42, 0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, + 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73, 0x1B80, 0x1B81, 0x1BA2, 0x1BA3, 0x1BA4, 0x1BA5, 0x1BA8, 0x1BA9, + 0x1BAB, 0x1BAC, 0x1BAD, 0x1BE6, 0x1BE8, 0x1BE9, 0x1BED, 0x1BEF, 0x1BF0, 0x1BF1, 0x1C2C, 0x1C2D, 0x1C2E, + 0x1C2F, 0x1C30, 0x1C31, 0x1C32, 0x1C33, 0x1C36, 0x1C37, 0x1CD0, 0x1CD1, 0x1CD2, 0x1CD4, 0x1CD5, 0x1CD6, + 0x1CD7, 0x1CD8, 0x1CD9, 0x1CDA, 0x1CDB, 0x1CDC, 0x1CDD, 0x1CDE, 0x1CDF, 0x1CE0, 0x1CE2, 0x1CE3, 0x1CE4, + 0x1CE5, 0x1CE6, 0x1CE7, 0x1CE8, 0x1CED, 0x1CF4, 0x1CF8, 0x1CF9, 0x1DC0, 0x1DC1, 0x1DC2, 0x1DC3, 0x1DC4, + 0x1DC5, 0x1DC6, 0x1DC7, 0x1DC8, 0x1DC9, 0x1DCA, 0x1DCB, 0x1DCC, 0x1DCD, 0x1DCE, 0x1DCF, 0x1DD0, 0x1DD1, + 0x1DD2, 0x1DD3, 0x1DD4, 0x1DD5, 0x1DD6, 0x1DD7, 0x1DD8, 0x1DD9, 0x1DDA, 0x1DDB, 0x1DDC, 0x1DDD, 0x1DDE, + 0x1DDF, 0x1DE0, 0x1DE1, 0x1DE2, 0x1DE3, 0x1DE4, 0x1DE5, 0x1DE6, 0x1DE7, 0x1DE8, 0x1DE9, 0x1DEA, 0x1DEB, + 0x1DEC, 0x1DED, 0x1DEE, 0x1DEF, 0x1DF0, 0x1DF1, 0x1DF2, 0x1DF3, 0x1DF4, 0x1DF5, 0x1DF6, 0x1DF7, 0x1DF8, + 0x1DF9, 0x1DFA, 0x1DFB, 0x1DFC, 0x1DFD, 0x1DFE, 0x1DFF, 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, + 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20E1, 0x20E5, 0x20E6, 0x20E7, 0x20E8, 0x20E9, + 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, 0x20F0, 0x2CEF, 0x2CF0, 0x2CF1, 0x2D7F, 0x2DE0, 0x2DE1, + 0x2DE2, 0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6, 0x2DE7, 0x2DE8, 0x2DE9, 0x2DEA, 0x2DEB, 0x2DEC, 0x2DED, 0x2DEE, + 0x2DEF, 0x2DF0, 0x2DF1, 0x2DF2, 0x2DF3, 0x2DF4, 0x2DF5, 0x2DF6, 0x2DF7, 0x2DF8, 0x2DF9, 0x2DFA, 0x2DFB, + 0x2DFC, 0x2DFD, 0x2DFE, 0x2DFF, 0x302A, 0x302B, 0x302C, 0x302D, 0x3099, 0x309A, 0xA66F, 0xA674, 0xA675, + 0xA676, 0xA677, 0xA678, 0xA679, 0xA67A, 0xA67B, 0xA67C, 0xA67D, 0xA69E, 0xA69F, 0xA6F0, 0xA6F1, 0xA802, + 0xA806, 0xA80B, 0xA825, 0xA826, 0xA82C, 0xA8C4, 0xA8C5, 0xA8E0, 0xA8E1, 0xA8E2, 0xA8E3, 0xA8E4, 0xA8E5, + 0xA8E6, 0xA8E7, 0xA8E8, 0xA8E9, 0xA8EA, 0xA8EB, 0xA8EC, 0xA8ED, 0xA8EE, 0xA8EF, 0xA8F0, 0xA8F1, 0xA8FF, + 0xA926, 0xA927, 0xA928, 0xA929, 0xA92A, 0xA92B, 0xA92C, 0xA92D, 0xA947, 0xA948, 0xA949, 0xA94A, 0xA94B, + 0xA94C, 0xA94D, 0xA94E, 0xA94F, 0xA950, 0xA951, 0xA980, 0xA981, 0xA982, 0xA9B3, 0xA9B6, 0xA9B7, 0xA9B8, + 0xA9B9, 0xA9BC, 0xA9BD, 0xA9E5, 0xAA29, 0xAA2A, 0xAA2B, 0xAA2C, 0xAA2D, 0xAA2E, 0xAA31, 0xAA32, 0xAA35, + 0xAA36, 0xAA43, 0xAA4C, 0xAA7C, 0xAAB0, 0xAAB2, 0xAAB3, 0xAAB4, 0xAAB7, 0xAAB8, 0xAABE, 0xAABF, 0xAAC1, + 0xAAEC, 0xAAED, 0xAAF6, 0xABE5, 0xABE8, 0xABED, 0xFB1E, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, + 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFE20, 0xFE21, 0xFE22, + 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F, + 0x101FD, 0x102E0, 0x10376, 0x10377, 0x10378, 0x10379, 0x1037A, 0x10A01, 0x10A02, 0x10A03, 0x10A05, 0x10A06, 0x10A0C, + 0x10A0D, 0x10A0E, 0x10A0F, 0x10A38, 0x10A39, 0x10A3A, 0x10A3F, 0x10AE5, 0x10AE6, 0x10D24, 0x10D25, 0x10D26, 0x10D27, + 0x10D69, 0x10D6A, 0x10D6B, 0x10D6C, 0x10D6D, 0x10EAB, 0x10EAC, 0x10EFC, 0x10EFD, 0x10EFE, 0x10EFF, 0x10F46, 0x10F47, + 0x10F48, 0x10F49, 0x10F4A, 0x10F4B, 0x10F4C, 0x10F4D, 0x10F4E, 0x10F4F, 0x10F50, 0x10F82, 0x10F83, 0x10F84, 0x10F85, + 0x11001, 0x11038, 0x11039, 0x1103A, 0x1103B, 0x1103C, 0x1103D, 0x1103E, 0x1103F, 0x11040, 0x11041, 0x11042, 0x11043, + 0x11044, 0x11045, 0x11046, 0x11070, 0x11073, 0x11074, 0x1107F, 0x11080, 0x11081, 0x110B3, 0x110B4, 0x110B5, 0x110B6, + 0x110B9, 0x110BA, 0x110C2, 0x11100, 0x11101, 0x11102, 0x11127, 0x11128, 0x11129, 0x1112A, 0x1112B, 0x1112D, 0x1112E, + 0x1112F, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11173, 0x11180, 0x11181, 0x111B6, 0x111B7, 0x111B8, 0x111B9, + 0x111BA, 0x111BB, 0x111BC, 0x111BD, 0x111BE, 0x111C9, 0x111CA, 0x111CB, 0x111CC, 0x111CF, 0x1122F, 0x11230, 0x11231, + 0x11234, 0x11236, 0x11237, 0x1123E, 0x11241, 0x112DF, 0x112E3, 0x112E4, 0x112E5, 0x112E6, 0x112E7, 0x112E8, 0x112E9, + 0x112EA, 0x11300, 0x11301, 0x1133B, 0x1133C, 0x11340, 0x11366, 0x11367, 0x11368, 0x11369, 0x1136A, 0x1136B, 0x1136C, + 0x11370, 0x11371, 0x11372, 0x11373, 0x11374, 0x113BB, 0x113BC, 0x113BD, 0x113BE, 0x113BF, 0x113C0, 0x113CE, 0x113D0, + 0x113D2, 0x113E1, 0x113E2, 0x11438, 0x11439, 0x1143A, 0x1143B, 0x1143C, 0x1143D, 0x1143E, 0x1143F, 0x11442, 0x11443, + 0x11444, 0x11446, 0x1145E, 0x114B3, 0x114B4, 0x114B5, 0x114B6, 0x114B7, 0x114B8, 0x114BA, 0x114BF, 0x114C0, 0x114C2, + 0x114C3, 0x115B2, 0x115B3, 0x115B4, 0x115B5, 0x115BC, 0x115BD, 0x115BF, 0x115C0, 0x115DC, 0x115DD, 0x11633, 0x11634, + 0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163A, 0x1163D, 0x1163F, 0x11640, 0x116AB, 0x116AD, 0x116B0, 0x116B1, + 0x116B2, 0x116B3, 0x116B4, 0x116B5, 0x116B7, 0x1171D, 0x1171F, 0x11722, 0x11723, 0x11724, 0x11725, 0x11727, 0x11728, + 0x11729, 0x1172A, 0x1172B, 0x1182F, 0x11830, 0x11831, 0x11832, 0x11833, 0x11834, 0x11835, 0x11836, 0x11837, 0x11839, + 0x1183A, 0x1193B, 0x1193C, 0x1193E, 0x11943, 0x119D4, 0x119D5, 0x119D6, 0x119D7, 0x119DA, 0x119DB, 0x119E0, 0x11A01, + 0x11A02, 0x11A03, 0x11A04, 0x11A05, 0x11A06, 0x11A07, 0x11A08, 0x11A09, 0x11A0A, 0x11A33, 0x11A34, 0x11A35, 0x11A36, + 0x11A37, 0x11A38, 0x11A3B, 0x11A3C, 0x11A3D, 0x11A3E, 0x11A47, 0x11A51, 0x11A52, 0x11A53, 0x11A54, 0x11A55, 0x11A56, + 0x11A59, 0x11A5A, 0x11A5B, 0x11A8A, 0x11A8B, 0x11A8C, 0x11A8D, 0x11A8E, 0x11A8F, 0x11A90, 0x11A91, 0x11A92, 0x11A93, + 0x11A94, 0x11A95, 0x11A96, 0x11A98, 0x11A99, 0x11C30, 0x11C31, 0x11C32, 0x11C33, 0x11C34, 0x11C35, 0x11C36, 0x11C38, + 0x11C39, 0x11C3A, 0x11C3B, 0x11C3C, 0x11C3D, 0x11C3F, 0x11C92, 0x11C93, 0x11C94, 0x11C95, 0x11C96, 0x11C97, 0x11C98, + 0x11C99, 0x11C9A, 0x11C9B, 0x11C9C, 0x11C9D, 0x11C9E, 0x11C9F, 0x11CA0, 0x11CA1, 0x11CA2, 0x11CA3, 0x11CA4, 0x11CA5, + 0x11CA6, 0x11CA7, 0x11CAA, 0x11CAB, 0x11CAC, 0x11CAD, 0x11CAE, 0x11CAF, 0x11CB0, 0x11CB2, 0x11CB3, 0x11CB5, 0x11CB6, + 0x11D31, 0x11D32, 0x11D33, 0x11D34, 0x11D35, 0x11D36, 0x11D3A, 0x11D3C, 0x11D3D, 0x11D3F, 0x11D40, 0x11D41, 0x11D42, + 0x11D43, 0x11D44, 0x11D45, 0x11D47, 0x11D90, 0x11D91, 0x11D95, 0x11D97, 0x11EF3, 0x11EF4, 0x11F00, 0x11F01, 0x11F36, + 0x11F37, 0x11F38, 0x11F39, 0x11F3A, 0x11F40, 0x11F42, 0x11F5A, 0x13440, 0x13447, 0x13448, 0x13449, 0x1344A, 0x1344B, + 0x1344C, 0x1344D, 0x1344E, 0x1344F, 0x13450, 0x13451, 0x13452, 0x13453, 0x13454, 0x13455, 0x1611E, 0x1611F, 0x16120, + 0x16121, 0x16122, 0x16123, 0x16124, 0x16125, 0x16126, 0x16127, 0x16128, 0x16129, 0x1612D, 0x1612E, 0x1612F, 0x16AF0, + 0x16AF1, 0x16AF2, 0x16AF3, 0x16AF4, 0x16B30, 0x16B31, 0x16B32, 0x16B33, 0x16B34, 0x16B35, 0x16B36, 0x16F4F, 0x16F8F, + 0x16F90, 0x16F91, 0x16F92, 0x16FE4, 0x1BC9D, 0x1BC9E, 0x1CF00, 0x1CF01, 0x1CF02, 0x1CF03, 0x1CF04, 0x1CF05, 0x1CF06, + 0x1CF07, 0x1CF08, 0x1CF09, 0x1CF0A, 0x1CF0B, 0x1CF0C, 0x1CF0D, 0x1CF0E, 0x1CF0F, 0x1CF10, 0x1CF11, 0x1CF12, 0x1CF13, + 0x1CF14, 0x1CF15, 0x1CF16, 0x1CF17, 0x1CF18, 0x1CF19, 0x1CF1A, 0x1CF1B, 0x1CF1C, 0x1CF1D, 0x1CF1E, 0x1CF1F, 0x1CF20, + 0x1CF21, 0x1CF22, 0x1CF23, 0x1CF24, 0x1CF25, 0x1CF26, 0x1CF27, 0x1CF28, 0x1CF29, 0x1CF2A, 0x1CF2B, 0x1CF2C, 0x1CF2D, + 0x1CF30, 0x1CF31, 0x1CF32, 0x1CF33, 0x1CF34, 0x1CF35, 0x1CF36, 0x1CF37, 0x1CF38, 0x1CF39, 0x1CF3A, 0x1CF3B, 0x1CF3C, + 0x1CF3D, 0x1CF3E, 0x1CF3F, 0x1CF40, 0x1CF41, 0x1CF42, 0x1CF43, 0x1CF44, 0x1CF45, 0x1CF46, 0x1D167, 0x1D168, 0x1D169, + 0x1D17B, 0x1D17C, 0x1D17D, 0x1D17E, 0x1D17F, 0x1D180, 0x1D181, 0x1D182, 0x1D185, 0x1D186, 0x1D187, 0x1D188, 0x1D189, + 0x1D18A, 0x1D18B, 0x1D1AA, 0x1D1AB, 0x1D1AC, 0x1D1AD, 0x1D242, 0x1D243, 0x1D244, 0x1DA00, 0x1DA01, 0x1DA02, 0x1DA03, + 0x1DA04, 0x1DA05, 0x1DA06, 0x1DA07, 0x1DA08, 0x1DA09, 0x1DA0A, 0x1DA0B, 0x1DA0C, 0x1DA0D, 0x1DA0E, 0x1DA0F, 0x1DA10, + 0x1DA11, 0x1DA12, 0x1DA13, 0x1DA14, 0x1DA15, 0x1DA16, 0x1DA17, 0x1DA18, 0x1DA19, 0x1DA1A, 0x1DA1B, 0x1DA1C, 0x1DA1D, + 0x1DA1E, 0x1DA1F, 0x1DA20, 0x1DA21, 0x1DA22, 0x1DA23, 0x1DA24, 0x1DA25, 0x1DA26, 0x1DA27, 0x1DA28, 0x1DA29, 0x1DA2A, + 0x1DA2B, 0x1DA2C, 0x1DA2D, 0x1DA2E, 0x1DA2F, 0x1DA30, 0x1DA31, 0x1DA32, 0x1DA33, 0x1DA34, 0x1DA35, 0x1DA36, 0x1DA3B, + 0x1DA3C, 0x1DA3D, 0x1DA3E, 0x1DA3F, 0x1DA40, 0x1DA41, 0x1DA42, 0x1DA43, 0x1DA44, 0x1DA45, 0x1DA46, 0x1DA47, 0x1DA48, + 0x1DA49, 0x1DA4A, 0x1DA4B, 0x1DA4C, 0x1DA4D, 0x1DA4E, 0x1DA4F, 0x1DA50, 0x1DA51, 0x1DA52, 0x1DA53, 0x1DA54, 0x1DA55, + 0x1DA56, 0x1DA57, 0x1DA58, 0x1DA59, 0x1DA5A, 0x1DA5B, 0x1DA5C, 0x1DA5D, 0x1DA5E, 0x1DA5F, 0x1DA60, 0x1DA61, 0x1DA62, + 0x1DA63, 0x1DA64, 0x1DA65, 0x1DA66, 0x1DA67, 0x1DA68, 0x1DA69, 0x1DA6A, 0x1DA6B, 0x1DA6C, 0x1DA75, 0x1DA84, 0x1DA9B, + 0x1DA9C, 0x1DA9D, 0x1DA9E, 0x1DA9F, 0x1DAA1, 0x1DAA2, 0x1DAA3, 0x1DAA4, 0x1DAA5, 0x1DAA6, 0x1DAA7, 0x1DAA8, 0x1DAA9, + 0x1DAAA, 0x1DAAB, 0x1DAAC, 0x1DAAD, 0x1DAAE, 0x1DAAF, 0x1E000, 0x1E001, 0x1E002, 0x1E003, 0x1E004, 0x1E005, 0x1E006, + 0x1E008, 0x1E009, 0x1E00A, 0x1E00B, 0x1E00C, 0x1E00D, 0x1E00E, 0x1E00F, 0x1E010, 0x1E011, 0x1E012, 0x1E013, 0x1E014, + 0x1E015, 0x1E016, 0x1E017, 0x1E018, 0x1E01B, 0x1E01C, 0x1E01D, 0x1E01E, 0x1E01F, 0x1E020, 0x1E021, 0x1E023, 0x1E024, + 0x1E026, 0x1E027, 0x1E028, 0x1E029, 0x1E02A, 0x1E08F, 0x1E130, 0x1E131, 0x1E132, 0x1E133, 0x1E134, 0x1E135, 0x1E136, + 0x1E2AE, 0x1E2EC, 0x1E2ED, 0x1E2EE, 0x1E2EF, 0x1E4EC, 0x1E4ED, 0x1E4EE, 0x1E4EF, 0x1E5EE, 0x1E5EF, 0x1E8D0, 0x1E8D1, + 0x1E8D2, 0x1E8D3, 0x1E8D4, 0x1E8D5, 0x1E8D6, 0x1E944, 0x1E945, 0x1E946, 0x1E947, 0x1E948, 0x1E949, 0x1E94A, 0xE0100, + 0xE0101, 0xE0102, 0xE0103, 0xE0104, 0xE0105, 0xE0106, 0xE0107, 0xE0108, 0xE0109, 0xE010A, 0xE010B, 0xE010C, 0xE010D, + 0xE010E, 0xE010F, 0xE0110, 0xE0111, 0xE0112, 0xE0113, 0xE0114, 0xE0115, 0xE0116, 0xE0117, 0xE0118, 0xE0119, 0xE011A, + 0xE011B, 0xE011C, 0xE011D, 0xE011E, 0xE011F, 0xE0120, 0xE0121, 0xE0122, 0xE0123, 0xE0124, 0xE0125, 0xE0126, 0xE0127, + 0xE0128, 0xE0129, 0xE012A, 0xE012B, 0xE012C, 0xE012D, 0xE012E, 0xE012F, 0xE0130, 0xE0131, 0xE0132, 0xE0133, 0xE0134, + 0xE0135, 0xE0136, 0xE0137, 0xE0138, 0xE0139, 0xE013A, 0xE013B, 0xE013C, 0xE013D, 0xE013E, 0xE013F, 0xE0140, 0xE0141, + 0xE0142, 0xE0143, 0xE0144, 0xE0145, 0xE0146, 0xE0147, 0xE0148, 0xE0149, 0xE014A, 0xE014B, 0xE014C, 0xE014D, 0xE014E, + 0xE014F, 0xE0150, 0xE0151, 0xE0152, 0xE0153, 0xE0154, 0xE0155, 0xE0156, 0xE0157, 0xE0158, 0xE0159, 0xE015A, 0xE015B, + 0xE015C, 0xE015D, 0xE015E, 0xE015F, 0xE0160, 0xE0161, 0xE0162, 0xE0163, 0xE0164, 0xE0165, 0xE0166, 0xE0167, 0xE0168, + 0xE0169, 0xE016A, 0xE016B, 0xE016C, 0xE016D, 0xE016E, 0xE016F, 0xE0170, 0xE0171, 0xE0172, 0xE0173, 0xE0174, 0xE0175, + 0xE0176, 0xE0177, 0xE0178, 0xE0179, 0xE017A, 0xE017B, 0xE017C, 0xE017D, 0xE017E, 0xE017F, 0xE0180, 0xE0181, 0xE0182, + 0xE0183, 0xE0184, 0xE0185, 0xE0186, 0xE0187, 0xE0188, 0xE0189, 0xE018A, 0xE018B, 0xE018C, 0xE018D, 0xE018E, 0xE018F, + 0xE0190, 0xE0191, 0xE0192, 0xE0193, 0xE0194, 0xE0195, 0xE0196, 0xE0197, 0xE0198, 0xE0199, 0xE019A, 0xE019B, 0xE019C, + 0xE019D, 0xE019E, 0xE019F, 0xE01A0, 0xE01A1, 0xE01A2, 0xE01A3, 0xE01A4, 0xE01A5, 0xE01A6, 0xE01A7, 0xE01A8, 0xE01A9, + 0xE01AA, 0xE01AB, 0xE01AC, 0xE01AD, 0xE01AE, 0xE01AF, 0xE01B0, 0xE01B1, 0xE01B2, 0xE01B3, 0xE01B4, 0xE01B5, 0xE01B6, + 0xE01B7, 0xE01B8, 0xE01B9, 0xE01BA, 0xE01BB, 0xE01BC, 0xE01BD, 0xE01BE, 0xE01BF, 0xE01C0, 0xE01C1, 0xE01C2, 0xE01C3, + 0xE01C4, 0xE01C5, 0xE01C6, 0xE01C7, 0xE01C8, 0xE01C9, 0xE01CA, 0xE01CB, 0xE01CC, 0xE01CD, 0xE01CE, 0xE01CF, 0xE01D0, + 0xE01D1, 0xE01D2, 0xE01D3, 0xE01D4, 0xE01D5, 0xE01D6, 0xE01D7, 0xE01D8, 0xE01D9, 0xE01DA, 0xE01DB, 0xE01DC, 0xE01DD, + 0xE01DE, 0xE01DF, 0xE01E0, 0xE01E1, 0xE01E2, 0xE01E3, 0xE01E4, 0xE01E5, 0xE01E6, 0xE01E7, 0xE01E8, 0xE01E9, 0xE01EA, + 0xE01EB, 0xE01EC, 0xE01ED, 0xE01EE, 0xE01EF + /* END: COMBINING CHAR TABLE */ +}; + +static const unsigned long combiningCharTableSize = sizeof(combiningCharTable) / sizeof(combiningCharTable[0]); + +static bool isCombiningChar(unsigned long cp) { + for (size_t i = 0; i < combiningCharTableSize; i++) { + auto code = combiningCharTable[i]; + if (code > cp) { + return false; + } + if (code == cp) { + return true; + } + } + return false; +} + +/* Get length of previous grapheme */ +static size_t defaultPrevCharLen(const char * buf, size_t /*buf_len*/, size_t pos, size_t * col_len) { + size_t end = pos; + while (pos > 0) { + size_t len = prevUtf8CodePointLen(buf, pos); + pos -= len; + int cp; + utf8BytesToCodePoint(buf + pos, len, &cp); + if (!isCombiningChar(cp)) { + if (col_len != NULL) { + *col_len = isWideChar(cp) ? 2 : 1; + } + return end - pos; + } + } + /* NOTREACHED */ + return 0; +} + +/* Get length of next grapheme */ +static size_t defaultNextCharLen(const char * buf, size_t buf_len, size_t pos, size_t * col_len) { + size_t beg = pos; + int cp; + size_t len = utf8BytesToCodePoint(buf + pos, buf_len - pos, &cp); + if (isCombiningChar(cp)) { + /* NOTREACHED */ + return 0; + } + if (col_len != NULL) { + *col_len = isWideChar(cp) ? 2 : 1; + } + pos += len; + while (pos < buf_len) { + int cp; + len = utf8BytesToCodePoint(buf + pos, buf_len - pos, &cp); + if (!isCombiningChar(cp)) { + return pos - beg; + } + pos += len; + } + return pos - beg; +} + +/* Read a Unicode from file. */ +static size_t defaultReadCode(int fd, char * buf, size_t buf_len, int * cp) { + if (buf_len < 1) { + return -1; + } + size_t nread = read(fd, &buf[0], 1); + if (nread <= 0) { + return nread; + } + + unsigned char byte = buf[0]; + if ((byte & 0x80) == 0) { + ; + } else if ((byte & 0xE0) == 0xC0) { + if (buf_len < 2) { + return -1; + } + nread = read(fd, &buf[1], 1); + if (nread <= 0) { + return nread; + } + } else if ((byte & 0xF0) == 0xE0) { + if (buf_len < 3) { + return -1; + } + nread = read(fd, &buf[1], 2); + if (nread <= 0) { + return nread; + } + } else if ((byte & 0xF8) == 0xF0) { + if (buf_len < 3) { + return -1; + } + nread = read(fd, &buf[1], 3); + if (nread <= 0) { + return nread; + } + } else { + return -1; + } + + return utf8BytesToCodePoint(buf, buf_len, cp); +} + +/* Set default encoding functions */ +static linenoisePrevCharLen * prevCharLen = defaultPrevCharLen; +static linenoiseNextCharLen * nextCharLen = defaultNextCharLen; +static linenoiseReadCode * readCode = defaultReadCode; + +/* Set used defined encoding functions */ +void linenoiseSetEncodingFunctions(linenoisePrevCharLen * prevCharLenFunc, linenoiseNextCharLen * nextCharLenFunc, + linenoiseReadCode * readCodeFunc) { + prevCharLen = prevCharLenFunc; + nextCharLen = nextCharLenFunc; + readCode = readCodeFunc; +} + /* ======================= Low level terminal handling ====================== */ /* Enable "mask mode". When it is enabled, instead of the input that @@ -408,6 +867,73 @@ static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseComple } } +enum ESC_TYPE { ESC_NULL = 0, ESC_DELETE, ESC_UP, ESC_DOWN, ESC_RIGHT, ESC_LEFT, ESC_HOME, ESC_END }; + +static ESC_TYPE readEscapeSequence(struct linenoiseState * l) { + /* Check if the file input has additional data. */ + struct pollfd pfd; + pfd.fd = l->ifd; + pfd.events = POLLIN; + + auto ret = poll(&pfd, 1, 1); // 1 millisecond timeout + if (ret <= 0) { // -1: error, 0: timeout + return ESC_NULL; + } + + /* Read the next two bytes representing the escape sequence. + * Use two calls to handle slow terminals returning the two + * chars at different times. */ + char seq[3]; + if (read(l->ifd, seq, 1) == -1) { + return ESC_NULL; + } + if (read(l->ifd, seq + 1, 1) == -1) { + return ESC_NULL; + } + + /* ESC [ sequences. */ + if (seq[0] == '[') { + if (seq[1] >= '0' && seq[1] <= '9') { + /* Extended escape, read additional byte. */ + if (read(l->ifd, seq + 2, 1) == -1) { + return ESC_NULL; + } + if (seq[2] == '~') { + switch (seq[1]) { + case '3': + return ESC_DELETE; + } + } + } else { + switch (seq[1]) { + case 'A': + return ESC_UP; + case 'B': + return ESC_DOWN; + case 'C': + return ESC_RIGHT; + case 'D': + return ESC_LEFT; + case 'H': + return ESC_HOME; + case 'F': + return ESC_END; + } + } + } + + /* ESC O sequences. */ + else if (seq[0] == 'O') { + switch (seq[1]) { + case 'H': + return ESC_HOME; + case 'F': + return ESC_END; + } + } + return ESC_NULL; +} + /* This is an helper function for linenoiseEdit*() and is called when the * user types the key in order to complete the string currently in the * input. @@ -418,11 +944,11 @@ static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseComple * If the function returns non-zero, the caller should handle the * returned value as a byte read from the standard input, and process * it as usually: this basically means that the function may return a byte - * read from the termianl but not processed. Otherwise, if zero is returned, + * read from the terminal but not processed. Otherwise, if zero is returned, * the input was consumed by the completeLine() function to navigate the * possible completions, and the caller should read for the next characters * from stdin. */ -static int completeLine(struct linenoiseState *ls, int keypressed) { +static int completeLine(struct linenoiseState * ls, int keypressed, ESC_TYPE esc_type) { linenoiseCompletions lc; int nwritten; char c = keypressed; @@ -432,31 +958,31 @@ static int completeLine(struct linenoiseState *ls, int keypressed) { linenoiseBeep(); ls->in_completion = 0; } else { - switch(c) { - case 9: /* tab */ - if (ls->in_completion == 0) { - ls->in_completion = 1; - ls->completion_idx = 0; - } else { - ls->completion_idx = (ls->completion_idx + 1) % (lc.len + 1); - if (ls->completion_idx == lc.len) linenoiseBeep(); + if (c == TAB) { + if (ls->in_completion == 0) { + ls->in_completion = 1; + ls->completion_idx = 0; + } else { + ls->completion_idx = (ls->completion_idx + 1) % (lc.len + 1); + if (ls->completion_idx == lc.len) { + linenoiseBeep(); } - c = 0; - break; - case 27: /* escape */ - /* Re-show original buffer */ - if (ls->completion_idx < lc.len) refreshLine(ls); - ls->in_completion = 0; - c = 0; - break; - default: - /* Update buffer and return */ - if (ls->completion_idx < lc.len) { - nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[ls->completion_idx]); - ls->len = ls->pos = nwritten; - } - ls->in_completion = 0; - break; + } + c = 0; + } else if (c == ESC && esc_type == ESC_NULL) { + /* Re-show original buffer */ + if (ls->completion_idx < lc.len) { + refreshLine(ls); + } + ls->in_completion = 0; + c = 0; + } else { + /* Update buffer and return */ + if (ls->completion_idx < lc.len) { + nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[ls->completion_idx]); + ls->len = ls->pos = nwritten; + } + ls->in_completion = 0; } /* Show completion or original buffer */ @@ -508,16 +1034,30 @@ void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { lc->cvec[lc->len++] = copy.release(); } +/* Get column length from begining of buffer to current byte position */ +static size_t columnPos(const char * buf, size_t buf_len, size_t pos) { + size_t ret = 0; + size_t off = 0; + while (off < pos) { + size_t col_len; + size_t len = nextCharLen(buf, buf_len, off, &col_len); + off += len; + ret += col_len; + } + return ret; +} + /* Helper of refreshSingleLine() and refreshMultiLine() to show hints * to the right of the prompt. */ -static void refreshShowHints(std::string & ab, struct linenoiseState * l, int plen) { +static void refreshShowHints(std::string & ab, struct linenoiseState * l, int pcollen) { char seq[64]; - if (hintsCallback && plen+l->len < l->cols) { + size_t collen = pcollen + columnPos(l->buf, l->len, l->len); + if (hintsCallback && collen < l->cols) { int color = -1, bold = 0; const char *hint = hintsCallback(l->buf,&color,&bold); if (hint) { int hintlen = strlen(hint); - int hintmaxlen = l->cols-(plen+l->len); + int hintmaxlen = l->cols - collen; if (hintlen > hintmaxlen) hintlen = hintmaxlen; if (bold == 1 && color == -1) color = 37; if (color != -1 || bold != 0) @@ -535,6 +1075,50 @@ static void refreshShowHints(std::string & ab, struct linenoiseState * l, int pl } } +/* Check if text is an ANSI escape sequence */ +static int isAnsiEscape(const char * buf, size_t buf_len, size_t * len) { + if (buf_len > 2 && !memcmp("\033[", buf, 2)) { + size_t off = 2; + while (off < buf_len) { + switch (buf[off++]) { + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'J': + case 'K': + case 'S': + case 'T': + case 'f': + case 'm': + *len = off; + return 1; + } + } + } + return 0; +} + +/* Get column length of prompt text */ +static size_t promptTextColumnLen(const char * prompt, size_t plen) { + char buf[LINENOISE_MAX_LINE]; + size_t buf_len = 0; + size_t off = 0; + while (off < plen) { + size_t len; + if (isAnsiEscape(prompt + off, plen - off, &len)) { + off += len; + continue; + } + buf[buf_len++] = prompt[off++]; + } + return columnPos(buf, buf_len, buf_len); +} + /* Single line low level line refresh. * * Rewrite the currently edited line accordingly to the buffer content, @@ -544,19 +1128,21 @@ static void refreshShowHints(std::string & ab, struct linenoiseState * l, int pl * prompt, just write it, or both. */ static void refreshSingleLine(struct linenoiseState *l, int flags) { char seq[64]; - size_t plen = strlen(l->prompt); + size_t pcollen = promptTextColumnLen(l->prompt, strlen(l->prompt)); int fd = l->ofd; char *buf = l->buf; size_t len = l->len; size_t pos = l->pos; std::string ab; - while((plen+pos) >= l->cols) { - buf++; - len--; - pos--; + + while ((pcollen + columnPos(buf, len, pos)) >= l->cols) { + int chlen = nextCharLen(buf, len, 0, NULL); + buf += chlen; + len -= chlen; + pos -= chlen; } - while (plen+len > l->cols) { - len--; + while (pcollen + columnPos(buf, len, len) > l->cols) { + len -= prevCharLen(buf, len, len, NULL); } /* Cursor to left edge */ @@ -574,7 +1160,7 @@ static void refreshSingleLine(struct linenoiseState *l, int flags) { ab.append(buf, len); } /* Show hits if any. */ - refreshShowHints(ab, l, plen); + refreshShowHints(ab, l, pcollen); } /* Erase to right */ @@ -582,13 +1168,43 @@ static void refreshSingleLine(struct linenoiseState *l, int flags) { ab.append(seq); if (flags & REFRESH_WRITE) { /* Move cursor to original position. */ - snprintf(seq,sizeof(seq),"\r\x1b[%dC", (int)(pos+plen)); + snprintf(seq, sizeof(seq), "\r\x1b[%dC", (int) (columnPos(buf, len, pos) + pcollen)); ab.append(seq); } (void) !write(fd, ab.c_str(), ab.size()); /* Can't recover from write error. */ } +/* Get column length from begining of buffer to current byte position for multiline mode*/ +static size_t columnPosForMultiLine(const char * buf, size_t buf_len, size_t pos, size_t cols, size_t ini_pos) { + size_t ret = 0; + size_t colwid = ini_pos; + + size_t off = 0; + while (off < buf_len) { + size_t col_len; + size_t len = nextCharLen(buf, buf_len, off, &col_len); + + int dif = (int) (colwid + col_len) - (int) cols; + if (dif > 0) { + ret += dif; + colwid = col_len; + } else if (dif == 0) { + colwid = 0; + } else { + colwid += col_len; + } + + if (off >= pos) { + break; + } + off += len; + ret += col_len; + } + + return ret; +} + /* Multi line low level line refresh. * * Rewrite the currently edited line accordingly to the buffer content, @@ -598,11 +1214,13 @@ static void refreshSingleLine(struct linenoiseState *l, int flags) { * prompt, just write it, or both. */ static void refreshMultiLine(struct linenoiseState *l, int flags) { char seq[64]; - int plen = strlen(l->prompt); - int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */ - int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */ + size_t pcollen = promptTextColumnLen(l->prompt, strlen(l->prompt)); + int colpos = columnPosForMultiLine(l->buf, l->len, l->len, l->cols, pcollen); + int colpos2; /* cursor column position. */ + int rows = (pcollen + colpos + l->cols - 1) / l->cols; /* rows used by current buf. */ + int rpos = (pcollen + l->oldcolpos + l->cols) / l->cols; /* cursor relative row. */ int rpos2; /* rpos after refresh. */ - int col; /* colum position, zero-based. */ + int col; /* column position, zero-based. */ int old_rows = l->oldrows; int fd = l->ofd, j; std::string ab; @@ -611,15 +1229,13 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) { /* First step: clear all the lines used before. To do so start by * going to the last row. */ if (flags & REFRESH_CLEAN) { - if (old_rows-rpos > 0) { - lndebug("go down %d", old_rows-rpos); + if (old_rows - rpos > 0) { snprintf(seq,64,"\x1b[%dB", old_rows-rpos); ab.append(seq); } /* Now for every row clear it, go up. */ - for (j = 0; j < old_rows-1; j++) { - lndebug("clear+up"); + for (j = 0; j < old_rows - 1; j++) { snprintf(seq,64,"\r\x1b[0K\x1b[1A"); ab.append(seq); } @@ -627,11 +1243,13 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) { if (flags & REFRESH_ALL) { /* Clean the top line. */ - lndebug("clear"); snprintf(seq,64,"\r\x1b[0K"); ab.append(seq); } + /* Get column length to cursor position */ + colpos2 = columnPosForMultiLine(l->buf, l->len, l->pos, l->cols, pcollen); + if (flags & REFRESH_WRITE) { /* Write the prompt and the current buffer content */ ab.append(l->prompt); @@ -644,15 +1262,11 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) { } /* Show hits if any. */ - refreshShowHints(ab, l, plen); + refreshShowHints(ab, l, pcollen); /* If we are at the very end of the screen with our prompt, we need to * emit a newline and move the prompt to the first column. */ - if (l->pos && - l->pos == l->len && - (l->pos+plen) % l->cols == 0) - { - lndebug(""); + if (l->pos && l->pos == l->len && (colpos2 + pcollen) % l->cols == 0) { ab.append("\n"); snprintf(seq,64,"\r"); ab.append(seq); @@ -661,19 +1275,16 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) { } /* Move cursor to right position. */ - rpos2 = (plen+l->pos+l->cols)/l->cols; /* Current cursor relative row */ - lndebug("rpos2 %d", rpos2); + rpos2 = (pcollen + colpos2 + l->cols) / l->cols; /* Current cursor relative row */ - /* Go up till we reach the expected positon. */ - if (rows-rpos2 > 0) { - lndebug("go-up %d", rows-rpos2); + /* Go up till we reach the expected position. */ + if (rows - rpos2 > 0) { snprintf(seq,64,"\x1b[%dA", rows-rpos2); ab.append(seq); } /* Set column. */ - col = (plen+(int)l->pos) % (int)l->cols; - lndebug("set col %d", 1+col); + col = (pcollen + colpos2) % l->cols; if (col) snprintf(seq,64,"\r\x1b[%dC", col); else @@ -681,8 +1292,8 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) { ab.append(seq); } - lndebug("\n"); - l->oldpos = l->pos; + l->oldcolpos = colpos2; + (void) !write(fd, ab.c_str(), ab.size()); /* Can't recover from write error. */ } @@ -720,26 +1331,36 @@ void linenoiseShow(struct linenoiseState *l) { /* Insert the character 'c' at cursor current position. * * On error writing to the terminal -1 is returned, otherwise 0. */ -static int linenoiseEditInsert(struct linenoiseState * l, char c) { - if (l->len < l->buflen) { +static int linenoiseEditInsert(struct linenoiseState * l, const char * cbuf, int clen) { + if (l->len + clen <= l->buflen) { if (l->len == l->pos) { - l->buf[l->pos] = c; - l->pos++; - l->len++; + memcpy(&l->buf[l->pos], cbuf, clen); + l->pos += clen; + l->len += clen; + ; l->buf[l->len] = '\0'; - if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) { + if ((!mlmode && promptTextColumnLen(l->prompt, l->plen) + columnPos(l->buf, l->len, l->len) < l->cols && + !hintsCallback)) { /* Avoid a full update of the line in the * trivial case. */ - char d = (maskmode==1) ? '*' : c; - if (write(l->ofd,&d,1) == -1) return -1; + if (maskmode == 1) { + static const char d = '*'; + if (write(l->ofd, &d, 1) == -1) { + return -1; + } + } else { + if (write(l->ofd, cbuf, clen) == -1) { + return -1; + } + } } else { refreshLine(l); } } else { - memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos); - l->buf[l->pos] = c; - l->len++; - l->pos++; + memmove(l->buf + l->pos + clen, l->buf + l->pos, l->len - l->pos); + memcpy(&l->buf[l->pos], cbuf, clen); + l->pos += clen; + l->len += clen; l->buf[l->len] = '\0'; refreshLine(l); } @@ -750,7 +1371,7 @@ static int linenoiseEditInsert(struct linenoiseState * l, char c) { /* Move cursor on the left. */ static void linenoiseEditMoveLeft(struct linenoiseState * l) { if (l->pos > 0) { - l->pos--; + l->pos -= prevCharLen(l->buf, l->len, l->pos, NULL); refreshLine(l); } } @@ -758,7 +1379,7 @@ static void linenoiseEditMoveLeft(struct linenoiseState * l) { /* Move cursor on the right. */ static void linenoiseEditMoveRight(struct linenoiseState * l) { if (l->pos != l->len) { - l->pos++; + l->pos += nextCharLen(l->buf, l->len, l->pos, NULL); refreshLine(l); } } @@ -810,8 +1431,9 @@ static void linenoiseEditHistoryNext(struct linenoiseState * l, int dir) { * position. Basically this is what happens with the "Delete" keyboard key. */ static void linenoiseEditDelete(struct linenoiseState * l) { if (l->len > 0 && l->pos < l->len) { - memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1); - l->len--; + int chlen = nextCharLen(l->buf, l->len, l->pos, NULL); + memmove(l->buf + l->pos, l->buf + l->pos + chlen, l->len - l->pos - chlen); + l->len -= chlen; l->buf[l->len] = '\0'; refreshLine(l); } @@ -820,15 +1442,16 @@ static void linenoiseEditDelete(struct linenoiseState * l) { /* Backspace implementation. */ static void linenoiseEditBackspace(struct linenoiseState * l) { if (l->pos > 0 && l->len > 0) { - memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos); - l->pos--; - l->len--; + int chlen = prevCharLen(l->buf, l->len, l->pos, NULL); + memmove(l->buf + l->pos - chlen, l->buf + l->pos, l->len - l->pos); + l->pos -= chlen; + l->len -= chlen; l->buf[l->len] = '\0'; refreshLine(l); } } -/* Delete the previosu word, maintaining the cursor at the start of the +/* Delete the previous word, maintaining the cursor at the start of the * current word. */ static void linenoiseEditDeletePrevWord(struct linenoiseState * l) { size_t old_pos = l->pos; @@ -855,7 +1478,7 @@ static void linenoiseEditDeletePrevWord(struct linenoiseState * l) { * each time there is some data arriving in the standard input. * * The user can also call linenoiseEditHide() and linenoiseEditShow() if it - * is required to show some input arriving asyncronously, without mixing + * is required to show some input arriving asynchronously, without mixing * it with the currently edited line. * * When linenoiseEditFeed() returns non-NULL, the user finished with the @@ -878,7 +1501,7 @@ int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, ch l->buflen = buflen; l->prompt = prompt; l->plen = strlen(prompt); - l->oldpos = l->pos = 0; + l->oldcolpos = l->pos = 0; l->len = 0; /* Enter raw mode. */ @@ -890,7 +1513,7 @@ int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, ch /* Buffer starts empty. */ l->buf[0] = '\0'; - l->buflen--; /* Make sure there is always space for the nulterm */ + l->buflen--; /* Make sure there is always space for the nullterm */ /* If stdin is not a tty, stop here with the initialization. We * will actually just read a line from standard input in blocking @@ -907,6 +1530,159 @@ int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, ch const char* linenoiseEditMore = "If you see this, you are misusing the API: when linenoiseEditFeed() is called, if it returns linenoiseEditMore the user is yet editing the line. See the README file for more information."; +static const char * handleEnterKey(struct linenoiseState * l) { + --history_len; + free(history[history_len]); + if (mlmode) { + linenoiseEditMoveEnd(l); + } + if (hintsCallback) { + /* Force a refresh without hints to leave the previous + * line as the user typed it after a newline. */ + linenoiseHintsCallback * hc = hintsCallback; + hintsCallback = NULL; + refreshLine(l); + hintsCallback = hc; + } + + return strdup(l->buf); +} + +static const char * handleCtrlCKey() { + errno = EAGAIN; + return NULL; +} + +static const char * handleCtrlDKey(struct linenoiseState * l) { + if (l->len > 0) { + linenoiseEditDelete(l); + return linenoiseEditMore; + } + + --history_len; + free(history[history_len]); + errno = ENOENT; + return NULL; +} + +static void handleCtrlTKey(struct linenoiseState * l) { + if (l->pos > 0 && l->pos < l->len) { + auto prev_chlen = prevCharLen(l->buf, l->len, l->pos, NULL); + auto curr_chlen = nextCharLen(l->buf, l->len, l->pos, NULL); + + std::string prev_char(prev_chlen, 0); + memcpy(prev_char.data(), l->buf + l->pos - prev_chlen, prev_chlen); + memmove(l->buf + l->pos - prev_chlen, l->buf + l->pos, curr_chlen); + memmove(l->buf + l->pos - prev_chlen + curr_chlen, prev_char.data(), prev_chlen); + + l->pos = l->pos - prev_chlen + curr_chlen; + if (l->pos + prev_chlen != l->len) { + l->pos += prev_chlen; + } + + refreshLine(l); + } +} + +static void handleEscapeSequence(struct linenoiseState * l, int esc_type) { + switch (esc_type) { + case ESC_NULL: + break; + case ESC_DELETE: + linenoiseEditDelete(l); + break; + case ESC_UP: + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV); + break; + case ESC_DOWN: + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT); + break; + case ESC_RIGHT: + linenoiseEditMoveRight(l); + break; + case ESC_LEFT: + linenoiseEditMoveLeft(l); + break; + case ESC_HOME: + linenoiseEditMoveHome(l); + break; + case ESC_END: + linenoiseEditMoveEnd(l); + break; + } +} + +static void handleCtrlUKey(struct linenoiseState * l) { + l->buf[0] = '\0'; + l->pos = l->len = 0; + refreshLine(l); +} + +static void handleCtrlKKey(struct linenoiseState * l) { + l->buf[l->pos] = '\0'; + l->len = l->pos; + refreshLine(l); +} + +static const char * processInputCharacter(struct linenoiseState * l, int c, char * cbuf, int nread, int esc_type) { + switch (c) { + case ENTER: + return handleEnterKey(l); + case CTRL_C: + return handleCtrlCKey(); + case BACKSPACE: + case CTRL_H: + linenoiseEditBackspace(l); + break; + case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the + line is empty, act as end-of-file. */ + return handleCtrlDKey(l); + case CTRL_T: + handleCtrlTKey(l); + break; + case CTRL_B: + linenoiseEditMoveLeft(l); + break; + case CTRL_F: + linenoiseEditMoveRight(l); + break; + case CTRL_P: + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV); + break; + case CTRL_N: + linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT); + break; + case ESC: + handleEscapeSequence(l, esc_type); + break; + default: + if (linenoiseEditInsert(l, cbuf, nread)) { + return NULL; + } + break; + case CTRL_U: /* Ctrl+u, delete the whole line. */ + handleCtrlUKey(l); + break; + case CTRL_K: /* Ctrl+k, delete from current to end of line. */ + handleCtrlKKey(l); + break; + case CTRL_A: /* Ctrl+a, go to the start of the line */ + linenoiseEditMoveHome(l); + break; + case CTRL_E: /* ctrl+e, go to the end of the line */ + linenoiseEditMoveEnd(l); + break; + case CTRL_L: /* ctrl+l, clear screen */ + linenoiseClearScreen(); + refreshLine(l); + break; + case CTRL_W: /* ctrl+w, delete previous word */ + linenoiseEditDeletePrevWord(l); + break; + } + return linenoiseEditMore; +} + /* This function is part of the multiplexed API of linenoise, see the top * comment on linenoiseEditStart() for more information. Call this function * each time there is some data to read from the standard input file @@ -925,163 +1701,33 @@ const char* linenoiseEditMore = "If you see this, you are misusing the API: when * * Some other errno: I/O error. */ -const char *linenoiseEditFeed(struct linenoiseState *l) { - /* Not a TTY, pass control to line reading without character - * count limits. */ +const char * linenoiseEditFeed(struct linenoiseState * l) { + /* Not a TTY, pass control to line reading without character count + * limits. */ if (!isatty(l->ifd)) return linenoiseNoTTY(); - char c; + int c; int nread; - char seq[3]; + char cbuf[32]; - nread = read(l->ifd,&c,1); + nread = readCode(l->ifd, cbuf, sizeof(cbuf), &c); if (nread <= 0) return NULL; + auto esc_type = ESC_NULL; + if (c == ESC) { + esc_type = readEscapeSequence(l); + } + /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the * character that should be handled next. */ if ((l->in_completion || c == 9) && completionCallback != NULL) { - c = completeLine(l,c); + c = completeLine(l, c, esc_type); /* Read next character when 0 */ if (c == 0) return linenoiseEditMore; } - switch(c) { - case ENTER: /* enter */ - history_len--; - free(history[history_len]); - if (mlmode) linenoiseEditMoveEnd(l); - if (hintsCallback) { - /* Force a refresh without hints to leave the previous - * line as the user typed it after a newline. */ - linenoiseHintsCallback *hc = hintsCallback; - hintsCallback = NULL; - refreshLine(l); - hintsCallback = hc; - } - return strdup(l->buf); - case CTRL_C: /* ctrl-c */ - errno = EAGAIN; - return NULL; - case BACKSPACE: /* backspace */ - case 8: /* ctrl-h */ - linenoiseEditBackspace(l); - break; - case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the - line is empty, act as end-of-file. */ - if (l->len > 0) { - linenoiseEditDelete(l); - } else { - history_len--; - free(history[history_len]); - errno = ENOENT; - return NULL; - } - break; - case CTRL_T: /* ctrl-t, swaps current character with previous. */ - if (l->pos > 0 && l->pos < l->len) { - int aux = l->buf[l->pos-1]; - l->buf[l->pos-1] = l->buf[l->pos]; - l->buf[l->pos] = aux; - if (l->pos != l->len-1) l->pos++; - refreshLine(l); - } - break; - case CTRL_B: /* ctrl-b */ - linenoiseEditMoveLeft(l); - break; - case CTRL_F: /* ctrl-f */ - linenoiseEditMoveRight(l); - break; - case CTRL_P: /* ctrl-p */ - linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV); - break; - case CTRL_N: /* ctrl-n */ - linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT); - break; - case ESC: /* escape sequence */ - /* Read the next two bytes representing the escape sequence. - * Use two calls to handle slow terminals returning the two - * chars at different times. */ - if (read(l->ifd,seq,1) == -1) break; - if (read(l->ifd,seq+1,1) == -1) break; - - /* ESC [ sequences. */ - if (seq[0] == '[') { - if (seq[1] >= '0' && seq[1] <= '9') { - /* Extended escape, read additional byte. */ - if (read(l->ifd,seq+2,1) == -1) break; - if (seq[2] == '~') { - switch(seq[1]) { - case '3': /* Delete key. */ - linenoiseEditDelete(l); - break; - } - } - } else { - switch(seq[1]) { - case 'A': /* Up */ - linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV); - break; - case 'B': /* Down */ - linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT); - break; - case 'C': /* Right */ - linenoiseEditMoveRight(l); - break; - case 'D': /* Left */ - linenoiseEditMoveLeft(l); - break; - case 'H': /* Home */ - linenoiseEditMoveHome(l); - break; - case 'F': /* End*/ - linenoiseEditMoveEnd(l); - break; - } - } - } - - /* ESC O sequences. */ - else if (seq[0] == 'O') { - switch(seq[1]) { - case 'H': /* Home */ - linenoiseEditMoveHome(l); - break; - case 'F': /* End*/ - linenoiseEditMoveEnd(l); - break; - } - } - break; - default: - if (linenoiseEditInsert(l,c)) return NULL; - break; - case CTRL_U: /* Ctrl+u, delete the whole line. */ - l->buf[0] = '\0'; - l->pos = l->len = 0; - refreshLine(l); - break; - case CTRL_K: /* Ctrl+k, delete from current to end of line. */ - l->buf[l->pos] = '\0'; - l->len = l->pos; - refreshLine(l); - break; - case CTRL_A: /* Ctrl+a, go to the start of the line */ - linenoiseEditMoveHome(l); - break; - case CTRL_E: /* ctrl+e, go to the end of the line */ - linenoiseEditMoveEnd(l); - break; - case CTRL_L: /* ctrl+l, clear screen */ - linenoiseClearScreen(); - refreshLine(l); - break; - case CTRL_W: /* ctrl+w, delete previous word */ - linenoiseEditDeletePrevWord(l); - break; - } - return linenoiseEditMore; + return processInputCharacter(l, c, cbuf, nread, esc_type); } /* This is part of the multiplexed linenoise API. See linenoiseEditStart() @@ -1095,7 +1741,7 @@ void linenoiseEditStop(struct linenoiseState *l) { } /* This just implements a blocking loop for the multiplexed API. - * In many applications that are not event-drivern, we can just call + * In many applications that are not event-driven, we can just call * the blocking linenoise API, wait for the user to complete the editing * and return the buffer. */ static const char *linenoiseBlockingEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) @@ -1135,8 +1781,7 @@ void linenoisePrintKeyCodes(void) { quit[sizeof(quit)-1] = c; /* Insert current char on the right. */ if (memcmp(quit,"quit",sizeof(quit)) == 0) break; - printf("'%c' %02x (%d) (type quit to exit)\n", - isprint(c) ? c : '?', (int)c, (int)c); + printf("'%c' %02x (%d) (type quit to exit)\n", isprint((int) c) ? c : '?', (int) c, (int) c); printf("\r"); /* Go left edge manually, we are in raw mode. */ fflush(stdout); } diff --git a/examples/run/linenoise.cpp/linenoise.h b/examples/run/linenoise.cpp/linenoise.h index a14ec6c74..9823ca36d 100644 --- a/examples/run/linenoise.cpp/linenoise.h +++ b/examples/run/linenoise.cpp/linenoise.h @@ -47,27 +47,27 @@ extern "C" { #include /* For size_t. */ #include -extern const char *linenoiseEditMore; +extern const char * linenoiseEditMore; /* The linenoiseState structure represents the state during line editing. * We pass this state to functions implementing specific editing * functionalities. */ struct linenoiseState { - int in_completion; /* The user pressed TAB and we are now in completion + int in_completion; /* The user pressed TAB and we are now in completion * mode, so input is handled by completeLine(). */ - size_t completion_idx; /* Index of next completion to propose. */ - int ifd; /* Terminal stdin file descriptor. */ - int ofd; /* Terminal stdout file descriptor. */ - char *buf; /* Edited line buffer. */ - size_t buflen; /* Edited line buffer size. */ - const char *prompt; /* Prompt to display. */ - size_t plen; /* Prompt length. */ - size_t pos; /* Current cursor position. */ - size_t oldpos; /* Previous refresh cursor position. */ - size_t len; /* Current edited line length. */ - size_t cols; /* Number of columns in terminal. */ - size_t oldrows; /* Rows used by last refrehsed line (multiline mode) */ - int history_index; /* The history index we are currently editing. */ + size_t completion_idx; /* Index of next completion to propose. */ + int ifd; /* Terminal stdin file descriptor. */ + int ofd; /* Terminal stdout file descriptor. */ + char * buf; /* Edited line buffer. */ + size_t buflen; /* Edited line buffer size. */ + const char * prompt; /* Prompt to display. */ + size_t plen; /* Prompt length. */ + size_t pos; /* Current cursor position. */ + size_t oldcolpos; /* Previous refresh cursor column position. */ + size_t len; /* Current edited line length. */ + size_t cols; /* Number of columns in terminal. */ + size_t oldrows; /* Rows used by last refreshed line (multiline mode) */ + int history_index; /* The history index we are currently editing. */ }; struct linenoiseCompletions { @@ -89,19 +89,20 @@ struct linenoiseCompletions { }; /* Non blocking API. */ -int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt); -const char *linenoiseEditFeed(struct linenoiseState *l); -void linenoiseEditStop(struct linenoiseState *l); -void linenoiseHide(struct linenoiseState *l); -void linenoiseShow(struct linenoiseState *l); +int linenoiseEditStart(struct linenoiseState * l, int stdin_fd, int stdout_fd, char * buf, size_t buflen, + const char * prompt); +const char * linenoiseEditFeed(struct linenoiseState * l); +void linenoiseEditStop(struct linenoiseState * l); +void linenoiseHide(struct linenoiseState * l); +void linenoiseShow(struct linenoiseState * l); /* Blocking API. */ -const char *linenoise(const char *prompt); -void linenoiseFree(void *ptr); +const char * linenoise(const char * prompt); +void linenoiseFree(void * ptr); /* Completion API. */ typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); -typedef const char*(linenoiseHintsCallback)(const char *, int *color, int *bold); +typedef const char *(linenoiseHintsCallback) (const char *, int * color, int * bold); typedef void(linenoiseFreeHintsCallback)(const char *); void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); void linenoiseSetHintsCallback(linenoiseHintsCallback *); @@ -109,10 +110,10 @@ void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); void linenoiseAddCompletion(linenoiseCompletions *, const char *); /* History API. */ -int linenoiseHistoryAdd(const char *line); +int linenoiseHistoryAdd(const char * line); int linenoiseHistorySetMaxLen(int len); -int linenoiseHistorySave(const char *filename); -int linenoiseHistoryLoad(const char *filename); +int linenoiseHistorySave(const char * filename); +int linenoiseHistoryLoad(const char * filename); /* Other utilities. */ void linenoiseClearScreen(void); @@ -121,6 +122,14 @@ void linenoisePrintKeyCodes(void); void linenoiseMaskModeEnable(void); void linenoiseMaskModeDisable(void); +/* Encoding functions. */ +typedef size_t(linenoisePrevCharLen)(const char * buf, size_t buf_len, size_t pos, size_t * col_len); +typedef size_t(linenoiseNextCharLen)(const char * buf, size_t buf_len, size_t pos, size_t * col_len); +typedef size_t(linenoiseReadCode)(int fd, char * buf, size_t buf_len, int * c); + +void linenoiseSetEncodingFunctions(linenoisePrevCharLen * prevCharLenFunc, linenoiseNextCharLen * nextCharLenFunc, + linenoiseReadCode * readCodeFunc); + #ifdef __cplusplus } #endif From 9660ffef582ca275092b621c87085a6eea136a90 Mon Sep 17 00:00:00 2001 From: ag2s20150909 <19373730+ag2s20150909@users.noreply.github.com> Date: Mon, 3 Mar 2025 20:54:08 +0800 Subject: [PATCH 09/87] ggml : fix kleidiai build (#12159) The libggml API has changed, but this has not been updated. --- ggml/src/ggml-cpu/kleidiai/kleidiai.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp b/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp index 66685fd16..4dff5c67e 100644 --- a/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp +++ b/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp @@ -190,10 +190,11 @@ static ggml::cpu::tensor_traits * get_tensor_traits(ggml_backend_buffer_t, struc } } // namespace ggml::cpu::kleidiai -static void ggml_backend_cpu_kleidiai_buffer_init_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor) { +GGML_API enum ggml_status ggml_backend_cpu_kleidiai_buffer_init_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor) { tensor->extra = (void *) ggml::cpu::kleidiai::get_tensor_traits(buffer, tensor); GGML_UNUSED(buffer); + return GGML_STATUS_SUCCESS; } static void ggml_backend_cpu_kleidiai_buffer_set_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, From d5c63cd7f932663a20a860ef11a238e627abac53 Mon Sep 17 00:00:00 2001 From: Diego Devesa Date: Mon, 3 Mar 2025 14:00:46 +0100 Subject: [PATCH 10/87] test-backend-ops : add option -p to filter by op params (#12155) --- tests/test-backend-ops.cpp | 49 ++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index 1dc2cdda3..b544dee45 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -23,16 +23,17 @@ #include #include #include -#include -#include #include +#include +#include +#include +#include +#include #include #include -#include -#include +#include #include #include -#include #include static void init_tensor_uniform(ggml_tensor * tensor, float min = -1.0f, float max = 1.0f) { @@ -4382,9 +4383,27 @@ static std::vector> make_test_cases_perf() { return test_cases; } -static bool test_backend(ggml_backend_t backend, test_mode mode, const char * op_name) { +static bool test_backend(ggml_backend_t backend, test_mode mode, const char * op_name, const char * params_filter) { + auto filter_test_cases = [](std::vector> & test_cases, const char * params_filter) { + if (params_filter == nullptr) { + return; + } + + std::regex params_filter_regex(params_filter); + + for (auto it = test_cases.begin(); it != test_cases.end();) { + if (!std::regex_search((*it)->vars(), params_filter_regex)) { + it = test_cases.erase(it); + continue; + } + + it++; + } + }; + if (mode == MODE_TEST) { auto test_cases = make_test_cases_eval(); + filter_test_cases(test_cases, params_filter); ggml_backend_t backend_cpu = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, NULL); if (backend_cpu == NULL) { printf(" Failed to initialize CPU backend\n"); @@ -4406,6 +4425,7 @@ static bool test_backend(ggml_backend_t backend, test_mode mode, const char * op if (mode == MODE_GRAD) { auto test_cases = make_test_cases_eval(); + filter_test_cases(test_cases, params_filter); size_t n_ok = 0; for (auto & test : test_cases) { if (test->eval_grad(backend, op_name)) { @@ -4419,6 +4439,7 @@ static bool test_backend(ggml_backend_t backend, test_mode mode, const char * op if (mode == MODE_PERF) { auto test_cases = make_test_cases_perf(); + filter_test_cases(test_cases, params_filter); for (auto & test : test_cases) { test->eval_perf(backend, op_name); } @@ -4429,7 +4450,7 @@ static bool test_backend(ggml_backend_t backend, test_mode mode, const char * op } static void usage(char ** argv) { - printf("Usage: %s [mode] [-o op] [-b backend]\n", argv[0]); + printf("Usage: %s [mode] [-o ] [-b ] [-p ]\n", argv[0]); printf(" valid modes:\n"); printf(" - test (default, compare with CPU backend for correctness)\n"); printf(" - grad (compare gradients from backpropagation with method of finite differences)\n"); @@ -4439,8 +4460,9 @@ static void usage(char ** argv) { int main(int argc, char ** argv) { test_mode mode = MODE_TEST; - const char * op_name_filter = NULL; - const char * backend_filter = NULL; + const char * op_name_filter = nullptr; + const char * backend_filter = nullptr; + const char * params_filter = nullptr; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "test") == 0) { @@ -4463,6 +4485,13 @@ int main(int argc, char ** argv) { usage(argv); return 1; } + } else if (strcmp(argv[i], "-p") == 0) { + if (i + 1 < argc) { + params_filter = argv[++i]; + } else { + usage(argv); + return 1; + } } else { usage(argv); return 1; @@ -4509,7 +4538,7 @@ int main(int argc, char ** argv) { printf(" Device memory: %zu MB (%zu MB free)\n", total / 1024 / 1024, free / 1024 / 1024); printf("\n"); - bool ok = test_backend(backend, mode, op_name_filter); + bool ok = test_backend(backend, mode, op_name_filter, params_filter); printf(" Backend %s: ", ggml_backend_name(backend)); if (ok) { From c43af9276b119dae7436b7878d59671d0f6b1a97 Mon Sep 17 00:00:00 2001 From: dm4 Date: Mon, 3 Mar 2025 21:09:29 +0800 Subject: [PATCH 11/87] tts: add speaker file support (#12048) * tts: add speaker file support Signed-off-by: dm4 * tts: handle outetts-0.3 * tts : add new line in error message --------- Signed-off-by: dm4 Co-authored-by: Georgi Gerganov --- common/arg.cpp | 7 + common/common.h | 2 + examples/tts/tts.cpp | 389 +++++++++++++++++++++++++++---------------- 3 files changed, 258 insertions(+), 140 deletions(-) diff --git a/common/arg.cpp b/common/arg.cpp index 5924c68c7..8773caaef 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -2452,6 +2452,13 @@ common_params_context common_params_parser_init(common_params & params, llama_ex params.vocoder.use_guide_tokens = true; } ).set_examples({LLAMA_EXAMPLE_TTS, LLAMA_EXAMPLE_SERVER})); + add_opt(common_arg( + {"--tts-speaker-file"}, "FNAME", + "speaker file path for audio generation", + [](common_params & params, const std::string & value) { + params.vocoder.speaker_file = value; + } + ).set_examples({LLAMA_EXAMPLE_TTS})); // model-specific add_opt(common_arg( diff --git a/common/common.h b/common/common.h index 5973677e8..615d179de 100644 --- a/common/common.h +++ b/common/common.h @@ -200,6 +200,8 @@ struct common_params_vocoder { std::string model = ""; // model path // NOLINT std::string model_url = ""; // model url to download // NOLINT + std::string speaker_file = ""; // speaker file path // NOLINT + bool use_guide_tokens = false; // enable guide tokens to improve TTS accuracy // NOLINT }; diff --git a/examples/tts/tts.cpp b/examples/tts/tts.cpp index f78f76303..8108bac8c 100644 --- a/examples/tts/tts.cpp +++ b/examples/tts/tts.cpp @@ -3,6 +3,7 @@ #include "sampling.h" #include "log.h" #include "llama.h" +#include "json.hpp" #define _USE_MATH_DEFINES // For M_PI on MSVC @@ -16,6 +17,13 @@ #include #include +using json = nlohmann::ordered_json; + +enum outetts_version { + OUTETTS_V0_2, + OUTETTS_V0_3, +}; + // // Terminal utils // @@ -371,7 +379,7 @@ static std::string replace_numbers_with_words(const std::string & input_text) { } // Based on: https://github.com/edwko/OuteTTS/blob/a613e79c489d8256dd657ea9168d78de75895d82/outetts/version/v1/prompt_processor.py#L39 -static std::string process_text(const std::string & text) { +static std::string process_text(const std::string & text, const outetts_version tts_version = OUTETTS_V0_2) { // For now I skipped text romanization as I am unsure how to handle // uroman and MeCab implementations in C++ @@ -401,7 +409,8 @@ static std::string process_text(const std::string & text) { if (c == ' ') { prompt_clean += "<|text_sep|>"; */ - processed_text = std::regex_replace(processed_text, std::regex(R"(\s)"), "<|text_sep|>"); + std::string separator = (tts_version == OUTETTS_V0_3) ? "<|space|>" : "<|text_sep|>"; + processed_text = std::regex_replace(processed_text, std::regex(R"(\s)"), separator); return processed_text; } @@ -425,8 +434,8 @@ static void prompt_init(llama_tokens & prompt, const llama_vocab * vocab) { prompt_add(prompt, vocab, "<|im_start|>\n", true, true); } -static std::vector prepare_guide_tokens(const llama_vocab * vocab, const std::string & str) { - const std::string& delimiter = "<|text_sep|>"; +static std::vector prepare_guide_tokens(const llama_vocab * vocab, const std::string & str, const outetts_version tts_version = OUTETTS_V0_2) { + const std::string& delimiter = (tts_version == OUTETTS_V0_3 ? "<|space|>" : "<|text_sep|>"); std::vector result; size_t start = 0; @@ -452,6 +461,78 @@ static std::vector prepare_guide_tokens(const llama_vocab * vocab, return result; } +static json speaker_from_file(const std::string & speaker_file) { + std::ifstream file(speaker_file); + if (!file) { + LOG_ERR("%s: Failed to open file '%s' for reading\n", __func__, speaker_file.c_str()); + return json(); + } + + json speaker = json::parse(file); + return speaker; +} + +static outetts_version get_tts_version(llama_model *model, json speaker = json::object()) { + if (speaker.contains("version")) { + std::string version = speaker["version"].get(); + if (version == "0.2") { + return OUTETTS_V0_2; + } else if (version == "0.3") { + return OUTETTS_V0_3; + } else { + LOG_ERR("%s: Unsupported speaker version '%s'\n", __func__, version.c_str()); + } + } + + // Also could get version from model itself + const char *chat_template = llama_model_chat_template(model, nullptr); + if (chat_template && std::string(chat_template) == "outetts-0.3") { + return OUTETTS_V0_3; + } + + // Use 0.2 as the default version + return OUTETTS_V0_2; +} + +static std::string audio_text_from_speaker(json speaker, const outetts_version tts_version = OUTETTS_V0_2) { + std::string audio_text = "<|text_start|>"; + + if (tts_version == OUTETTS_V0_2 || tts_version == OUTETTS_V0_3) { + std::string separator = (tts_version == OUTETTS_V0_3) ? "<|space|>" : "<|text_sep|>"; + for (const auto &word : speaker["words"]) { + audio_text += word["word"].get() + separator; + } + } + + return audio_text; +} + +static std::string audio_data_from_speaker(json speaker, const outetts_version tts_version = OUTETTS_V0_2) { + std::string audio_data = "<|audio_start|>\n"; + + if (tts_version == OUTETTS_V0_2 || tts_version == OUTETTS_V0_3) { + std::string code_start = (tts_version == OUTETTS_V0_3) ? "" : "<|code_start|>"; + std::string code_end = (tts_version == OUTETTS_V0_3) ? "<|space|>" : "<|code_end|>"; + for (const auto &word : speaker["words"]) { + std::string word_text = word["word"].get(); + double duration = word["duration"].get(); + std::vector codes = word["codes"].get>(); + + // Create the audio output entry + std::ostringstream word_entry; + word_entry << word_text << "<|t_" << std::fixed << std::setprecision(2) + << duration << "|>" + code_start; + for (const auto &Code : codes) { + word_entry << "<|" << Code << "|>"; + } + word_entry << code_end << "\n"; + audio_data += word_entry.str(); + } + } + + return audio_data; +} + int main(int argc, char ** argv) { common_params params; @@ -523,34 +604,9 @@ int main(int argc, char ** argv) { std::vector codes; std::vector guide_tokens; - // process prompt and generate voice codes - { - LOG_INF("%s: constructing prompt ..\n", __func__); - - std::vector prompt_inp; - - prompt_init(prompt_inp, vocab); - - prompt_add(prompt_inp, vocab, "<|text_start|>the<|text_sep|>overall<|text_sep|>package<|text_sep|>from<|text_sep|>just<|text_sep|>two<|text_sep|>people<|text_sep|>is<|text_sep|>pretty<|text_sep|>remarkable<|text_sep|>sure<|text_sep|>i<|text_sep|>have<|text_sep|>some<|text_sep|>critiques<|text_sep|>about<|text_sep|>some<|text_sep|>of<|text_sep|>the<|text_sep|>gameplay<|text_sep|>aspects<|text_sep|>but<|text_sep|>its<|text_sep|>still<|text_sep|>really<|text_sep|>enjoyable<|text_sep|>and<|text_sep|>it<|text_sep|>looks<|text_sep|>lovely<|text_sep|>", false, true); - - // convert the input text into the necessary format expected by OuteTTS - { - std::string prompt_clean = process_text(params.prompt); - if (params.vocoder.use_guide_tokens) { - guide_tokens = prepare_guide_tokens(vocab, prompt_clean); - } - - LOG_INF("%s: prompt: '%s'\n", __func__, prompt_clean.c_str()); - - prompt_add(prompt_inp, vocab, prompt_clean, false, true); - } - - prompt_add(prompt_inp, vocab, "<|text_end|>\n", false, true); - - // disabled to save time on tokenizing each time - // TODO: load voices from the json files -#if 0 - const std::string voice_data = R"(<|audio_start|> + // the default speaker profile is from: https://github.com/edwko/OuteTTS/blob/main/outetts/version/v1/default_speakers/en_male_1.json + std::string audio_text = "<|text_start|>the<|text_sep|>overall<|text_sep|>package<|text_sep|>from<|text_sep|>just<|text_sep|>two<|text_sep|>people<|text_sep|>is<|text_sep|>pretty<|text_sep|>remarkable<|text_sep|>sure<|text_sep|>i<|text_sep|>have<|text_sep|>some<|text_sep|>critiques<|text_sep|>about<|text_sep|>some<|text_sep|>of<|text_sep|>the<|text_sep|>gameplay<|text_sep|>aspects<|text_sep|>but<|text_sep|>its<|text_sep|>still<|text_sep|>really<|text_sep|>enjoyable<|text_sep|>and<|text_sep|>it<|text_sep|>looks<|text_sep|>lovely<|text_sep|>"; + std::string audio_data = R"(<|audio_start|> the<|t_0.08|><|code_start|><|257|><|740|><|636|><|913|><|788|><|1703|><|code_end|> overall<|t_0.36|><|code_start|><|127|><|201|><|191|><|774|><|700|><|532|><|1056|><|557|><|798|><|298|><|1741|><|747|><|1662|><|1617|><|1702|><|1527|><|368|><|1588|><|1049|><|1008|><|1625|><|747|><|1576|><|728|><|1019|><|1696|><|1765|><|code_end|> package<|t_0.56|><|code_start|><|935|><|584|><|1319|><|627|><|1016|><|1491|><|1344|><|1117|><|1526|><|1040|><|239|><|1435|><|951|><|498|><|723|><|1180|><|535|><|789|><|1649|><|1637|><|78|><|465|><|1668|><|901|><|595|><|1675|><|117|><|1009|><|1667|><|320|><|840|><|79|><|507|><|1762|><|1508|><|1228|><|1768|><|802|><|1450|><|1457|><|232|><|639|><|code_end|> @@ -582,117 +638,170 @@ it<|t_0.09|><|code_start|><|848|><|1366|><|395|><|1601|><|1513|><|593|><|1302|>< looks<|t_0.27|><|code_start|><|1281|><|1266|><|1755|><|572|><|248|><|1751|><|1257|><|695|><|1380|><|457|><|659|><|585|><|1315|><|1105|><|1776|><|736|><|24|><|736|><|654|><|1027|><|code_end|> lovely<|t_0.56|><|code_start|><|634|><|596|><|1766|><|1556|><|1306|><|1285|><|1481|><|1721|><|1123|><|438|><|1246|><|1251|><|795|><|659|><|1381|><|1658|><|217|><|1772|><|562|><|952|><|107|><|1129|><|1112|><|467|><|550|><|1079|><|840|><|1615|><|1469|><|1380|><|168|><|917|><|836|><|1827|><|437|><|583|><|67|><|595|><|1087|><|1646|><|1493|><|1677|><|code_end|>)"; - auto tmp = common_tokenize(vocab, voice_data, false, true); - printf("\n\n"); - for (int i = 0; i < tmp.size(); ++i) { - printf("%d, ", tmp[i]); + // audio data for 0.3 version + outetts_version tts_version = get_tts_version(model_ttc); + if (tts_version == OUTETTS_V0_3) { + audio_text = std::regex_replace(audio_text, std::regex(R"(<\|text_sep\|>)"), "<|space|>"); + audio_data = std::regex_replace(audio_data, std::regex(R"(<\|code_start\|>)"), ""); + audio_data = std::regex_replace(audio_data, std::regex(R"(<\|code_end\|>)"), "<|space|>"); + } + + // load speaker if given + if (!params.vocoder.speaker_file.empty()) { + LOG_INF("%s: loading speaker ..\n", __func__); + json speaker = speaker_from_file(params.vocoder.speaker_file); + if (speaker.empty()) { + LOG_ERR("%s: Failed to load speaker file '%s'\n", __func__, params.vocoder.speaker_file.c_str()); + return 1; } - printf("\n\n"); + audio_text = audio_text_from_speaker(speaker, tts_version); + audio_data = audio_data_from_speaker(speaker, tts_version); + } + + // process prompt and generate voice codes + { + LOG_INF("%s: constructing prompt ..\n", __func__); + + std::vector prompt_inp; + + prompt_init(prompt_inp, vocab); + + prompt_add(prompt_inp, vocab, audio_text, false, true); + + // convert the input text into the necessary format expected by OuteTTS + { + std::string prompt_clean = process_text(params.prompt, tts_version); + if (params.vocoder.use_guide_tokens) { + guide_tokens = prepare_guide_tokens(vocab, prompt_clean, tts_version); + } + + LOG_INF("%s: prompt: '%s'\n", __func__, prompt_clean.c_str()); + + prompt_add(prompt_inp, vocab, prompt_clean, false, true); + } + + prompt_add(prompt_inp, vocab, "<|text_end|>\n", false, true); + + if (!params.vocoder.speaker_file.empty()) { + prompt_add(prompt_inp, vocab, audio_data, false, true); + } else { + // disabled to save time on tokenizing each time +#if 1 + const std::string voice_data = audio_data; + + auto tmp = common_tokenize(vocab, voice_data, false, true); + printf("\n\n"); + for (size_t i = 0; i < tmp.size(); ++i) { + printf("%d, ", tmp[i]); + } + printf("\n\n"); + prompt_add(prompt_inp, tmp); #else - prompt_add(prompt_inp, llama_tokens { - 151667, 198, 1782, 155780, 151669, 151929, 152412, 152308, 152585, - 152460, 153375, 151670, 198, 74455, 155808, 151669, 151799, - 151873, 151863, 152446, 152372, 152204, 152728, 152229, 152470, - 151970, 153413, 152419, 153334, 153289, 153374, 153199, 152040, - 153260, 152721, 152680, 153297, 152419, 153248, 152400, 152691, - 153368, 153437, 151670, 198, 1722, 155828, 151669, 152607, - 152256, 152991, 152299, 152688, 153163, 153016, 152789, 153198, - 152712, 151911, 153107, 152623, 152170, 152395, 152852, 152207, - 152461, 153321, 153309, 151750, 152137, 153340, 152573, 152267, - 153347, 151789, 152681, 153339, 151992, 152512, 151751, 152179, - 153434, 153180, 152900, 153440, 152474, 153122, 153129, 151904, - 152311, 151670, 198, 1499, 155791, 151669, 152276, 152454, - 153354, 152544, 153204, 153272, 152708, 153433, 152319, 153226, - 153043, 152325, 153267, 152622, 151670, 198, 4250, 155797, - 151669, 153454, 153342, 151989, 152458, 153420, 152303, 152271, - 152827, 153036, 153196, 151708, 153263, 152561, 153207, 152213, - 152112, 153204, 151722, 152542, 151670, 198, 19789, 155796, - 151669, 153353, 153182, 152345, 152471, 152477, 153014, 152002, - 152191, 151734, 152312, 152810, 152237, 153224, 153169, 153224, - 152244, 153387, 153404, 151670, 198, 16069, 155811, 151669, - 152265, 151946, 151808, 152412, 152363, 152305, 153156, 152733, - 152810, 153157, 152016, 152100, 152069, 153234, 152317, 152589, - 152707, 153121, 153341, 152159, 152114, 153156, 153001, 153504, - 153376, 152272, 152433, 152325, 151941, 151670, 198, 285, - 155788, 151669, 152238, 152255, 153427, 152318, 153009, 152381, - 152474, 152680, 152157, 153255, 152324, 151682, 151670, 198, - 32955, 155804, 151669, 153490, 153419, 152364, 152405, 152682, - 152206, 152078, 153369, 152725, 153193, 153027, 152946, 152488, - 153070, 151883, 152890, 152489, 153144, 153375, 152358, 151685, - 152494, 152117, 152740, 151670, 198, 37448, 480, 155840, 151669, - 151902, 152720, 153377, 152027, 152378, 152821, 153207, 153459, - 153028, 153068, 152507, 153255, 152158, 152921, 151958, 152609, - 152748, 152822, 152286, 151714, 152730, 152377, 152353, 152470, - 152606, 152162, 152186, 153071, 152244, 153118, 153375, 153018, - 152712, 153098, 152976, 152336, 151843, 153202, 152297, 151736, - 153380, 153502, 152702, 152115, 153181, 152735, 153277, 153457, - 152393, 153112, 152595, 151670, 198, 19098, 155808, 151669, - 152464, 153452, 152595, 153312, 151937, 151933, 153197, 152239, - 153163, 152922, 153402, 152034, 152591, 153438, 152215, 151673, - 152005, 151785, 152642, 151924, 153278, 151805, 151974, 153482, - 152718, 152862, 153347, 151670, 198, 72, 155780, 151669, 151795, - 152111, 152746, 152377, 153471, 152309, 151670, 198, 19016, - 155788, 151669, 153181, 152271, 152190, 152842, 152224, 152701, - 152939, 152536, 152091, 151815, 152733, 151672, 151670, 198, - 14689, 155788, 151669, 152291, 152072, 152942, 151734, 153042, - 153504, 152589, 153333, 151839, 151941, 153038, 153180, 151670, - 198, 36996, 8303, 155832, 151669, 152231, 152256, 152835, - 152801, 152985, 153400, 152393, 152818, 152765, 152249, 152600, - 151699, 152302, 152752, 153018, 153009, 151992, 153054, 152847, - 153354, 153228, 152662, 153355, 152532, 153393, 151782, 152458, - 152048, 152757, 152428, 153195, 151906, 153006, 153178, 153250, - 152331, 152284, 152780, 153138, 153319, 151980, 153142, 152418, - 152228, 152733, 151670, 198, 9096, 155801, 151669, 151698, - 153321, 152217, 153039, 152935, 153400, 152122, 152531, 153106, - 152169, 152892, 152957, 151851, 152427, 152826, 152451, 151851, - 152901, 152885, 152594, 153446, 153080, 151670, 198, 14689, - 155795, 151669, 152658, 151700, 153321, 152450, 152530, 153191, - 151673, 151690, 151698, 152714, 152846, 152981, 153171, 153384, - 153364, 153188, 153246, 151670, 198, 1055, 155779, 151669, - 151869, 152388, 152711, 153334, 151736, 151670, 198, 1782, - 155780, 151669, 153483, 153240, 152241, 152558, 152697, 153046, - 151670, 198, 5804, 1363, 155820, 151669, 152941, 152764, 152605, - 153034, 153434, 153372, 153347, 151887, 152453, 152758, 152133, - 152510, 152694, 152431, 152321, 153088, 152676, 152223, 152581, - 152459, 152015, 152502, 153063, 152712, 153294, 153451, 153032, - 152903, 152859, 152989, 151748, 152669, 152661, 152650, 152409, - 151861, 151670, 198, 300, 7973, 155828, 151669, 153095, 152469, - 152988, 152894, 151819, 152391, 153019, 152058, 153062, 153230, - 151826, 152112, 152306, 152264, 152769, 153390, 152384, 152435, - 152790, 153393, 152983, 152540, 152252, 152034, 153107, 152540, - 151919, 151893, 152558, 152817, 152946, 152956, 152129, 152715, - 153131, 153490, 151734, 152271, 152707, 151734, 153321, 152450, - 151670, 198, 8088, 155792, 151669, 152452, 153497, 153353, - 152679, 152533, 152382, 152374, 152611, 153341, 153163, 152285, - 153411, 152495, 153141, 152320, 151670, 198, 1199, 155781, - 151669, 151764, 152360, 153295, 152634, 153342, 152199, 152271, - 151670, 198, 43366, 155799, 151669, 152308, 151682, 152889, - 152016, 152385, 152629, 152495, 151826, 153321, 152958, 152180, - 151886, 153432, 152922, 152128, 153024, 153040, 152593, 152287, - 151677, 151670, 198, 53660, 155808, 151669, 151727, 152092, - 152680, 153331, 151699, 152316, 152938, 152289, 152433, 153384, - 151781, 153137, 153259, 152175, 153213, 152291, 151869, 152691, - 152489, 151941, 152049, 152034, 153053, 152179, 153160, 151676, - 153367, 151670, 198, 268, 4123, 480, 155821, 151669, 152350, - 152173, 152536, 151991, 151960, 153144, 153013, 152358, 152234, - 153135, 152291, 153235, 152143, 152583, 152402, 153483, 152678, - 152192, 152533, 152946, 151797, 153103, 152310, 152293, 151825, - 152548, 153442, 152109, 152659, 153325, 152781, 152570, 152957, - 151752, 152265, 153381, 152515, 151670, 198, 437, 155787, - 151669, 152957, 152659, 151975, 152709, 152402, 152836, 152174, - 151792, 153409, 153327, 152990, 151670, 198, 275, 155781, - 151669, 152520, 153038, 152067, 153273, 153185, 152265, 152974, - 151670, 198, 94273, 155799, 151669, 152953, 152938, 153427, - 152244, 151920, 153423, 152929, 152367, 153052, 152129, 152331, - 152257, 152987, 152777, 153448, 152408, 151696, 152408, 152326, - 152699, 151670, 198, 385, 16239, 155828, 151669, 152306, 152268, - 153438, 153228, 152978, 152957, 153153, 153393, 152795, 152110, - 152918, 152923, 152467, 152331, 153053, 153330, 151889, 153444, - 152234, 152624, 151779, 152801, 152784, 152139, 152222, 152751, - 152512, 153287, 153141, 153052, 151840, 152589, 152508, 153499, - 152109, 152255, 151739, 152267, 152759, 153318, 153165, 153349, - 151670,}); + prompt_add(prompt_inp, llama_tokens { + 151667, 198, 1782, 155780, 151669, 151929, 152412, 152308, 152585, + 152460, 153375, 151670, 198, 74455, 155808, 151669, 151799, + 151873, 151863, 152446, 152372, 152204, 152728, 152229, 152470, + 151970, 153413, 152419, 153334, 153289, 153374, 153199, 152040, + 153260, 152721, 152680, 153297, 152419, 153248, 152400, 152691, + 153368, 153437, 151670, 198, 1722, 155828, 151669, 152607, + 152256, 152991, 152299, 152688, 153163, 153016, 152789, 153198, + 152712, 151911, 153107, 152623, 152170, 152395, 152852, 152207, + 152461, 153321, 153309, 151750, 152137, 153340, 152573, 152267, + 153347, 151789, 152681, 153339, 151992, 152512, 151751, 152179, + 153434, 153180, 152900, 153440, 152474, 153122, 153129, 151904, + 152311, 151670, 198, 1499, 155791, 151669, 152276, 152454, + 153354, 152544, 153204, 153272, 152708, 153433, 152319, 153226, + 153043, 152325, 153267, 152622, 151670, 198, 4250, 155797, + 151669, 153454, 153342, 151989, 152458, 153420, 152303, 152271, + 152827, 153036, 153196, 151708, 153263, 152561, 153207, 152213, + 152112, 153204, 151722, 152542, 151670, 198, 19789, 155796, + 151669, 153353, 153182, 152345, 152471, 152477, 153014, 152002, + 152191, 151734, 152312, 152810, 152237, 153224, 153169, 153224, + 152244, 153387, 153404, 151670, 198, 16069, 155811, 151669, + 152265, 151946, 151808, 152412, 152363, 152305, 153156, 152733, + 152810, 153157, 152016, 152100, 152069, 153234, 152317, 152589, + 152707, 153121, 153341, 152159, 152114, 153156, 153001, 153504, + 153376, 152272, 152433, 152325, 151941, 151670, 198, 285, + 155788, 151669, 152238, 152255, 153427, 152318, 153009, 152381, + 152474, 152680, 152157, 153255, 152324, 151682, 151670, 198, + 32955, 155804, 151669, 153490, 153419, 152364, 152405, 152682, + 152206, 152078, 153369, 152725, 153193, 153027, 152946, 152488, + 153070, 151883, 152890, 152489, 153144, 153375, 152358, 151685, + 152494, 152117, 152740, 151670, 198, 37448, 480, 155840, 151669, + 151902, 152720, 153377, 152027, 152378, 152821, 153207, 153459, + 153028, 153068, 152507, 153255, 152158, 152921, 151958, 152609, + 152748, 152822, 152286, 151714, 152730, 152377, 152353, 152470, + 152606, 152162, 152186, 153071, 152244, 153118, 153375, 153018, + 152712, 153098, 152976, 152336, 151843, 153202, 152297, 151736, + 153380, 153502, 152702, 152115, 153181, 152735, 153277, 153457, + 152393, 153112, 152595, 151670, 198, 19098, 155808, 151669, + 152464, 153452, 152595, 153312, 151937, 151933, 153197, 152239, + 153163, 152922, 153402, 152034, 152591, 153438, 152215, 151673, + 152005, 151785, 152642, 151924, 153278, 151805, 151974, 153482, + 152718, 152862, 153347, 151670, 198, 72, 155780, 151669, 151795, + 152111, 152746, 152377, 153471, 152309, 151670, 198, 19016, + 155788, 151669, 153181, 152271, 152190, 152842, 152224, 152701, + 152939, 152536, 152091, 151815, 152733, 151672, 151670, 198, + 14689, 155788, 151669, 152291, 152072, 152942, 151734, 153042, + 153504, 152589, 153333, 151839, 151941, 153038, 153180, 151670, + 198, 36996, 8303, 155832, 151669, 152231, 152256, 152835, + 152801, 152985, 153400, 152393, 152818, 152765, 152249, 152600, + 151699, 152302, 152752, 153018, 153009, 151992, 153054, 152847, + 153354, 153228, 152662, 153355, 152532, 153393, 151782, 152458, + 152048, 152757, 152428, 153195, 151906, 153006, 153178, 153250, + 152331, 152284, 152780, 153138, 153319, 151980, 153142, 152418, + 152228, 152733, 151670, 198, 9096, 155801, 151669, 151698, + 153321, 152217, 153039, 152935, 153400, 152122, 152531, 153106, + 152169, 152892, 152957, 151851, 152427, 152826, 152451, 151851, + 152901, 152885, 152594, 153446, 153080, 151670, 198, 14689, + 155795, 151669, 152658, 151700, 153321, 152450, 152530, 153191, + 151673, 151690, 151698, 152714, 152846, 152981, 153171, 153384, + 153364, 153188, 153246, 151670, 198, 1055, 155779, 151669, + 151869, 152388, 152711, 153334, 151736, 151670, 198, 1782, + 155780, 151669, 153483, 153240, 152241, 152558, 152697, 153046, + 151670, 198, 5804, 1363, 155820, 151669, 152941, 152764, 152605, + 153034, 153434, 153372, 153347, 151887, 152453, 152758, 152133, + 152510, 152694, 152431, 152321, 153088, 152676, 152223, 152581, + 152459, 152015, 152502, 153063, 152712, 153294, 153451, 153032, + 152903, 152859, 152989, 151748, 152669, 152661, 152650, 152409, + 151861, 151670, 198, 300, 7973, 155828, 151669, 153095, 152469, + 152988, 152894, 151819, 152391, 153019, 152058, 153062, 153230, + 151826, 152112, 152306, 152264, 152769, 153390, 152384, 152435, + 152790, 153393, 152983, 152540, 152252, 152034, 153107, 152540, + 151919, 151893, 152558, 152817, 152946, 152956, 152129, 152715, + 153131, 153490, 151734, 152271, 152707, 151734, 153321, 152450, + 151670, 198, 8088, 155792, 151669, 152452, 153497, 153353, + 152679, 152533, 152382, 152374, 152611, 153341, 153163, 152285, + 153411, 152495, 153141, 152320, 151670, 198, 1199, 155781, + 151669, 151764, 152360, 153295, 152634, 153342, 152199, 152271, + 151670, 198, 43366, 155799, 151669, 152308, 151682, 152889, + 152016, 152385, 152629, 152495, 151826, 153321, 152958, 152180, + 151886, 153432, 152922, 152128, 153024, 153040, 152593, 152287, + 151677, 151670, 198, 53660, 155808, 151669, 151727, 152092, + 152680, 153331, 151699, 152316, 152938, 152289, 152433, 153384, + 151781, 153137, 153259, 152175, 153213, 152291, 151869, 152691, + 152489, 151941, 152049, 152034, 153053, 152179, 153160, 151676, + 153367, 151670, 198, 268, 4123, 480, 155821, 151669, 152350, + 152173, 152536, 151991, 151960, 153144, 153013, 152358, 152234, + 153135, 152291, 153235, 152143, 152583, 152402, 153483, 152678, + 152192, 152533, 152946, 151797, 153103, 152310, 152293, 151825, + 152548, 153442, 152109, 152659, 153325, 152781, 152570, 152957, + 151752, 152265, 153381, 152515, 151670, 198, 437, 155787, + 151669, 152957, 152659, 151975, 152709, 152402, 152836, 152174, + 151792, 153409, 153327, 152990, 151670, 198, 275, 155781, + 151669, 152520, 153038, 152067, 153273, 153185, 152265, 152974, + 151670, 198, 94273, 155799, 151669, 152953, 152938, 153427, + 152244, 151920, 153423, 152929, 152367, 153052, 152129, 152331, + 152257, 152987, 152777, 153448, 152408, 151696, 152408, 152326, + 152699, 151670, 198, 385, 16239, 155828, 151669, 152306, 152268, + 153438, 153228, 152978, 152957, 153153, 153393, 152795, 152110, + 152918, 152923, 152467, 152331, 153053, 153330, 151889, 153444, + 152234, 152624, 151779, 152801, 152784, 152139, 152222, 152751, + 152512, 153287, 153141, 153052, 151840, 152589, 152508, 153499, + 152109, 152255, 151739, 152267, 152759, 153318, 153165, 153349, + 151670,}); #endif + } // print the prompt token-by-token From 2679c3b55d1c9c3fed56dea00fea713622e42594 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Mon, 3 Mar 2025 16:17:36 +0100 Subject: [PATCH 12/87] ci : set GITHUB_ACTION env var for server tests (#12162) This commit tries to address/improve an issue with the server tests which are failing with a timeout. Looking at the logs it seems like they are timing out after 12 seconds: ``` FAILED unit/test_chat_completion.py::test_completion_with_json_schema[False-json_schema0-6-"42"] - TimeoutError: Server did not start within 12 seconds ``` This is somewhat strange as in utils.py we have the following values: ```python DEFAULT_HTTP_TIMEOUT = 12 if "LLAMA_SANITIZE" in os.environ or "GITHUB_ACTION" in os.environ: DEFAULT_HTTP_TIMEOUT = 30 def start(self, timeout_seconds: int | None = DEFAULT_HTTP_TIMEOUT) -> None: ``` It should be the case that a test running in a github action should have a timeout of 30 seconds. However, it seems like this is not the case. Inspecting the logs from the CI job we can see the following environment variables: ```console Run cd examples/server/tests 2 cd examples/server/tests 3 ./tests.sh 4 shell: /usr/bin/bash -e {0} 5 env: 6 LLAMA_LOG_COLORS: 1 7 LLAMA_LOG_PREFIX: 1 8 LLAMA_LOG_TIMESTAMPS: 1 9 LLAMA_LOG_VERBOSITY: 10 10 pythonLocation: /opt/hostedtoolcache/Python/3.11.11/x64 ``` This probably does not address the underlying issue that the servers that are providing the models to be downloaded occasionally take a longer time to response but might improve these situations in some cases. --- .github/workflows/server.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index 3a29107d0..092c928bd 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -161,6 +161,8 @@ jobs: - name: Tests id: server_integration_tests if: ${{ matrix.sanitizer == '' }} + env: + GITHUB_ACTIONS: "true" run: | cd examples/server/tests ./tests.sh From aede2074f608d7bf6614cdd047bce687a2b3d908 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Fri, 28 Feb 2025 09:09:38 +0200 Subject: [PATCH 13/87] scripts : sync-ggml-am.sh fix --- scripts/sync-ggml-am.sh | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/scripts/sync-ggml-am.sh b/scripts/sync-ggml-am.sh index ec4f4b0a2..33e8c6414 100755 --- a/scripts/sync-ggml-am.sh +++ b/scripts/sync-ggml-am.sh @@ -149,29 +149,29 @@ if [ -f $SRC_LLAMA/ggml-src.patch ]; then # scripts/gen-authors.sh -> scripts/gen-authors.sh cat ggml-src.patch | sed -E \ - -e 's/([[:space:]]|[ab]\/)CMakeLists.txt/\1ggml\/CMakeLists.txt/g' \ - -e 's/([[:space:]]|[ab]\/)src\/CMakeLists.txt/\1ggml\/src\/CMakeLists.txt/g' \ - -e 's/([[:space:]]|[ab]\/)cmake\/FindSIMD.cmake/\1ggml\/cmake\/FindSIMD.cmake/g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml(.*)\.c/\1ggml\/src\/ggml\2.c/g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml(.*)\.cpp/\1ggml\/src\/ggml\2.cpp/g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml(.*)\.h/\1ggml\/src\/ggml\2.h/g' \ - -e 's/([[:space:]]|[ab]\/)src\/gguf(.*)\.cpp/\1ggml\/src\/gguf\2.cpp/g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-blas\//\1ggml\/src\/ggml-blas\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-cann\//\1ggml\/src\/ggml-cann\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-cpu\//\1ggml\/src\/ggml-cpu\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-cuda\//\1ggml\/src\/ggml-cuda\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-hip\//\1ggml\/src\/ggml-hip\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-kompute\//\1ggml\/src\/ggml-kompute\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-metal\//\1ggml\/src\/ggml-metal\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-opencl\//\1ggml\/src\/ggml-opencl\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-rpc\//\1ggml\/src\/ggml-rpc\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-sycl\//\1ggml\/src\/ggml-sycl\//g' \ - -e 's/([[:space:]]|[ab]\/)src\/ggml-vulkan\//\1ggml\/src\/ggml-vulkan\//g' \ - -e 's/([[:space:]]|[ab]\/)include\/ggml(.*)\.h/\1ggml\/include\/ggml\2.h/g' \ - -e 's/([[:space:]]|[ab]\/)include\/gguf(.*)\.h/\1ggml\/include\/gguf\2.h/g' \ - -e 's/([[:space:]]|[ab]\/)tests\/(.*)\.cpp/\1tests\/\2.cpp/g' \ - -e 's/([[:space:]]|[ab]\/)LICENSE/\1LICENSE/g' \ - -e 's/([[:space:]]|[ab]\/)scripts\/gen-authors\.sh/\1scripts\/gen-authors.sh/g' \ + -e 's/(^[[:space:]]| [ab]\/)CMakeLists.txt/\1ggml\/CMakeLists.txt/g' \ + -e 's/(^[[:space:]]| [ab]\/)src\/CMakeLists.txt/\1ggml\/src\/CMakeLists.txt/g' \ + -e 's/(^[[:space:]]| [ab]\/)cmake\/FindSIMD.cmake/\1ggml\/cmake\/FindSIMD.cmake/g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml(.*)\.c/\1ggml\/src\/ggml\2.c/g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml(.*)\.cpp/\1ggml\/src\/ggml\2.cpp/g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml(.*)\.h/\1ggml\/src\/ggml\2.h/g' \ + -e 's/([[:space:]]| [ab]\/)src\/gguf(.*)\.cpp/\1ggml\/src\/gguf\2.cpp/g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-blas\//\1ggml\/src\/ggml-blas\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-cann\//\1ggml\/src\/ggml-cann\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-cpu\//\1ggml\/src\/ggml-cpu\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-cuda\//\1ggml\/src\/ggml-cuda\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-hip\//\1ggml\/src\/ggml-hip\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-kompute\//\1ggml\/src\/ggml-kompute\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-metal\//\1ggml\/src\/ggml-metal\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-opencl\//\1ggml\/src\/ggml-opencl\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-rpc\//\1ggml\/src\/ggml-rpc\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-sycl\//\1ggml\/src\/ggml-sycl\//g' \ + -e 's/([[:space:]]| [ab]\/)src\/ggml-vulkan\//\1ggml\/src\/ggml-vulkan\//g' \ + -e 's/^([[:space:]]| [ab]\/)include\/ggml(.*)\.h/\1ggml\/include\/ggml\2.h/g' \ + -e 's/^([[:space:]]| [ab]\/)include\/gguf(.*)\.h/\1ggml\/include\/gguf\2.h/g' \ + -e 's/^([[:space:]]| [ab]\/)tests\/(.*)\.cpp/\1tests\/\2.cpp/g' \ + -e 's/^([[:space:]]| [ab]\/)LICENSE/\1LICENSE/g' \ + -e 's/^([[:space:]]| [ab]\/)scripts\/gen-authors\.sh/\1scripts\/gen-authors.sh/g' \ > ggml-src.patch.tmp mv ggml-src.patch.tmp ggml-src.patch From f54a4ba11ed8ab59da778d5e280f7dc73c775a7a Mon Sep 17 00:00:00 2001 From: cmdr2 Date: Tue, 25 Feb 2025 18:06:34 +0530 Subject: [PATCH 14/87] Support pure float16 add/sub/mul/div operations in the CUDA (and CPU) backend (ggml/1121) * Support float16-to-float16 add/sub/mul/div operations in the CUDA backend * Add fp16 support for add/sub/mul/div on the CPU backend * Add test cases for fp16 add/sub/mul/div --- ggml/src/ggml-cpu/ggml-cpu.c | 213 +++++++++++++++++++++++++++++++-- ggml/src/ggml-cuda/binbcast.cu | 6 +- tests/test-backend-ops.cpp | 61 +++++----- 3 files changed, 237 insertions(+), 43 deletions(-) diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c index 723253495..33ab5e9c6 100644 --- a/ggml/src/ggml-cpu/ggml-cpu.c +++ b/ggml/src/ggml-cpu/ggml-cpu.c @@ -1415,15 +1415,35 @@ inline static void ggml_vec_cpy_i32(const int n, int32_t * y, const int32_t * x) inline static void ggml_vec_set_f16(const int n, ggml_fp16_t * x, const int32_t v) { for (int i = 0; i < n; ++i) x[i] = v; } inline static void ggml_vec_set_bf16(const int n, ggml_bf16_t * x, const ggml_bf16_t v) { for (int i = 0; i < n; ++i) x[i] = v; } inline static void ggml_vec_add_f32 (const int n, float * z, const float * x, const float * y) { for (int i = 0; i < n; ++i) z[i] = x[i] + y[i]; } +inline static void ggml_vec_add_f16 (const int n, ggml_fp16_t * z, const ggml_fp16_t * x, const ggml_fp16_t * y) { + for (int i = 0; i < n; ++i) { + z[i] = GGML_FP32_TO_FP16(GGML_FP16_TO_FP32(x[i]) + GGML_FP16_TO_FP32(y[i])); + } +} inline static void ggml_vec_add1_f32(const int n, float * z, const float * x, const float v) { for (int i = 0; i < n; ++i) z[i] = x[i] + v; } inline static void ggml_vec_acc_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] += x[i]; } inline static void ggml_vec_acc1_f32(const int n, float * y, const float v) { for (int i = 0; i < n; ++i) y[i] += v; } inline static void ggml_vec_sub_f32 (const int n, float * z, const float * x, const float * y) { for (int i = 0; i < n; ++i) z[i] = x[i] - y[i]; } +inline static void ggml_vec_sub_f16 (const int n, ggml_fp16_t * z, const ggml_fp16_t * x, const ggml_fp16_t * y) { + for (int i = 0; i < n; ++i) { + z[i] = GGML_FP32_TO_FP16(GGML_FP16_TO_FP32(x[i]) - GGML_FP16_TO_FP32(y[i])); + } +} inline static void ggml_vec_set_f32 (const int n, float * x, const float v) { for (int i = 0; i < n; ++i) x[i] = v; } inline static void ggml_vec_cpy_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = x[i]; } inline static void ggml_vec_neg_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = -x[i]; } inline static void ggml_vec_mul_f32 (const int n, float * z, const float * x, const float * y) { for (int i = 0; i < n; ++i) z[i] = x[i]*y[i]; } +inline static void ggml_vec_mul_f16 (const int n, ggml_fp16_t * z, const ggml_fp16_t * x, const ggml_fp16_t * y) { + for (int i = 0; i < n; ++i) { + z[i] = GGML_FP32_TO_FP16(GGML_FP16_TO_FP32(x[i]) * GGML_FP16_TO_FP32(y[i])); + } +} inline static void ggml_vec_div_f32 (const int n, float * z, const float * x, const float * y) { for (int i = 0; i < n; ++i) z[i] = x[i]/y[i]; } +inline static void ggml_vec_div_f16 (const int n, ggml_fp16_t * z, const ggml_fp16_t * x, const ggml_fp16_t * y) { + for (int i = 0; i < n; ++i) { + z[i] = GGML_FP32_TO_FP16(GGML_FP16_TO_FP32(x[i]) / GGML_FP16_TO_FP32(y[i])); + } +} static void ggml_vec_dot_f32(int n, float * restrict s, size_t bs, const float * restrict x, size_t bx, const float * restrict y, size_t by, int nrc) { assert(nrc == 1); @@ -4379,7 +4399,7 @@ static void ggml_compute_forward_add_f16_f16( const struct ggml_tensor * src0 = dst->src[0]; const struct ggml_tensor * src1 = dst->src[1]; - GGML_ASSERT(ggml_are_same_shape(src0, src1) && ggml_are_same_shape(src0, dst)); + GGML_ASSERT(ggml_can_repeat(src1, src0) && ggml_are_same_shape(src0, dst)); const int ith = params->ith; const int nth = params->nth; @@ -4404,17 +4424,22 @@ static void ggml_compute_forward_add_f16_f16( if (nb10 == sizeof(ggml_fp16_t)) { for (int ir = ir0; ir < ir1; ++ir) { - // src0, src1 and dst are same shape => same indices - const int i3 = ir/(ne2*ne1); - const int i2 = (ir - i3*ne2*ne1)/ne1; - const int i1 = (ir - i3*ne2*ne1 - i2*ne1); + // src1 is broadcastable across src0 and dst in i1, i2, i3 + const int64_t i03 = ir/(ne02*ne01); + const int64_t i02 = (ir - i03*ne02*ne01)/ne01; + const int64_t i01 = (ir - i03*ne02*ne01 - i02*ne01); - ggml_fp16_t * dst_ptr = (ggml_fp16_t *) ((char *) dst->data + i3*nb3 + i2*nb2 + i1*nb1); - ggml_fp16_t * src0_ptr = (ggml_fp16_t *) ((char *) src0->data + i3*nb03 + i2*nb02 + i1*nb01); - ggml_fp16_t * src1_ptr = (ggml_fp16_t *) ((char *) src1->data + i3*nb13 + i2*nb12 + i1*nb11); + const int64_t i13 = i03 % ne13; + const int64_t i12 = i02 % ne12; + const int64_t i11 = i01 % ne11; + const int64_t nr0 = ne00 / ne10; - for (int i = 0; i < ne0; i++) { - dst_ptr[i] = GGML_FP32_TO_FP16(GGML_FP16_TO_FP32(src0_ptr[i]) + GGML_FP16_TO_FP32(src1_ptr[i])); + ggml_fp16_t * dst_ptr = (ggml_fp16_t *) ((char *) dst->data + i03*nb3 + i02*nb2 + i01*nb1 ); + ggml_fp16_t * src0_ptr = (ggml_fp16_t *) ((char *) src0->data + i03*nb03 + i02*nb02 + i01*nb01); + ggml_fp16_t * src1_ptr = (ggml_fp16_t *) ((char *) src1->data + i13*nb13 + i12*nb12 + i11*nb11); + + for (int64_t r = 0; r < nr0; ++r) { + ggml_vec_add_f16(ne10, dst_ptr + r*ne10, src0_ptr + r*ne10, src1_ptr); } } } @@ -5202,6 +5227,62 @@ static void ggml_compute_forward_sub_f32( } } +static void ggml_compute_forward_sub_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + const struct ggml_tensor * src1 = dst->src[1]; + + assert(ggml_can_repeat(src1, src0) && ggml_are_same_shape(src0, dst)); + + const int ith = params->ith; + const int nth = params->nth; + + const int nr = ggml_nrows(src0); + + GGML_TENSOR_BINARY_OP_LOCALS + + GGML_ASSERT(src0->type == GGML_TYPE_F16); + GGML_ASSERT(src1->type == GGML_TYPE_F16); + GGML_ASSERT(dst->type == GGML_TYPE_F16); + + GGML_ASSERT( nb0 == sizeof(ggml_fp16_t)); + GGML_ASSERT(nb00 == sizeof(ggml_fp16_t)); + + // rows per thread + const int dr = (nr + nth - 1)/nth; + + // row range for this thread + const int ir0 = dr*ith; + const int ir1 = MIN(ir0 + dr, nr); + + if (nb10 == sizeof(ggml_fp16_t)) { + for (int ir = ir0; ir < ir1; ++ir) { + // src1 is broadcastable across src0 and dst in i1, i2, i3 + const int64_t i03 = ir/(ne02*ne01); + const int64_t i02 = (ir - i03*ne02*ne01)/ne01; + const int64_t i01 = (ir - i03*ne02*ne01 - i02*ne01); + + const int64_t i13 = i03 % ne13; + const int64_t i12 = i02 % ne12; + const int64_t i11 = i01 % ne11; + const int64_t nr0 = ne00 / ne10; + + ggml_fp16_t * dst_ptr = (ggml_fp16_t *) ((char *) dst->data + i03*nb3 + i02*nb2 + i01*nb1 ); + ggml_fp16_t * src0_ptr = (ggml_fp16_t *) ((char *) src0->data + i03*nb03 + i02*nb02 + i01*nb01); + ggml_fp16_t * src1_ptr = (ggml_fp16_t *) ((char *) src1->data + i13*nb13 + i12*nb12 + i11*nb11); + + for (int64_t r = 0; r < nr0; ++r) { + ggml_vec_sub_f16(ne10, dst_ptr + r*ne10, src0_ptr + r*ne10, src1_ptr); + } + } + } else { + // src1 is not contiguous + GGML_ABORT("unimplemented error"); + } +} + static void ggml_compute_forward_sub( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5213,6 +5294,10 @@ static void ggml_compute_forward_sub( { ggml_compute_forward_sub_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_sub_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -5293,6 +5378,55 @@ static void ggml_compute_forward_mul_f32( } } +static void ggml_compute_forward_mul_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + const struct ggml_tensor * src1 = dst->src[1]; + + GGML_ASSERT(ggml_can_repeat(src1, src0) && ggml_are_same_shape(src0, dst)); + + const int ith = params->ith; + const int nth = params->nth; + + const int64_t nr = ggml_nrows(src0); + + GGML_TENSOR_BINARY_OP_LOCALS + + GGML_ASSERT(src0->type == GGML_TYPE_F16); + GGML_ASSERT(src1->type == GGML_TYPE_F16); + GGML_ASSERT(dst->type == GGML_TYPE_F16); + + GGML_ASSERT( nb0 == sizeof(ggml_fp16_t)); + GGML_ASSERT(nb00 == sizeof(ggml_fp16_t)); + + if (nb10 == sizeof(ggml_fp16_t)) { + for (int64_t ir = ith; ir < nr; ir += nth) { + // src0 and dst are same shape => same indices + const int64_t i03 = ir/(ne02*ne01); + const int64_t i02 = (ir - i03*ne02*ne01)/ne01; + const int64_t i01 = (ir - i03*ne02*ne01 - i02*ne01); + + const int64_t i13 = i03 % ne13; + const int64_t i12 = i02 % ne12; + const int64_t i11 = i01 % ne11; + const int64_t nr0 = ne00 / ne10; + + ggml_fp16_t * dst_ptr = (ggml_fp16_t *) ((char *) dst->data + i03*nb3 + i02*nb2 + i01*nb1 ); + ggml_fp16_t * src0_ptr = (ggml_fp16_t *) ((char *) src0->data + i03*nb03 + i02*nb02 + i01*nb01); + ggml_fp16_t * src1_ptr = (ggml_fp16_t *) ((char *) src1->data + i13*nb13 + i12*nb12 + i11*nb11); + + for (int64_t r = 0 ; r < nr0; ++r) { + ggml_vec_mul_f16(ne10, dst_ptr + r*ne10, src0_ptr + r*ne10, src1_ptr); + } + } + } else { + // src1 is not contiguous + GGML_ABORT("unimplemented error"); + } +} + static void ggml_compute_forward_mul( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5300,13 +5434,17 @@ static void ggml_compute_forward_mul( const struct ggml_tensor * src0 = dst->src[0]; const struct ggml_tensor * src1 = dst->src[1]; - GGML_ASSERT(src1->type == GGML_TYPE_F32 && "only f32 src1 supported for now"); + GGML_ASSERT((src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16) && "only f32/f16 src1 supported for now"); switch (src0->type) { case GGML_TYPE_F32: { ggml_compute_forward_mul_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_mul_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -5387,6 +5525,55 @@ static void ggml_compute_forward_div_f32( } } +static void ggml_compute_forward_div_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + const struct ggml_tensor * src1 = dst->src[1]; + + GGML_ASSERT(ggml_can_repeat(src1, src0) && ggml_are_same_shape(src0, dst)); + + const int ith = params->ith; + const int nth = params->nth; + + const int64_t nr = ggml_nrows(src0); + + GGML_TENSOR_BINARY_OP_LOCALS + + GGML_ASSERT(src0->type == GGML_TYPE_F16); + GGML_ASSERT(src1->type == GGML_TYPE_F16); + GGML_ASSERT(dst->type == GGML_TYPE_F16); + + GGML_ASSERT( nb0 == sizeof(ggml_fp16_t)); + GGML_ASSERT(nb00 == sizeof(ggml_fp16_t)); + + if (nb10 == sizeof(ggml_fp16_t)) { + for (int64_t ir = ith; ir < nr; ir += nth) { + // src0 and dst are same shape => same indices + const int64_t i03 = ir/(ne02*ne01); + const int64_t i02 = (ir - i03*ne02*ne01)/ne01; + const int64_t i01 = (ir - i03*ne02*ne01 - i02*ne01); + + const int64_t i13 = i03 % ne13; + const int64_t i12 = i02 % ne12; + const int64_t i11 = i01 % ne11; + const int64_t nr0 = ne00 / ne10; + + ggml_fp16_t * dst_ptr = (ggml_fp16_t *) ((char *) dst->data + i03*nb3 + i02*nb2 + i01*nb1 ); + ggml_fp16_t * src0_ptr = (ggml_fp16_t *) ((char *) src0->data + i03*nb03 + i02*nb02 + i01*nb01); + ggml_fp16_t * src1_ptr = (ggml_fp16_t *) ((char *) src1->data + i13*nb13 + i12*nb12 + i11*nb11); + + for (int64_t r = 0; r < nr0; ++r) { + ggml_vec_div_f16(ne10, dst_ptr + r*ne10, src0_ptr + r*ne10, src1_ptr); + } + } + } else { + // src1 is not contiguous + GGML_ABORT("unimplemented error"); + } +} + static void ggml_compute_forward_div( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5398,6 +5585,10 @@ static void ggml_compute_forward_div( { ggml_compute_forward_div_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_div_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); diff --git a/ggml/src/ggml-cuda/binbcast.cu b/ggml/src/ggml-cuda/binbcast.cu index ce4b9cfb5..e1fbf0e13 100644 --- a/ggml/src/ggml-cuda/binbcast.cu +++ b/ggml/src/ggml-cuda/binbcast.cu @@ -294,11 +294,13 @@ static void ggml_cuda_op_bin_bcast( const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const void * src0_dd, const void * src1_dd, void * dst_dd, cudaStream_t stream) { - GGML_ASSERT(src1->type == GGML_TYPE_F32); + GGML_ASSERT(src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16); if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { op()(src0, src1, dst, (const float *)src0_dd, (const float *)src1_dd, (float *)dst_dd, stream); - } else if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { + } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { + op()(src0, src1, dst, (const half *) src0_dd, (const half *)src1_dd, (half *) dst_dd, stream); + } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F16) { op()(src0, src1, dst, (const half *) src0_dd, (const float *)src1_dd, (half *) dst_dd, stream); } else if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F32) { op()(src0, src1, dst, (const half *) src0_dd, (const float *)src1_dd, (float *)dst_dd, stream); diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index b544dee45..e2412bf31 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -3961,37 +3961,38 @@ static std::vector> make_test_cases_eval() { test_cases.emplace_back(new test_bin_bcast(op, type, ne, nr)); } }; + for (ggml_type type : {GGML_TYPE_F16, GGML_TYPE_F32}) { + add_test_bin_bcast(type, {1, 1, 8, 1}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {1, 1, 1, 1}, {32, 1, 1, 1}); + add_test_bin_bcast(type, {1, 1, 320, 320}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {10, 5, 1, 1}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {10, 5, 4, 1}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {2, 1, 1, 1}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {1, 2, 1, 1}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {1, 1, 2, 1}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {1, 1, 1, 2}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {1, 1, 2, 2}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {1, 2, 2, 2}); + add_test_bin_bcast(type, {10, 5, 4, 3}, {2, 2, 2, 2}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 8, 1}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 1, 1}, {32, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 320, 320}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 1, 1}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 1}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {2, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {1, 2, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {1, 1, 2, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {1, 1, 1, 2}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {1, 1, 2, 2}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {1, 2, 2, 2}); - add_test_bin_bcast(GGML_TYPE_F32, {10, 5, 4, 3}, {2, 2, 2, 2}); - - // stable diffusion - add_test_bin_bcast(GGML_TYPE_F32, {1280, 1, 1, 1}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1280, 1, 1, 1}, {1, 16, 16, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1280, 16, 16, 1}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1280, 1, 1, 1}, {1, 256, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 1280, 1}, {16, 16, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {16, 16, 1280, 1}, {1, 1, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 1920, 1}, {16, 16, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 2560, 1}, {16, 16, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 1280, 1}, {32, 32, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 1920, 1}, {32, 32, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {1, 1, 640, 1}, {32, 32, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {5120, 1, 1, 1}, {1, 256, 1, 1}); - add_test_bin_bcast(GGML_TYPE_F32, {640, 1, 1, 1}, {1, 1, 1, 1}); - //add_test_bin_bcast(GGML_TYPE_F32, {3, 3, 2560, 1280}, {1, 1, 1, 1}); - //add_test_bin_bcast(GGML_TYPE_F32, {3, 3, 2560, 1280}, {2, 1, 1, 1}); + // stable diffusion + add_test_bin_bcast(type, {1280, 1, 1, 1}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {1280, 1, 1, 1}, {1, 16, 16, 1}); + add_test_bin_bcast(type, {1280, 16, 16, 1}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {1280, 1, 1, 1}, {1, 256, 1, 1}); + add_test_bin_bcast(type, {1, 1, 1280, 1}, {16, 16, 1, 1}); + add_test_bin_bcast(type, {16, 16, 1280, 1}, {1, 1, 1, 1}); + add_test_bin_bcast(type, {1, 1, 1920, 1}, {16, 16, 1, 1}); + add_test_bin_bcast(type, {1, 1, 2560, 1}, {16, 16, 1, 1}); + add_test_bin_bcast(type, {1, 1, 1280, 1}, {32, 32, 1, 1}); + add_test_bin_bcast(type, {1, 1, 1920, 1}, {32, 32, 1, 1}); + add_test_bin_bcast(type, {1, 1, 640, 1}, {32, 32, 1, 1}); + add_test_bin_bcast(type, {5120, 1, 1, 1}, {1, 256, 1, 1}); + add_test_bin_bcast(type, {640, 1, 1, 1}, {1, 1, 1, 1}); + //add_test_bin_bcast(type, {3, 3, 2560, 1280}, {1, 1, 1, 1}); + //add_test_bin_bcast(type, {3, 3, 2560, 1280}, {2, 1, 1, 1}); + } test_cases.emplace_back(new test_add1()); test_cases.emplace_back(new test_scale()); From 4512055792cff7ea107f2d2231f79aa1af073c62 Mon Sep 17 00:00:00 2001 From: petterreinholdtsen Date: Wed, 26 Feb 2025 21:44:00 +0100 Subject: [PATCH 15/87] Told cmake to install ggml-cpp.h as a public header file. (ggml/1126) It is used by Whisper talk-llama example. Co-authored-by: Petter Reinholdtsen --- ggml/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ggml/CMakeLists.txt b/ggml/CMakeLists.txt index 9e7db3560..835bf16e5 100644 --- a/ggml/CMakeLists.txt +++ b/ggml/CMakeLists.txt @@ -250,6 +250,7 @@ set(GGML_PUBLIC_HEADERS include/ggml-backend.h include/ggml-blas.h include/ggml-cann.h + include/ggml-cpp.h include/ggml-cuda.h include/ggml-kompute.h include/ggml-opt.h From 6512a9003741bd3fe2e11bf3bb3608ec497d368d Mon Sep 17 00:00:00 2001 From: midnight Date: Wed, 5 Feb 2025 04:41:10 -0800 Subject: [PATCH 16/87] cmake : fix compile assumptions for power9/etc (whisper/2777) * Add small comment re: VSX to readme Co-authored-by: midnight --- ggml/src/ggml-cpu/CMakeLists.txt | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/ggml/src/ggml-cpu/CMakeLists.txt b/ggml/src/ggml-cpu/CMakeLists.txt index aa5ad5d8d..f8836ed61 100644 --- a/ggml/src/ggml-cpu/CMakeLists.txt +++ b/ggml/src/ggml-cpu/CMakeLists.txt @@ -281,19 +281,15 @@ function(ggml_add_cpu_backend_variant_impl tag_name) endif() elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64") message(STATUS "PowerPC detected") - execute_process(COMMAND bash -c "grep POWER10 /proc/cpuinfo | head -n 1" OUTPUT_VARIABLE POWER10_M) - string(FIND "${POWER10_M}" "POWER10" substring_index) - if (NOT DEFINED substring_index OR "${substring_index}" STREQUAL "") - set(substring_index -1) - endif() - - if (${substring_index} GREATER_EQUAL 0) - list(APPEND ARCH_FLAGS -mcpu=power10) + execute_process(COMMAND bash -c "grep POWER /proc/cpuinfo | head -n 1" OUTPUT_VARIABLE POWER_M) + if (${POWER_M} MATCHES "POWER10") + list(APPEND ARCH_FLAGS -mcpu=power10) + elseif (${POWER_M} MATCHES "POWER9") + list(APPEND ARCH_FLAGS -mcpu=power9) elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64le") - list(APPEND ARCH_FLAGS -mcpu=powerpc64le) + list(APPEND ARCH_FLAGS -mcpu=powerpc64le -mtune=native) else() - list(APPEND ARCH_FLAGS -mcpu=native -mtune=native) - # TODO: Add targets for Power8/Power9 (Altivec/VSX) and Power10(MMA) and query for big endian systems (ppc64/le/be) + list(APPEND ARCH_FLAGS -mcpu=powerpc64 -mtune=native) endif() elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "loongarch64") message(STATUS "loongarch64 detected") From 6d4c23b81b03c7b089a5f7a21ca73d1385d37191 Mon Sep 17 00:00:00 2001 From: Diego Devesa Date: Thu, 27 Feb 2025 13:35:07 +0100 Subject: [PATCH 17/87] whisper : support GGML_BACKEND_DL (whisper/2843) * whisper : support GGML_BACKEND_DL * fix DTW crash * whisper.objc : fix build - add ggml-cpp.h --------- Co-authored-by: Georgi Gerganov --- ggml/src/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ggml/src/CMakeLists.txt b/ggml/src/CMakeLists.txt index 0002ac18a..fcb354e16 100644 --- a/ggml/src/CMakeLists.txt +++ b/ggml/src/CMakeLists.txt @@ -226,6 +226,9 @@ add_library(ggml-base gguf.cpp) target_include_directories(ggml-base PRIVATE .) +if (GGML_BACKEND_DL) + target_compile_definitions(ggml-base PUBLIC GGML_BACKEND_DL) +endif() add_library(ggml ggml-backend-reg.cpp) From 87abb7e903635a2660e89f9336122f374d683e0a Mon Sep 17 00:00:00 2001 From: cmdr2 Date: Fri, 28 Feb 2025 12:34:39 +0530 Subject: [PATCH 18/87] cuda/cpu: Increase support for fp16 unary operations (ggml/1125) * Support fp16 unary operations in the CUDA backend * cpu: increase fp16 support for unary operators in the CPU backend * cuda: increase fp16 support for unary operators in the CUDA backend * Add test cases for fp16 unary operators * metal: update supports_op for unary operators that don't support fp16, to prevent test-backend-ops from failing * metal: fix PR comments for unary op support after fp16 unary tests --- ggml/src/ggml-cpu/ggml-cpu.c | 829 ++++++++++++++++++++++++++++++- ggml/src/ggml-cuda/clamp.cu | 23 +- ggml/src/ggml-cuda/ggml-cuda.cu | 12 + ggml/src/ggml-cuda/unary.cu | 526 ++++++++++++++------ ggml/src/ggml-cuda/unary.cuh | 6 + ggml/src/ggml-metal/ggml-metal.m | 16 +- tests/test-backend-ops.cpp | 29 +- 7 files changed, 1266 insertions(+), 175 deletions(-) diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c index 33ab5e9c6..9ab24522c 100644 --- a/ggml/src/ggml-cpu/ggml-cpu.c +++ b/ggml/src/ggml-cpu/ggml-cpu.c @@ -1432,6 +1432,12 @@ inline static void ggml_vec_sub_f16 (const int n, ggml_fp16_t * z, const ggml_fp inline static void ggml_vec_set_f32 (const int n, float * x, const float v) { for (int i = 0; i < n; ++i) x[i] = v; } inline static void ggml_vec_cpy_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = x[i]; } inline static void ggml_vec_neg_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = -x[i]; } +inline static void ggml_vec_neg_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(-GGML_FP16_TO_FP32(x[i])); + } +} + inline static void ggml_vec_mul_f32 (const int n, float * z, const float * x, const float * y) { for (int i = 0; i < n; ++i) z[i] = x[i]*y[i]; } inline static void ggml_vec_mul_f16 (const int n, ggml_fp16_t * z, const ggml_fp16_t * x, const ggml_fp16_t * y) { for (int i = 0; i < n; ++i) { @@ -1830,22 +1836,107 @@ inline static void ggml_vec_scale_f16(const int n, ggml_fp16_t * y, const float inline static void ggml_vec_norm_f32 (const int n, float * s, const float * x) { ggml_vec_dot_f32(n, s, 0, x, 0, x, 0, 1); *s = sqrtf(*s); } inline static void ggml_vec_sqr_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = x[i]*x[i]; } +inline static void ggml_vec_sqr_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + float v = GGML_FP16_TO_FP32(x[i]); + y[i] = GGML_FP32_TO_FP16(v*v); + } +} inline static void ggml_vec_sqrt_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = sqrtf(x[i]); } +inline static void ggml_vec_sqrt_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(sqrtf(GGML_FP16_TO_FP32(x[i]))); + } +} inline static void ggml_vec_log_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = logf(x[i]); } +inline static void ggml_vec_log_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(logf(GGML_FP16_TO_FP32(x[i]))); + } +} inline static void ggml_vec_sin_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = sinf(x[i]); } +inline static void ggml_vec_sin_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(sinf(GGML_FP16_TO_FP32(x[i]))); + } +} inline static void ggml_vec_cos_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = cosf(x[i]); } +inline static void ggml_vec_cos_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(cosf(GGML_FP16_TO_FP32(x[i]))); + } +} inline static void ggml_vec_abs_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = fabsf(x[i]); } +inline static void ggml_vec_abs_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(fabsf(GGML_FP16_TO_FP32(x[i]))); + } +} inline static void ggml_vec_sgn_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = (x[i] > 0.f) ? 1.f : ((x[i] < 0.f) ? -1.f : 0.f); } +inline static void ggml_vec_sgn_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + float v = GGML_FP16_TO_FP32(x[i]); + y[i] = GGML_FP32_TO_FP16((v > 0.f) ? 1.f : ((v < 0.f) ? -1.f : 0.f)); + } +} inline static void ggml_vec_step_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = (x[i] > 0.f) ? 1.f : 0.f; } +inline static void ggml_vec_step_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16((GGML_FP16_TO_FP32(x[i]) > 0.f) ? 1.f : 0.f); + } +} inline static void ggml_vec_tanh_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = tanhf(x[i]); } +inline static void ggml_vec_tanh_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(tanhf(GGML_FP16_TO_FP32(x[i]))); + } +} inline static void ggml_vec_elu_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = (x[i] > 0.f) ? x[i] : expm1f(x[i]); } +inline static void ggml_vec_elu_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(expm1f(GGML_FP16_TO_FP32(x[i]))); + } +} inline static void ggml_vec_relu_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = (x[i] > 0.f) ? x[i] : 0.f; } +inline static void ggml_vec_relu_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + float v = GGML_FP16_TO_FP32(x[i]); + y[i] = GGML_FP32_TO_FP16((v > 0.f) ? v : 0.f); + } +} inline static void ggml_vec_leaky_relu_f32 (const int n, float * y, const float * x, const float ns) { for (int i = 0; i < n; ++i) y[i] = ((x[i] > 0.f) ? x[i] : 0.f) + ns * ((x[i] < 0.0f) ? x[i] : 0.f); } +inline static void ggml_vec_leaky_relu_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x, const float ns) { + for (int i = 0; i < n; ++i) { + float v = GGML_FP16_TO_FP32(x[i]); + y[i] = GGML_FP32_TO_FP16(((v > 0.f) ? v : 0.f) + ns * ((v < 0.0f) ? v : 0.f)); + } +} inline static void ggml_vec_sigmoid_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = 1.f / (1.f + expf(-x[i])); } +inline static void ggml_vec_sigmoid_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(1.f / (1.f + expf(-GGML_FP16_TO_FP32(x[i])))); + } +} // TODO: optimize performance inline static void ggml_vec_hardswish_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = x[i] * fminf(1.0f, fmaxf(0.0f, (x[i] + 3.0f) / 6.0f)); } +inline static void ggml_vec_hardswish_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + float v = GGML_FP16_TO_FP32(x[i]); + y[i] = GGML_FP32_TO_FP16(v * fminf(1.0f, fmaxf(0.0f, (v + 3.0f) / 6.0f))); + } +} inline static void ggml_vec_hardsigmoid_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = fminf(1.0f, fmaxf(0.0f, (x[i] + 3.0f) / 6.0f)); } +inline static void ggml_vec_hardsigmoid_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(fminf(1.0f, fmaxf(0.0f, (GGML_FP16_TO_FP32(x[i]) + 3.0f) / 6.0f))); + } +} inline static void ggml_vec_exp_f32 (const int n, float * y, const float * x) { for (int i = 0; i < n; ++i) y[i] = expf(x[i]); } +inline static void ggml_vec_exp_f16 (const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = GGML_FP32_TO_FP16(expf(GGML_FP16_TO_FP32(x[i]))); + } +} static const float GELU_COEF_A = 0.044715f; static const float GELU_QUICK_COEF = -1.702f; @@ -1913,10 +2004,21 @@ inline static void ggml_vec_gelu_quick_f32(const int n, float * y, const float * } #endif +inline static void ggml_vec_gelu_quick_f16(const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + float v = GGML_FP16_TO_FP32(x[i]); + y[i] = GGML_FP32_TO_FP16(v*(1.0f/(1.0f+expf(GELU_QUICK_COEF*v)))); + } +} + // Sigmoid Linear Unit (SiLU) function inline static float ggml_silu_f32(float x) { return x/(1.0f + expf(-x)); } +inline static ggml_fp16_t ggml_silu_f16(ggml_fp16_t x) { + float v = GGML_FP16_TO_FP32(x); + return GGML_FP32_TO_FP16(v/(1.0f + expf(-v))); +} #if __FINITE_MATH_ONLY__ #error "some routines in ggml.c require non-finite math arithmetics -- pass -fno-finite-math-only to the compiler to fix" @@ -2140,6 +2242,12 @@ static void ggml_vec_silu_f32(const int n, float * y, const float * x) { } } +inline static void ggml_vec_silu_f16(const int n, ggml_fp16_t * y, const ggml_fp16_t * x) { + for (int i = 0; i < n; ++i) { + y[i] = ggml_silu_f16(x[i]); + } +} + static ggml_float ggml_vec_soft_max_f32(const int n, float * y, const float * x, float max) { int i = 0; ggml_float sum = 0; @@ -2211,12 +2319,24 @@ inline static float ggml_silu_backward_f32(float x, float dy) { return dy*s*(1.0f + x*(1.0f - s)); } +inline static ggml_fp16_t ggml_silu_backward_f16(ggml_fp16_t x, ggml_fp16_t dy) { + const float v = GGML_FP16_TO_FP32(x); + const float s = 1.0f/(1.0f + expf(-v)); + return GGML_FP32_TO_FP16(GGML_FP16_TO_FP32(dy)*s*(1.0f + v*(1.0f - s))); +} + inline static void ggml_vec_silu_backward_f32(const int n, float * dx, const float * x, const float * dy) { for (int i = 0; i < n; ++i) { dx[i] = ggml_silu_backward_f32(x[i], dy[i]); } } +inline static void ggml_vec_silu_backward_f16(const int n, ggml_fp16_t * dx, const ggml_fp16_t * x, const ggml_fp16_t * dy) { + for (int i = 0; i < n; ++i) { + dx[i] = ggml_silu_backward_f16(x[i], dy[i]); + } +} + inline static void ggml_vec_sum_f32(const int n, float * s, const float * x) { #ifndef GGML_USE_ACCELERATE ggml_float sum = 0.0; @@ -5623,6 +5743,31 @@ static void ggml_compute_forward_sqr_f32( } } +static void ggml_compute_forward_sqr_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + assert( dst->nb[0] == sizeof(ggml_fp16_t)); + assert(src0->nb[0] == sizeof(ggml_fp16_t)); + + for (int i = 0; i < n; i++) { + ggml_vec_sqr_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_sqr( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5634,6 +5779,10 @@ static void ggml_compute_forward_sqr( { ggml_compute_forward_sqr_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_sqr_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -5668,6 +5817,31 @@ static void ggml_compute_forward_sqrt_f32( } } +static void ggml_compute_forward_sqrt_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + assert( dst->nb[0] == sizeof(ggml_fp16_t)); + assert(src0->nb[0] == sizeof(ggml_fp16_t)); + + for (int i = 0; i < n; i++) { + ggml_vec_sqrt_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_sqrt( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5679,6 +5853,10 @@ static void ggml_compute_forward_sqrt( { ggml_compute_forward_sqrt_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_sqrt_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -5713,6 +5891,31 @@ static void ggml_compute_forward_log_f32( } } +static void ggml_compute_forward_log_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + GGML_ASSERT(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + GGML_ASSERT( dst->nb[0] == sizeof(ggml_fp16_t)); + GGML_ASSERT(src0->nb[0] == sizeof(ggml_fp16_t)); + + for (int i = 0; i < n; i++) { + ggml_vec_log_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_log( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5724,6 +5927,10 @@ static void ggml_compute_forward_log( { ggml_compute_forward_log_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_log_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -5758,6 +5965,31 @@ static void ggml_compute_forward_sin_f32( } } +static void ggml_compute_forward_sin_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + GGML_ASSERT(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + GGML_ASSERT( dst->nb[0] == sizeof(ggml_fp16_t)); + GGML_ASSERT(src0->nb[0] == sizeof(ggml_fp16_t)); + + for (int i = 0; i < n; i++) { + ggml_vec_sin_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_sin( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5769,6 +6001,10 @@ static void ggml_compute_forward_sin( { ggml_compute_forward_sin_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_sin_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -5803,6 +6039,31 @@ static void ggml_compute_forward_cos_f32( } } +static void ggml_compute_forward_cos_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + GGML_ASSERT(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + GGML_ASSERT( dst->nb[0] == sizeof(ggml_fp16_t)); + GGML_ASSERT(src0->nb[0] == sizeof(ggml_fp16_t)); + + for (int i = 0; i < n; i++) { + ggml_vec_cos_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_cos( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -5814,6 +6075,10 @@ static void ggml_compute_forward_cos( { ggml_compute_forward_cos_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_cos_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6471,6 +6736,30 @@ static void ggml_compute_forward_abs_f32( } } +static void ggml_compute_forward_abs_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_abs_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_abs( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6482,6 +6771,10 @@ static void ggml_compute_forward_abs( { ggml_compute_forward_abs_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_abs_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6515,6 +6808,30 @@ static void ggml_compute_forward_sgn_f32( } } +static void ggml_compute_forward_sgn_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_sgn_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_sgn( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6526,6 +6843,10 @@ static void ggml_compute_forward_sgn( { ggml_compute_forward_sgn_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_sgn_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6559,6 +6880,30 @@ static void ggml_compute_forward_neg_f32( } } +static void ggml_compute_forward_neg_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_neg_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_neg( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6570,6 +6915,10 @@ static void ggml_compute_forward_neg( { ggml_compute_forward_neg_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_neg_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6603,6 +6952,30 @@ static void ggml_compute_forward_step_f32( } } +static void ggml_compute_forward_step_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_step_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_step( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6614,6 +6987,10 @@ static void ggml_compute_forward_step( { ggml_compute_forward_step_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_step_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6647,6 +7024,30 @@ static void ggml_compute_forward_tanh_f32( } } +static void ggml_compute_forward_tanh_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_tanh_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_tanh( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6658,6 +7059,10 @@ static void ggml_compute_forward_tanh( { ggml_compute_forward_tanh_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_tanh_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6691,6 +7096,30 @@ static void ggml_compute_forward_elu_f32( } } +static void ggml_compute_forward_elu_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_elu_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_elu( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6702,6 +7131,10 @@ static void ggml_compute_forward_elu( { ggml_compute_forward_elu_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_elu_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6735,6 +7168,30 @@ static void ggml_compute_forward_relu_f32( } } +static void ggml_compute_forward_relu_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_relu_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_relu( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6746,6 +7203,10 @@ static void ggml_compute_forward_relu( { ggml_compute_forward_relu_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_relu_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6779,6 +7240,30 @@ static void ggml_compute_forward_sigmoid_f32( } } +static void ggml_compute_forward_sigmoid_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_sigmoid_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_sigmoid( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6790,6 +7275,10 @@ static void ggml_compute_forward_sigmoid( { ggml_compute_forward_sigmoid_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_sigmoid_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6838,6 +7327,46 @@ static void ggml_compute_forward_gelu_f32( } } +static void ggml_compute_forward_gelu_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int ith = params->ith; + const int nth = params->nth; + + const int nc = src0->ne[0]; + const int nr = ggml_nrows(src0); + + // rows per thread + const int dr = (nr + nth - 1)/nth; + + // row range for this thread + const int ir0 = dr*ith; + const int ir1 = MIN(ir0 + dr, nr); + + for (int i1 = ir0; i1 < ir1; i1++) { + ggml_vec_gelu_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i1*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i1*(src0->nb[1]))); + +#ifndef NDEBUG + for (int k = 0; k < nc; k++) { + const ggml_fp16_t x = ((ggml_fp16_t *) ((char *) dst->data + i1*( dst->nb[1])))[k]; + const float v = GGML_FP16_TO_FP32(x); + UNUSED(v); + assert(!isnan(v)); + assert(!isinf(v)); + } +#endif + } +} + static void ggml_compute_forward_gelu( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6849,6 +7378,10 @@ static void ggml_compute_forward_gelu( { ggml_compute_forward_gelu_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_gelu_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6897,6 +7430,46 @@ static void ggml_compute_forward_gelu_quick_f32( } } +static void ggml_compute_forward_gelu_quick_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int ith = params->ith; + const int nth = params->nth; + + const int nc = src0->ne[0]; + const int nr = ggml_nrows(src0); + + // rows per thread + const int dr = (nr + nth - 1)/nth; + + // row range for this thread + const int ir0 = dr*ith; + const int ir1 = MIN(ir0 + dr, nr); + + for (int i1 = ir0; i1 < ir1; i1++) { + ggml_vec_gelu_quick_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i1*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i1*(src0->nb[1]))); + +#ifndef NDEBUG + for (int k = 0; k < nc; k++) { + const ggml_fp16_t x = ((ggml_fp16_t *) ((char *) dst->data + i1*( dst->nb[1])))[k]; + const float v = GGML_FP16_TO_FP32(x); + UNUSED(v); + assert(!isnan(v)); + assert(!isinf(v)); + } +#endif + } +} + static void ggml_compute_forward_gelu_quick( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6908,6 +7481,10 @@ static void ggml_compute_forward_gelu_quick( { ggml_compute_forward_gelu_quick_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_gelu_quick_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -6956,6 +7533,46 @@ static void ggml_compute_forward_silu_f32( } } +static void ggml_compute_forward_silu_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int ith = params->ith; + const int nth = params->nth; + + const int nc = src0->ne[0]; + const int nr = ggml_nrows(src0); + + // rows per thread + const int dr = (nr + nth - 1)/nth; + + // row range for this thread + const int ir0 = dr*ith; + const int ir1 = MIN(ir0 + dr, nr); + + for (int i1 = ir0; i1 < ir1; i1++) { + ggml_vec_silu_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i1*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i1*(src0->nb[1]))); + +#ifndef NDEBUG + for (int k = 0; k < nc; k++) { + const ggml_fp16_t x = ((ggml_fp16_t *) ((char *) dst->data + i1*(dst->nb[1])))[k]; + const float v = GGML_FP16_TO_FP32(x); + UNUSED(v); + assert(!isnan(v)); + assert(!isinf(v)); + } +#endif + } +} + static void ggml_compute_forward_silu( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6967,6 +7584,10 @@ static void ggml_compute_forward_silu( { ggml_compute_forward_silu_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_silu_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -7005,6 +7626,36 @@ static void ggml_compute_forward_leaky_relu_f32( } } +static void ggml_compute_forward_leaky_relu_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + float negative_slope; + memcpy(&negative_slope, dst->op_params, sizeof(float)); + + assert(dst->nb[0] == sizeof(ggml_fp16_t)); + assert(src0->nb[0] == sizeof(ggml_fp16_t)); + + for (int i = 0; i < n; i++) { + ggml_vec_leaky_relu_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1])), negative_slope); + } +} + static void ggml_compute_forward_leaky_relu( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -7016,6 +7667,10 @@ static void ggml_compute_forward_leaky_relu( { ggml_compute_forward_leaky_relu_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_leaky_relu_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -7068,6 +7723,50 @@ static void ggml_compute_forward_silu_back_f32( } } +static void ggml_compute_forward_silu_back_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * grad = dst->src[0]; + const struct ggml_tensor * src1 = dst->src[1]; + + assert(ggml_is_contiguous_1(grad)); + assert(ggml_is_contiguous_1(src1)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src1, dst)); + assert(ggml_are_same_shape(src1, grad)); + + const int ith = params->ith; + const int nth = params->nth; + + const int nc = src1->ne[0]; + const int nr = ggml_nrows(src1); + + // rows per thread + const int dr = (nr + nth - 1)/nth; + + // row range for this thread + const int ir0 = dr*ith; + const int ir1 = MIN(ir0 + dr, nr); + + for (int i1 = ir0; i1 < ir1; i1++) { + ggml_vec_silu_backward_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i1*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src1->data + i1*(src1->nb[1])), + (ggml_fp16_t *) ((char *) grad->data + i1*(grad->nb[1]))); + + #ifndef NDEBUG + for (int k = 0; k < nc; k++) { + const float x = ((ggml_fp16_t *) ((char *) dst->data + i1*( dst->nb[1])))[k]; + const float v = GGML_FP16_TO_FP32(x); + UNUSED(v); + assert(!isnan(v)); + assert(!isinf(v)); + } + #endif + } +} + static void ggml_compute_forward_silu_back( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -7079,6 +7778,10 @@ static void ggml_compute_forward_silu_back( { ggml_compute_forward_silu_back_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_silu_back_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -7086,7 +7789,6 @@ static void ggml_compute_forward_silu_back( } } - static void ggml_compute_forward_hardswish_f32( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -7110,6 +7812,31 @@ static void ggml_compute_forward_hardswish_f32( (float *) ((char *) src0->data + i*(src0->nb[1]))); } } + +static void ggml_compute_forward_hardswish_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_hardswish_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_hardswish( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -7121,6 +7848,10 @@ static void ggml_compute_forward_hardswish( { ggml_compute_forward_hardswish_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_hardswish_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -7152,6 +7883,30 @@ static void ggml_compute_forward_hardsigmoid_f32( } } +static void ggml_compute_forward_hardsigmoid_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_hardsigmoid_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_hardsigmoid( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -7163,6 +7918,10 @@ static void ggml_compute_forward_hardsigmoid( { ggml_compute_forward_hardsigmoid_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_hardsigmoid_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -7194,6 +7953,30 @@ static void ggml_compute_forward_exp_f32( } } +static void ggml_compute_forward_exp_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + if (params->ith != 0) { + return; + } + + assert(ggml_is_contiguous_1(src0)); + assert(ggml_is_contiguous_1(dst)); + assert(ggml_are_same_shape(src0, dst)); + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + for (int i = 0; i < n; i++) { + ggml_vec_exp_f16(nc, + (ggml_fp16_t *) ((char *) dst->data + i*( dst->nb[1])), + (ggml_fp16_t *) ((char *) src0->data + i*(src0->nb[1]))); + } +} + static void ggml_compute_forward_exp( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -7205,6 +7988,10 @@ static void ggml_compute_forward_exp( { ggml_compute_forward_exp_f32(params, dst); } break; + case GGML_TYPE_F16: + { + ggml_compute_forward_exp_f16(params, dst); + } break; default: { GGML_ABORT("fatal error"); @@ -9489,6 +10276,43 @@ static void ggml_compute_forward_clamp_f32( } } +static void ggml_compute_forward_clamp_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + + float min; + float max; + memcpy(&min, (float *) dst->op_params + 0, sizeof(float)); + memcpy(&max, (float *) dst->op_params + 1, sizeof(float)); + + const int ith = params->ith; + const int nth = params->nth; + + const int n = ggml_nrows(src0); + const int nc = src0->ne[0]; + + const size_t nb00 = src0->nb[0]; + const size_t nb01 = src0->nb[1]; + + const size_t nb0 = dst->nb[0]; + const size_t nb1 = dst->nb[1]; + + GGML_ASSERT( nb0 == sizeof(ggml_fp16_t)); + GGML_ASSERT(nb00 == sizeof(ggml_fp16_t)); + + for (int j = ith; j < n; j += nth) { + ggml_fp16_t * dst_ptr = (ggml_fp16_t *) ((char *) dst->data + j*nb1); + ggml_fp16_t * src0_ptr = (ggml_fp16_t *) ((char *) src0->data + j*nb01); + + for (int i = 0; i < nc; i++) { + float v = GGML_FP16_TO_FP32(src0_ptr[i]); + dst_ptr[i] = GGML_FP32_TO_FP16(MAX(MIN(v, max), min)); + } + } +} + static void ggml_compute_forward_clamp( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -9501,6 +10325,9 @@ static void ggml_compute_forward_clamp( ggml_compute_forward_clamp_f32(params, dst); } break; case GGML_TYPE_F16: + { + ggml_compute_forward_clamp_f16(params, dst); + } break; case GGML_TYPE_BF16: case GGML_TYPE_Q4_0: case GGML_TYPE_Q4_1: diff --git a/ggml/src/ggml-cuda/clamp.cu b/ggml/src/ggml-cuda/clamp.cu index 8009a3e3d..611db8864 100644 --- a/ggml/src/ggml-cuda/clamp.cu +++ b/ggml/src/ggml-cuda/clamp.cu @@ -1,6 +1,7 @@ #include "clamp.cuh" -static __global__ void clamp_f32(const float * x, float * dst, const float min, const float max, const int k) { +template +static __global__ void op_clamp(const T * x, T * dst, const T min, const T max, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -10,25 +11,31 @@ static __global__ void clamp_f32(const float * x, float * dst, const float min, dst[i] = x[i] < min ? min : (x[i] > max ? max : x[i]); } -static void clamp_f32_cuda(const float * x, float * dst, const float min, const float max, const int k, cudaStream_t stream) { +template +static void clamp_cuda(const T * x, T * dst, const T min, const T max, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_CLAMP_BLOCK_SIZE - 1) / CUDA_CLAMP_BLOCK_SIZE; - clamp_f32<<>>(x, dst, min, max, k); + op_clamp<<>>(x, dst, min, max, k); } void ggml_cuda_op_clamp(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); float min; float max; memcpy(&min, dst->op_params, sizeof(float)); memcpy(&max, (float *) dst->op_params + 1, sizeof(float)); - clamp_f32_cuda(src0_d, dst_d, min, max, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + clamp_cuda((const half *)src0_d, (half *)dst_d, (half)min, (half)max, ggml_nelements(src0), stream); + } else { + clamp_cuda((const float *)src0_d, (float *)dst_d, (float)min, (float)max, ggml_nelements(src0), stream); + } } diff --git a/ggml/src/ggml-cuda/ggml-cuda.cu b/ggml/src/ggml-cuda/ggml-cuda.cu index d23686d16..a28b7037b 100644 --- a/ggml/src/ggml-cuda/ggml-cuda.cu +++ b/ggml/src/ggml-cuda/ggml-cuda.cu @@ -2147,6 +2147,12 @@ static bool ggml_cuda_compute_forward(ggml_backend_cuda_context & ctx, struct gg break; case GGML_OP_UNARY: switch (ggml_get_unary_op(dst)) { + case GGML_UNARY_OP_ABS: + ggml_cuda_op_abs(ctx, dst); + break; + case GGML_UNARY_OP_SGN: + ggml_cuda_op_sgn(ctx, dst); + break; case GGML_UNARY_OP_NEG: ggml_cuda_op_neg(ctx, dst); break; @@ -2244,6 +2250,9 @@ static bool ggml_cuda_compute_forward(ggml_backend_cuda_context & ctx, struct gg case GGML_OP_CLAMP: ggml_cuda_op_clamp(ctx, dst); break; + case GGML_OP_LOG: + ggml_cuda_op_log(ctx, dst); + break; case GGML_OP_NONE: case GGML_OP_RESHAPE: case GGML_OP_VIEW: @@ -2962,6 +2971,8 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g switch (op->op) { case GGML_OP_UNARY: switch (ggml_get_unary_op(op)) { + case GGML_UNARY_OP_ABS: + case GGML_UNARY_OP_SGN: case GGML_UNARY_OP_NEG: case GGML_UNARY_OP_STEP: case GGML_UNARY_OP_GELU: @@ -3168,6 +3179,7 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g case GGML_OP_SIN: case GGML_OP_COS: case GGML_OP_CLAMP: + case GGML_OP_LOG: return true; case GGML_OP_CONT: return op->src[0]->type != GGML_TYPE_BF16; diff --git a/ggml/src/ggml-cuda/unary.cu b/ggml/src/ggml-cuda/unary.cu index 6b21f407d..9b0eaaccd 100644 --- a/ggml/src/ggml-cuda/unary.cu +++ b/ggml/src/ggml-cuda/unary.cu @@ -1,6 +1,29 @@ #include "unary.cuh" -static __global__ void neg_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_abs(const T * x, T * dst, const int k) { + const int i = blockDim.x*blockIdx.x + threadIdx.x; + + if (i >= k) { + return; + } + + dst[i] = fabsf(x[i]); +} + +template +static __global__ void op_sgn(const T * x, T * dst, const int k) { + const int i = blockDim.x*blockIdx.x + threadIdx.x; + + if (i >= k) { + return; + } + + dst[i] = (T)(x[i] > (T)0.f ? 1.f : ((x[i] < (T)0.f ? -1.f : 0.f))); +} + +template +static __global__ void op_neg(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -10,61 +33,67 @@ static __global__ void neg_f32(const float * x, float * dst, const int k) { dst[i] = -x[i]; } -static __global__ void step_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_step(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = x[i] > 0.0f; + dst[i] = x[i] > (T)0.0f; } -static __global__ void gelu_f32(const float * x, float * dst, const int k) { - const float GELU_COEF_A = 0.044715f; - const float SQRT_2_OVER_PI = 0.79788456080286535587989211986876f; +template +static __global__ void op_gelu(const T * x, T * dst, const int k) { + const T GELU_COEF_A = 0.044715f; + const T SQRT_2_OVER_PI = 0.79788456080286535587989211986876f; const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - float xi = x[i]; - dst[i] = 0.5f*xi*(1.0f + tanhf(SQRT_2_OVER_PI*xi*(1.0f + GELU_COEF_A*xi*xi))); + T xi = x[i]; + dst[i] = (T)0.5f*xi*((T)1.0f + (T)tanhf(SQRT_2_OVER_PI*xi*((T)1.0f + GELU_COEF_A*xi*xi))); } -static __global__ void gelu_quick_f32(const float * x, float * dst, int k) { - const float GELU_QUICK_COEF = -1.702f; +template +static __global__ void op_gelu_quick(const T * x, T * dst, int k) { + const T GELU_QUICK_COEF = -1.702f; const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = x[i] * (1.0f / (1.0f + expf(GELU_QUICK_COEF * x[i]))); + dst[i] = x[i] * ((T)1.0f / ((T)1.0f + (T)expf(GELU_QUICK_COEF * x[i]))); } -static __global__ void silu_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_silu(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = x[i] / (1.0f + expf(-x[i])); + dst[i] = x[i] / ((T)1.0f + (T)expf(-x[i])); } -static __global__ void silu_back_f32( - const float * grad, const float * xf, float * dst, const int k) { +template +static __global__ void op_silu_back( + const T * grad, const T * xf, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - const float xfi = xf[i]; - const float s = 1.0f / (1.0f + expf(-xfi)); - dst[i] = grad[i] * s * (1.0f + xfi * (1.0f - s)); + const T xfi = xf[i]; + const T s = (T)1.0f / ((T)1.0f + (T)expf(-xfi)); + dst[i] = grad[i] * s * ((T)1.0f + xfi * ((T)1.0f - s)); } -static __global__ void tanh_f32(const float * x, float * dst, int k) { +template +static __global__ void op_tanh(const T * x, T * dst, int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; @@ -72,7 +101,8 @@ static __global__ void tanh_f32(const float * x, float * dst, int k) { dst[i] = tanhf(x[i]); } -static __global__ void relu_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_relu(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -81,34 +111,38 @@ static __global__ void relu_f32(const float * x, float * dst, const int k) { dst[i] = fmaxf(x[i], 0); } -static __global__ void sigmoid_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_sigmoid(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = 1.0f / (1.0f + expf(-x[i])); + dst[i] = (T)1.0f / ((T)1.0f + (T)expf(-x[i])); } -static __global__ void hardsigmoid_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_hardsigmoid(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = fminf(1.0f, fmaxf(0.0f, (x[i] + 3.0f) / 6.0f)); + dst[i] = fminf(1.0f, fmaxf(0.0f, (x[i] + (T)3.0f) / (T)6.0f)); } -static __global__ void hardswish_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_hardswish(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = x[i] * fminf(1.0f, fmaxf(0.0f, (x[i] + 3.0f) / 6.0f)); + dst[i] = x[i] * (T)fminf(1.0f, fmaxf(0.0f, (x[i] + (T)3.0f) / (T)6.0f)); } -static __global__ void exp_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_exp(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -117,15 +151,17 @@ static __global__ void exp_f32(const float * x, float * dst, const int k) { dst[i] = expf(x[i]); } -static __global__ void leaky_relu_f32(const float * x, float * dst, const int k, const float negative_slope) { +template +static __global__ void op_leaky_relu(const T * x, T * dst, const int k, const float negative_slope) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = fmaxf(x[i], 0) + fminf(x[i], 0.0f) * negative_slope; + dst[i] = (T)fmaxf(x[i], 0) + (T)fminf(x[i], 0.0f) * (T)negative_slope; } -static __global__ void sqr_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_sqr(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -134,7 +170,8 @@ static __global__ void sqr_f32(const float * x, float * dst, const int k) { dst[i] = x[i] * x[i]; } -static __global__ void sqrt_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_sqrt(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -143,7 +180,8 @@ static __global__ void sqrt_f32(const float * x, float * dst, const int k) { dst[i] = sqrtf(x[i]); } -static __global__ void sin_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_sin(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -152,7 +190,8 @@ static __global__ void sin_f32(const float * x, float * dst, const int k) { dst[i] = sinf(x[i]); } -static __global__ void cos_f32(const float * x, float * dst, const int k) { +template +static __global__ void op_cos(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { @@ -161,145 +200,248 @@ static __global__ void cos_f32(const float * x, float * dst, const int k) { dst[i] = cosf(x[i]); } -static void neg_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static __global__ void op_log(const T * x, T * dst, const int k) { + const int i = blockDim.x*blockIdx.x + threadIdx.x; + + if (i >= k) { + return; + } + dst[i] = logf(x[i]); +} + +template +static void abs_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_NEG_BLOCK_SIZE - 1) / CUDA_NEG_BLOCK_SIZE; - neg_f32<<>>(x, dst, k); + op_abs<<>>(x, dst, k); } -static void step_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void sgn_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { + const int num_blocks = (k + CUDA_NEG_BLOCK_SIZE - 1) / CUDA_NEG_BLOCK_SIZE; + op_sgn<<>>(x, dst, k); +} + +template +static void neg_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { + const int num_blocks = (k + CUDA_NEG_BLOCK_SIZE - 1) / CUDA_NEG_BLOCK_SIZE; + op_neg<<>>(x, dst, k); +} + +template +static void step_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_STEP_BLOCK_SIZE - 1) / CUDA_STEP_BLOCK_SIZE; - step_f32<<>>(x, dst, k); + op_step<<>>(x, dst, k); } -static void gelu_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void gelu_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_GELU_BLOCK_SIZE - 1) / CUDA_GELU_BLOCK_SIZE; - gelu_f32<<>>(x, dst, k); + op_gelu<<>>(x, dst, k); } -static void gelu_quick_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void gelu_quick_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_GELU_BLOCK_SIZE - 1) / CUDA_GELU_BLOCK_SIZE; - gelu_quick_f32<<>>(x, dst, k); + op_gelu_quick<<>>(x, dst, k); } -static void silu_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void silu_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_SILU_BLOCK_SIZE - 1) / CUDA_SILU_BLOCK_SIZE; - silu_f32<<>>(x, dst, k); + op_silu<<>>(x, dst, k); } -static void silu_back_f32_cuda(const float * grad, const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void silu_back_cuda(const T * grad, const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_SILU_BACK_BLOCK_SIZE - 1) / CUDA_SILU_BLOCK_SIZE; - silu_back_f32<<>>(grad, x, dst, k); + op_silu_back<<>>(grad, x, dst, k); } -static void tanh_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void tanh_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_TANH_BLOCK_SIZE - 1) / CUDA_TANH_BLOCK_SIZE; - tanh_f32<<>>(x, dst, k); + op_tanh<<>>(x, dst, k); } -static void relu_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void relu_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_RELU_BLOCK_SIZE - 1) / CUDA_RELU_BLOCK_SIZE; - relu_f32<<>>(x, dst, k); + op_relu<<>>(x, dst, k); } -static void sigmoid_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void sigmoid_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_SIGMOID_BLOCK_SIZE - 1) / CUDA_SIGMOID_BLOCK_SIZE; - sigmoid_f32<<>>(x, dst, k); + op_sigmoid<<>>(x, dst, k); } -static void hardsigmoid_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void hardsigmoid_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_HARDSIGMOID_BLOCK_SIZE - 1) / CUDA_HARDSIGMOID_BLOCK_SIZE; - hardsigmoid_f32<<>>(x, dst, k); + op_hardsigmoid<<>>(x, dst, k); } -static void hardswish_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void hardswish_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_HARDSWISH_BLOCK_SIZE - 1) / CUDA_HARDSWISH_BLOCK_SIZE; - hardswish_f32<<>>(x, dst, k); + op_hardswish<<>>(x, dst, k); } -static void exp_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void exp_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_EXP_BLOCK_SIZE - 1) / CUDA_EXP_BLOCK_SIZE; - exp_f32<<>>(x, dst, k); + op_exp<<>>(x, dst, k); } -static void leaky_relu_f32_cuda(const float * x, float * dst, const int k, const float negative_slope, cudaStream_t stream) { +template +static void leaky_relu_cuda(const T * x, T * dst, const int k, const float negative_slope, cudaStream_t stream) { const int num_blocks = (k + CUDA_RELU_BLOCK_SIZE - 1) / CUDA_RELU_BLOCK_SIZE; - leaky_relu_f32<<>>(x, dst, k, negative_slope); + op_leaky_relu<<>>(x, dst, k, negative_slope); } -static void sqr_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void sqr_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_SQR_BLOCK_SIZE - 1) / CUDA_SQR_BLOCK_SIZE; - sqr_f32<<>>(x, dst, k); + op_sqr<<>>(x, dst, k); } -static void sqrt_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void sqrt_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_SQRT_BLOCK_SIZE - 1) / CUDA_SQRT_BLOCK_SIZE; - sqrt_f32<<>>(x, dst, k); + op_sqrt<<>>(x, dst, k); } -static void sin_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void sin_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_SIN_BLOCK_SIZE - 1) / CUDA_SIN_BLOCK_SIZE; - sin_f32<<>>(x, dst, k); + op_sin<<>>(x, dst, k); } -static void cos_f32_cuda(const float * x, float * dst, const int k, cudaStream_t stream) { +template +static void cos_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_COS_BLOCK_SIZE - 1) / CUDA_COS_BLOCK_SIZE; - cos_f32<<>>(x, dst, k); + op_cos<<>>(x, dst, k); +} + +template +static void log_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { + const int num_blocks = (k + CUDA_COS_BLOCK_SIZE - 1) / CUDA_COS_BLOCK_SIZE; + op_log<<>>(x, dst, k); +} + +void ggml_cuda_op_abs(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + const ggml_tensor * src0 = dst->src[0]; + const void * src0_d = src0->data; + void * dst_d = dst->data; + cudaStream_t stream = ctx.stream(); + + GGML_ASSERT(ggml_is_contiguous(src0)); + + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); + + if (src0->type == GGML_TYPE_F16) { + abs_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + abs_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } +} + +void ggml_cuda_op_sgn(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + const ggml_tensor * src0 = dst->src[0]; + const void * src0_d = src0->data; + void * dst_d = dst->data; + cudaStream_t stream = ctx.stream(); + + GGML_ASSERT(ggml_is_contiguous(src0)); + + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); + + if (src0->type == GGML_TYPE_F16) { + sgn_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + sgn_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_neg(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - neg_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + neg_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + neg_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_step(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - step_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + step_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + step_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_gelu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - gelu_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + gelu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + gelu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_silu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - silu_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + silu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + silu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_silu_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { @@ -314,179 +456,263 @@ void ggml_cuda_op_silu_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - silu_back_f32_cuda(src0_d, src1_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + silu_back_cuda((const half *)src0_d, (const half *)src1_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + silu_back_cuda((const float*)src0_d, (const float*)src1_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_gelu_quick(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - gelu_quick_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + gelu_quick_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + gelu_quick_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_tanh(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - tanh_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + tanh_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + tanh_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - relu_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + relu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + relu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_sigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - sigmoid_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + sigmoid_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + sigmoid_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_hardsigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - hardsigmoid_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + hardsigmoid_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + hardsigmoid_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_hardswish(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - hardswish_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + hardswish_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + hardswish_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_exp(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - exp_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + exp_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + exp_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_leaky_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); float negative_slope; memcpy(&negative_slope, dst->op_params, sizeof(float)); - leaky_relu_f32_cuda(src0_d, dst_d, ggml_nelements(src0), negative_slope, stream); + if (src0->type == GGML_TYPE_F16) { + leaky_relu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), negative_slope, stream); + } else { + leaky_relu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), negative_slope, stream); + } } void ggml_cuda_op_sqr(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - sqr_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + sqr_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + sqr_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_sqrt(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - sqrt_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + sqrt_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + sqrt_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_sin(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - sin_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + sin_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + sin_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } void ggml_cuda_op_cos(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { const ggml_tensor * src0 = dst->src[0]; - const float * src0_d = (const float *)src0->data; - float * dst_d = (float *)dst->data; + const void * src0_d = src0->data; + void * dst_d = dst->data; cudaStream_t stream = ctx.stream(); GGML_ASSERT(ggml_is_contiguous(src0)); - GGML_ASSERT(src0->type == GGML_TYPE_F32); - GGML_ASSERT( dst->type == GGML_TYPE_F32); + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); - cos_f32_cuda(src0_d, dst_d, ggml_nelements(src0), stream); + if (src0->type == GGML_TYPE_F16) { + cos_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + cos_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } +} + +void ggml_cuda_op_log(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + const ggml_tensor * src0 = dst->src[0]; + const void * src0_d = src0->data; + void * dst_d = dst->data; + cudaStream_t stream = ctx.stream(); + + GGML_ASSERT(ggml_is_contiguous(src0)); + + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); + + if (src0->type == GGML_TYPE_F16) { + log_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + log_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } } diff --git a/ggml/src/ggml-cuda/unary.cuh b/ggml/src/ggml-cuda/unary.cuh index e7f62643a..940a1feed 100644 --- a/ggml/src/ggml-cuda/unary.cuh +++ b/ggml/src/ggml-cuda/unary.cuh @@ -16,6 +16,10 @@ #define CUDA_SIN_BLOCK_SIZE 256 #define CUDA_COS_BLOCK_SIZE 256 +void ggml_cuda_op_abs(ggml_backend_cuda_context & ctx, ggml_tensor * dst); + +void ggml_cuda_op_sgn(ggml_backend_cuda_context & ctx, ggml_tensor * dst); + void ggml_cuda_op_neg(ggml_backend_cuda_context & ctx, ggml_tensor * dst); void ggml_cuda_op_step(ggml_backend_cuda_context & ctx, ggml_tensor * dst); @@ -49,3 +53,5 @@ void ggml_cuda_op_sqrt(ggml_backend_cuda_context & ctx, ggml_tensor * dst); void ggml_cuda_op_sin(ggml_backend_cuda_context & ctx, ggml_tensor * dst); void ggml_cuda_op_cos(ggml_backend_cuda_context & ctx, ggml_tensor * dst); + +void ggml_cuda_op_log(ggml_backend_cuda_context & ctx, ggml_tensor * dst); diff --git a/ggml/src/ggml-metal/ggml-metal.m b/ggml/src/ggml-metal/ggml-metal.m index c550142a7..9eb9a0db6 100644 --- a/ggml/src/ggml-metal/ggml-metal.m +++ b/ggml/src/ggml-metal/ggml-metal.m @@ -1200,7 +1200,7 @@ static bool ggml_metal_supports_op(const struct ggml_backend_metal_device_contex case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_SILU: case GGML_UNARY_OP_ELU: - return ggml_is_contiguous(op->src[0]); + return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32; default: return false; } @@ -1210,21 +1210,26 @@ static bool ggml_metal_supports_op(const struct ggml_backend_metal_device_contex case GGML_OP_TRANSPOSE: case GGML_OP_PERMUTE: case GGML_OP_CONCAT: + return true; case GGML_OP_ADD: case GGML_OP_SUB: - case GGML_OP_ACC: case GGML_OP_MUL: case GGML_OP_DIV: + return op->src[0]->type == GGML_TYPE_F32; + case GGML_OP_ACC: case GGML_OP_REPEAT: case GGML_OP_SCALE: - case GGML_OP_CLAMP: case GGML_OP_CONV_TRANSPOSE_1D: return true; + case GGML_OP_CLAMP: + return op->src[0]->type == GGML_TYPE_F32; case GGML_OP_SQR: case GGML_OP_SQRT: case GGML_OP_SIN: case GGML_OP_COS: - return ggml_is_contiguous(op->src[0]); + return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32; + case GGML_OP_LOG: + return false; // TODO: implement case GGML_OP_SUM_ROWS: case GGML_OP_SOFT_MAX: case GGML_OP_GROUP_NORM: @@ -1254,10 +1259,11 @@ static bool ggml_metal_supports_op(const struct ggml_backend_metal_device_contex case GGML_OP_UPSCALE: case GGML_OP_PAD: case GGML_OP_PAD_REFLECT_1D: - case GGML_OP_ARANGE: case GGML_OP_TIMESTEP_EMBEDDING: case GGML_OP_ARGSORT: case GGML_OP_LEAKY_RELU: + return op->src[0]->type == GGML_TYPE_F32; + case GGML_OP_ARANGE: return true; case GGML_OP_FLASH_ATTN_EXT: if (op->src[1]->type != op->src[2]->type) { diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index e2412bf31..c393bf16b 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -3771,10 +3771,12 @@ static std::vector> make_test_cases_eval() { std::default_random_engine rng(0); // unary ops - for (int v : {0, 1}) { - for (int op = 0; op < GGML_UNARY_OP_COUNT; op++) { - test_cases.emplace_back(new test_unary((ggml_unary_op) op, GGML_TYPE_F32, { 128, 2, 2, 2 }, v)); - test_cases.emplace_back(new test_unary((ggml_unary_op) op, GGML_TYPE_F32, { 5, 7, 11, 13 }, v)); + for (ggml_type type : {GGML_TYPE_F16, GGML_TYPE_F32}) { + for (int v : {0, 1}) { + for (int op = 0; op < GGML_UNARY_OP_COUNT; op++) { + test_cases.emplace_back(new test_unary((ggml_unary_op) op, type, { 128, 2, 2, 2 }, v)); + test_cases.emplace_back(new test_unary((ggml_unary_op) op, type, { 5, 7, 11, 13 }, v)); + } } } @@ -3996,7 +3998,10 @@ static std::vector> make_test_cases_eval() { test_cases.emplace_back(new test_add1()); test_cases.emplace_back(new test_scale()); - test_cases.emplace_back(new test_silu_back()); + + for (ggml_type type : {GGML_TYPE_F16, GGML_TYPE_F32}) { + test_cases.emplace_back(new test_silu_back()); + } for (float eps : {0.0f, 1e-6f, 1e-4f, 1e-1f}) { for (bool v : {false, true}) { @@ -4156,12 +4161,14 @@ static std::vector> make_test_cases_eval() { } } - test_cases.emplace_back(new test_sqr()); - test_cases.emplace_back(new test_sqrt()); - test_cases.emplace_back(new test_log()); - test_cases.emplace_back(new test_sin()); - test_cases.emplace_back(new test_cos()); - test_cases.emplace_back(new test_clamp()); + for (ggml_type type : {GGML_TYPE_F16, GGML_TYPE_F32}) { + test_cases.emplace_back(new test_sqr(type)); + test_cases.emplace_back(new test_sqrt(type)); + test_cases.emplace_back(new test_log(type)); + test_cases.emplace_back(new test_sin(type)); + test_cases.emplace_back(new test_cos(type)); + test_cases.emplace_back(new test_clamp(type)); + } test_cases.emplace_back(new test_diag_mask_inf(GGML_TYPE_F32, {10, 10, 1, 1}, 5)); test_cases.emplace_back(new test_diag_mask_inf(GGML_TYPE_F32, {10, 10, 3, 1}, 5)); From 8371d445958195f9ecdff39f67c0b357f1347e3a Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Fri, 28 Feb 2025 09:09:58 +0200 Subject: [PATCH 19/87] sync : ggml ggml-ci --- scripts/sync-ggml.last | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sync-ggml.last b/scripts/sync-ggml.last index f99625dca..23938a754 100644 --- a/scripts/sync-ggml.last +++ b/scripts/sync-ggml.last @@ -1 +1 @@ -98a61a0d0b43cba06c3ac1c603813639552a0701 +0d1ea2e1e08944aba29885c3c9ef73ceec27ba49 From 0cbee131ad332a8dab5bc72315f085a544682c26 Mon Sep 17 00:00:00 2001 From: cmdr2 Date: Fri, 28 Feb 2025 12:36:46 +0200 Subject: [PATCH 20/87] cuda/vulkan: specify fp32-only support for some operations in supports_op (ggml/1129) ggml-ci --- ggml/src/ggml-cuda/ggml-cuda.cu | 2 +- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 11 ++++++----- tests/test-backend-ops.cpp | 5 +---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/ggml/src/ggml-cuda/ggml-cuda.cu b/ggml/src/ggml-cuda/ggml-cuda.cu index a28b7037b..b5d2c8411 100644 --- a/ggml/src/ggml-cuda/ggml-cuda.cu +++ b/ggml/src/ggml-cuda/ggml-cuda.cu @@ -3155,7 +3155,7 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g return false; } break; case GGML_OP_SILU_BACK: - return ggml_is_contiguous(op->src[0]); + return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32; break; case GGML_OP_NORM: case GGML_OP_RMS_NORM: diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index a413441eb..ff53bdfbe 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -8452,7 +8452,7 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: case GGML_UNARY_OP_SIGMOID: - return ggml_is_contiguous(op->src[0]); + return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32; default: return false; } @@ -8653,19 +8653,20 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm case GGML_OP_RMS_NORM: return ggml_is_contiguous(op->src[0]); case GGML_OP_ADD: - case GGML_OP_ACC: case GGML_OP_SUB: case GGML_OP_MUL: case GGML_OP_DIV: - case GGML_OP_CONCAT: case GGML_OP_SILU_BACK: case GGML_OP_RMS_NORM_BACK: - case GGML_OP_UPSCALE: - case GGML_OP_SCALE: case GGML_OP_SQR: case GGML_OP_SIN: case GGML_OP_COS: case GGML_OP_CLAMP: + return op->src[0]->type == GGML_TYPE_F32; + case GGML_OP_ACC: + case GGML_OP_CONCAT: + case GGML_OP_UPSCALE: + case GGML_OP_SCALE: case GGML_OP_PAD: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index c393bf16b..b4e3631ed 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -3998,10 +3998,7 @@ static std::vector> make_test_cases_eval() { test_cases.emplace_back(new test_add1()); test_cases.emplace_back(new test_scale()); - - for (ggml_type type : {GGML_TYPE_F16, GGML_TYPE_F32}) { - test_cases.emplace_back(new test_silu_back()); - } + test_cases.emplace_back(new test_silu_back()); for (float eps : {0.0f, 1e-6f, 1e-4f, 1e-1f}) { for (bool v : {false, true}) { From 3d1cf3cf3394f2288dca3e1fb1fbb467d366e4bb Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Fri, 28 Feb 2025 12:37:35 +0200 Subject: [PATCH 21/87] sync : ggml ggml-ci --- scripts/sync-ggml.last | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sync-ggml.last b/scripts/sync-ggml.last index 23938a754..0d9ba73af 100644 --- a/scripts/sync-ggml.last +++ b/scripts/sync-ggml.last @@ -1 +1 @@ -0d1ea2e1e08944aba29885c3c9ef73ceec27ba49 +ff9052988b76e137bcf92bb335733933ca196ac0 From b64d7cc2720a90c03480d9408fae40d936c110e2 Mon Sep 17 00:00:00 2001 From: cmdr2 Date: Mon, 3 Mar 2025 20:51:31 +0530 Subject: [PATCH 22/87] cuda: unary ops as float + de-duplicate (ggml/1130) --- ggml/src/ggml-cuda/clamp.cu | 10 +- ggml/src/ggml-cuda/unary.cu | 845 +++++++++--------------------------- 2 files changed, 210 insertions(+), 645 deletions(-) diff --git a/ggml/src/ggml-cuda/clamp.cu b/ggml/src/ggml-cuda/clamp.cu index 611db8864..fe415e7f7 100644 --- a/ggml/src/ggml-cuda/clamp.cu +++ b/ggml/src/ggml-cuda/clamp.cu @@ -1,20 +1,24 @@ #include "clamp.cuh" +static __device__ __forceinline__ float op_clamp(float x, float min, float max) { + return fminf(fmaxf(x, min), max); +} + template -static __global__ void op_clamp(const T * x, T * dst, const T min, const T max, const int k) { +static __global__ void op_clamp_kernel(const T * x, T * dst, const T min, const T max, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = x[i] < min ? min : (x[i] > max ? max : x[i]); + dst[i] = (T)op_clamp((float)x[i], (float)min, (float)max); } template static void clamp_cuda(const T * x, T * dst, const T min, const T max, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_CLAMP_BLOCK_SIZE - 1) / CUDA_CLAMP_BLOCK_SIZE; - op_clamp<<>>(x, dst, min, max, k); + op_clamp_kernel<<>>(x, dst, min, max, k); } diff --git a/ggml/src/ggml-cuda/unary.cu b/ggml/src/ggml-cuda/unary.cu index 9b0eaaccd..ec5773e01 100644 --- a/ggml/src/ggml-cuda/unary.cu +++ b/ggml/src/ggml-cuda/unary.cu @@ -1,447 +1,213 @@ #include "unary.cuh" -template -static __global__ void op_abs(const T * x, T * dst, const int k) { +static __device__ __forceinline__ float op_abs(float x) { + return fabsf(x); +} + +static __device__ __forceinline__ float op_sgn(float x) { + return (x > 0.f ? 1.f : ((x < 0.f ? -1.f : 0.f))); +} + +static __device__ __forceinline__ float op_neg(float x) { + return -x; +} + +static __device__ __forceinline__ float op_step(float x) { + return x > 0.0f; +} + +static __device__ __forceinline__ float op_gelu(float x) { + const float GELU_COEF_A = 0.044715f; + const float SQRT_2_OVER_PI = 0.79788456080286535587989211986876f; + + return 0.5f*x*(1.0f + tanhf(SQRT_2_OVER_PI*x*(1.0f + GELU_COEF_A*x*x))); +} + +static __device__ __forceinline__ float op_gelu_quick(float x) { + const float GELU_QUICK_COEF = -1.702f; + + return x * (1.0f / (1.0f + expf(GELU_QUICK_COEF * x))); +} + +static __device__ __forceinline__ float op_silu(float x) { + return x / (1.0f + expf(-x)); +} + +static __device__ __forceinline__ float op_tanh(float x) { + return tanhf(x); +} + +static __device__ __forceinline__ float op_relu(float x) { + return fmaxf(x, 0); +} + +static __device__ __forceinline__ float op_sigmoid(float x) { + return 1.0f / (1.0f + expf(-x)); +} + +static __device__ __forceinline__ float op_hardsigmoid(float x) { + return fminf(1.0f, fmaxf(0.0f, (x + 3.0f) / 6.0f)); +} + +static __device__ __forceinline__ float op_hardswish(float x) { + return x * fminf(1.0f, fmaxf(0.0f, (x + 3.0f) / 6.0f)); +} + +static __device__ __forceinline__ float op_exp(float x) { + return expf(x); +} + +static __device__ __forceinline__ float op_sqr(float x) { + return x * x; +} + +static __device__ __forceinline__ float op_sqrt(float x) { + return sqrtf(x); +} + +static __device__ __forceinline__ float op_sin(float x) { + return sinf(x); +} + +static __device__ __forceinline__ float op_cos(float x) { + return cosf(x); +} + +static __device__ __forceinline__ float op_log(float x) { + return logf(x); +} + +template +static __global__ void unary_op_kernel(const T * x, T * dst, const int k) { const int i = blockDim.x*blockIdx.x + threadIdx.x; if (i >= k) { return; } - dst[i] = fabsf(x[i]); + dst[i] = (T)op((float)x[i]); } -template -static __global__ void op_sgn(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - - dst[i] = (T)(x[i] > (T)0.f ? 1.f : ((x[i] < (T)0.f ? -1.f : 0.f))); -} - -template -static __global__ void op_neg(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - - dst[i] = -x[i]; -} - -template -static __global__ void op_step(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - - dst[i] = x[i] > (T)0.0f; -} - -template -static __global__ void op_gelu(const T * x, T * dst, const int k) { - const T GELU_COEF_A = 0.044715f; - const T SQRT_2_OVER_PI = 0.79788456080286535587989211986876f; - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - - T xi = x[i]; - dst[i] = (T)0.5f*xi*((T)1.0f + (T)tanhf(SQRT_2_OVER_PI*xi*((T)1.0f + GELU_COEF_A*xi*xi))); -} - -template -static __global__ void op_gelu_quick(const T * x, T * dst, int k) { - const T GELU_QUICK_COEF = -1.702f; - const int i = blockDim.x*blockIdx.x + threadIdx.x; - if (i >= k) { - return; - } - dst[i] = x[i] * ((T)1.0f / ((T)1.0f + (T)expf(GELU_QUICK_COEF * x[i]))); -} - -template -static __global__ void op_silu(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = x[i] / ((T)1.0f + (T)expf(-x[i])); -} - -template -static __global__ void op_silu_back( - const T * grad, const T * xf, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - - const T xfi = xf[i]; - const T s = (T)1.0f / ((T)1.0f + (T)expf(-xfi)); - dst[i] = grad[i] * s * ((T)1.0f + xfi * ((T)1.0f - s)); -} - -template -static __global__ void op_tanh(const T * x, T * dst, int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - if (i >= k) { - return; - } - dst[i] = tanhf(x[i]); -} - -template -static __global__ void op_relu(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = fmaxf(x[i], 0); -} - -template -static __global__ void op_sigmoid(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = (T)1.0f / ((T)1.0f + (T)expf(-x[i])); -} - -template -static __global__ void op_hardsigmoid(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = fminf(1.0f, fmaxf(0.0f, (x[i] + (T)3.0f) / (T)6.0f)); -} - -template -static __global__ void op_hardswish(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = x[i] * (T)fminf(1.0f, fmaxf(0.0f, (x[i] + (T)3.0f) / (T)6.0f)); -} - -template -static __global__ void op_exp(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = expf(x[i]); -} - -template -static __global__ void op_leaky_relu(const T * x, T * dst, const int k, const float negative_slope) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - if (i >= k) { - return; - } - dst[i] = (T)fmaxf(x[i], 0) + (T)fminf(x[i], 0.0f) * (T)negative_slope; -} - -template -static __global__ void op_sqr(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = x[i] * x[i]; -} - -template -static __global__ void op_sqrt(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = sqrtf(x[i]); -} - -template -static __global__ void op_sin(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = sinf(x[i]); -} - -template -static __global__ void op_cos(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = cosf(x[i]); -} - -template -static __global__ void op_log(const T * x, T * dst, const int k) { - const int i = blockDim.x*blockIdx.x + threadIdx.x; - - if (i >= k) { - return; - } - dst[i] = logf(x[i]); -} - -template -static void abs_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { +template +static void unary_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_NEG_BLOCK_SIZE - 1) / CUDA_NEG_BLOCK_SIZE; - op_abs<<>>(x, dst, k); + unary_op_kernel<<>>(x, dst, k); +} + +template +void ggml_cuda_op_unary(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + const ggml_tensor * src0 = dst->src[0]; + const void * src0_d = src0->data; + void * dst_d = dst->data; + cudaStream_t stream = ctx.stream(); + + GGML_ASSERT(ggml_is_contiguous(src0)); + + GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); + GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); + GGML_ASSERT(src0->type == dst->type); + + if (src0->type == GGML_TYPE_F16) { + unary_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); + } else { + unary_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + } +} + +void ggml_cuda_op_abs(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_sgn(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_neg(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_step(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_gelu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_gelu_quick(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_silu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_tanh(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_sigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_hardsigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_hardswish(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_exp(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_sqr(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_sqrt(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_sin(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_cos(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +void ggml_cuda_op_log(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { + ggml_cuda_op_unary(ctx, dst); +} + +/* silu_back */ + +static __device__ __forceinline__ float op_silu_back(float grad, float x) { + const float s = 1.0f / (1.0f + expf(-x)); + return grad * s * (1.0f + x * (1.0f - s)); } template -static void sgn_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_NEG_BLOCK_SIZE - 1) / CUDA_NEG_BLOCK_SIZE; - op_sgn<<>>(x, dst, k); -} +static __global__ void silu_back_kernel(const T * grad, const T * xf, T * dst, const int k) { + const int i = blockDim.x*blockIdx.x + threadIdx.x; -template -static void neg_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_NEG_BLOCK_SIZE - 1) / CUDA_NEG_BLOCK_SIZE; - op_neg<<>>(x, dst, k); -} + if (i >= k) { + return; + } -template -static void step_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_STEP_BLOCK_SIZE - 1) / CUDA_STEP_BLOCK_SIZE; - op_step<<>>(x, dst, k); -} - -template -static void gelu_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_GELU_BLOCK_SIZE - 1) / CUDA_GELU_BLOCK_SIZE; - op_gelu<<>>(x, dst, k); -} - -template -static void gelu_quick_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_GELU_BLOCK_SIZE - 1) / CUDA_GELU_BLOCK_SIZE; - op_gelu_quick<<>>(x, dst, k); -} - -template -static void silu_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_SILU_BLOCK_SIZE - 1) / CUDA_SILU_BLOCK_SIZE; - op_silu<<>>(x, dst, k); + dst[i] = (T)op_silu_back((float)grad[i], (float)xf[i]); } template static void silu_back_cuda(const T * grad, const T * x, T * dst, const int k, cudaStream_t stream) { const int num_blocks = (k + CUDA_SILU_BACK_BLOCK_SIZE - 1) / CUDA_SILU_BLOCK_SIZE; - op_silu_back<<>>(grad, x, dst, k); -} - -template -static void tanh_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_TANH_BLOCK_SIZE - 1) / CUDA_TANH_BLOCK_SIZE; - op_tanh<<>>(x, dst, k); -} - -template -static void relu_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_RELU_BLOCK_SIZE - 1) / CUDA_RELU_BLOCK_SIZE; - op_relu<<>>(x, dst, k); -} - -template -static void sigmoid_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_SIGMOID_BLOCK_SIZE - 1) / CUDA_SIGMOID_BLOCK_SIZE; - op_sigmoid<<>>(x, dst, k); -} - -template -static void hardsigmoid_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_HARDSIGMOID_BLOCK_SIZE - 1) / CUDA_HARDSIGMOID_BLOCK_SIZE; - op_hardsigmoid<<>>(x, dst, k); -} - -template -static void hardswish_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_HARDSWISH_BLOCK_SIZE - 1) / CUDA_HARDSWISH_BLOCK_SIZE; - op_hardswish<<>>(x, dst, k); -} - -template -static void exp_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_EXP_BLOCK_SIZE - 1) / CUDA_EXP_BLOCK_SIZE; - op_exp<<>>(x, dst, k); -} - -template -static void leaky_relu_cuda(const T * x, T * dst, const int k, const float negative_slope, cudaStream_t stream) { - const int num_blocks = (k + CUDA_RELU_BLOCK_SIZE - 1) / CUDA_RELU_BLOCK_SIZE; - op_leaky_relu<<>>(x, dst, k, negative_slope); -} - -template -static void sqr_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_SQR_BLOCK_SIZE - 1) / CUDA_SQR_BLOCK_SIZE; - op_sqr<<>>(x, dst, k); -} - -template -static void sqrt_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_SQRT_BLOCK_SIZE - 1) / CUDA_SQRT_BLOCK_SIZE; - op_sqrt<<>>(x, dst, k); -} - -template -static void sin_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_SIN_BLOCK_SIZE - 1) / CUDA_SIN_BLOCK_SIZE; - op_sin<<>>(x, dst, k); -} - -template -static void cos_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_COS_BLOCK_SIZE - 1) / CUDA_COS_BLOCK_SIZE; - op_cos<<>>(x, dst, k); -} - -template -static void log_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { - const int num_blocks = (k + CUDA_COS_BLOCK_SIZE - 1) / CUDA_COS_BLOCK_SIZE; - op_log<<>>(x, dst, k); -} - -void ggml_cuda_op_abs(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - abs_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - abs_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_sgn(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - sgn_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - sgn_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_neg(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - neg_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - neg_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_step(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - step_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - step_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_gelu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - gelu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - gelu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_silu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - silu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - silu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } + silu_back_kernel<<>>(grad, x, dst, k); } void ggml_cuda_op_silu_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { @@ -467,137 +233,27 @@ void ggml_cuda_op_silu_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) } } -void ggml_cuda_op_gelu_quick(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); +/* leaky relu */ - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - gelu_quick_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - gelu_quick_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } +static __device__ __forceinline__ float op_leaky_relu(float x, const float negative_slope) { + return fmaxf(x, 0) + fminf(x, 0.0f) * negative_slope; } -void ggml_cuda_op_tanh(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); +template +static __global__ void leaky_relu_kernel(const T * x, T * dst, const int k, const float negative_slope) { + const int i = blockDim.x*blockIdx.x + threadIdx.x; - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - tanh_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - tanh_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); + if (i >= k) { + return; } + + dst[i] = (T)op_leaky_relu((float)x[i], negative_slope); } -void ggml_cuda_op_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - relu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - relu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_sigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - sigmoid_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - sigmoid_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_hardsigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - hardsigmoid_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - hardsigmoid_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_hardswish(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - hardswish_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - hardswish_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_exp(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - exp_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - exp_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } +template +static void leaky_relu_cuda(const T * x, T * dst, const int k, const float negative_slope, cudaStream_t stream) { + const int num_blocks = (k + CUDA_RELU_BLOCK_SIZE - 1) / CUDA_RELU_BLOCK_SIZE; + leaky_relu_kernel<<>>(x, dst, k, negative_slope); } void ggml_cuda_op_leaky_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { @@ -621,98 +277,3 @@ void ggml_cuda_op_leaky_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) leaky_relu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), negative_slope, stream); } } - -void ggml_cuda_op_sqr(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - sqr_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - sqr_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_sqrt(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - sqrt_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - sqrt_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_sin(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - sin_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - sin_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_cos(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - cos_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - cos_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} - -void ggml_cuda_op_log(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { - const ggml_tensor * src0 = dst->src[0]; - const void * src0_d = src0->data; - void * dst_d = dst->data; - cudaStream_t stream = ctx.stream(); - - GGML_ASSERT(ggml_is_contiguous(src0)); - - GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); - GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); - GGML_ASSERT(src0->type == dst->type); - - if (src0->type == GGML_TYPE_F16) { - log_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); - } else { - log_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); - } -} From dfd6b2c0be191b3abe2fd9c1b25deff01c6249d8 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Mon, 3 Mar 2025 17:57:38 +0200 Subject: [PATCH 23/87] sync : ggml ggml-ci --- scripts/sync-ggml.last | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sync-ggml.last b/scripts/sync-ggml.last index 0d9ba73af..040b53ca3 100644 --- a/scripts/sync-ggml.last +++ b/scripts/sync-ggml.last @@ -1 +1 @@ -ff9052988b76e137bcf92bb335733933ca196ac0 +58ecf6b96d887e408b6869915863fa1126483d51 From becade5de77674696539163dfbaf5c041a1a8e97 Mon Sep 17 00:00:00 2001 From: David Huang <1969802+hjc4869@users.noreply.github.com> Date: Tue, 4 Mar 2025 05:10:54 +0800 Subject: [PATCH 24/87] HIP: implement FlashAttention via rocWMMA for CDNA and RDNA3+ (#12032) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds GGML_HIP_ROCWMMA_FATTN and rocwmma header check Adds rocWMMA support to fattn-wmma-f16 --- Signed-off-by: Carl Klemm Co-authored-by: Johannes Gäßler Co-authored-by: Ben Jackson --- ggml/CMakeLists.txt | 1 + ggml/src/ggml-cuda/common.cuh | 15 ++- ggml/src/ggml-cuda/fattn-common.cuh | 66 +++++++------ ggml/src/ggml-cuda/fattn-wmma-f16.cu | 136 ++++++++++++++------------- ggml/src/ggml-cuda/fattn.cu | 12 ++- ggml/src/ggml-hip/CMakeLists.txt | 10 ++ 6 files changed, 145 insertions(+), 95 deletions(-) diff --git a/ggml/CMakeLists.txt b/ggml/CMakeLists.txt index 835bf16e5..92a62ea6f 100644 --- a/ggml/CMakeLists.txt +++ b/ggml/CMakeLists.txt @@ -162,6 +162,7 @@ set_property(CACHE GGML_CUDA_COMPRESSION_MODE PROPERTY STRINGS "none;speed;balan option(GGML_HIP "ggml: use HIP" OFF) option(GGML_HIP_GRAPHS "ggml: use HIP graph, experimental, slow" OFF) option(GGML_HIP_NO_VMM "ggml: do not try to use HIP VMM" ON) +option(GGML_HIP_ROCWMMA_FATTN "ggml: enable rocWMMA for FlashAttention" OFF) option(GGML_HIP_UMA "ggml: use HIP unified memory architecture" OFF) option(GGML_VULKAN "ggml: use Vulkan" OFF) option(GGML_VULKAN_CHECK_RESULTS "ggml: run Vulkan op checks" OFF) diff --git a/ggml/src/ggml-cuda/common.cuh b/ggml/src/ggml-cuda/common.cuh index adf0d3ecb..1832314ec 100644 --- a/ggml/src/ggml-cuda/common.cuh +++ b/ggml/src/ggml-cuda/common.cuh @@ -62,6 +62,7 @@ #define GGML_CUDA_CC_RDNA2 (GGML_CUDA_CC_OFFSET_AMD + 0x1030) // RX 6000, minimum for dp4a #define GGML_CUDA_CC_RDNA3 (GGML_CUDA_CC_OFFSET_AMD + 0x1100) // RX 7000, minimum for WMMA +#define GGML_CUDA_CC_IS_AMD(cc) (cc >= GGML_CUDA_CC_OFFSET_AMD) #define GGML_CUDA_CC_IS_RDNA(cc) (cc >= GGML_CUDA_CC_RDNA1) #define GGML_CUDA_CC_IS_RDNA1(cc) (cc >= GGML_CUDA_CC_RDNA1 && cc < GGML_CUDA_CC_RDNA2) #define GGML_CUDA_CC_IS_RDNA2(cc) (cc >= GGML_CUDA_CC_RDNA2 && cc < GGML_CUDA_CC_RDNA3) @@ -196,6 +197,10 @@ typedef float2 dfloat2; #define FP16_MMA_AVAILABLE #endif // !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) && __CUDA_ARCH__ >= GGML_CUDA_CC_VOLTA +#if defined(GGML_HIP_ROCWMMA_FATTN) && (defined(CDNA) || defined(RDNA3)) +#define FP16_MMA_AVAILABLE +#endif // defined(GGML_HIP_ROCWMMA_FATTN) && (defined(CDNA) || defined(RDNA3)) + #if !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) && __CUDA_ARCH__ >= GGML_CUDA_CC_TURING #define NEW_MMA_AVAILABLE #endif // !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) && __CUDA_ARCH__ >= GGML_CUDA_CC_TURING @@ -223,12 +228,18 @@ static bool fast_fp16_hardware_available(const int cc) { // Any FP16 tensor core instructions are available for ggml code. static bool fp16_mma_available(const int cc) { - return cc < GGML_CUDA_CC_OFFSET_AMD && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_VOLTA; +#if defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__) && !defined(GGML_HIP_ROCWMMA_FATTN) + return false; +#else + return cc < GGML_CUDA_CC_OFFSET_AMD && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_VOLTA || + GGML_CUDA_CC_IS_CDNA(cc) || cc >= GGML_CUDA_CC_RDNA3; +#endif // defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__) && !defined(GGML_HIP_ROCWMMA_FATTN) } // To be used for feature selection of external libraries, e.g. cuBLAS. static bool fp16_mma_hardware_available(const int cc) { - return cc < GGML_CUDA_CC_OFFSET_AMD && cc >= GGML_CUDA_CC_VOLTA; + return cc < GGML_CUDA_CC_OFFSET_AMD && cc >= GGML_CUDA_CC_VOLTA || + GGML_CUDA_CC_IS_CDNA(cc) || cc >= GGML_CUDA_CC_RDNA3; } // Volta technically had FP16 tensor cores but they work very differently compared to Turing and later. diff --git a/ggml/src/ggml-cuda/fattn-common.cuh b/ggml/src/ggml-cuda/fattn-common.cuh index 7b9566fb4..46de14093 100644 --- a/ggml/src/ggml-cuda/fattn-common.cuh +++ b/ggml/src/ggml-cuda/fattn-common.cuh @@ -57,12 +57,13 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_0( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q4_0 * K_q4_0 = (const block_q4_0 *) K_c; + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; #pragma unroll - for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += WARP_SIZE) { + for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += warp_size) { const int k_KQ = k_KQ_0 + threadIdx.x; const int ib = k_KQ / QI8_1; @@ -70,7 +71,7 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_0( const int shift = k_KQ & (QI8_1/2); const int v = (get_int_b2(K_q4_0[ib].qs, iqs4) >> shift) & 0x0F0F0F0F; - const int u = Q_q8[k_KQ_0/WARP_SIZE]; + const int u = Q_q8[k_KQ_0/warp_size]; const int sumi = ggml_cuda_dp4a(v, u, 0); @@ -78,14 +79,14 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_0( if (std::is_same::value) { const half2 * Q_ds = (const half2 *) Q_ds_v; - const half2 sum2 = __half2half2(K_q4_0[ib].d) * Q_ds[k_KQ_0/WARP_SIZE]; + const half2 sum2 = __half2half2(K_q4_0[ib].d) * Q_ds[k_KQ_0/warp_size]; sum += (T) (((half) sumi)*__low2half(sum2) - __high2half(sum2) /* *8/QI8_1 == 1 */); } else #endif // FP16_AVAILABLE { const float2 * Q_ds = (const float2 *) Q_ds_v; - sum += (T) (__half2float(K_q4_0[ib].d) * (sumi*Q_ds[k_KQ_0/WARP_SIZE].x - (8/QI8_1)*Q_ds[k_KQ_0/WARP_SIZE].y)); + sum += (T) (__half2float(K_q4_0[ib].d) * (sumi*Q_ds[k_KQ_0/warp_size].x - (8/QI8_1)*Q_ds[k_KQ_0/warp_size].y)); } } @@ -97,12 +98,13 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_1( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q4_1 * K_q4_1 = (const block_q4_1 *) K_c; + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; #pragma unroll - for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += WARP_SIZE) { + for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += warp_size) { const int k_KQ = k_KQ_0 + threadIdx.x; const int ib = k_KQ / QI8_1; @@ -110,7 +112,7 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_1( const int shift = k_KQ & (QI8_1/2); const int v = (get_int_b4(K_q4_1[ib].qs, iqs4) >> shift) & 0x0F0F0F0F; - const int u = Q_q8[k_KQ_0/WARP_SIZE]; + const int u = Q_q8[k_KQ_0/warp_size]; const int sumi = ggml_cuda_dp4a(v, u, 0); @@ -118,7 +120,7 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_1( if (std::is_same::value) { const half2 * Q_ds = (const half2 *) Q_ds_v; - const half2 d4d8_m4s8 = K_q4_1[ib].dm * Q_ds[k_KQ_0/WARP_SIZE]; + const half2 d4d8_m4s8 = K_q4_1[ib].dm * Q_ds[k_KQ_0/warp_size]; const half2 sumid4d8_m4s8scaled = d4d8_m4s8 * make_half2(sumi, 1.0f/QI8_1); sum += (T) (__low2half(sumid4d8_m4s8scaled) + __high2half(sumid4d8_m4s8scaled)); } else @@ -126,8 +128,8 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_1( { const float2 * Q_ds = (const float2 *) Q_ds_v; - const float sumid4d8 = __low2float(K_q4_1[ib].dm)*Q_ds[k_KQ_0/WARP_SIZE].x * sumi; - const float m4s8scaled = __high2float(K_q4_1[ib].dm)*Q_ds[k_KQ_0/WARP_SIZE].y / QI8_1; + const float sumid4d8 = __low2float(K_q4_1[ib].dm)*Q_ds[k_KQ_0/warp_size].x * sumi; + const float m4s8scaled = __high2float(K_q4_1[ib].dm)*Q_ds[k_KQ_0/warp_size].y / QI8_1; sum += (T) (sumid4d8 + m4s8scaled); } @@ -141,12 +143,13 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_0( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q5_0 * K_q5_0 = (const block_q5_0 *) K_c; + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; #pragma unroll - for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += WARP_SIZE) { + for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += warp_size) { const int k_KQ = k_KQ_0 + threadIdx.x; const int ib = k_KQ / QI8_1; @@ -161,7 +164,7 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_0( v |= (vh << 18) & 0x00100000; // 2 -> 20 v |= (vh << 25) & 0x10000000; // 3 -> 28 - const int u = Q_q8[k_KQ_0/WARP_SIZE]; + const int u = Q_q8[k_KQ_0/warp_size]; const int sumi = ggml_cuda_dp4a(v, u, 0); @@ -169,14 +172,14 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_0( if (std::is_same::value) { const half2 * Q_ds = (const half2 *) Q_ds_v; - const half2 sum2 = __half2half2(K_q5_0[ib].d) * Q_ds[k_KQ_0/WARP_SIZE]; + const half2 sum2 = __half2half2(K_q5_0[ib].d) * Q_ds[k_KQ_0/warp_size]; sum += (T) (((half) sumi)*__low2half(sum2) - __high2half(sum2)*__float2half(2.0f)) /* *16/QI8_1 == 2 */; } else #endif // FP16_AVAILABLE { const float2 * Q_ds = (const float2 *) Q_ds_v; - sum += (T) (__half2float(K_q5_0[ib].d) * (sumi*Q_ds[k_KQ_0/WARP_SIZE].x - (16/QI8_1)*Q_ds[k_KQ_0/WARP_SIZE].y)); + sum += (T) (__half2float(K_q5_0[ib].d) * (sumi*Q_ds[k_KQ_0/warp_size].x - (16/QI8_1)*Q_ds[k_KQ_0/warp_size].y)); } } @@ -188,12 +191,13 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_1( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q5_1 * K_q5_1 = (const block_q5_1 *) K_c; + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; #pragma unroll - for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += WARP_SIZE) { + for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += warp_size) { const int k_KQ = k_KQ_0 + threadIdx.x; const int ib = k_KQ / QI8_1; @@ -208,7 +212,7 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_1( v |= (vh << 18) & 0x00100000; // 2 -> 20 v |= (vh << 25) & 0x10000000; // 3 -> 28 - const int u = Q_q8[k_KQ_0/WARP_SIZE]; + const int u = Q_q8[k_KQ_0/warp_size]; const int sumi = ggml_cuda_dp4a(v, u, 0); @@ -216,7 +220,7 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_1( if (std::is_same::value) { const half2 * Q_ds = (const half2 *) Q_ds_v; - const half2 d5d8_m5s8 = K_q5_1[ib].dm * Q_ds[k_KQ_0/WARP_SIZE]; + const half2 d5d8_m5s8 = K_q5_1[ib].dm * Q_ds[k_KQ_0/warp_size]; const half2 sumid5d8_m5s8scaled = d5d8_m5s8 * make_half2(sumi, 1.0f/QI8_1); sum += (T) (__low2half(sumid5d8_m5s8scaled) + __high2half(sumid5d8_m5s8scaled)); } else @@ -224,8 +228,8 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_1( { const float2 * Q_ds = (const float2 *) Q_ds_v; - const float sumid5d8 = __low2float(K_q5_1[ib].dm)*Q_ds[k_KQ_0/WARP_SIZE].x * sumi; - const float m5s8scaled = __high2float(K_q5_1[ib].dm)*Q_ds[k_KQ_0/WARP_SIZE].y / QI8_1; + const float sumid5d8 = __low2float(K_q5_1[ib].dm)*Q_ds[k_KQ_0/warp_size].x * sumi; + const float m5s8scaled = __high2float(K_q5_1[ib].dm)*Q_ds[k_KQ_0/warp_size].y / QI8_1; sum += (T) (sumid5d8 + m5s8scaled); } @@ -239,12 +243,13 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q8_0( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q8_0 * K_q8_0 = (const block_q8_0 *) K_c; + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; #pragma unroll - for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += WARP_SIZE) { + for (int k_KQ_0 = 0; k_KQ_0 < D/sizeof(int); k_KQ_0 += warp_size) { const int k_KQ = k_KQ_0 + threadIdx.x; const int ib = k_KQ / QI8_0; @@ -255,13 +260,13 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q8_0( T Q_d; if (std::is_same::value) { const half2 * Q_ds = (const half2 *) Q_ds_v; - Q_d = __low2half(Q_ds[k_KQ_0/WARP_SIZE]); + Q_d = __low2half(Q_ds[k_KQ_0/warp_size]); } else { const float2 * Q_ds = (const float2 *) Q_ds_v; - Q_d = Q_ds[k_KQ_0/WARP_SIZE].x; + Q_d = Q_ds[k_KQ_0/warp_size].x; } - sum += vec_dot_q8_0_q8_1_impl(&v, &Q_q8[k_KQ_0/WARP_SIZE], K_q8_0[ib].d, Q_d); + sum += vec_dot_q8_0_q8_1_impl(&v, &Q_q8[k_KQ_0/warp_size], K_q8_0[ib].d, Q_d); } return sum; @@ -272,6 +277,7 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_f16( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8 , const void * __restrict__ Q_ds_v) { const half2 * K_h2 = (const half2 *) K_c; + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_q8); GGML_UNUSED(Q_ds_v); @@ -282,11 +288,11 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_f16( half2 sum2 = make_half2(0.0f, 0.0f); #pragma unroll - for (int k_KQ_0 = 0; k_KQ_0 < D/2; k_KQ_0 += WARP_SIZE) { + for (int k_KQ_0 = 0; k_KQ_0 < D/2; k_KQ_0 += warp_size) { const int k_KQ = k_KQ_0 + threadIdx.x; const half2 K_ik = K_h2[k_KQ]; - sum2 += K_ik * Q_h2[k_KQ_0/WARP_SIZE]; + sum2 += K_ik * Q_h2[k_KQ_0/warp_size]; } return __low2half(sum2) + __high2half(sum2); @@ -298,12 +304,12 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_f16( float sum = 0.0f; #pragma unroll - for (int k_KQ_0 = 0; k_KQ_0 < D/2; k_KQ_0 += WARP_SIZE) { + for (int k_KQ_0 = 0; k_KQ_0 < D/2; k_KQ_0 += warp_size) { const int k_KQ = k_KQ_0 + threadIdx.x; const half2 K_ik = K_h2[k_KQ]; - sum += __low2float(K_ik) * Q_f2[k_KQ_0/WARP_SIZE].x; - sum += __high2float(K_ik) * Q_f2[k_KQ_0/WARP_SIZE].y; + sum += __low2float(K_ik) * Q_f2[k_KQ_0/warp_size].x; + sum += __high2float(K_ik) * Q_f2[k_KQ_0/warp_size].y; } return sum; @@ -698,6 +704,8 @@ void launch_fattn( GGML_ASSERT(Q->ne[3] == 1); + const int warp_size = ggml_cuda_info().devices[ctx.device].warp_size; + ggml_cuda_pool & pool = ctx.pool(); cudaStream_t main_stream = ctx.stream(); const int id = ggml_cuda_get_device(); @@ -750,7 +758,7 @@ void launch_fattn( const int ntiles_x = ((Q->ne[1] + ncols1 - 1) / ncols1); const int ntiles_total = ntiles_x * (Q->ne[2] / ncols2) * Q->ne[3]; - const dim3 block_dim(WARP_SIZE, nwarps, 1); + const dim3 block_dim(warp_size, nwarps, 1); dim3 blocks_num; if (parallel_blocks == 0) { // For short contexts it can be faster to have the SMs work on whole tiles because this lets us skip the fixup. @@ -796,6 +804,8 @@ void launch_fattn( const float m0 = powf(2.0f, -(max_bias ) / n_head_log2); const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2); + GGML_ASSERT(block_dim.x % warp_size == 0); + GGML_ASSERT(!GGML_CUDA_CC_IS_AMD(cc) || block_dim.x * block_dim.y <= 4 * (unsigned int)warp_size); fattn_kernel<<>>( (const char *) Q->data, K_data, diff --git a/ggml/src/ggml-cuda/fattn-wmma-f16.cu b/ggml/src/ggml-cuda/fattn-wmma-f16.cu index 8828652fb..622cf2857 100644 --- a/ggml/src/ggml-cuda/fattn-wmma-f16.cu +++ b/ggml/src/ggml-cuda/fattn-wmma-f16.cu @@ -7,14 +7,19 @@ #include "fattn-wmma-f16.cuh" #ifdef FP16_MMA_AVAILABLE +#if !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) #include +namespace wmma = nvcuda::wmma; +#elif defined(GGML_HIP_ROCWMMA_FATTN) && defined(FP16_MMA_AVAILABLE) +#undef HIP_ENABLE_WARP_SYNC_BUILTINS // conflicts with rocWMMA headers +#include +namespace wmma = rocwmma; +#endif // !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) #endif // FP16_MMA_AVAILABLE // D == head size, VKQ_stride == num VKQ rows calculated in parallel: template -#if !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) -__launch_bounds__(nwarps*WARP_SIZE, 1) -#endif // !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) +__launch_bounds__(nwarps*ggml_cuda_get_physical_warp_size(), 1) static __global__ void flash_attn_ext_f16( const char * __restrict__ Q, const char * __restrict__ K, @@ -51,7 +56,7 @@ static __global__ void flash_attn_ext_f16( const int ne1, const int ne2, const int ne3) { -#if defined(FLASH_ATTN_AVAILABLE) && __CUDA_ARCH__ == GGML_CUDA_CC_VOLTA +#if defined(FLASH_ATTN_AVAILABLE) && (__CUDA_ARCH__ == GGML_CUDA_CC_VOLTA || (defined(GGML_HIP_ROCWMMA_FATTN) && defined(FP16_MMA_AVAILABLE))) // Skip unused kernel variants for faster compilation: if (use_logit_softcap && !(D == 128 || D == 256)) { NO_DEVICE_CODE; @@ -60,6 +65,8 @@ static __global__ void flash_attn_ext_f16( //In this kernel Q, K, V are matrices while i, j, k are matrix indices. + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); + const int ic0 = ncols*(blockIdx.x / parallel_blocks); // Index of the first Q/QKV column to work on. const int ip = blockIdx.x % parallel_blocks; // Index in group of blocks running for the same column in parallel. @@ -68,11 +75,11 @@ static __global__ void flash_attn_ext_f16( constexpr int frag_m = ncols == 8 ? 32 : 16; constexpr int frag_n = ncols == 8 ? 8 : 16; static_assert(D % frag_m == 0, "If ncols == 8 then D % frag_m must be 0."); - typedef nvcuda::wmma::fragment frag_a_K; - typedef nvcuda::wmma::fragment frag_a_V; - typedef nvcuda::wmma::fragment frag_b; - typedef nvcuda::wmma::fragment frag_c_KQ; - typedef nvcuda::wmma::fragment frag_c_VKQ; + typedef wmma::fragment frag_a_K; + typedef wmma::fragment frag_a_V; + typedef wmma::fragment frag_b; + typedef wmma::fragment frag_c_KQ; + typedef wmma::fragment frag_c_VKQ; constexpr int KQ_stride_tc = nwarps*frag_m; // Number of KQ rows calculated in parallel. constexpr int VKQ_ratio = KQ_stride_tc/VKQ_stride; // Number of parallel VKQ accumulators needed to keep all warps busy. @@ -132,9 +139,9 @@ static __global__ void flash_attn_ext_f16( for (int j0 = 0; j0 < ncols; j0 += nwarps) { const int j = j0 + threadIdx.y; #pragma unroll - for (int i0 = 0; i0 < D/2; i0 += WARP_SIZE) { + for (int i0 = 0; i0 < D/2; i0 += warp_size) { const int i = i0 + threadIdx.x; - if (i0 + WARP_SIZE > D/2 && i >= D/2) { + if (i0 + warp_size > D/2 && i >= D/2) { break; } VKQ2[j*(D_padded/2) + i] = make_half2(0.0f, 0.0f); @@ -146,9 +153,9 @@ static __global__ void flash_attn_ext_f16( for (int j0 = 0; j0 < ncols; j0 += nwarps) { const int j = j0 + threadIdx.y; #pragma unroll - for (int i0 = 0; i0 < D; i0 += WARP_SIZE) { + for (int i0 = 0; i0 < D; i0 += warp_size) { const int i = i0 + threadIdx.x; - if (i0 + WARP_SIZE > D && i >= D) { + if (i0 + warp_size > D && i >= D) { break; } KQ[j*D_padded + i] = ic0 + j < ne01 ? Q_f[j*stride_Q + i] * scale : 0.0f; @@ -162,7 +169,7 @@ static __global__ void flash_attn_ext_f16( for (int i0 = 0; i0 < D; i0 += 16) { #pragma unroll for (int j0 = 0; j0 < ncols; j0 += frag_n) { - nvcuda::wmma::load_matrix_sync(Q_b[i0/16][j0/frag_n], KQ + j0*D_padded + i0, D_padded); + wmma::load_matrix_sync(Q_b[i0/16][j0/frag_n], KQ + j0*D_padded + i0, D_padded); } } @@ -176,20 +183,20 @@ static __global__ void flash_attn_ext_f16( frag_c_KQ KQ_c[ncols/frag_n]; #pragma unroll for (int j = 0; j < ncols/frag_n; ++j) { - nvcuda::wmma::fill_fragment(KQ_c[j], 0.0f); + wmma::fill_fragment(KQ_c[j], static_cast(0.0f)); } #pragma unroll for (int k_KQ_0 = 0; k_KQ_0 < D; k_KQ_0 += 16) { frag_a_K K_a; - nvcuda::wmma::load_matrix_sync(K_a, K_h + (k_VKQ_0 + i_KQ_0 + frag_m*threadIdx.y)*stride_KV + k_KQ_0, stride_KV); + wmma::load_matrix_sync(K_a, K_h + (k_VKQ_0 + i_KQ_0 + frag_m*threadIdx.y)*stride_KV + k_KQ_0, stride_KV); #pragma unroll for (int j = 0; j < ncols/frag_n; ++j) { - nvcuda::wmma::mma_sync(KQ_c[j], K_a, Q_b[k_KQ_0/16][j], KQ_c[j]); + wmma::mma_sync(KQ_c[j], K_a, Q_b[k_KQ_0/16][j], KQ_c[j]); } } #pragma unroll for (int j0 = 0; j0 < ncols; j0 += frag_n) { - nvcuda::wmma::store_matrix_sync((KQ_acc_t *) KQ + j0*kqs_padded + i_KQ_0 + frag_m*threadIdx.y, KQ_c[j0/frag_n], kqs_padded, nvcuda::wmma::mem_col_major); + wmma::store_matrix_sync((KQ_acc_t *) KQ + j0*kqs_padded + i_KQ_0 + frag_m*threadIdx.y, KQ_c[j0/frag_n], kqs_padded, wmma::mem_col_major); } } @@ -202,27 +209,27 @@ static __global__ void flash_attn_ext_f16( const int j = j0 + threadIdx.y; if (std::is_same::value) { - float KQ_f_tmp[FATTN_KQ_STRIDE / WARP_SIZE]; + float KQ_f_tmp[FATTN_KQ_STRIDE / warp_size]; #pragma unroll - for (int k0 = 0; k0 < FATTN_KQ_STRIDE; k0 += WARP_SIZE) { + for (int k0 = 0; k0 < FATTN_KQ_STRIDE; k0 += warp_size) { const int k = k0 + threadIdx.x; - KQ_f_tmp[k0/WARP_SIZE] = KQ_f[j*kqs_padded + k]; + KQ_f_tmp[k0/warp_size] = KQ_f[j*kqs_padded + k]; if (use_logit_softcap) { - KQ_f_tmp[k0/WARP_SIZE] = logit_softcap*tanhf(KQ_f_tmp[k0/WARP_SIZE]); + KQ_f_tmp[k0/warp_size] = logit_softcap*tanhf(KQ_f_tmp[k0/warp_size]); } } float KQ_max_new = KQ_max_f[j0/nwarps]; #pragma unroll - for (int k0 = 0; k0 < FATTN_KQ_STRIDE; k0 += WARP_SIZE) { + for (int k0 = 0; k0 < FATTN_KQ_STRIDE; k0 += warp_size) { const int k = k0 + threadIdx.x; - KQ_f_tmp[k0/WARP_SIZE] += mask ? __half2float(slopeh*maskh[j*(nb31/sizeof(half)) + k_VKQ_0 + k]) : 0.0f; - KQ_max_new = max(KQ_max_new, KQ_f_tmp[k0/WARP_SIZE]); + KQ_f_tmp[k0/warp_size] += mask ? __half2float(slopeh*maskh[j*(nb31/sizeof(half)) + k_VKQ_0 + k]) : 0.0f; + KQ_max_new = max(KQ_max_new, KQ_f_tmp[k0/warp_size]); } - KQ_max_new = warp_reduce_max(KQ_max_new); + KQ_max_new = warp_reduce_max(KQ_max_new); const float diff = KQ_max_f[j0/nwarps] - KQ_max_new; KQ_max_scale_f[j0/nwarps] = expf(diff); @@ -233,48 +240,48 @@ static __global__ void flash_attn_ext_f16( float KQ_rowsum_add = 0.0f; #pragma unroll - for (int k0 = 0; k0 < FATTN_KQ_STRIDE; k0 += WARP_SIZE) { + for (int k0 = 0; k0 < FATTN_KQ_STRIDE; k0 += warp_size) { const int k = k0 + threadIdx.x; - const float diff = KQ_f_tmp[k0/WARP_SIZE] - KQ_max_f[j0/nwarps]; - KQ_f_tmp[k0/WARP_SIZE] = expf(diff); + const float diff = KQ_f_tmp[k0/warp_size] - KQ_max_f[j0/nwarps]; + KQ_f_tmp[k0/warp_size] = expf(diff); if (diff <= SOFTMAX_FTZ_THRESHOLD) { - KQ_f_tmp[k0/WARP_SIZE] = 0.0f; + KQ_f_tmp[k0/warp_size] = 0.0f; } - KQ_rowsum_add += KQ_f_tmp[k0/WARP_SIZE]; - KQ[j*(kqar*kqs_padded) + k] = KQ_f_tmp[k0/WARP_SIZE]; + KQ_rowsum_add += KQ_f_tmp[k0/warp_size]; + KQ[j*(kqar*kqs_padded) + k] = KQ_f_tmp[k0/warp_size]; } - KQ_rowsum_add = warp_reduce_sum(KQ_rowsum_add); + KQ_rowsum_add = warp_reduce_sum(KQ_rowsum_add); // Scale previous KQ_rowsum to account for a potential increase in KQ_max: KQ_rowsum_f[j0/nwarps] = KQ_max_scale_f[j0/nwarps]*KQ_rowsum_f[j0/nwarps] + KQ_rowsum_add; } else { - half2 KQ2_tmp[FATTN_KQ_STRIDE/(2*WARP_SIZE)]; + half2 KQ2_tmp[FATTN_KQ_STRIDE/(2*warp_size)]; #pragma unroll - for (int k0 = 0; k0 < FATTN_KQ_STRIDE/2; k0 += WARP_SIZE) { + for (int k0 = 0; k0 < FATTN_KQ_STRIDE/2; k0 += warp_size) { const int k = k0 + threadIdx.x; - KQ2_tmp[k0/WARP_SIZE] = KQ2[j*(kqs_padded/2) + k]; + KQ2_tmp[k0/warp_size] = KQ2[j*(kqs_padded/2) + k]; if (use_logit_softcap) { // There is no dedicated tangens hyperbolicus function for half2. - KQ2_tmp[k0/WARP_SIZE] = h2exp(KQ2_tmp[k0/WARP_SIZE]*make_half2(2.0f, 2.0f)); - KQ2_tmp[k0/WARP_SIZE] = (KQ2_tmp[k0/WARP_SIZE] - make_half2(1.0f, 1.0f)) - /(KQ2_tmp[k0/WARP_SIZE] + make_half2(1.0f, 1.0f)); + KQ2_tmp[k0/warp_size] = h2exp(KQ2_tmp[k0/warp_size]*make_half2(2.0f, 2.0f)); + KQ2_tmp[k0/warp_size] = (KQ2_tmp[k0/warp_size] - make_half2(1.0f, 1.0f)) + /(KQ2_tmp[k0/warp_size] + make_half2(1.0f, 1.0f)); - KQ2_tmp[k0/WARP_SIZE] *= logit_softcap_2; + KQ2_tmp[k0/warp_size] *= logit_softcap_2; } } half2 KQ_max_new = KQ_max_h2[j0/nwarps]; #pragma unroll - for (int k0 = 0; k0 < FATTN_KQ_STRIDE/2; k0 += WARP_SIZE) { + for (int k0 = 0; k0 < FATTN_KQ_STRIDE/2; k0 += warp_size) { const int k = k0 + threadIdx.x; - KQ2_tmp[k0/WARP_SIZE] += mask ? slope2*mask2[(j*ne11 + k_VKQ_0)/2 + k] : make_half2(0.0f, 0.0f); - KQ_max_new = ggml_cuda_hmax2(KQ_max_new, KQ2_tmp[k0/WARP_SIZE]); + KQ2_tmp[k0/warp_size] += mask ? slope2*mask2[(j*ne11 + k_VKQ_0)/2 + k] : make_half2(0.0f, 0.0f); + KQ_max_new = ggml_cuda_hmax2(KQ_max_new, KQ2_tmp[k0/warp_size]); } - KQ_max_new = __half2half2(warp_reduce_max(ggml_cuda_hmax(__low2half(KQ_max_new), __high2half(KQ_max_new)))); + KQ_max_new = __half2half2(warp_reduce_max(ggml_cuda_hmax(__low2half(KQ_max_new), __high2half(KQ_max_new)))); const half2 diff = KQ_max_h2[j0/nwarps] - KQ_max_new; KQ_max_scale_h2[j0/nwarps] = h2exp(diff); const uint32_t ftz_mask = __hgt2_mask(diff, make_half2(SOFTMAX_FTZ_THRESHOLD, SOFTMAX_FTZ_THRESHOLD)); @@ -283,17 +290,17 @@ static __global__ void flash_attn_ext_f16( half2 KQ_rowsum_add = make_half2(0.0f, 0.0f); #pragma unroll - for (int k0 = 0; k0 < FATTN_KQ_STRIDE/2; k0 += WARP_SIZE) { + for (int k0 = 0; k0 < FATTN_KQ_STRIDE/2; k0 += warp_size) { const int k = k0 + threadIdx.x; - const half2 diff = KQ2_tmp[k0/WARP_SIZE] - KQ_max_h2[j0/nwarps]; - KQ2_tmp[k0/WARP_SIZE] = h2exp(diff); + const half2 diff = KQ2_tmp[k0/warp_size] - KQ_max_h2[j0/nwarps]; + KQ2_tmp[k0/warp_size] = h2exp(diff); const uint32_t ftz_mask = __hgt2_mask(diff, make_half2(SOFTMAX_FTZ_THRESHOLD, SOFTMAX_FTZ_THRESHOLD)); - *((uint32_t *) &KQ2_tmp[k0/WARP_SIZE]) &= ftz_mask; - KQ_rowsum_add += KQ2_tmp[k0/WARP_SIZE]; - KQ2[j*(kqs_padded/2) + k] = KQ2_tmp[k0/WARP_SIZE]; + *((uint32_t *) &KQ2_tmp[k0/warp_size]) &= ftz_mask; + KQ_rowsum_add += KQ2_tmp[k0/warp_size]; + KQ2[j*(kqs_padded/2) + k] = KQ2_tmp[k0/warp_size]; } - KQ_rowsum_add = warp_reduce_sum(KQ_rowsum_add); + KQ_rowsum_add = warp_reduce_sum(KQ_rowsum_add); // Scale previous KQ_rowsum to account for a potential increase in KQ_max: KQ_rowsum_h2[j0/nwarps] = KQ_max_scale_h2[j0/nwarps]*KQ_rowsum_h2[j0/nwarps] + KQ_rowsum_add; @@ -308,7 +315,7 @@ static __global__ void flash_attn_ext_f16( #pragma unroll for (int k0 = 0; k0 < FATTN_KQ_STRIDE; k0 += VKQ_ratio*16) { const int k = k0 + (threadIdx.y % VKQ_ratio)*16; - nvcuda::wmma::load_matrix_sync( + wmma::load_matrix_sync( KQ_b[k0/(VKQ_ratio*16)][j0/frag_n], KQ + j0*(kqar*kqs_padded) + k, kqar*kqs_padded); @@ -320,7 +327,7 @@ static __global__ void flash_attn_ext_f16( for (int i_VKQ_0 = 0; i_VKQ_0 < D; i_VKQ_0 += VKQ_stride) { #pragma unroll for (int j = 0; j < ncols/frag_n; ++j) { - nvcuda::wmma::fill_fragment(VKQ_c[i_VKQ_0/VKQ_stride][j], 0.0f); + wmma::fill_fragment(VKQ_c[i_VKQ_0/VKQ_stride][j], static_cast(0.0f)); } #pragma unroll @@ -328,10 +335,10 @@ static __global__ void flash_attn_ext_f16( const int k = k0 + (threadIdx.y % VKQ_ratio)*16; frag_a_V v_a; - nvcuda::wmma::load_matrix_sync(v_a, V_h + (k_VKQ_0 + k)*stride_KV + i_VKQ_0 + frag_m*(threadIdx.y/VKQ_ratio), stride_KV); + wmma::load_matrix_sync(v_a, V_h + (k_VKQ_0 + k)*stride_KV + i_VKQ_0 + frag_m*(threadIdx.y/VKQ_ratio), stride_KV); #pragma unroll for (int j = 0; j < ncols/frag_n; ++j) { - nvcuda::wmma::mma_sync(VKQ_c[i_VKQ_0/VKQ_stride][j], v_a, KQ_b[k0/(VKQ_ratio*16)][j], VKQ_c[i_VKQ_0/VKQ_stride][j]); + wmma::mma_sync(VKQ_c[i_VKQ_0/VKQ_stride][j], v_a, KQ_b[k0/(VKQ_ratio*16)][j], VKQ_c[i_VKQ_0/VKQ_stride][j]); } } } @@ -343,10 +350,10 @@ static __global__ void flash_attn_ext_f16( for (int i_KQ_0 = 0; i_KQ_0 < D; i_KQ_0 += VKQ_stride) { #pragma unroll for (int j0 = 0; j0 < ncols; j0 += frag_n) { - nvcuda::wmma::store_matrix_sync( + wmma::store_matrix_sync( KQ + offset_k + j0*D_padded + i_KQ_0 + frag_m*(threadIdx.y/VKQ_ratio), VKQ_c[i_KQ_0/VKQ_stride][j0/frag_n], - D_padded, nvcuda::wmma::mem_col_major); + D_padded, wmma::mem_col_major); } } @@ -364,9 +371,9 @@ static __global__ void flash_attn_ext_f16( } #pragma unroll - for (int i0 = 0; i0 < D/2; i0 += WARP_SIZE) { + for (int i0 = 0; i0 < D/2; i0 += warp_size) { const int i = i0 + threadIdx.x; - if (i0 + WARP_SIZE > D/2 && i >= D/2) { + if (i0 + warp_size > D/2 && i >= D/2) { break; } @@ -398,9 +405,9 @@ static __global__ void flash_attn_ext_f16( } #pragma unroll - for (int i0 = 0; i0 < D; i0 += WARP_SIZE) { + for (int i0 = 0; i0 < D; i0 += warp_size) { const int i = i0 + threadIdx.x; - if (i0 + WARP_SIZE > D && i >= D) { + if (i0 + warp_size > D && i >= D) { break; } float dst_val = VKQ[j_VKQ*D_padded + i]; @@ -425,7 +432,7 @@ static __global__ void flash_attn_ext_f16( } #else NO_DEVICE_CODE; -#endif // defined(FLASH_ATTN_AVAILABLE) && __CUDA_ARCH__ == GGML_CUDA_CC_VOLTA +#endif // defined(FLASH_ATTN_AVAILABLE) && (__CUDA_ARCH__ == GGML_CUDA_CC_VOLTA || (defined(GGML_HIP_ROCWMMA_FATTN) && defined(FP16_MMA_AVAILABLE))) } constexpr int get_max_power_of_2(int x) { @@ -515,6 +522,7 @@ void ggml_cuda_flash_attn_ext_wmma_f16(ggml_backend_cuda_context & ctx, ggml_ten const ggml_tensor * Q = dst->src[0]; const enum ggml_prec prec = ggml_flash_attn_ext_get_prec(KQV); + const int warp_size = ggml_cuda_info().devices[ctx.device].warp_size; if (prec != GGML_PREC_DEFAULT) { if (Q->ne[1] <= 32 || Q->ne[0] > 128) { @@ -571,7 +579,8 @@ void ggml_cuda_flash_attn_ext_wmma_f16(ggml_backend_cuda_context & ctx, ggml_ten return; } - if (Q->ne[1] <= 8 && Q->ne[0] % WARP_SIZE == 0) { +#if !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) + if (Q->ne[1] <= 8 && Q->ne[0] % warp_size == 0) { constexpr int cols_per_block = 8; switch (Q->ne[0]) { case 64: @@ -592,6 +601,7 @@ void ggml_cuda_flash_attn_ext_wmma_f16(ggml_backend_cuda_context & ctx, ggml_ten } return; } +#endif // !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) if (Q->ne[1] <= 32) { constexpr int cols_per_block = 16; diff --git a/ggml/src/ggml-cuda/fattn.cu b/ggml/src/ggml-cuda/fattn.cu index b1becccb4..24f973056 100644 --- a/ggml/src/ggml-cuda/fattn.cu +++ b/ggml/src/ggml-cuda/fattn.cu @@ -250,10 +250,18 @@ void ggml_cuda_flash_attn_ext(ggml_backend_cuda_context & ctx, ggml_tensor * dst ggml_cuda_set_device(ctx.device); const int cc = ggml_cuda_info().devices[ggml_cuda_get_device()].cc; + const int warp_size = ggml_cuda_info().devices[ggml_cuda_get_device()].warp_size; const enum ggml_prec prec = ggml_flash_attn_ext_get_prec(KQV); - // On AMD the tile kernels perform poorly, use the vec kernel instead: if (cc >= GGML_CUDA_CC_OFFSET_AMD) { +#if defined(GGML_HIP_ROCWMMA_FATTN) + if (fp16_mma_available(cc)) { + ggml_cuda_flash_attn_ext_wmma_f16(ctx, dst); + return; + } +#endif // defined(GGML_HIP_ROCWMMA_FATTN) + + // On AMD the tile kernels perform poorly, use the vec kernel instead: if (prec == GGML_PREC_DEFAULT && fast_fp16_available(cc)) { ggml_cuda_flash_attn_ext_vec_f16(ctx, dst); } else { @@ -291,7 +299,7 @@ void ggml_cuda_flash_attn_ext(ggml_backend_cuda_context & ctx, ggml_tensor * dst const int gqa_ratio = Q->ne[2] / K->ne[2]; const bool mma_fast_for_bs1 = fp16_mma_available(cc) && gqa_ratio % 2 == 0 && K->type == GGML_TYPE_F16 && V->type == GGML_TYPE_F16 && mask; - if (Q->ne[1] == 1 && Q->ne[0] % (2*WARP_SIZE) == 0 && !mma_fast_for_bs1) { + if (Q->ne[1] == 1 && Q->ne[0] % (2*warp_size) == 0 && !mma_fast_for_bs1) { if (prec == GGML_PREC_DEFAULT) { ggml_cuda_flash_attn_ext_vec_f16(ctx, dst); return; diff --git a/ggml/src/ggml-hip/CMakeLists.txt b/ggml/src/ggml-hip/CMakeLists.txt index 4a0384dd4..e3762649f 100644 --- a/ggml/src/ggml-hip/CMakeLists.txt +++ b/ggml/src/ggml-hip/CMakeLists.txt @@ -39,6 +39,12 @@ endif() find_package(hip REQUIRED) find_package(hipblas REQUIRED) find_package(rocblas REQUIRED) +if (GGML_HIP_ROCWMMA_FATTN) + CHECK_INCLUDE_FILE_CXX("rocwmma/rocwmma.hpp" FOUND_ROCWMMA) + if (NOT ${FOUND_ROCWMMA}) + message(FATAL_ERROR "rocwmma has not been found") + endif() +endif() if (${hip_VERSION} VERSION_LESS 5.5) message(FATAL_ERROR "At least ROCM/HIP V5.5 is required") @@ -107,6 +113,10 @@ if (GGML_HIP_NO_VMM) add_compile_definitions(GGML_HIP_NO_VMM) endif() +if (GGML_HIP_ROCWMMA_FATTN) + add_compile_definitions(GGML_HIP_ROCWMMA_FATTN) +endif() + if (NOT GGML_CUDA_FA) add_compile_definitions(GGML_CUDA_NO_FA) endif() From 1a24c4621f0280306b0d53a4fa474fc65d3f1b2e Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Tue, 4 Mar 2025 06:24:07 +0000 Subject: [PATCH 25/87] `server`: fix deadly typo in response_format.json_schema.schema handling (#12168) --- examples/server/tests/unit/test_chat_completion.py | 1 + examples/server/utils.hpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/server/tests/unit/test_chat_completion.py b/examples/server/tests/unit/test_chat_completion.py index af1dcb5b9..491cb3a5d 100644 --- a/examples/server/tests/unit/test_chat_completion.py +++ b/examples/server/tests/unit/test_chat_completion.py @@ -144,6 +144,7 @@ def test_apply_chat_template(): @pytest.mark.parametrize("response_format,n_predicted,re_content", [ ({"type": "json_object", "schema": {"const": "42"}}, 6, "\"42\""), ({"type": "json_object", "schema": {"items": [{"type": "integer"}]}}, 10, "[ -3000 ]"), + ({"type": "json_schema", "json_schema": {"schema": {"const": "foooooo"}}}, 10, "\"foooooo\""), ({"type": "json_object"}, 10, "(\\{|John)+"), ({"type": "sound"}, 0, None), # invalid response format (expected to fail) diff --git a/examples/server/utils.hpp b/examples/server/utils.hpp index 6830c2e1a..144d914c2 100644 --- a/examples/server/utils.hpp +++ b/examples/server/utils.hpp @@ -590,8 +590,8 @@ static json oaicompat_completion_params_parse( if (response_type == "json_object") { json_schema = json_value(response_format, "schema", json::object()); } else if (response_type == "json_schema") { - json json_schema = json_value(response_format, "json_schema", json::object()); - json_schema = json_value(json_schema, "schema", json::object()); + auto schema_wrapper = json_value(response_format, "json_schema", json::object()); + json_schema = json_value(schema_wrapper, "schema", json::object()); } else if (!response_type.empty() && response_type != "text") { throw std::runtime_error("response_format type must be one of \"text\" or \"json_object\", but got: " + response_type); } From 56d7a9f81274717fe035db192f315a049261c7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigbj=C3=B8rn=20Skj=C3=A6ret?= Date: Tue, 4 Mar 2025 17:19:39 +0100 Subject: [PATCH 26/87] main: allow preloading conversation with -p and add -st / --single-turn (#12145) * Add chat template formatting to -no-cnv * only enable prompt formatting if explicitly enabled * add -st / --single-turn * add --single-turn and -p in conversation mode * fix -sys + -p * reword warning * small readability change and fix (long) outdated example usage * only activate single turn in conversation mode --- common/arg.cpp | 9 +++++++ common/common.h | 2 ++ examples/main/main.cpp | 55 +++++++++++++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/common/arg.cpp b/common/arg.cpp index 8773caaef..3e549ede0 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -949,6 +949,15 @@ common_params_context common_params_parser_init(common_params & params, llama_ex params.conversation_mode = COMMON_CONVERSATION_MODE_DISABLED; } ).set_examples({LLAMA_EXAMPLE_MAIN})); + add_opt(common_arg( + {"-st", "--single-turn"}, + "run conversation for a single turn only, then exit when done\n" + "will not be interactive if first turn is predefined with --prompt\n" + "(default: false)", + [](common_params & params) { + params.single_turn = true; + } + ).set_examples({LLAMA_EXAMPLE_MAIN})); add_opt(common_arg( {"-i", "--interactive"}, string_format("run in interactive mode (default: %s)", params.interactive ? "true" : "false"), diff --git a/common/common.h b/common/common.h index 615d179de..f4b4a96fb 100644 --- a/common/common.h +++ b/common/common.h @@ -328,6 +328,8 @@ struct common_params { bool warmup = true; // warmup run bool check_tensors = false; // validate tensor data + bool single_turn = false; // single turn chat conversation + ggml_type cache_type_k = GGML_TYPE_F16; // KV cache data type for the K ggml_type cache_type_v = GGML_TYPE_F16; // KV cache data type for the V diff --git a/examples/main/main.cpp b/examples/main/main.cpp index acf79a892..4e0c69473 100644 --- a/examples/main/main.cpp +++ b/examples/main/main.cpp @@ -45,8 +45,8 @@ static void print_usage(int argc, char ** argv) { (void) argc; LOG("\nexample usage:\n"); - LOG("\n text generation: %s -m your_model.gguf -p \"I believe the meaning of life is\" -n 128\n", argv[0]); - LOG("\n chat (conversation): %s -m your_model.gguf -p \"You are a helpful assistant\" -cnv\n", argv[0]); + LOG("\n text generation: %s -m your_model.gguf -p \"I believe the meaning of life is\" -n 128 -no-cnv\n", argv[0]); + LOG("\n chat (conversation): %s -m your_model.gguf -sys \"You are a helpful assistant\"\n", argv[0]); LOG("\n"); } @@ -217,8 +217,8 @@ int main(int argc, char ** argv) { // print chat template example in conversation mode if (params.conversation_mode) { if (params.enable_chat_template) { - if (!params.prompt.empty()) { - LOG_WRN("*** User-specified prompt in conversation mode will be ignored, did you mean to set --system-prompt (-sys) instead?\n"); + if (!params.prompt.empty() && params.system_prompt.empty()) { + LOG_WRN("*** User-specified prompt will pre-start conversation, did you mean to set --system-prompt (-sys) instead?\n"); } LOG_INF("%s: chat template example:\n%s\n", __func__, common_chat_format_example(chat_templates.get(), params.use_jinja).c_str()); @@ -265,7 +265,7 @@ int main(int argc, char ** argv) { std::vector embd_inp; - bool waiting_for_first_input = params.conversation_mode && params.enable_chat_template && params.system_prompt.empty(); + bool waiting_for_first_input = false; auto chat_add_and_format = [&chat_msgs, &chat_templates](const std::string & role, const std::string & content) { common_chat_msg new_msg; new_msg.role = role; @@ -276,22 +276,34 @@ int main(int argc, char ** argv) { return formatted; }; + std::string prompt; { - std::string prompt; - if (params.conversation_mode && params.enable_chat_template) { - // format the system prompt in conversation mode (will use template default if empty) - prompt = params.system_prompt; + if (!params.system_prompt.empty()) { + // format the system prompt (will use template default if empty) + chat_add_and_format("system", params.system_prompt); + } - if (!prompt.empty()) { - prompt = chat_add_and_format("system", prompt); + if (!params.prompt.empty()) { + // format and append the user prompt + chat_add_and_format("user", params.prompt); + } else { + waiting_for_first_input = true; + } + + if (!params.system_prompt.empty() || !params.prompt.empty()) { + common_chat_templates_inputs inputs; + inputs.messages = chat_msgs; + inputs.add_generation_prompt = !params.prompt.empty(); + + prompt = common_chat_templates_apply(chat_templates.get(), inputs).prompt; } } else { // otherwise use the prompt as is prompt = params.prompt; } - if (params.interactive_first || !params.prompt.empty() || session_tokens.empty()) { + if (params.interactive_first || !prompt.empty() || session_tokens.empty()) { LOG_DBG("tokenize the prompt\n"); embd_inp = common_tokenize(ctx, prompt, true, true); } else { @@ -304,7 +316,7 @@ int main(int argc, char ** argv) { } // Should not run without any tokens - if (!params.conversation_mode && embd_inp.empty()) { + if (!waiting_for_first_input && embd_inp.empty()) { if (add_bos) { embd_inp.push_back(llama_vocab_bos(vocab)); LOG_WRN("embd_inp was considered empty and bos was added: %s\n", string_from(ctx, embd_inp).c_str()); @@ -364,7 +376,12 @@ int main(int argc, char ** argv) { } if (params.conversation_mode) { - params.interactive_first = true; + if (params.single_turn && !params.prompt.empty()) { + params.interactive = false; + params.interactive_first = false; + } else { + params.interactive_first = true; + } } // enable interactive mode if interactive start is specified @@ -808,6 +825,11 @@ int main(int argc, char ** argv) { if (params.conversation_mode && !waiting_for_first_input) { const auto id = common_sampler_last(smpl); assistant_ss << common_token_to_piece(ctx, id, false); + + if (!prompt.empty()) { + prompt.clear(); + is_interacting = false; + } } if ((n_past > 0 || waiting_for_first_input) && is_interacting) { @@ -905,6 +927,11 @@ int main(int argc, char ** argv) { common_sampler_reset(smpl); } is_interacting = false; + + if (waiting_for_first_input && params.single_turn) { + params.interactive = false; + params.interactive_first = false; + } waiting_for_first_input = false; } } From 20a9b8f5e1380243ed03aeb50ae1bf94b8d68501 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Tue, 4 Mar 2025 18:42:44 +0200 Subject: [PATCH 27/87] readme : fix roadmap link (#12185) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f7f1a521e..ffb59a422 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Server](https://github.com/ggml-org/llama.cpp/actions/workflows/server.yml/badge.svg)](https://github.com/ggml-org/llama.cpp/actions/workflows/server.yml) -[Roadmap](https://github.com/users/ggml-org/projects/7) / [Project status](https://github.com/ggml-org/llama.cpp/discussions/3471) / [Manifesto](https://github.com/ggml-org/llama.cpp/discussions/205) / [ggml](https://github.com/ggml-org/ggml) +[Roadmap](https://github.com/users/ggerganov/projects/7) / [Project status](https://github.com/ggml-org/llama.cpp/discussions/3471) / [Manifesto](https://github.com/ggml-org/llama.cpp/discussions/205) / [ggml](https://github.com/ggml-org/ggml) Inference of Meta's [LLaMA](https://arxiv.org/abs/2302.13971) model (and others) in pure C/C++ From 5bbe6a9fe9a8796a9389c85accec89dbc4d91e39 Mon Sep 17 00:00:00 2001 From: mgroeber9110 <45620825+mgroeber9110@users.noreply.github.com> Date: Tue, 4 Mar 2025 17:53:26 +0100 Subject: [PATCH 28/87] ggml : portability fixes for VS 2017 (#12150) * Add include files for std::min/max and std::toupper/tolower * win32: move _USE_MATH_DEFINES before includes to ensure M_PI is defined * Use GGML_RESTRICT instead of "restrict" keyword everywhere, and use "__restrict" in MSVC plain C mode * win32: only use __restrict in MSVC if C11/C17 support is not enabled --------- Co-authored-by: Marcus Groeber --- common/ngram-cache.cpp | 1 + common/sampling.cpp | 1 + common/speculative.cpp | 1 + examples/embedding/embedding.cpp | 1 + examples/lookahead/lookahead.cpp | 1 + examples/parallel/parallel.cpp | 1 + examples/passkey/passkey.cpp | 1 + examples/quantize/quantize.cpp | 1 + examples/tts/tts.cpp | 4 +- ggml/include/ggml.h | 6 +- ggml/src/ggml-backend-reg.cpp | 1 + ggml/src/ggml-backend.cpp | 1 + ggml/src/ggml-cpu/ggml-cpu-quants.c | 792 ++++++++++++++-------------- ggml/src/ggml-cpu/ggml-cpu.c | 26 +- ggml/src/ggml-quants.c | 228 ++++---- ggml/src/ggml.c | 6 +- src/llama-chat.cpp | 1 + src/llama-kv-cache.h | 1 + src/llama-mmap.cpp | 1 + src/llama-vocab.cpp | 1 + 20 files changed, 547 insertions(+), 529 deletions(-) diff --git a/common/ngram-cache.cpp b/common/ngram-cache.cpp index a057ae45f..d1a4d84c4 100644 --- a/common/ngram-cache.cpp +++ b/common/ngram-cache.cpp @@ -7,6 +7,7 @@ #include #include #include +#include void common_ngram_cache_update(common_ngram_cache & ngram_cache, int ngram_min, int ngram_max, std::vector & inp, int nnew, bool print_progress) { diff --git a/common/sampling.cpp b/common/sampling.cpp index 37a0d9c85..972fbe9da 100644 --- a/common/sampling.cpp +++ b/common/sampling.cpp @@ -4,6 +4,7 @@ #include #include +#include // the ring buffer works similarly to std::deque, but with a fixed capacity // TODO: deduplicate with llama-impl.h diff --git a/common/speculative.cpp b/common/speculative.cpp index b1fff27a5..1bac3a1ce 100644 --- a/common/speculative.cpp +++ b/common/speculative.cpp @@ -5,6 +5,7 @@ #include "sampling.h" #include +#include #define SPEC_VOCAB_MAX_SIZE_DIFFERENCE 128 #define SPEC_VOCAB_CHECK_START_TOKEN_ID 5 diff --git a/examples/embedding/embedding.cpp b/examples/embedding/embedding.cpp index 38d22c90f..3dd9f2b07 100644 --- a/examples/embedding/embedding.cpp +++ b/examples/embedding/embedding.cpp @@ -4,6 +4,7 @@ #include "llama.h" #include +#include #if defined(_MSC_VER) #pragma warning(disable: 4244 4267) // possible loss of data diff --git a/examples/lookahead/lookahead.cpp b/examples/lookahead/lookahead.cpp index 2f0898e62..b9e8de694 100644 --- a/examples/lookahead/lookahead.cpp +++ b/examples/lookahead/lookahead.cpp @@ -7,6 +7,7 @@ #include #include #include +#include struct ngram_data { bool active = false; diff --git a/examples/parallel/parallel.cpp b/examples/parallel/parallel.cpp index 7ef43d5e1..be18909ed 100644 --- a/examples/parallel/parallel.cpp +++ b/examples/parallel/parallel.cpp @@ -12,6 +12,7 @@ #include #include #include +#include // trim whitespace from the beginning and end of a string static std::string trim(const std::string & str) { diff --git a/examples/passkey/passkey.cpp b/examples/passkey/passkey.cpp index 5953928d4..fa8519051 100644 --- a/examples/passkey/passkey.cpp +++ b/examples/passkey/passkey.cpp @@ -7,6 +7,7 @@ #include #include #include +#include static void print_usage(int, char ** argv) { LOG("\nexample usage:\n"); diff --git a/examples/quantize/quantize.cpp b/examples/quantize/quantize.cpp index 8d47b17b6..a4468b169 100644 --- a/examples/quantize/quantize.cpp +++ b/examples/quantize/quantize.cpp @@ -8,6 +8,7 @@ #include #include #include +#include struct quant_option { std::string name; diff --git a/examples/tts/tts.cpp b/examples/tts/tts.cpp index 8108bac8c..c658f3182 100644 --- a/examples/tts/tts.cpp +++ b/examples/tts/tts.cpp @@ -1,3 +1,5 @@ +#define _USE_MATH_DEFINES // For M_PI on MSVC + #include "arg.h" #include "common.h" #include "sampling.h" @@ -5,8 +7,6 @@ #include "llama.h" #include "json.hpp" -#define _USE_MATH_DEFINES // For M_PI on MSVC - #include #include #include diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index dd0c6a96e..2e5076d36 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -2140,7 +2140,11 @@ extern "C" { # define GGML_RESTRICT # endif #else -# define GGML_RESTRICT restrict +# if defined (_MSC_VER) && (__STDC_VERSION__ < 201112L) +# define GGML_RESTRICT __restrict +# else +# define GGML_RESTRICT restrict +# endif #endif typedef void (*ggml_to_float_t) (const void * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k); typedef void (*ggml_from_float_t)(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k); diff --git a/ggml/src/ggml-backend-reg.cpp b/ggml/src/ggml-backend-reg.cpp index 23ddf41d4..d0d68becd 100644 --- a/ggml/src/ggml-backend-reg.cpp +++ b/ggml/src/ggml-backend-reg.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN diff --git a/ggml/src/ggml-backend.cpp b/ggml/src/ggml-backend.cpp index 184f99af5..273075f4e 100644 --- a/ggml/src/ggml-backend.cpp +++ b/ggml/src/ggml-backend.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef __APPLE__ #include diff --git a/ggml/src/ggml-cpu/ggml-cpu-quants.c b/ggml/src/ggml-cpu/ggml-cpu-quants.c index 2679b71ff..c30ac0318 100644 --- a/ggml/src/ggml-cpu/ggml-cpu-quants.c +++ b/ggml/src/ggml-cpu/ggml-cpu-quants.c @@ -719,28 +719,28 @@ static inline __m128i packNibbles( __m256i bytes ) { } #endif //__loongarch_asx -void quantize_row_q4_0(const float * restrict x, void * restrict y, int64_t k) { +void quantize_row_q4_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) { quantize_row_q4_0_ref(x, y, k); } -void quantize_row_q4_1(const float * restrict x, void * restrict y, int64_t k) { +void quantize_row_q4_1(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) { quantize_row_q4_1_ref(x, y, k); } -void quantize_row_q5_0(const float * restrict x, void * restrict y, int64_t k) { +void quantize_row_q5_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) { quantize_row_q5_0_ref(x, y, k); } -void quantize_row_q5_1(const float * restrict x, void * restrict y, int64_t k) { +void quantize_row_q5_1(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) { quantize_row_q5_1_ref(x, y, k); } -void quantize_row_q8_0(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_q8_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { assert(QK8_0 == 32); assert(k % QK8_0 == 0); const int nb = k / QK8_0; - block_q8_0 * restrict y = vy; + block_q8_0 * GGML_RESTRICT y = vy; #if defined(__ARM_NEON) for (int i = 0; i < nb; i++) { @@ -1050,11 +1050,11 @@ void quantize_row_q8_0(const float * restrict x, void * restrict vy, int64_t k) #endif } -void quantize_row_q8_1(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_q8_1(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { assert(k % QK8_1 == 0); const int nb = k / QK8_1; - block_q8_1 * restrict y = vy; + block_q8_1 * GGML_RESTRICT y = vy; #if defined(__ARM_NEON) for (int i = 0; i < nb; i++) { @@ -1428,8 +1428,8 @@ static inline int nearest_int(float fval) { return (i & 0x007fffff) - 0x00400000; } -static float make_qx_quants(int n, int nmax, const float * restrict x, int8_t * restrict L, int rmse_type, - const float * restrict qw) { +static float make_qx_quants(int n, int nmax, const float * GGML_RESTRICT x, int8_t * GGML_RESTRICT L, int rmse_type, + const float * GGML_RESTRICT qw) { float max = 0; float amax = 0; for (int i = 0; i < n; ++i) { @@ -1497,7 +1497,7 @@ static float make_qx_quants(int n, int nmax, const float * restrict x, int8_t * return scale; } -static float make_q3_quants(int n, int nmax, const float * restrict x, int8_t * restrict L, bool do_rmse) { +static float make_q3_quants(int n, int nmax, const float * GGML_RESTRICT x, int8_t * GGML_RESTRICT L, bool do_rmse) { float max = 0; float amax = 0; for (int i = 0; i < n; ++i) { @@ -1556,7 +1556,7 @@ static float make_q3_quants(int n, int nmax, const float * restrict x, int8_t * return 1/iscale; } -static float make_qkx1_quants(int n, int nmax, const float * restrict x, uint8_t * restrict L, float * restrict the_min, +static float make_qkx1_quants(int n, int nmax, const float * GGML_RESTRICT x, uint8_t * GGML_RESTRICT L, float * GGML_RESTRICT the_min, int ntry, float alpha) { float min = x[0]; float max = x[0]; @@ -1599,8 +1599,8 @@ static float make_qkx1_quants(int n, int nmax, const float * restrict x, uint8_t return scale; } -static float make_qkx2_quants(int n, int nmax, const float * restrict x, const float * restrict weights, - uint8_t * restrict L, float * restrict the_min, uint8_t * restrict Laux, +static float make_qkx2_quants(int n, int nmax, const float * GGML_RESTRICT x, const float * GGML_RESTRICT weights, + uint8_t * GGML_RESTRICT L, float * GGML_RESTRICT the_min, uint8_t * GGML_RESTRICT Laux, float rmin, float rdelta, int nstep, bool use_mad) { float min = x[0]; float max = x[0]; @@ -1680,7 +1680,7 @@ static float make_qkx2_quants(int n, int nmax, const float * restrict x, const f return scale; } -static inline void get_scale_min_k4(int j, const uint8_t * restrict q, uint8_t * restrict d, uint8_t * restrict m) { +static inline void get_scale_min_k4(int j, const uint8_t * GGML_RESTRICT q, uint8_t * GGML_RESTRICT d, uint8_t * GGML_RESTRICT m) { if (j < 4) { *d = q[j] & 63; *m = q[j + 4] & 63; } else { @@ -1691,51 +1691,51 @@ static inline void get_scale_min_k4(int j, const uint8_t * restrict q, uint8_t * //========================- 2-bit (de)-quantization -void quantize_row_q2_K(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_q2_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { quantize_row_q2_K_ref(x, vy, k); } //========================= 3-bit (de)-quantization -void quantize_row_q3_K(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_q3_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { quantize_row_q3_K_ref(x, vy, k); } // ====================== 4-bit (de)-quantization -void quantize_row_q4_K(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_q4_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { assert(k % QK_K == 0); - block_q4_K * restrict y = vy; + block_q4_K * GGML_RESTRICT y = vy; quantize_row_q4_K_ref(x, y, k); } // ====================== 5-bit (de)-quantization -void quantize_row_q5_K(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_q5_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { assert(k % QK_K == 0); - block_q5_K * restrict y = vy; + block_q5_K * GGML_RESTRICT y = vy; quantize_row_q5_K_ref(x, y, k); } // ====================== 6-bit (de)-quantization -void quantize_row_q6_K(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_q6_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { assert(k % QK_K == 0); - block_q6_K * restrict y = vy; + block_q6_K * GGML_RESTRICT y = vy; quantize_row_q6_K_ref(x, y, k); } // ====================== Ternary (de)-quantization (BitNet b1.58 and TriLMs) -void quantize_row_tq1_0(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_tq1_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { assert(k % QK_K == 0); - block_tq1_0 * restrict y = vy; + block_tq1_0 * GGML_RESTRICT y = vy; quantize_row_tq1_0_ref(x, y, k); } -void quantize_row_tq2_0(const float * restrict x, void * restrict vy, int64_t k) { +void quantize_row_tq2_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { assert(k % QK_K == 0); - block_tq2_0 * restrict y = vy; + block_tq2_0 * GGML_RESTRICT y = vy; quantize_row_tq2_0_ref(x, y, k); } @@ -1743,11 +1743,11 @@ static const int8_t kvalues_iq4nl[16] = {-127, -104, -83, -65, -49, -35, -22, -1 //===================================== Q8_K ============================================== -void quantize_row_q8_K(const float * restrict x, void * restrict y, int64_t k) { +void quantize_row_q8_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) { #ifdef __wasm_simd128__ assert(k % QK_K == 0); const int64_t nb = k / QK_K; - block_q8_K * restrict yc = y; // Cast to proper type + block_q8_K * GGML_RESTRICT yc = y; // Cast to proper type for (int i = 0; i < nb; i++) { const float * x_block = x + i * QK_K; @@ -1909,7 +1909,7 @@ static inline __m128i get_scale_shuffle(int i) { } #endif -void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q4_0_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { const int qk = QK8_0; const int nb = n / qk; @@ -1924,23 +1924,23 @@ void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q4_0 * restrict x = vx; - const block_q8_0 * restrict y = vy; + const block_q4_0 * GGML_RESTRICT x = vx; + const block_q8_0 * GGML_RESTRICT y = vy; #if defined(__ARM_FEATURE_MATMUL_INT8) if (nrc == 2) { - const block_q4_0 * restrict vx0 = vx; - const block_q4_0 * restrict vx1 = (const block_q4_0 *) ((const uint8_t*)vx + bx); - const block_q8_0 * restrict vy0 = vy; - const block_q8_0 * restrict vy1 = (const block_q8_0 *) ((const uint8_t*)vy + by); + const block_q4_0 * GGML_RESTRICT vx0 = vx; + const block_q4_0 * GGML_RESTRICT vx1 = (const block_q4_0 *) ((const uint8_t*)vx + bx); + const block_q8_0 * GGML_RESTRICT vy0 = vy; + const block_q8_0 * GGML_RESTRICT vy1 = (const block_q8_0 *) ((const uint8_t*)vy + by); float32x4_t sumv0 = vdupq_n_f32(0.0f); for (int i = 0; i < nb; i++) { - const block_q4_0 * restrict b_x0 = &vx0[i]; - const block_q4_0 * restrict b_x1 = &vx1[i]; - const block_q8_0 * restrict b_y0 = &vy0[i]; - const block_q8_0 * restrict b_y1 = &vy1[i]; + const block_q4_0 * GGML_RESTRICT b_x0 = &vx0[i]; + const block_q4_0 * GGML_RESTRICT b_x1 = &vx1[i]; + const block_q8_0 * GGML_RESTRICT b_y0 = &vy0[i]; + const block_q8_0 * GGML_RESTRICT b_y1 = &vy1[i]; const uint8x16_t m4b = vdupq_n_u8(0x0F); const int8x16_t s8b = vdupq_n_s8(0x8); @@ -2017,10 +2017,10 @@ void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * r const svbool_t ph4 = svptrue_pat_b32(SV_VL4); for (; ib + 1 < nb; ib += 2) { - const block_q4_0 * restrict x0 = &x[ib + 0]; - const block_q4_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q4_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q4_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; // load x const svuint8_t qx0r = svld1rq_u8(svptrue_b8(), x0->qs); @@ -2063,10 +2063,10 @@ void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * r const svbool_t pl16 = svnot_b_z(svptrue_b8(), ph16); for (; ib + 1 < nb; ib += 2) { - const block_q4_0 * restrict x0 = &x[ib + 0]; - const block_q4_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q4_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q4_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; // load x const svuint8_t qx0r = svld1rq_u8(svptrue_b8(), x0->qs); @@ -2104,10 +2104,10 @@ void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * r const svbool_t pl16 = svnot_b_z(ph32, ph16); for (; ib + 1 < nb; ib += 2) { - const block_q4_0 * restrict x0 = &x[ib + 0]; - const block_q4_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q4_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q4_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; // load x const svuint8_t qx0r = svld1rq_u8(ph32, x0->qs); @@ -2144,10 +2144,10 @@ void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * r float32x4_t sumv1 = vdupq_n_f32(0.0f); for (; ib + 1 < nb; ib += 2) { - const block_q4_0 * restrict x0 = &x[ib + 0]; - const block_q4_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q4_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q4_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; const uint8x16_t m4b = vdupq_n_u8(0x0F); const int8x16_t s8b = vdupq_n_s8(0x8); @@ -2189,10 +2189,10 @@ void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * r const v128_t s8b = wasm_i8x16_splat(0x8); for (; ib + 1 < nb; ib += 2) { - const block_q4_0 * restrict x0 = &x[ib]; - const block_q4_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q4_0 * GGML_RESTRICT x0 = &x[ib]; + const block_q4_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; // Load and process x0 v128_t v0_0 = wasm_v128_load(x0->qs); @@ -2609,7 +2609,7 @@ void ggml_vec_dot_q4_0_q8_0(int n, float * restrict s, size_t bs, const void * r *s = sumf; } -void ggml_vec_dot_q4_1_q8_1(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q4_1_q8_1(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { const int qk = QK8_1; const int nb = n / qk; @@ -2624,24 +2624,24 @@ void ggml_vec_dot_q4_1_q8_1(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q4_1 * restrict x = vx; - const block_q8_1 * restrict y = vy; + const block_q4_1 * GGML_RESTRICT x = vx; + const block_q8_1 * GGML_RESTRICT y = vy; #if defined(__ARM_FEATURE_MATMUL_INT8) if (nrc == 2) { - const block_q4_1 * restrict vx0 = vx; - const block_q4_1 * restrict vx1 = (const block_q4_1 *) ((const uint8_t*)vx + bx); - const block_q8_1 * restrict vy0 = vy; - const block_q8_1 * restrict vy1 = (const block_q8_1 *) ((const uint8_t*)vy + by); + const block_q4_1 * GGML_RESTRICT vx0 = vx; + const block_q4_1 * GGML_RESTRICT vx1 = (const block_q4_1 *) ((const uint8_t*)vx + bx); + const block_q8_1 * GGML_RESTRICT vy0 = vy; + const block_q8_1 * GGML_RESTRICT vy1 = (const block_q8_1 *) ((const uint8_t*)vy + by); float32x4_t sumv0 = vdupq_n_f32(0.0f); float32x4_t summs0 = vdupq_n_f32(0.0f); for (int i = 0; i < nb; i++) { - const block_q4_1 * restrict b_x0 = &vx0[i]; - const block_q4_1 * restrict b_x1 = &vx1[i]; - const block_q8_1 * restrict b_y0 = &vy0[i]; - const block_q8_1 * restrict b_y1 = &vy1[i]; + const block_q4_1 * GGML_RESTRICT b_x0 = &vx0[i]; + const block_q4_1 * GGML_RESTRICT b_x1 = &vx1[i]; + const block_q8_1 * GGML_RESTRICT b_y0 = &vy0[i]; + const block_q8_1 * GGML_RESTRICT b_y1 = &vy1[i]; float32_t summs_t[4] = { GGML_FP16_TO_FP32(b_x0->m) * GGML_FP16_TO_FP32(b_y0->s), @@ -2715,10 +2715,10 @@ void ggml_vec_dot_q4_1_q8_1(int n, float * restrict s, size_t bs, const void * r float summs = 0; for (; ib + 1 < nb; ib += 2) { - const block_q4_1 * restrict x0 = &x[ib + 0]; - const block_q4_1 * restrict x1 = &x[ib + 1]; - const block_q8_1 * restrict y0 = &y[ib + 0]; - const block_q8_1 * restrict y1 = &y[ib + 1]; + const block_q4_1 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q4_1 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_1 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_1 * GGML_RESTRICT y1 = &y[ib + 1]; summs += GGML_FP16_TO_FP32(x0->m) * GGML_FP16_TO_FP32(y0->s) + GGML_FP16_TO_FP32(x1->m) * GGML_FP16_TO_FP32(y1->s); @@ -2931,7 +2931,7 @@ void ggml_vec_dot_q4_1_q8_1(int n, float * restrict s, size_t bs, const void * r *s = sumf; } -void ggml_vec_dot_q5_0_q8_0(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q5_0_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { const int qk = QK8_0; const int nb = n / qk; @@ -2946,8 +2946,8 @@ void ggml_vec_dot_q5_0_q8_0(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q5_0 * restrict x = vx; - const block_q8_0 * restrict y = vy; + const block_q5_0 * GGML_RESTRICT x = vx; + const block_q8_0 * GGML_RESTRICT y = vy; #if defined(__ARM_NEON) float32x4_t sumv0 = vdupq_n_f32(0.0f); @@ -2960,10 +2960,10 @@ void ggml_vec_dot_q5_0_q8_0(int n, float * restrict s, size_t bs, const void * r uint64_t tmp1[4]; for (; ib + 1 < nb; ib += 2) { - const block_q5_0 * restrict x0 = &x[ib]; - const block_q5_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q5_0 * GGML_RESTRICT x0 = &x[ib]; + const block_q5_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; const uint8x16_t m4b = vdupq_n_u8(0x0F); @@ -3024,8 +3024,8 @@ void ggml_vec_dot_q5_0_q8_0(int n, float * restrict s, size_t bs, const void * r // TODO: check if unrolling this is better for (; ib < nb; ++ib) { - const block_q5_0 * restrict x0 = &x[ib]; - const block_q8_0 * restrict y0 = &y[ib]; + const block_q5_0 * GGML_RESTRICT x0 = &x[ib]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib]; const v128_t m4b = wasm_i8x16_splat(0x0F); @@ -3286,7 +3286,7 @@ void ggml_vec_dot_q5_0_q8_0(int n, float * restrict s, size_t bs, const void * r *s = sumf; } -void ggml_vec_dot_q5_1_q8_1(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q5_1_q8_1(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { const int qk = QK8_1; const int nb = n / qk; @@ -3301,8 +3301,8 @@ void ggml_vec_dot_q5_1_q8_1(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q5_1 * restrict x = vx; - const block_q8_1 * restrict y = vy; + const block_q5_1 * GGML_RESTRICT x = vx; + const block_q8_1 * GGML_RESTRICT y = vy; #if defined(__ARM_NEON) float32x4_t sumv0 = vdupq_n_f32(0.0f); @@ -3318,10 +3318,10 @@ void ggml_vec_dot_q5_1_q8_1(int n, float * restrict s, size_t bs, const void * r uint64_t tmp1[4]; for (; ib + 1 < nb; ib += 2) { - const block_q5_1 * restrict x0 = &x[ib]; - const block_q5_1 * restrict x1 = &x[ib + 1]; - const block_q8_1 * restrict y0 = &y[ib]; - const block_q8_1 * restrict y1 = &y[ib + 1]; + const block_q5_1 * GGML_RESTRICT x0 = &x[ib]; + const block_q5_1 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_1 * GGML_RESTRICT y0 = &y[ib]; + const block_q8_1 * GGML_RESTRICT y1 = &y[ib + 1]; const uint8x16_t m4b = vdupq_n_u8(0x0F); @@ -3387,8 +3387,8 @@ void ggml_vec_dot_q5_1_q8_1(int n, float * restrict s, size_t bs, const void * r // TODO: check if unrolling this is better for (; ib < nb; ++ib) { - const block_q5_1 * restrict x0 = &x[ib]; - const block_q8_1 * restrict y0 = &y[ib]; + const block_q5_1 * GGML_RESTRICT x0 = &x[ib]; + const block_q8_1 * GGML_RESTRICT y0 = &y[ib]; summs += GGML_FP16_TO_FP32(x0->m) * GGML_FP16_TO_FP32(y0->s); @@ -3660,7 +3660,7 @@ void ggml_vec_dot_q5_1_q8_1(int n, float * restrict s, size_t bs, const void * r *s = sumf; } -void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q8_0_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { const int qk = QK8_0; const int nb = n / qk; @@ -3675,24 +3675,24 @@ void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q8_0 * restrict x = vx; - const block_q8_0 * restrict y = vy; + const block_q8_0 * GGML_RESTRICT x = vx; + const block_q8_0 * GGML_RESTRICT y = vy; #if defined(__ARM_FEATURE_MATMUL_INT8) if (nrc == 2) { - const block_q8_0 * restrict vx0 = vx; - const block_q8_0 * restrict vx1 = (const block_q8_0 *) ((const uint8_t*)vx + bx); - const block_q8_0 * restrict vy0 = vy; - const block_q8_0 * restrict vy1 = (const block_q8_0 *) ((const uint8_t*)vy + by); + const block_q8_0 * GGML_RESTRICT vx0 = vx; + const block_q8_0 * GGML_RESTRICT vx1 = (const block_q8_0 *) ((const uint8_t*)vx + bx); + const block_q8_0 * GGML_RESTRICT vy0 = vy; + const block_q8_0 * GGML_RESTRICT vy1 = (const block_q8_0 *) ((const uint8_t*)vy + by); float32x4_t sumv0 = vdupq_n_f32(0.0f); for (int i = 0; i < nb; i++) { - const block_q8_0 * restrict b_x0 = &vx0[i]; - const block_q8_0 * restrict b_y0 = &vy0[i]; + const block_q8_0 * GGML_RESTRICT b_x0 = &vx0[i]; + const block_q8_0 * GGML_RESTRICT b_y0 = &vy0[i]; - const block_q8_0 * restrict b_x1 = &vx1[i]; - const block_q8_0 * restrict b_y1 = &vy1[i]; + const block_q8_0 * GGML_RESTRICT b_x1 = &vx1[i]; + const block_q8_0 * GGML_RESTRICT b_y1 = &vy1[i]; const int8x16_t x0_l = vld1q_s8(b_x0->qs); const int8x16_t x0_h = vld1q_s8(b_x0->qs + 16); @@ -3757,10 +3757,10 @@ void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * r const svbool_t pl16 = svptrue_pat_b32(SV_VL4); for (; ib + 1 < nb; ib += 2) { - const block_q8_0 * restrict x0 = &x[ib + 0]; - const block_q8_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q8_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q8_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; // load x const svint8_t qx0_0 = svld1_s8(ph16, x0->qs); @@ -3788,10 +3788,10 @@ void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * r { //printf("sve256"); for (; ib + 1 < nb; ib += 2) { - const block_q8_0 * restrict x0 = &x[ib + 0]; - const block_q8_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q8_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q8_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; // load x const svint8_t qx0 = svld1_s8(svptrue_b8(), x0->qs); @@ -3824,10 +3824,10 @@ void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * r svfloat32_t sumv00 = svdup_n_f32(0.0f); for (; ib + 1 < nb; ib += 2) { - const block_q8_0 * restrict x0 = &x[ib + 0]; - const block_q8_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q8_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q8_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; //load 32 int8_t in first half of vector and put another 32 int8_t in second vector lower bits // and add them to make one 64 element vector @@ -3867,10 +3867,10 @@ void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * r float32x4_t sumv1 = vdupq_n_f32(0.0f); for (; ib + 1 < nb; ib += 2) { - const block_q8_0 * restrict x0 = &x[ib + 0]; - const block_q8_0 * restrict x1 = &x[ib + 1]; - const block_q8_0 * restrict y0 = &y[ib + 0]; - const block_q8_0 * restrict y1 = &y[ib + 1]; + const block_q8_0 * GGML_RESTRICT x0 = &x[ib + 0]; + const block_q8_0 * GGML_RESTRICT x1 = &x[ib + 1]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib + 0]; + const block_q8_0 * GGML_RESTRICT y1 = &y[ib + 1]; const int8x16_t x0_0 = vld1q_s8(x0->qs); const int8x16_t x0_1 = vld1q_s8(x0->qs + 16); @@ -3897,8 +3897,8 @@ void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * r v128_t sumv = wasm_f32x4_splat(0.0f); for (; ib < nb; ++ib) { - const block_q8_0 * restrict x0 = &x[ib]; - const block_q8_0 * restrict y0 = &y[ib]; + const block_q8_0 * GGML_RESTRICT x0 = &x[ib]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib]; const v128_t x0_0 = wasm_v128_load(x0->qs); const v128_t x0_1 = wasm_v128_load(x0->qs + 16); @@ -4080,15 +4080,15 @@ void ggml_vec_dot_q8_0_q8_0(int n, float * restrict s, size_t bs, const void * r *s = sumf; } -void ggml_vec_dot_tq1_0_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_tq1_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs); - const block_tq1_0 * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_tq1_0 * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -4403,15 +4403,15 @@ void ggml_vec_dot_tq1_0_q8_K(int n, float * restrict s, size_t bs, const void * #endif } -void ggml_vec_dot_tq2_0_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_tq2_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs); - const block_tq2_0 * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_tq2_0 * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -4575,15 +4575,15 @@ void ggml_vec_dot_tq2_0_q8_K(int n, float * restrict s, size_t bs, const void * #endif } -void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q2_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs); - const block_q2_K * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_q2_K * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -4603,9 +4603,9 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); svfloat32_t dmin_broad = svdup_n_f32((float32_t)dmin); - const uint8_t * restrict q2 = x[i].qs; - const int8_t * restrict q8_sv = y[i].qs; - const uint8_t * restrict sc = x[i].scales; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8_sv = y[i].qs; + const uint8_t * GGML_RESTRICT sc = x[i].scales; svuint32_t mins_and_scales_sve = svld1ub_u32(svptrue_b32(), sc); const svint32_t mins_sv_1 = svreinterpret_s32_u32(svlsr_n_u32_x(svptrue_b32(), mins_and_scales_sve, 4)); @@ -4748,9 +4748,9 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); svfloat32_t dmin_broad = svdup_n_f32((float32_t)dmin); - const uint8_t * restrict q2 = x[i].qs; - const int8_t * restrict q8_sv = y[i].qs; - const uint8_t * restrict sc = x[i].scales; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8_sv = y[i].qs; + const uint8_t * GGML_RESTRICT sc = x[i].scales; const svuint32_t mins_and_scales_sve = svld1ub_u32(svptrue_pat_b32(SV_VL8), sc); sc += 8; const svint32_t scales_sv = svreinterpret_s32_u32(svand_u32_m(svptrue_pat_b32(SV_VL8), mins_and_scales_sve, m4s)); @@ -4847,9 +4847,9 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); - const uint8_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; - const uint8_t * restrict sc = x[i].scales; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; + const uint8_t * GGML_RESTRICT sc = x[i].scales; const uint8x16_t mins_and_scales = vld1q_u8(sc); const uint8x16_t scales = vandq_u8(mins_and_scales, m4); @@ -4912,8 +4912,8 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); - const uint8_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const __m128i mins_and_scales = _mm_loadu_si128((const __m128i*)x[i].scales); const __m128i scales8 = _mm_and_si128(mins_and_scales, m4); @@ -4979,8 +4979,8 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float dall = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); - const uint8_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // load mins and scales from block_q2_K.scales[QK_K/16] const __m128i mins_and_scales = _mm_loadu_si128((const __m128i*)x[i].scales); @@ -5306,8 +5306,8 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r vector signed int vsumi6 = v0; vector signed int vsumi7 = v0; - const uint8_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/128; ++j) { __builtin_prefetch(q2, 0, 1); @@ -5398,8 +5398,8 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); - const uint8_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const __m128i mins_and_scales128 = __lsx_vld((const __m128i*)x[i].scales, 0); const __m128i scales128 = __lsx_vandi_b(mins_and_scales128, 0xf); @@ -5492,7 +5492,7 @@ void ggml_vec_dot_q2_K_q8_K(int n, float * restrict s, size_t bs, const void * r #endif } -void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q3_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -5503,8 +5503,8 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r const uint32_t kmask1 = 0x03030303; const uint32_t kmask2 = 0x0f0f0f0f; - const block_q3_K * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_q3_K * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -5529,9 +5529,9 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q3_sv = x[i].qs; - const uint8_t * restrict qh_sv = x[i].hmask; - const int8_t * restrict q8_sv = y[i].qs; + const uint8_t * GGML_RESTRICT q3_sv = x[i].qs; + const uint8_t * GGML_RESTRICT qh_sv = x[i].hmask; + const int8_t * GGML_RESTRICT q8_sv = y[i].qs; // Set up scales memcpy(aux, x[i].scales, 12); @@ -5705,9 +5705,9 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict qh = x[i].hmask; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].hmask; + const int8_t * GGML_RESTRICT q8 = y[i].qs; ggml_uint8x16x2_t qhbits = ggml_vld1q_u8_x2(qh); @@ -5791,8 +5791,8 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q3 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // Set up scales memcpy(aux, x[i].scales, 12); @@ -5896,8 +5896,8 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q3 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // Set up scales aux = (const uint32_t *)x[i].scales; @@ -6030,9 +6030,9 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r float sumf = 0; for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict hm = x[i].hmask; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT hm = x[i].hmask; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // Process blocks with SIMD int8_t * a = aux8; @@ -6119,9 +6119,9 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r float sumf = 0; for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict qh = x[i].hmask; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].hmask; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(aux, x[i].scales, 12); utmp[3] = ((aux[1] >> 4) & kmask2) | (((aux[2] >> 6) & kmask1) << 4); @@ -6261,8 +6261,8 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r vector signed int vsumi6 = v0; vector signed int vsumi7 = v0; - const uint8_t * restrict q3 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/128; ++j) { __builtin_prefetch(q3, 0, 1); @@ -6375,8 +6375,8 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r for (int i = 0; i < nb; ++i) { const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q3 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // Set up scales memcpy(aux, x[i].scales, 12); __m128i scales128 = lsx_set_w( @@ -6461,11 +6461,11 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r float sumf = 0; for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict hm = x[i].hmask; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT hm = x[i].hmask; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memset(aux32, 0, 8*sizeof(int32_t)); - int8_t * restrict a = aux8; + int8_t * GGML_RESTRICT a = aux8; uint8_t m = 1; for (int j = 0; j < QK_K; j += 128) { for (int l = 0; l < 32; ++l) a[l] = q3[l] & 3; @@ -6508,7 +6508,7 @@ void ggml_vec_dot_q3_K_q8_K(int n, float * restrict s, size_t bs, const void * r } -void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q4_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -6516,8 +6516,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q4_K * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_q4_K * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -6552,8 +6552,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r const uint8_t * scales = (const uint8_t *)utmp; - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const int vector_length = ggml_cpu_get_sve_cnt()*8; const svuint8_t m4b = svdup_n_u8(0xf); @@ -6640,8 +6640,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r const uint8_t * scales = (const uint8_t *)utmp; - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; int32_t sumi1 = 0; int32_t sumi2 = 0; @@ -6679,8 +6679,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = y[i].d * GGML_FP16_TO_FP32(x[i].dmin); // Corrected sign - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // Process scales and mins memcpy(utmp, x[i].scales, 12); @@ -6692,7 +6692,7 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r // Sum mins * q8sums int32_t sumi = 0; - const int16_t * restrict q8sums = y[i].bsums; + const int16_t * GGML_RESTRICT q8sums = y[i].bsums; const uint8_t * m = (const uint8_t *)&utmp[2]; for (int j = 0; j < 16; j += 2) { sumi += (q8sums[j] + q8sums[j+1]) * m[j/2]; @@ -6791,8 +6791,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r utmp[2] = uaux; utmp[0] &= kmask1; - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const __m256i mins_and_scales = _mm256_cvtepu8_epi16(_mm_set_epi32(utmp[3], utmp[2], utmp[1], utmp[0])); @@ -6850,8 +6850,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(utmp, x[i].scales, 12); utmp[3] = ((utmp[2] >> 4) & kmask2) | (((utmp[1] >> 6) & kmask3) << 4); @@ -6951,8 +6951,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r vint32m1_t sumi = __riscv_vredsum_vs_i32m1_i32m1(prod, __riscv_vmv_v_x_i32m1(0, 1), vl); sumf -= dmin * __riscv_vmv_x_s_i32m1_i32(sumi); - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; vl = 32; @@ -7053,8 +7053,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r vector signed int vsumi2 = v0; vector signed int vsumi3 = v0; - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/64; j+=2) { __builtin_prefetch(q4, 0, 1); @@ -7145,8 +7145,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r utmp[2] = uaux; utmp[0] &= kmask1; - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const __m128i mins_and_scales128 = lsx_set_w(utmp[3], utmp[2], utmp[1], utmp[0]); const __m128i mins128 = __lsx_vexth_h_b(mins_and_scales128); @@ -7228,8 +7228,8 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r sumf -= dmin * (v_mins[0] + v_mins[1] + v_mins[2] + v_mins[3]); const uint8_t * scales = (const uint8_t *)utmp; - const uint8_t * restrict x0 = x[i].qs; - const int8_t * restrict y0 = y[i].qs; + const uint8_t * GGML_RESTRICT x0 = x[i].qs; + const int8_t * GGML_RESTRICT y0 = y[i].qs; int32_t sumi1 = 0; int32_t sumi2 = 0; @@ -7277,10 +7277,10 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r float sumf = 0; for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q4 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memset(aux32, 0, 8*sizeof(int32_t)); - int8_t * restrict a = aux8; + int8_t * GGML_RESTRICT a = aux8; for (int j = 0; j < QK_K/64; ++j) { for (int l = 0; l < 32; ++l) a[l] = (int8_t)(q4[l] & 0xF); a += 32; @@ -7323,7 +7323,7 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * restrict s, size_t bs, const void * r #endif } -void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q5_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -7331,8 +7331,8 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q5_K * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_q5_K * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -7374,9 +7374,9 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r const uint8_t * scales = (const uint8_t *)utmp; - const uint8_t * restrict q5 = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q5 = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; ggml_uint8x16x2_t qhbits = ggml_vld1q_u8_x2(qh); @@ -7421,8 +7421,8 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r float summs = 0.f; for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q5 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q5 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); @@ -7505,8 +7505,8 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); - const uint8_t * restrict q5 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q5 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(utmp, x[i].scales, 12); utmp[3] = ((utmp[2] >> 4) & kmask2) | (((utmp[1] >> 6) & kmask3) << 4); @@ -7597,9 +7597,9 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = y[i].d * GGML_FP16_TO_FP32(x[i].dmin); // Fixed sign - const uint8_t * restrict q5 = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q5 = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // Process scales and mins memcpy(utmp, x[i].scales, 12); @@ -7611,7 +7611,7 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r // Sum mins * q8sums int32_t sumi_mins = 0; - const int16_t * restrict q8sums = y[i].bsums; + const int16_t * GGML_RESTRICT q8sums = y[i].bsums; const uint8_t * m = (const uint8_t *)&utmp[2]; for (int j = 0; j < 16; j += 2) { sumi_mins += (q8sums[j] + q8sums[j+1]) * m[j/2]; @@ -7715,9 +7715,9 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r vl = 8; - const uint8_t * restrict q5 = x[i].qs; - const uint8_t * restrict hm = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q5 = x[i].qs; + const uint8_t * GGML_RESTRICT hm = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; const float dmin = GGML_FP16_TO_FP32(x[i].dmin) * y[i].d; @@ -7856,8 +7856,8 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r vector signed int vsumi2 = v0; vector signed int vsumi3 = v0; - const uint8_t * restrict q5 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q5 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/64; ++j) { __builtin_prefetch(q5, 0, 1); @@ -7929,8 +7929,8 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q5 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q5 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); const float dmin = -y[i].d * GGML_FP16_TO_FP32(x[i].dmin); @@ -8039,9 +8039,9 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r const int32_t mins = v_mins[0] + v_mins[1] + v_mins[2] + v_mins[3]; const uint8_t * scales = (const uint8_t *)utmp; - const uint8_t * restrict x0l = x[i].qs; - const uint8_t * restrict x0h = x[i].qh; - const int8_t * restrict y0 = y[i].qs; + const uint8_t * GGML_RESTRICT x0l = x[i].qs; + const uint8_t * GGML_RESTRICT x0h = x[i].qh; + const int8_t * GGML_RESTRICT y0 = y[i].qs; v_xh[0] = vec_xl(0 , x0h); v_xh[1] = vec_xl(16, x0h); @@ -8094,11 +8094,11 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r float sumf = 0; for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q4 = x[i].qs; - const uint8_t * restrict hm = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].qs; + const uint8_t * GGML_RESTRICT hm = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memset(aux32, 0, 8*sizeof(int32_t)); - int8_t * restrict a = aux8; + int8_t * GGML_RESTRICT a = aux8; uint8_t m = 1; for (int j = 0; j < QK_K/64; ++j) { for (int l = 0; l < 32; ++l) a[l] = (int8_t)(q4[l] & 0xF); @@ -8145,7 +8145,7 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * restrict s, size_t bs, const void * r #endif } -void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -8153,8 +8153,8 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r UNUSED(by); UNUSED(bs); - const block_q6_K * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_q6_K * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -8174,11 +8174,11 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d_all = GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q6 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q6 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; - const int8_t * restrict scale = x[i].scales; + const int8_t * GGML_RESTRICT scale = x[i].scales; const ggml_int16x8x2_t q8sums = ggml_vld1q_s16_x2(y[i].bsums); const int8x16_t scales = vld1q_s8(scale); @@ -8265,9 +8265,9 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q4 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const __m128i scales = _mm_loadu_si128((const __m128i*)x[i].scales); @@ -8343,9 +8343,9 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q4 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; // handle the q6_k -32 offset separately using bsums const __m128i q8sums_0 = _mm_loadu_si128((const __m128i*)y[i].bsums); @@ -8444,8 +8444,8 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r for (int i = 0; i < nb; ++i) { // Unpack 6-bit quantized data into aux8 (unchanged) - const uint8_t * restrict q4 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; + const uint8_t * GGML_RESTRICT q4 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; int8_t * a = aux8; for (int j = 0; j < QK_K; j += 128) { for (int l = 0; l < 32; ++l) { @@ -8459,8 +8459,8 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r qh += 32; } - const int8_t * restrict a_ptr = aux8; - const int8_t * restrict q8 = y[i].qs; + const int8_t * GGML_RESTRICT a_ptr = aux8; + const int8_t * GGML_RESTRICT q8 = y[i].qs; v128_t acc0 = wasm_i32x4_splat(0); v128_t acc1 = wasm_i32x4_splat(0); @@ -8523,11 +8523,11 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict q6 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q6 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; - const int8_t * restrict scale = x[i].scales; + const int8_t * GGML_RESTRICT scale = x[i].scales; size_t vl; @@ -8629,10 +8629,10 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r vector signed int vsumi6 = v0; vector signed int vsumi7 = v0; - const uint8_t * restrict q6 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict qs = x[i].scales; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q6 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT qs = x[i].scales; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/128; ++j) { __builtin_prefetch(q6, 0, 0); @@ -8748,9 +8748,9 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r const float d = y[i].d * GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q4 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const __m128i scales128 = __lsx_vld((const __m128i*)x[i].scales, 0); const v16i8 shuffle_mask = {0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15}; @@ -8816,11 +8816,11 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r for (int i = 0; i < nb; ++i) { const float d_all = GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict x0l = x[i].ql; - const uint8_t * restrict x0h = x[i].qh; - const int8_t * restrict y0 = y[i].qs; + const uint8_t * GGML_RESTRICT x0l = x[i].ql; + const uint8_t * GGML_RESTRICT x0h = x[i].qh; + const int8_t * GGML_RESTRICT y0 = y[i].qs; - const int8_t * restrict scale = x[i].scales; + const int8_t * GGML_RESTRICT scale = x[i].scales; const int16x8_t v_ysumsl = vec_xl(0 , y[i].bsums); const int16x8_t v_ysumsh = vec_xl(16, y[i].bsums); @@ -8931,11 +8931,11 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * restrict s, size_t bs, const void * r float sumf = 0; for (int i = 0; i < nb; ++i) { - const uint8_t * restrict q4 = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q4 = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memset(aux32, 0, 8*sizeof(int32_t)); - int8_t * restrict a = aux8; + int8_t * GGML_RESTRICT a = aux8; for (int j = 0; j < QK_K; j += 128) { for (int l = 0; l < 32; ++l) { a[l + 0] = (int8_t)((q4[l + 0] & 0xF) | (((qh[l] >> 0) & 3) << 4)) - 32; @@ -9003,7 +9003,7 @@ static const int8_t keven_signs_q2xs[1024] = { }; #endif -void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq2_xxs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -9011,8 +9011,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void UNUSED(by); UNUSED(bs); - const block_iq2_xxs * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq2_xxs * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -9030,8 +9030,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void float sumf = 0; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; float sumf1 = 0, sumf2 = 0; for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { q8b = ggml_vld1q_s8_x4(q8); q8 += 64; @@ -9067,8 +9067,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m256i sumi1 = _mm256_setzero_si256(); __m256i sumi2 = _mm256_setzero_si256(); for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { @@ -9108,8 +9108,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m128i sumi1_0 = _mm_setzero_si128(); __m128i sumi1_1 = _mm_setzero_si128(); __m128i sumi2_0 = _mm_setzero_si128(); @@ -9173,8 +9173,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void vector signed int vsumi2 = v0; vector signed int vsumi3 = v0; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/32; j += 2) { __builtin_prefetch(q2, 0, 1); @@ -9250,8 +9250,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void __m256 accumf = (__m256)__lasx_xvldi(0); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m256i sumi1 = __lasx_xvldi(0); __m256i sumi2 = __lasx_xvldi(0); for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { @@ -9291,8 +9291,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void // // for (int i = 0; i < nb; ++i) { // const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; -// const uint16_t * restrict q2 = x[i].qs; -// const int8_t * restrict q8 = y[i].qs; +// const uint16_t * GGML_RESTRICT q2 = x[i].qs; +// const int8_t * GGML_RESTRICT q8 = y[i].qs; // // float sumf1 = 0, sumf2 = 0; // @@ -9340,8 +9340,8 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void float sumf = 0.f; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; int32_t bsum = 0; for (int ib32 = 0; ib32 < QK_K/32; ++ib32) { memcpy(aux32, q2, 2*sizeof(uint32_t)); @@ -9364,7 +9364,7 @@ void ggml_vec_dot_iq2_xxs_q8_K(int n, float * restrict s, size_t bs, const void #endif } -void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq2_xs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -9372,8 +9372,8 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * UNUSED(by); UNUSED(bs); - const block_iq2_xs * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq2_xs * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -9390,8 +9390,8 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * float sumf = 0; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; const uint8x8_t scales8 = vld1_u8(x[i].scales); const uint8x8_t scales_l = vand_u8(scales8, vdup_n_u8(0xf)); const uint8x8_t scales_h = vshr_n_u8(scales8, 4); @@ -9468,8 +9468,8 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(&aux64, x[i].scales, 8); __m128i stmp = _mm_set1_epi64x(aux64); @@ -9589,8 +9589,8 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(&aux64, x[i].scales, 8); __m128i stmp = _mm_set1_epi64x(aux64); @@ -9744,8 +9744,8 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * __m256 accumf = (__m256)__lasx_xvldi(0); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(&aux64, x[i].scales, 8); __m128i stmp = __lsx_vreplgr2vr_d(aux64); @@ -9842,9 +9842,9 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * vector signed int vsumi2 = v0; vector signed int vsumi3 = v0; - const uint16_t * restrict q2 = x[i].qs; - const uint8_t * restrict sc = x[i].scales; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const uint8_t * GGML_RESTRICT sc = x[i].scales; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/64; ++j) { __builtin_prefetch(q2, 0, 1); @@ -9914,9 +9914,9 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * float sumf = 0.f; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint16_t * restrict q2 = x[i].qs; - const uint8_t * restrict sc = x[i].scales; - const int8_t * restrict q8 = y[i].qs; + const uint16_t * GGML_RESTRICT q2 = x[i].qs; + const uint8_t * GGML_RESTRICT sc = x[i].scales; + const int8_t * GGML_RESTRICT q8 = y[i].qs; int32_t bsum = 0; for (int ib32 = 0; ib32 < QK_K/32; ++ib32) { const uint16_t ls1 = 2*(sc[ib32] & 0xf) + 1; @@ -9949,7 +9949,7 @@ void ggml_vec_dot_iq2_xs_q8_K(int n, float * restrict s, size_t bs, const void * #endif } -void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq2_s_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -9957,8 +9957,8 @@ void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * UNUSED(by); UNUSED(bs); - const block_iq2_s * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq2_s * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -9984,10 +9984,10 @@ void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)(x[i].qs + QK_K/8); - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)(x[i].qs + QK_K/8); + const int8_t * GGML_RESTRICT q8 = y[i].qs; int sumi1 = 0, sumi2 = 0; for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { @@ -10058,10 +10058,10 @@ void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)(x[i].qs + QK_K/8); - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)(x[i].qs + QK_K/8); + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(&aux64, x[i].scales, 8); const __m128i scales8 = _mm_add_epi8(_mm_slli_epi16(_mm_and_si128(_mm_set_epi64x(aux64 >> 4, aux64), m4), 1), m1); @@ -10131,10 +10131,10 @@ void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)(x[i].qs + QK_K/8); - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)(x[i].qs + QK_K/8); + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(&aux64, x[i].scales, 8); const __m128i scales8 = _mm_add_epi8(_mm_slli_epi16(_mm_and_si128(_mm_set_epi64x(aux64 >> 4, aux64), m4), 1), m1); @@ -10229,11 +10229,11 @@ void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * vector signed int vsumi2 = v0; vector signed int vsumi3 = v0; - const uint8_t * restrict q2 = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)(x[i].qs + QK_K/8); - const uint8_t * restrict sc = x[i].scales; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q2 = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)(x[i].qs + QK_K/8); + const uint8_t * GGML_RESTRICT sc = x[i].scales; + const int8_t * GGML_RESTRICT q8 = y[i].qs; for (int j = 0; j < QK_K/32; j += 2) { __builtin_prefetch(q2, 0, 1); @@ -10330,10 +10330,10 @@ void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * __m256 accumf = (__m256)__lasx_xvldi(0); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)(x[i].qs + QK_K/8); - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)(x[i].qs + QK_K/8); + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m128i tmp1; memcpy(&aux64, x[i].scales, 8); @@ -10427,7 +10427,7 @@ void ggml_vec_dot_iq2_s_q8_K(int n, float * restrict s, size_t bs, const void * } -void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq3_xxs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -10435,8 +10435,8 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void UNUSED(by); UNUSED(bs); - const block_iq3_xxs * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq3_xxs * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -10452,9 +10452,9 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void float sumf = 0; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict gas = x[i].qs + QK_K/4; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT gas = x[i].qs + QK_K/4; + const int8_t * GGML_RESTRICT q8 = y[i].qs; float sumf1 = 0, sumf2 = 0; for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { q8b = ggml_vld1q_s8_x4(q8); q8 += 64; @@ -10490,9 +10490,9 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict gas = x[i].qs + QK_K/4; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT gas = x[i].qs + QK_K/4; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m256i sumi1 = _mm256_setzero_si256(); __m256i sumi2 = _mm256_setzero_si256(); for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { @@ -10535,9 +10535,9 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict gas = x[i].qs + QK_K/4; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT gas = x[i].qs + QK_K/4; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m128i sumi1_0 = _mm_setzero_si128(); __m128i sumi1_1 = _mm_setzero_si128(); __m128i sumi2_0 = _mm_setzero_si128(); @@ -10604,9 +10604,9 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void vector signed int vsumi2 = v0; vector signed int vsumi3 = v0; - const uint8_t * restrict q3 = x[i].qs; - const uint32_t * restrict signs = (const uint32_t *)(x[i].qs + QK_K/4); - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint32_t * GGML_RESTRICT signs = (const uint32_t *)(x[i].qs + QK_K/4); + const int8_t * GGML_RESTRICT q8 = y[i].qs; #pragma GCC unroll 1 for (int j = 0; j < QK_K/32; j += 2) { @@ -10678,9 +10678,9 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void __m256 accumf = (__m256)__lasx_xvldi(0); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict gas = x[i].qs + QK_K/4; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT gas = x[i].qs + QK_K/4; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m256i sumi1 = __lasx_xvldi(0); __m256i sumi2 = __lasx_xvldi(0); for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { @@ -10723,9 +10723,9 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void float sumf = 0.f; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict gas = x[i].qs + QK_K/4; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT gas = x[i].qs + QK_K/4; + const int8_t * GGML_RESTRICT q8 = y[i].qs; int32_t bsum = 0; for (int ib32 = 0; ib32 < QK_K/32; ++ib32) { memcpy(&aux32, gas, sizeof(uint32_t)); gas += sizeof(uint32_t); @@ -10750,7 +10750,7 @@ void ggml_vec_dot_iq3_xxs_q8_K(int n, float * restrict s, size_t bs, const void #endif } -void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq3_s_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -10758,8 +10758,8 @@ void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * UNUSED(by); UNUSED(bs); - const block_iq3_s * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq3_s * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -10796,10 +10796,10 @@ void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * float sumf = 0; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)x[i].signs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)x[i].signs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; memcpy(scales32, x[i].scales, 4); scales32[1] = (((scales32[0] >> 4) & 0x0f0f0f0f) << 1) | 0x01010101; @@ -10878,10 +10878,10 @@ void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)x[i].signs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)x[i].signs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m256i sumi1 = _mm256_setzero_si256(); __m256i sumi2 = _mm256_setzero_si256(); for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { @@ -10963,10 +10963,10 @@ void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * __m256 accumf = _mm256_setzero_ps(); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)x[i].signs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)x[i].signs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m128i sumi1_0 = _mm_setzero_si128(); __m128i sumi1_1 = _mm_setzero_si128(); __m128i sumi2_0 = _mm_setzero_si128(); @@ -11064,11 +11064,11 @@ void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * vector float vyd = vec_splats(y[i].d); vector float vd = vec_mul(vxd, vyd); - const uint8_t * restrict q3 = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)(x[i].signs); - const uint8_t * restrict sc = x[i].scales; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT q3 = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)(x[i].signs); + const uint8_t * GGML_RESTRICT sc = x[i].scales; + const int8_t * GGML_RESTRICT q8 = y[i].qs; vector signed int vsumi0 = v0; vector signed int vsumi1 = v0; @@ -11175,10 +11175,10 @@ void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * __m256 accumf = (__m256)__lasx_xvldi(0); for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint16_t * restrict signs = (const uint16_t *)x[i].signs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint16_t * GGML_RESTRICT signs = (const uint16_t *)x[i].signs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; __m256i sumi1 = __lasx_xvldi(0); __m256i sumi2 = __lasx_xvldi(0); for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { @@ -11236,10 +11236,10 @@ void ggml_vec_dot_iq3_s_q8_K (int n, float * restrict s, size_t bs, const void * float sumf = 0.f; for (int i = 0; i < nb; ++i) { const float d = GGML_FP16_TO_FP32(x[i].d) * y[i].d; - const uint8_t * restrict qs = x[i].qs; - const uint8_t * restrict qh = x[i].qh; - const uint8_t * restrict signs = x[i].signs; - const int8_t * restrict q8 = y[i].qs; + const uint8_t * GGML_RESTRICT qs = x[i].qs; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const uint8_t * GGML_RESTRICT signs = x[i].signs; + const int8_t * GGML_RESTRICT q8 = y[i].qs; int32_t bsum = 0; for (int ib32 = 0; ib32 < QK_K/32; ib32 += 2) { const uint32_t ls1 = 2*(x[i].scales[ib32/2] & 0xf) + 1; @@ -11291,7 +11291,7 @@ static inline __m256i mul_add_epi8(const __m256i x, const __m256i y) { } #endif -void ggml_vec_dot_iq1_s_q8_K (int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq1_s_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -11299,8 +11299,8 @@ void ggml_vec_dot_iq1_s_q8_K (int n, float * restrict s, size_t bs, const void UNUSED(by); UNUSED(bs); - const block_iq1_s * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq1_s * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -11458,10 +11458,10 @@ void ggml_vec_dot_iq1_s_q8_K (int n, float * restrict s, size_t bs, const void vector signed int vsumi3 = vec_splats((int32_t)0); vector signed int vsumi8 = vec_splats((int32_t)0); - const uint8_t * restrict q1 = x[i].qs; - const uint16_t * restrict qh = x[i].qh; - const int8_t * restrict q8 = y[i].qs; - const int16_t * restrict qs = y[i].bsums; + const uint8_t * GGML_RESTRICT q1 = x[i].qs; + const uint16_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT q8 = y[i].qs; + const int16_t * GGML_RESTRICT qs = y[i].bsums; for (int j = 0; j < QK_K/32; j += 2) { __builtin_prefetch(q1, 0, 1); @@ -11622,7 +11622,7 @@ void ggml_vec_dot_iq1_s_q8_K (int n, float * restrict s, size_t bs, const void #endif } -void ggml_vec_dot_iq1_m_q8_K (int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(n % QK_K == 0); assert(nrc == 1); UNUSED(nrc); @@ -11630,8 +11630,8 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * restrict s, size_t bs, const void UNUSED(by); UNUSED(bs); - const block_iq1_m * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq1_m * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -11912,7 +11912,7 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * restrict s, size_t bs, const void #endif } -void ggml_vec_dot_iq4_nl_q8_0(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq4_nl_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); @@ -11921,8 +11921,8 @@ void ggml_vec_dot_iq4_nl_q8_0(int n, float * restrict s, size_t bs, const void * assert(n % QK4_NL == 0); static_assert(QK4_NL == QK8_0, "QK4_NL and QK8_0 must be the same"); - const block_iq4_nl * restrict x = vx; - const block_q8_0 * restrict y = vy; + const block_iq4_nl * GGML_RESTRICT x = vx; + const block_q8_0 * GGML_RESTRICT y = vy; const int nb = n / QK4_NL; @@ -12097,8 +12097,8 @@ void ggml_vec_dot_iq4_nl_q8_0(int n, float * restrict s, size_t bs, const void * const uint8x16_t v_m = vec_splat_u8(0x0F); for (; ib < nb; ++ib) { - const block_iq4_nl * restrict x0 = &x[ib]; - const block_q8_0 * restrict y0 = &y[ib]; + const block_iq4_nl * GGML_RESTRICT x0 = &x[ib]; + const block_q8_0 * GGML_RESTRICT y0 = &y[ib]; const uint8x16_t v_x = vec_xl(0, x0->qs); int8x16_t v_xl = (int8x16_t)vec_and(v_x, v_m); @@ -12126,7 +12126,7 @@ void ggml_vec_dot_iq4_nl_q8_0(int n, float * restrict s, size_t bs, const void * *s = sumf; } -void ggml_vec_dot_iq4_xs_q8_K(int n, float * restrict s, size_t bs, const void * restrict vx, size_t bx, const void * restrict vy, size_t by, int nrc) { +void ggml_vec_dot_iq4_xs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); @@ -12134,8 +12134,8 @@ void ggml_vec_dot_iq4_xs_q8_K(int n, float * restrict s, size_t bs, const void * UNUSED(bs); assert(n % QK_K == 0); - const block_iq4_xs * restrict x = vx; - const block_q8_K * restrict y = vy; + const block_iq4_xs * GGML_RESTRICT x = vx; + const block_q8_K * GGML_RESTRICT y = vy; const int nb = n / QK_K; @@ -12292,9 +12292,9 @@ void ggml_vec_dot_iq4_xs_q8_K(int n, float * restrict s, size_t bs, const void * uint16_t h = x[ibl].scales_h; - const uint8_t * restrict q4 = x[ibl].qs; - const uint8_t * restrict sc = x[ibl].scales_l; - const int8_t * restrict q8 = y[ibl].qs; + const uint8_t * GGML_RESTRICT q4 = x[ibl].qs; + const uint8_t * GGML_RESTRICT sc = x[ibl].scales_l; + const int8_t * GGML_RESTRICT q8 = y[ibl].qs; for (int ib = 0; ib < QK_K/64; ib ++ ) { __builtin_prefetch(q4, 0, 1); @@ -12398,8 +12398,8 @@ void ggml_vec_dot_iq4_xs_q8_K(int n, float * restrict s, size_t bs, const void * float sumf = 0; for (int ibl = 0; ibl < nb; ++ibl) { - const uint8_t * restrict q4 = x[ibl].qs; - const int8_t * restrict q8 = y[ibl].qs; + const uint8_t * GGML_RESTRICT q4 = x[ibl].qs; + const int8_t * GGML_RESTRICT q8 = y[ibl].qs; uint16_t h = x[ibl].scales_h; @@ -12479,12 +12479,12 @@ void ggml_vec_dot_iq4_xs_q8_K(int n, float * restrict s, size_t bs, const void * // ============================ 4-bit non-linear quants -void quantize_row_iq4_nl(const float * restrict x, void * restrict y, int64_t k) { +void quantize_row_iq4_nl(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) { assert(k % QK4_NL == 0); quantize_row_iq4_nl_ref(x, y, k); } -void quantize_row_iq4_xs(const float * restrict x, void * restrict y, int64_t k) { +void quantize_row_iq4_xs(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); quantize_iq4_xs(x, y, 1, k, NULL); } diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c index 9ab24522c..2a5463fdf 100644 --- a/ggml/src/ggml-cpu/ggml-cpu.c +++ b/ggml/src/ggml-cpu/ggml-cpu.c @@ -247,9 +247,9 @@ typedef pthread_t ggml_thread_t; static const size_t CACHE_LINE_SIZE_F32 = CACHE_LINE_SIZE/sizeof(float); -static void ggml_vec_dot_f32(int n, float * restrict s, size_t bs, const float * restrict x, size_t bx, const float * restrict y, size_t by, int nrc); -static void ggml_vec_dot_f16(int n, float * restrict s, size_t bs, ggml_fp16_t * restrict x, size_t bx, ggml_fp16_t * restrict y, size_t by, int nrc); -static void ggml_vec_dot_bf16(int n, float * restrict s, size_t bs, ggml_bf16_t * restrict x, size_t bx, ggml_bf16_t * restrict y, size_t by, int nrc); +static void ggml_vec_dot_f32(int n, float * GGML_RESTRICT s, size_t bs, const float * GGML_RESTRICT x, size_t bx, const float * GGML_RESTRICT y, size_t by, int nrc); +static void ggml_vec_dot_f16(int n, float * GGML_RESTRICT s, size_t bs, ggml_fp16_t * GGML_RESTRICT x, size_t bx, ggml_fp16_t * GGML_RESTRICT y, size_t by, int nrc); +static void ggml_vec_dot_bf16(int n, float * GGML_RESTRICT s, size_t bs, ggml_bf16_t * GGML_RESTRICT x, size_t bx, ggml_bf16_t * GGML_RESTRICT y, size_t by, int nrc); static const struct ggml_type_traits_cpu type_traits_cpu[GGML_TYPE_COUNT] = { [GGML_TYPE_F32] = { @@ -1451,7 +1451,7 @@ inline static void ggml_vec_div_f16 (const int n, ggml_fp16_t * z, const ggml_fp } } -static void ggml_vec_dot_f32(int n, float * restrict s, size_t bs, const float * restrict x, size_t bx, const float * restrict y, size_t by, int nrc) { +static void ggml_vec_dot_f32(int n, float * GGML_RESTRICT s, size_t bs, const float * GGML_RESTRICT x, size_t bx, const float * GGML_RESTRICT y, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); @@ -1494,7 +1494,7 @@ static void ggml_vec_dot_f32(int n, float * restrict s, size_t bs, const float * *s = sumf; } -static void ggml_vec_dot_bf16(int n, float * restrict s, size_t bs, ggml_bf16_t * restrict x, size_t bx, ggml_bf16_t * restrict y, size_t by, int nrc) { +static void ggml_vec_dot_bf16(int n, float * GGML_RESTRICT s, size_t bs, ggml_bf16_t * GGML_RESTRICT x, size_t bx, ggml_bf16_t * GGML_RESTRICT y, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); @@ -1562,7 +1562,7 @@ static void ggml_vec_dot_bf16(int n, float * restrict s, size_t bs, ggml_bf16_t *s = sumf; } -static void ggml_vec_dot_f16(int n, float * restrict s, size_t bs, ggml_fp16_t * restrict x, size_t bx, ggml_fp16_t * restrict y, size_t by, int nrc) { +static void ggml_vec_dot_f16(int n, float * GGML_RESTRICT s, size_t bs, ggml_fp16_t * GGML_RESTRICT x, size_t bx, ggml_fp16_t * GGML_RESTRICT y, size_t by, int nrc) { assert(nrc == 1); UNUSED(nrc); UNUSED(bx); @@ -1606,10 +1606,10 @@ static void ggml_vec_dot_f16(int n, float * restrict s, size_t bs, ggml_fp16_t * // compute GGML_VEC_DOT_UNROLL dot products at once // xs - x row stride in bytes -inline static void ggml_vec_dot_f16_unroll(const int n, const int xs, float * restrict s, void * restrict xv, ggml_fp16_t * restrict y) { +inline static void ggml_vec_dot_f16_unroll(const int n, const int xs, float * GGML_RESTRICT s, void * GGML_RESTRICT xv, ggml_fp16_t * GGML_RESTRICT y) { ggml_float sumf[GGML_VEC_DOT_UNROLL] = { 0.0 }; - ggml_fp16_t * restrict x[GGML_VEC_DOT_UNROLL]; + ggml_fp16_t * GGML_RESTRICT x[GGML_VEC_DOT_UNROLL]; for (int i = 0; i < GGML_VEC_DOT_UNROLL; ++i) { x[i] = (ggml_fp16_t *) ((char *) xv + i*xs); @@ -1659,7 +1659,7 @@ inline static void ggml_vec_dot_f16_unroll(const int n, const int xs, float * re } } -inline static void ggml_vec_mad_f32(const int n, float * restrict y, const float * restrict x, const float v) { +inline static void ggml_vec_mad_f32(const int n, float * GGML_RESTRICT y, const float * GGML_RESTRICT x, const float v) { #if defined(GGML_SIMD) const int np = (n & ~(GGML_F32_STEP - 1)); @@ -1690,7 +1690,7 @@ inline static void ggml_vec_mad_f32(const int n, float * restrict y, const float #endif } -inline static void ggml_vec_mad_f16(const int n, ggml_fp16_t * restrict y, const ggml_fp16_t * restrict x, const float v) { +inline static void ggml_vec_mad_f16(const int n, ggml_fp16_t * GGML_RESTRICT y, const ggml_fp16_t * GGML_RESTRICT x, const float v) { #if defined(GGML_SIMD) const int np = (n & ~(GGML_F16_STEP - 1)); @@ -1722,10 +1722,10 @@ inline static void ggml_vec_mad_f16(const int n, ggml_fp16_t * restrict y, const } // xs and vs are byte strides of x and v -inline static void ggml_vec_mad_f32_unroll(const int n, const int xs, const int vs, float * restrict y, const float * restrict xv, const float * restrict vv) { +inline static void ggml_vec_mad_f32_unroll(const int n, const int xs, const int vs, float * GGML_RESTRICT y, const float * GGML_RESTRICT xv, const float * GGML_RESTRICT vv) { - const float * restrict x[GGML_VEC_MAD_UNROLL]; - const float * restrict v[GGML_VEC_MAD_UNROLL]; + const float * GGML_RESTRICT x[GGML_VEC_MAD_UNROLL]; + const float * GGML_RESTRICT v[GGML_VEC_MAD_UNROLL]; for (int i = 0; i < GGML_VEC_MAD_UNROLL; ++i) { x[i] = (const float *) ((const char *) xv + i*xs); diff --git a/ggml/src/ggml-quants.c b/ggml/src/ggml-quants.c index 7918388ae..ac918a60d 100644 --- a/ggml/src/ggml-quants.c +++ b/ggml/src/ggml-quants.c @@ -28,7 +28,7 @@ #define UNUSED GGML_UNUSED // reference implementation for deterministic creation of model files -void quantize_row_q4_0_ref(const float * restrict x, block_q4_0 * restrict y, int64_t k) { +void quantize_row_q4_0_ref(const float * GGML_RESTRICT x, block_q4_0 * GGML_RESTRICT y, int64_t k) { static const int qk = QK4_0; assert(k % qk == 0); @@ -65,7 +65,7 @@ void quantize_row_q4_0_ref(const float * restrict x, block_q4_0 * restrict y, in } } -void quantize_row_q4_1_ref(const float * restrict x, block_q4_1 * restrict y, int64_t k) { +void quantize_row_q4_1_ref(const float * GGML_RESTRICT x, block_q4_1 * GGML_RESTRICT y, int64_t k) { const int qk = QK4_1; assert(k % qk == 0); @@ -102,7 +102,7 @@ void quantize_row_q4_1_ref(const float * restrict x, block_q4_1 * restrict y, in } } -void quantize_row_q5_0_ref(const float * restrict x, block_q5_0 * restrict y, int64_t k) { +void quantize_row_q5_0_ref(const float * GGML_RESTRICT x, block_q5_0 * GGML_RESTRICT y, int64_t k) { static const int qk = QK5_0; assert(k % qk == 0); @@ -146,7 +146,7 @@ void quantize_row_q5_0_ref(const float * restrict x, block_q5_0 * restrict y, in } } -void quantize_row_q5_1_ref(const float * restrict x, block_q5_1 * restrict y, int64_t k) { +void quantize_row_q5_1_ref(const float * GGML_RESTRICT x, block_q5_1 * GGML_RESTRICT y, int64_t k) { const int qk = QK5_1; assert(k % qk == 0); @@ -191,7 +191,7 @@ void quantize_row_q5_1_ref(const float * restrict x, block_q5_1 * restrict y, in } // reference implementation for deterministic creation of model files -void quantize_row_q8_0_ref(const float * restrict x, block_q8_0 * restrict y, int64_t k) { +void quantize_row_q8_0_ref(const float * GGML_RESTRICT x, block_q8_0 * GGML_RESTRICT y, int64_t k) { assert(k % QK8_0 == 0); const int nb = k / QK8_0; @@ -217,7 +217,7 @@ void quantize_row_q8_0_ref(const float * restrict x, block_q8_0 * restrict y, in } // reference implementation for deterministic creation of model files -void quantize_row_q8_1_ref(const float * restrict x, block_q8_1 * restrict y, int64_t k) { +void quantize_row_q8_1_ref(const float * GGML_RESTRICT x, block_q8_1 * GGML_RESTRICT y, int64_t k) { assert(QK8_1 == 32); assert(k % QK8_1 == 0); const int nb = k / QK8_1; @@ -252,7 +252,7 @@ void quantize_row_q8_1_ref(const float * restrict x, block_q8_1 * restrict y, in } } -void dequantize_row_q4_0(const block_q4_0 * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q4_0(const block_q4_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { static const int qk = QK4_0; assert(k % qk == 0); @@ -272,7 +272,7 @@ void dequantize_row_q4_0(const block_q4_0 * restrict x, float * restrict y, int6 } } -void dequantize_row_q4_1(const block_q4_1 * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q4_1(const block_q4_1 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { static const int qk = QK4_1; assert(k % qk == 0); @@ -293,7 +293,7 @@ void dequantize_row_q4_1(const block_q4_1 * restrict x, float * restrict y, int6 } } -void dequantize_row_q5_0(const block_q5_0 * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q5_0(const block_q5_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { static const int qk = QK5_0; assert(k % qk == 0); @@ -319,7 +319,7 @@ void dequantize_row_q5_0(const block_q5_0 * restrict x, float * restrict y, int6 } } -void dequantize_row_q5_1(const block_q5_1 * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q5_1(const block_q5_1 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { static const int qk = QK5_1; assert(k % qk == 0); @@ -346,7 +346,7 @@ void dequantize_row_q5_1(const block_q5_1 * restrict x, float * restrict y, int6 } } -void dequantize_row_q8_0(const block_q8_0 * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q8_0(const block_q8_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { static const int qk = QK8_0; assert(k % qk == 0); @@ -376,8 +376,8 @@ static inline int nearest_int(float fval) { return (i & 0x007fffff) - 0x00400000; } -static float make_qx_quants(int n, int nmax, const float * restrict x, int8_t * restrict L, int rmse_type, - const float * restrict qw) { +static float make_qx_quants(int n, int nmax, const float * GGML_RESTRICT x, int8_t * GGML_RESTRICT L, int rmse_type, + const float * GGML_RESTRICT qw) { float max = 0; float amax = 0; for (int i = 0; i < n; ++i) { @@ -445,7 +445,7 @@ static float make_qx_quants(int n, int nmax, const float * restrict x, int8_t * return scale; } -static float make_q3_quants(int n, int nmax, const float * restrict x, int8_t * restrict L, bool do_rmse) { +static float make_q3_quants(int n, int nmax, const float * GGML_RESTRICT x, int8_t * GGML_RESTRICT L, bool do_rmse) { float max = 0; float amax = 0; for (int i = 0; i < n; ++i) { @@ -504,7 +504,7 @@ static float make_q3_quants(int n, int nmax, const float * restrict x, int8_t * return 1/iscale; } -static float make_qkx1_quants(int n, int nmax, const float * restrict x, uint8_t * restrict L, float * restrict the_min, +static float make_qkx1_quants(int n, int nmax, const float * GGML_RESTRICT x, uint8_t * GGML_RESTRICT L, float * GGML_RESTRICT the_min, int ntry, float alpha) { float min = x[0]; float max = x[0]; @@ -547,8 +547,8 @@ static float make_qkx1_quants(int n, int nmax, const float * restrict x, uint8_t return scale; } -static float make_qkx2_quants(int n, int nmax, const float * restrict x, const float * restrict weights, - uint8_t * restrict L, float * restrict the_min, uint8_t * restrict Laux, +static float make_qkx2_quants(int n, int nmax, const float * GGML_RESTRICT x, const float * GGML_RESTRICT weights, + uint8_t * GGML_RESTRICT L, float * GGML_RESTRICT the_min, uint8_t * GGML_RESTRICT Laux, float rmin, float rdelta, int nstep, bool use_mad) { float min = x[0]; float max = x[0]; @@ -628,7 +628,7 @@ static float make_qkx2_quants(int n, int nmax, const float * restrict x, const f return scale; } -static inline void get_scale_min_k4(int j, const uint8_t * restrict q, uint8_t * restrict d, uint8_t * restrict m) { +static inline void get_scale_min_k4(int j, const uint8_t * GGML_RESTRICT q, uint8_t * GGML_RESTRICT d, uint8_t * GGML_RESTRICT m) { if (j < 4) { *d = q[j] & 63; *m = q[j + 4] & 63; } else { @@ -639,7 +639,7 @@ static inline void get_scale_min_k4(int j, const uint8_t * restrict q, uint8_t * //========================- 2-bit (de)-quantization -void quantize_row_q2_K_ref(const float * restrict x, block_q2_K * restrict y, int64_t k) { +void quantize_row_q2_K_ref(const float * GGML_RESTRICT x, block_q2_K * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int nb = k / QK_K; @@ -709,7 +709,7 @@ void quantize_row_q2_K_ref(const float * restrict x, block_q2_K * restrict y, in } } -void dequantize_row_q2_K(const block_q2_K * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q2_K(const block_q2_K * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int nb = k / QK_K; @@ -741,8 +741,8 @@ void dequantize_row_q2_K(const block_q2_K * restrict x, float * restrict y, int6 } } -static float make_qkx3_quants(int n, int nmax, const float * restrict x, const float * restrict weights, - uint8_t * restrict L, float * restrict the_min, uint8_t * restrict Laux, +static float make_qkx3_quants(int n, int nmax, const float * GGML_RESTRICT x, const float * GGML_RESTRICT weights, + uint8_t * GGML_RESTRICT L, float * GGML_RESTRICT the_min, uint8_t * GGML_RESTRICT Laux, float rmin, float rdelta, int nstep, bool use_mad) { float min = x[0]; float max = x[0]; @@ -824,7 +824,7 @@ static float make_qkx3_quants(int n, int nmax, const float * restrict x, const f return scale; } -static float make_qp_quants(int n, int nmax, const float * restrict x, uint8_t * restrict L, const float * quant_weights) { +static float make_qp_quants(int n, int nmax, const float * GGML_RESTRICT x, uint8_t * GGML_RESTRICT L, const float * quant_weights) { float max = 0; for (int i = 0; i < n; ++i) { max = MAX(max, x[i]); @@ -897,7 +897,7 @@ static float make_qp_quants(int n, int nmax, const float * restrict x, uint8_t * return sumlx/suml2; } -static void quantize_row_q2_K_impl(const float * restrict x, block_q2_K * restrict y, int k, const float * restrict quant_weights) { +static void quantize_row_q2_K_impl(const float * GGML_RESTRICT x, block_q2_K * GGML_RESTRICT y, int k, const float * GGML_RESTRICT quant_weights) { GGML_ASSERT(quant_weights); assert(k % QK_K == 0); const int nb = k / QK_K; @@ -917,7 +917,7 @@ static void quantize_row_q2_K_impl(const float * restrict x, block_q2_K * restri for (int j = 0; j < QK_K; ++j) sumx2 += x[j]*x[j]; float sigma2 = sumx2/QK_K; for (int j = 0; j < QK_K/16; ++j) { - const float * restrict qw = quant_weights + QK_K * i + 16*j; + const float * GGML_RESTRICT qw = quant_weights + QK_K * i + 16*j; for (int l = 0; l < 16; ++l) weight[l] = qw[l] * sqrtf(sigma2 + x[16*j + l]*x[16*j + l]); for (int l = 0; l < QK_K/16; ++l) sw[j] += weight[l]; scales[j] = make_qkx3_quants(16, 3, x + 16*j, weight, L + 16*j, &mins[j], Laux, -0.9f, 0.05f, 36, false); @@ -959,7 +959,7 @@ static void quantize_row_q2_K_impl(const float * restrict x, block_q2_K * restri } } -size_t quantize_q2_K(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q2_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { size_t row_size = ggml_row_size(GGML_TYPE_Q2_K, n_per_row); if (!quant_weights) { quantize_row_q2_K_ref(src, dst, (int64_t)nrow*n_per_row); @@ -977,7 +977,7 @@ size_t quantize_q2_K(const float * restrict src, void * restrict dst, int64_t nr //========================= 3-bit (de)-quantization -void quantize_row_q3_K_ref(const float * restrict x, block_q3_K * restrict y, int64_t k) { +void quantize_row_q3_K_ref(const float * GGML_RESTRICT x, block_q3_K * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int nb = k / QK_K; @@ -1053,7 +1053,7 @@ void quantize_row_q3_K_ref(const float * restrict x, block_q3_K * restrict y, in } } -void dequantize_row_q3_K(const block_q3_K * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q3_K(const block_q3_K * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int nb = k / QK_K; @@ -1067,8 +1067,8 @@ void dequantize_row_q3_K(const block_q3_K * restrict x, float * restrict y, int6 const float d_all = GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict q = x[i].qs; - const uint8_t * restrict hm = x[i].hmask; + const uint8_t * GGML_RESTRICT q = x[i].qs; + const uint8_t * GGML_RESTRICT hm = x[i].hmask; uint8_t m = 1; memcpy(aux, x[i].scales, 12); @@ -1103,7 +1103,7 @@ void dequantize_row_q3_K(const block_q3_K * restrict x, float * restrict y, int6 } } -static void quantize_row_q3_K_impl(const float * restrict x, block_q3_K * restrict y, int64_t n_per_row, const float * restrict quant_weights) { +static void quantize_row_q3_K_impl(const float * GGML_RESTRICT x, block_q3_K * GGML_RESTRICT y, int64_t n_per_row, const float * GGML_RESTRICT quant_weights) { assert(n_per_row % QK_K == 0); const int nb = n_per_row / QK_K; @@ -1187,7 +1187,7 @@ static void quantize_row_q3_K_impl(const float * restrict x, block_q3_K * restri } } -size_t quantize_q3_K(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q3_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { size_t row_size = ggml_row_size(GGML_TYPE_Q3_K, n_per_row); if (!quant_weights) { quantize_row_q3_K_ref(src, dst, (int64_t)nrow*n_per_row); @@ -1205,7 +1205,7 @@ size_t quantize_q3_K(const float * restrict src, void * restrict dst, int64_t nr // ====================== 4-bit (de)-quantization -void quantize_row_q4_K_ref(const float * restrict x, block_q4_K * restrict y, int64_t k) { +void quantize_row_q4_K_ref(const float * GGML_RESTRICT x, block_q4_K * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int nb = k / QK_K; @@ -1277,7 +1277,7 @@ void quantize_row_q4_K_ref(const float * restrict x, block_q4_K * restrict y, in } } -void dequantize_row_q4_K(const block_q4_K * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q4_K(const block_q4_K * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int nb = k / QK_K; @@ -1301,7 +1301,7 @@ void dequantize_row_q4_K(const block_q4_K * restrict x, float * restrict y, int6 } } -static void quantize_row_q4_K_impl(const float * restrict x, block_q4_K * restrict y, int64_t n_per_row, const float * quant_weights) { +static void quantize_row_q4_K_impl(const float * GGML_RESTRICT x, block_q4_K * GGML_RESTRICT y, int64_t n_per_row, const float * quant_weights) { assert(n_per_row % QK_K == 0); const int64_t nb = n_per_row / QK_K; @@ -1374,7 +1374,7 @@ static void quantize_row_q4_K_impl(const float * restrict x, block_q4_K * restri } } -size_t quantize_q4_K(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q4_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { size_t row_size = ggml_row_size(GGML_TYPE_Q4_K, n_per_row); if (!quant_weights) { quantize_row_q4_K_ref(src, dst, (int64_t)nrow*n_per_row); @@ -1392,7 +1392,7 @@ size_t quantize_q4_K(const float * restrict src, void * restrict dst, int64_t nr // ====================== 5-bit (de)-quantization -void quantize_row_q5_K_ref(const float * restrict x, block_q5_K * restrict y, int64_t k) { +void quantize_row_q5_K_ref(const float * GGML_RESTRICT x, block_q5_K * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -1454,8 +1454,8 @@ void quantize_row_q5_K_ref(const float * restrict x, block_q5_K * restrict y, in } } - uint8_t * restrict qh = y[i].qh; - uint8_t * restrict ql = y[i].qs; + uint8_t * GGML_RESTRICT qh = y[i].qh; + uint8_t * GGML_RESTRICT ql = y[i].qs; memset(qh, 0, QK_K/8); uint8_t m1 = 1, m2 = 2; @@ -1479,7 +1479,7 @@ void quantize_row_q5_K_ref(const float * restrict x, block_q5_K * restrict y, in } } -void dequantize_row_q5_K(const block_q5_K * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q5_K(const block_q5_K * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -1506,7 +1506,7 @@ void dequantize_row_q5_K(const block_q5_K * restrict x, float * restrict y, int6 } } -static void quantize_row_q5_K_impl(const float * restrict x, block_q5_K * restrict y, int64_t n_per_row, const float * quant_weights) { +static void quantize_row_q5_K_impl(const float * GGML_RESTRICT x, block_q5_K * GGML_RESTRICT y, int64_t n_per_row, const float * quant_weights) { assert(n_per_row % QK_K == 0); const int64_t nb = n_per_row / QK_K; @@ -1573,8 +1573,8 @@ static void quantize_row_q5_K_impl(const float * restrict x, block_q5_K * restri } } - uint8_t * restrict qh = y[i].qh; - uint8_t * restrict ql = y[i].qs; + uint8_t * GGML_RESTRICT qh = y[i].qh; + uint8_t * GGML_RESTRICT ql = y[i].qs; memset(qh, 0, QK_K/8); uint8_t m1 = 1, m2 = 2; @@ -1599,7 +1599,7 @@ static void quantize_row_q5_K_impl(const float * restrict x, block_q5_K * restri } } -size_t quantize_q5_K(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q5_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { size_t row_size = ggml_row_size(GGML_TYPE_Q5_K, n_per_row); if (!quant_weights) { quantize_row_q5_K_ref(src, dst, (int64_t)nrow*n_per_row); @@ -1617,7 +1617,7 @@ size_t quantize_q5_K(const float * restrict src, void * restrict dst, int64_t nr // ====================== 6-bit (de)-quantization -void quantize_row_q6_K_ref(const float * restrict x, block_q6_K * restrict y, int64_t k) { +void quantize_row_q6_K_ref(const float * GGML_RESTRICT x, block_q6_K * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -1667,8 +1667,8 @@ void quantize_row_q6_K_ref(const float * restrict x, block_q6_K * restrict y, in } } - uint8_t * restrict ql = y[i].ql; - uint8_t * restrict qh = y[i].qh; + uint8_t * GGML_RESTRICT ql = y[i].ql; + uint8_t * GGML_RESTRICT qh = y[i].qh; for (int j = 0; j < QK_K; j += 128) { for (int l = 0; l < 32; ++l) { const uint8_t q1 = L[j + l + 0] & 0xF; @@ -1687,16 +1687,16 @@ void quantize_row_q6_K_ref(const float * restrict x, block_q6_K * restrict y, in } } -void dequantize_row_q6_K(const block_q6_K * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q6_K(const block_q6_K * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; for (int i = 0; i < nb; i++) { const float d = GGML_FP16_TO_FP32(x[i].d); - const uint8_t * restrict ql = x[i].ql; - const uint8_t * restrict qh = x[i].qh; - const int8_t * restrict sc = x[i].scales; + const uint8_t * GGML_RESTRICT ql = x[i].ql; + const uint8_t * GGML_RESTRICT qh = x[i].qh; + const int8_t * GGML_RESTRICT sc = x[i].scales; for (int n = 0; n < QK_K; n += 128) { for (int l = 0; l < 32; ++l) { @@ -1718,7 +1718,7 @@ void dequantize_row_q6_K(const block_q6_K * restrict x, float * restrict y, int6 } } -static void quantize_row_q6_K_impl(const float * restrict x, block_q6_K * restrict y, int64_t n_per_row, const float * quant_weights) { +static void quantize_row_q6_K_impl(const float * GGML_RESTRICT x, block_q6_K * GGML_RESTRICT y, int64_t n_per_row, const float * quant_weights) { assert(n_per_row % QK_K == 0); const int64_t nb = n_per_row / QK_K; @@ -1781,8 +1781,8 @@ static void quantize_row_q6_K_impl(const float * restrict x, block_q6_K * restri } } - uint8_t * restrict ql = y[i].ql; - uint8_t * restrict qh = y[i].qh; + uint8_t * GGML_RESTRICT ql = y[i].ql; + uint8_t * GGML_RESTRICT qh = y[i].qh; for (int j = 0; j < QK_K; j += 128) { for (int l = 0; l < 32; ++l) { const uint8_t q1 = L[j + l + 0] & 0xF; @@ -1802,7 +1802,7 @@ static void quantize_row_q6_K_impl(const float * restrict x, block_q6_K * restri } } -size_t quantize_q6_K(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q6_K(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { size_t row_size = ggml_row_size(GGML_TYPE_Q6_K, n_per_row); if (!quant_weights) { quantize_row_q6_K_ref(src, dst, (int64_t)nrow*n_per_row); @@ -1818,7 +1818,7 @@ size_t quantize_q6_K(const float * restrict src, void * restrict dst, int64_t nr return nrow * row_size; } -static void quantize_row_q4_0_impl(const float * restrict x, block_q4_0 * restrict y, int64_t n_per_row, const float * quant_weights) { +static void quantize_row_q4_0_impl(const float * GGML_RESTRICT x, block_q4_0 * GGML_RESTRICT y, int64_t n_per_row, const float * quant_weights) { static_assert(QK4_0 == 32, "QK4_0 must be 32"); if (!quant_weights) { @@ -1846,7 +1846,7 @@ static void quantize_row_q4_0_impl(const float * restrict x, block_q4_0 * restri } } -size_t quantize_q4_0(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q4_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { if (!quant_weights) { quantize_row_q4_0_ref(src, dst, (int64_t)nrow*n_per_row); return nrow * ggml_row_size(GGML_TYPE_Q4_0, n_per_row); @@ -1861,7 +1861,7 @@ size_t quantize_q4_0(const float * restrict src, void * restrict dst, int64_t nr return nrow * row_size; } -static void quantize_row_q4_1_impl(const float * restrict x, block_q4_1 * restrict y, int64_t n_per_row, const float * quant_weights) { +static void quantize_row_q4_1_impl(const float * GGML_RESTRICT x, block_q4_1 * GGML_RESTRICT y, int64_t n_per_row, const float * quant_weights) { static_assert(QK4_1 == 32, "QK4_1 must be 32"); if (!quant_weights) { @@ -1891,7 +1891,7 @@ static void quantize_row_q4_1_impl(const float * restrict x, block_q4_1 * restri } } -size_t quantize_q4_1(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q4_1(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { if (!quant_weights) { quantize_row_q4_1_ref(src, dst, (int64_t)nrow*n_per_row); return nrow * ggml_row_size(GGML_TYPE_Q4_1, n_per_row); @@ -1906,7 +1906,7 @@ size_t quantize_q4_1(const float * restrict src, void * restrict dst, int64_t nr return nrow * row_size; } -static void quantize_row_q5_0_impl(const float * restrict x, block_q5_0 * restrict y, int64_t n_per_row, const float * quant_weights) { +static void quantize_row_q5_0_impl(const float * GGML_RESTRICT x, block_q5_0 * GGML_RESTRICT y, int64_t n_per_row, const float * quant_weights) { static_assert(QK5_0 == 32, "QK5_0 must be 32"); if (!quant_weights) { @@ -1945,7 +1945,7 @@ static void quantize_row_q5_0_impl(const float * restrict x, block_q5_0 * restri } } -size_t quantize_q5_0(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q5_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { if (!quant_weights) { quantize_row_q5_0_ref(src, dst, (int64_t)nrow*n_per_row); return nrow * ggml_row_size(GGML_TYPE_Q5_0, n_per_row); @@ -1960,7 +1960,7 @@ size_t quantize_q5_0(const float * restrict src, void * restrict dst, int64_t nr return nrow * row_size; } -static void quantize_row_q5_1_impl(const float * restrict x, block_q5_1 * restrict y, int64_t n_per_row, const float * quant_weights) { +static void quantize_row_q5_1_impl(const float * GGML_RESTRICT x, block_q5_1 * GGML_RESTRICT y, int64_t n_per_row, const float * quant_weights) { static_assert(QK5_1 == 32, "QK5_1 must be 32"); if (!quant_weights) { @@ -1998,7 +1998,7 @@ static void quantize_row_q5_1_impl(const float * restrict x, block_q5_1 * restri } } -size_t quantize_q5_1(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q5_1(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { if (!quant_weights) { quantize_row_q5_1_ref(src, dst, (int64_t)nrow*n_per_row); return nrow * ggml_row_size(GGML_TYPE_Q5_1, n_per_row); @@ -2013,7 +2013,7 @@ size_t quantize_q5_1(const float * restrict src, void * restrict dst, int64_t nr return nrow * row_size; } -size_t quantize_q8_0(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_q8_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { (void)quant_weights; // not used const size_t row_size = ggml_row_size(GGML_TYPE_Q8_0, n_per_row); quantize_row_q8_0_ref(src, dst, (int64_t)nrow*n_per_row); @@ -2022,7 +2022,7 @@ size_t quantize_q8_0(const float * restrict src, void * restrict dst, int64_t nr // ====================== Ternary (de)-quantization (BitNet b1.58 and TriLMs) -void quantize_row_tq1_0_ref(const float * restrict x, block_tq1_0 * restrict y, int64_t k) { +void quantize_row_tq1_0_ref(const float * GGML_RESTRICT x, block_tq1_0 * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2088,7 +2088,7 @@ void quantize_row_tq1_0_ref(const float * restrict x, block_tq1_0 * restrict y, } } -void quantize_row_tq2_0_ref(const float * restrict x, block_tq2_0 * restrict y, int64_t k) { +void quantize_row_tq2_0_ref(const float * GGML_RESTRICT x, block_tq2_0 * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2120,21 +2120,21 @@ void quantize_row_tq2_0_ref(const float * restrict x, block_tq2_0 * restrict y, } } -size_t quantize_tq1_0(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_tq1_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { (void)quant_weights; // not used const size_t row_size = ggml_row_size(GGML_TYPE_TQ1_0, n_per_row); quantize_row_tq1_0_ref(src, dst, (int64_t)nrow*n_per_row); return nrow * row_size; } -size_t quantize_tq2_0(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_tq2_0(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { (void)quant_weights; // not used const size_t row_size = ggml_row_size(GGML_TYPE_TQ2_0, n_per_row); quantize_row_tq2_0_ref(src, dst, (int64_t)nrow*n_per_row); return nrow * row_size; } -void dequantize_row_tq1_0(const block_tq1_0 * restrict x, float * restrict y, int64_t k) { +void dequantize_row_tq1_0(const block_tq1_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2173,7 +2173,7 @@ void dequantize_row_tq1_0(const block_tq1_0 * restrict x, float * restrict y, in } } -void dequantize_row_tq2_0(const block_tq2_0 * restrict x, float * restrict y, int64_t k) { +void dequantize_row_tq2_0(const block_tq2_0 * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2194,7 +2194,7 @@ void dequantize_row_tq2_0(const block_tq2_0 * restrict x, float * restrict y, in // ====================== "True" 2-bit (de)-quantization -void dequantize_row_iq2_xxs(const block_iq2_xxs * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq2_xxs(const block_iq2_xxs * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2222,7 +2222,7 @@ void dequantize_row_iq2_xxs(const block_iq2_xxs * restrict x, float * restrict y // ====================== 2.3125 bpw (de)-quantization -void dequantize_row_iq2_xs(const block_iq2_xs * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq2_xs(const block_iq2_xs * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2249,7 +2249,7 @@ void dequantize_row_iq2_xs(const block_iq2_xs * restrict x, float * restrict y, // ====================== 2.5625 bpw (de)-quantization -void dequantize_row_iq2_s(const block_iq2_s * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq2_s(const block_iq2_s * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2281,7 +2281,7 @@ void dequantize_row_iq2_s(const block_iq2_s * restrict x, float * restrict y, in // ====================== 3.0625 bpw (de)-quantization -void dequantize_row_iq3_xxs(const block_iq3_xxs * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq3_xxs(const block_iq3_xxs * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2313,7 +2313,7 @@ void dequantize_row_iq3_xxs(const block_iq3_xxs * restrict x, float * restrict y // ====================== 3.3125 bpw (de)-quantization -void dequantize_row_iq3_s(const block_iq3_s * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq3_s(const block_iq3_s * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2356,7 +2356,7 @@ void dequantize_row_iq3_s(const block_iq3_s * restrict x, float * restrict y, in // ====================== 1.5625 bpw (de)-quantization -void dequantize_row_iq1_s(const block_iq1_s * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq1_s(const block_iq1_s * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2381,7 +2381,7 @@ void dequantize_row_iq1_s(const block_iq1_s * restrict x, float * restrict y, in } } -void dequantize_row_iq1_m(const block_iq1_m * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq1_m(const block_iq1_m * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2433,7 +2433,7 @@ void dequantize_row_iq1_m(const block_iq1_m * restrict x, float * restrict y, in static const int8_t kvalues_iq4nl[16] = {-127, -104, -83, -65, -49, -35, -22, -10, 1, 13, 25, 38, 53, 69, 89, 113}; -void dequantize_row_iq4_nl(const block_iq4_nl * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq4_nl(const block_iq4_nl * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK4_NL == 0); const int64_t nb = k / QK4_NL; @@ -2451,7 +2451,7 @@ void dequantize_row_iq4_nl(const block_iq4_nl * restrict x, float * restrict y, } } -void dequantize_row_iq4_xs(const block_iq4_xs * restrict x, float * restrict y, int64_t k) { +void dequantize_row_iq4_xs(const block_iq4_xs * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2476,7 +2476,7 @@ void dequantize_row_iq4_xs(const block_iq4_xs * restrict x, float * restrict y, //===================================== Q8_K ============================================== -void quantize_row_q8_K_ref(const float * restrict x, block_q8_K * restrict y, int64_t k) { +void quantize_row_q8_K_ref(const float * GGML_RESTRICT x, block_q8_K * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2515,7 +2515,7 @@ void quantize_row_q8_K_ref(const float * restrict x, block_q8_K * restrict y, in } } -void dequantize_row_q8_K(const block_q8_K * restrict x, float * restrict y, int64_t k) { +void dequantize_row_q8_K(const block_q8_K * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); const int64_t nb = k / QK_K; @@ -2927,8 +2927,8 @@ void iq2xs_free_impl(enum ggml_type type) { } } -static int iq2_find_best_neighbour(const uint16_t * restrict neighbours, const uint64_t * restrict grid, - const float * restrict xval, const float * restrict weight, float scale, int8_t * restrict L) { +static int iq2_find_best_neighbour(const uint16_t * GGML_RESTRICT neighbours, const uint64_t * GGML_RESTRICT grid, + const float * GGML_RESTRICT xval, const float * GGML_RESTRICT weight, float scale, int8_t * GGML_RESTRICT L) { int num_neighbors = neighbours[0]; GGML_ASSERT(num_neighbors > 0); float best_d2 = FLT_MAX; @@ -2951,7 +2951,7 @@ static int iq2_find_best_neighbour(const uint16_t * restrict neighbours, const u return grid_index; } -static void quantize_row_iq2_xxs_impl(const float * restrict x, void * restrict vy, int64_t n, const float * restrict quant_weights) { +static void quantize_row_iq2_xxs_impl(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t n, const float * GGML_RESTRICT quant_weights) { const int gindex = iq2_data_index(GGML_TYPE_IQ2_XXS); @@ -3124,7 +3124,7 @@ static void quantize_row_iq2_xxs_impl(const float * restrict x, void * restrict } } -static void quantize_row_iq2_xs_impl(const float * restrict x, void * restrict vy, int64_t n, const float * restrict quant_weights) { +static void quantize_row_iq2_xs_impl(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t n, const float * GGML_RESTRICT quant_weights) { const int gindex = iq2_data_index(GGML_TYPE_IQ2_XS); @@ -3304,7 +3304,7 @@ static void quantize_row_iq2_xs_impl(const float * restrict x, void * restrict v } } -size_t quantize_iq2_xxs(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq2_xxs(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); int64_t nblock = n_per_row/QK_K; char * qrow = (char *)dst; @@ -3316,7 +3316,7 @@ size_t quantize_iq2_xxs(const float * restrict src, void * restrict dst, int64_t return nrow * nblock * sizeof(block_iq2_xxs); } -size_t quantize_iq2_xs(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq2_xs(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); int64_t nblock = n_per_row/QK_K; char * qrow = (char *)dst; @@ -3521,8 +3521,8 @@ void iq3xs_free_impl(int grid_size) { } } -static int iq3_find_best_neighbour(const uint16_t * restrict neighbours, const uint32_t * restrict grid, - const float * restrict xval, const float * restrict weight, float scale, int8_t * restrict L) { +static int iq3_find_best_neighbour(const uint16_t * GGML_RESTRICT neighbours, const uint32_t * GGML_RESTRICT grid, + const float * GGML_RESTRICT xval, const float * GGML_RESTRICT weight, float scale, int8_t * GGML_RESTRICT L) { int num_neighbors = neighbours[0]; GGML_ASSERT(num_neighbors > 0); float best_d2 = FLT_MAX; @@ -3545,8 +3545,8 @@ static int iq3_find_best_neighbour(const uint16_t * restrict neighbours, const u return grid_index; } -static void quantize_row_iq3_xxs_impl(int grid_size, const float * restrict x, void * restrict vy, int64_t n, - const float * restrict quant_weights) { +static void quantize_row_iq3_xxs_impl(int grid_size, const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t n, + const float * GGML_RESTRICT quant_weights) { const int gindex = iq3_data_index(grid_size); @@ -3758,7 +3758,7 @@ static void quantize_row_iq3_xxs_impl(int grid_size, const float * restrict x, v } } -size_t quantize_iq3_xxs(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq3_xxs(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); int64_t nblock = n_per_row/QK_K; char * qrow = (char *)dst; @@ -3770,13 +3770,13 @@ size_t quantize_iq3_xxs(const float * restrict src, void * restrict dst, int64_t return nrow * nblock * sizeof(block_iq3_xxs); } -void quantize_row_iq3_xxs_ref(const float * restrict x, block_iq3_xxs * restrict y, int64_t k) { +void quantize_row_iq3_xxs_ref(const float * GGML_RESTRICT x, block_iq3_xxs * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); quantize_row_iq3_xxs_impl(256, x, y, k, NULL); } -static void quantize_row_iq3_s_impl(int block_size, const float * restrict x, void * restrict vy, int n, - const float * restrict quant_weights, +static void quantize_row_iq3_s_impl(int block_size, const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int n, + const float * GGML_RESTRICT quant_weights, float * scales, float * weight, float * xval, @@ -3958,7 +3958,7 @@ static void quantize_row_iq3_s_impl(int block_size, const float * restrict x, vo } #define IQ3S_BLOCK_SIZE 32 -size_t quantize_iq3_s(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq3_s(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); int64_t nblock = n_per_row/QK_K; float scales[QK_K/IQ3S_BLOCK_SIZE]; @@ -3980,7 +3980,7 @@ size_t quantize_iq3_s(const float * restrict src, void * restrict dst, int64_t n return nrow * nblock * sizeof(block_iq3_s); } -void quantize_row_iq3_s_ref(const float * restrict x, block_iq3_s * restrict y, int64_t k) { +void quantize_row_iq3_s_ref(const float * GGML_RESTRICT x, block_iq3_s * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); quantize_iq3_s(x, y, 1, k, NULL); } @@ -3988,8 +3988,8 @@ void quantize_row_iq3_s_ref(const float * restrict x, block_iq3_s * restrict y, // =================================== 1.5 bpw =================================================== -static int iq1_find_best_neighbour(const uint16_t * restrict neighbours, const uint64_t * restrict grid, - const float * restrict xval, const float * restrict weight, float * scale, int8_t * restrict L, int ngrid) { +static int iq1_find_best_neighbour(const uint16_t * GGML_RESTRICT neighbours, const uint64_t * GGML_RESTRICT grid, + const float * GGML_RESTRICT xval, const float * GGML_RESTRICT weight, float * scale, int8_t * GGML_RESTRICT L, int ngrid) { int num_neighbors = neighbours[0]; GGML_ASSERT(num_neighbors > 0); float best_score = -FLT_MAX; @@ -4048,8 +4048,8 @@ static int iq1_find_best_neighbour(const uint16_t * restrict neighbours, const u return grid_index; } -static int iq1_find_best_neighbour2(const uint16_t * restrict neighbours, const uint64_t * restrict grid, - const float * restrict xval, const float * restrict weight, float scale, const float * restrict xg, int8_t * restrict L, int ngrid) { +static int iq1_find_best_neighbour2(const uint16_t * GGML_RESTRICT neighbours, const uint64_t * GGML_RESTRICT grid, + const float * GGML_RESTRICT xval, const float * GGML_RESTRICT weight, float scale, const float * GGML_RESTRICT xg, int8_t * GGML_RESTRICT L, int ngrid) { int num_neighbors = neighbours[0]; GGML_ASSERT(num_neighbors > 0); float best_score = FLT_MAX; @@ -4113,7 +4113,7 @@ static int iq1_sort_helper(const void * left, const void * right) { #define IQ1S_BLOCK_SIZE 32 #define IQ1M_BLOCK_SIZE 16 -static void quantize_row_iq1_s_impl(const float * restrict x, void * restrict vy, int64_t n, const float * restrict quant_weights, +static void quantize_row_iq1_s_impl(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t n, const float * GGML_RESTRICT quant_weights, float * scales, float * weight, float * sumx, @@ -4271,7 +4271,7 @@ static void quantize_row_iq1_s_impl(const float * restrict x, void * restrict vy } } -size_t quantize_iq1_s(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq1_s(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); float scales[QK_K/IQ1S_BLOCK_SIZE]; float weight[IQ1S_BLOCK_SIZE]; @@ -4291,7 +4291,7 @@ size_t quantize_iq1_s(const float * restrict src, void * restrict dst, int64_t n return nrow * nblock * sizeof(block_iq1_s); } -static void quantize_row_iq1_m_impl(const float * restrict x, void * restrict vy, int64_t n, const float * restrict quant_weights, +static void quantize_row_iq1_m_impl(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t n, const float * GGML_RESTRICT quant_weights, float * scales, float * weight, float * pairs, @@ -4539,7 +4539,7 @@ static void quantize_row_iq1_m_impl(const float * restrict x, void * restrict vy } } -size_t quantize_iq1_m(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq1_m(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); float scales[QK_K/IQ1M_BLOCK_SIZE]; float weight[IQ1M_BLOCK_SIZE]; @@ -4570,7 +4570,7 @@ static inline int best_index_int8(int n, const int8_t * val, float x) { return x - val[mu-1] < val[mu] - x ? mu-1 : mu; } -static void quantize_row_iq4_nl_impl(const int super_block_size, const int block_size, const float * restrict x, +static void quantize_row_iq4_nl_impl(const int super_block_size, const int block_size, const float * GGML_RESTRICT x, ggml_fp16_t * dh, uint8_t * q4, uint16_t * scales_h, uint8_t * scales_l, float * scales, float * weight, uint8_t * L, const int8_t * values, @@ -4681,7 +4681,7 @@ static void quantize_row_iq4_nl_impl(const int super_block_size, const int block } } -size_t quantize_iq4_nl(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq4_nl(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK4_NL == 0); int64_t nblock = n_per_row/QK4_NL; char * qrow = (char *)dst; @@ -4703,8 +4703,8 @@ size_t quantize_iq4_nl(const float * restrict src, void * restrict dst, int64_t return nrow * nblock * sizeof(block_iq4_nl); } -//void quantize_row_iq4_nl_ref(const float * restrict x, void * restrict vy, int64_t k) { -void quantize_row_iq4_nl_ref(const float * restrict x, block_iq4_nl * restrict y, int64_t k) { +//void quantize_row_iq4_nl_ref(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { +void quantize_row_iq4_nl_ref(const float * GGML_RESTRICT x, block_iq4_nl * GGML_RESTRICT y, int64_t k) { GGML_ASSERT(k%QK4_NL == 0); int64_t nblock = k/QK4_NL; uint8_t L[QK4_NL]; @@ -4719,7 +4719,7 @@ void quantize_row_iq4_nl_ref(const float * restrict x, block_iq4_nl * restrict y } } -size_t quantize_iq4_xs(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq4_xs(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); int64_t nblock = n_per_row/QK_K; char * qrow = (char *)dst; @@ -4739,14 +4739,14 @@ size_t quantize_iq4_xs(const float * restrict src, void * restrict dst, int64_t return nrow * nblock * sizeof(block_iq4_xs); } -void quantize_row_iq4_xs_ref(const float * restrict x, block_iq4_xs * restrict y, int64_t k) { +void quantize_row_iq4_xs_ref(const float * GGML_RESTRICT x, block_iq4_xs * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); quantize_iq4_xs(x, y, 1, k, NULL); } // =============================== 2.5625 bpw -static void quantize_row_iq2_s_impl(const float * restrict x, void * restrict vy, int64_t n, const float * restrict quant_weights) { +static void quantize_row_iq2_s_impl(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t n, const float * GGML_RESTRICT quant_weights) { const int gindex = iq2_data_index(GGML_TYPE_IQ2_S); @@ -4914,7 +4914,7 @@ static void quantize_row_iq2_s_impl(const float * restrict x, void * restrict vy } } -size_t quantize_iq2_s(const float * restrict src, void * restrict dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { +size_t quantize_iq2_s(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrow, int64_t n_per_row, const float * quant_weights) { GGML_ASSERT(n_per_row%QK_K == 0); int64_t nblock = n_per_row/QK_K; char * qrow = (char *)dst; @@ -4926,7 +4926,7 @@ size_t quantize_iq2_s(const float * restrict src, void * restrict dst, int64_t n return nrow * nblock * sizeof(block_iq2_s); } -void quantize_row_iq2_s_ref(const float * restrict x, block_iq2_s * restrict y, int64_t k) { +void quantize_row_iq2_s_ref(const float * GGML_RESTRICT x, block_iq2_s * GGML_RESTRICT y, int64_t k) { assert(k % QK_K == 0); quantize_iq2_s(x, y, 1, k, NULL); } diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index 7fc06724e..084240331 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -565,9 +565,9 @@ FILE * ggml_fopen(const char * fname, const char * mode) { #endif } -static void ggml_vec_dot_f32(int n, float * restrict s, size_t bs, const float * restrict x, size_t bx, const float * restrict y, size_t by, int nrc); -static void ggml_vec_dot_f16(int n, float * restrict s, size_t bs, ggml_fp16_t * restrict x, size_t bx, ggml_fp16_t * restrict y, size_t by, int nrc); -static void ggml_vec_dot_bf16(int n, float * restrict s, size_t bs, ggml_bf16_t * restrict x, size_t bx, ggml_bf16_t * restrict y, size_t by, int nrc); +static void ggml_vec_dot_f32(int n, float * GGML_RESTRICT s, size_t bs, const float * GGML_RESTRICT x, size_t bx, const float * GGML_RESTRICT y, size_t by, int nrc); +static void ggml_vec_dot_f16(int n, float * GGML_RESTRICT s, size_t bs, ggml_fp16_t * GGML_RESTRICT x, size_t bx, ggml_fp16_t * GGML_RESTRICT y, size_t by, int nrc); +static void ggml_vec_dot_bf16(int n, float * GGML_RESTRICT s, size_t bs, ggml_bf16_t * GGML_RESTRICT x, size_t bx, ggml_bf16_t * GGML_RESTRICT y, size_t by, int nrc); static const struct ggml_type_traits type_traits[GGML_TYPE_COUNT] = { [GGML_TYPE_I8] = { diff --git a/src/llama-chat.cpp b/src/llama-chat.cpp index 028a64794..de4458696 100644 --- a/src/llama-chat.cpp +++ b/src/llama-chat.cpp @@ -4,6 +4,7 @@ #include #include +#include #if __cplusplus >= 202000L #define LU8(x) (const char*)(u8##x) diff --git a/src/llama-kv-cache.h b/src/llama-kv-cache.h index 1ed688e3b..1ce0850ec 100644 --- a/src/llama-kv-cache.h +++ b/src/llama-kv-cache.h @@ -6,6 +6,7 @@ #include #include +#include struct llama_kv_cell { llama_pos pos = -1; diff --git a/src/llama-mmap.cpp b/src/llama-mmap.cpp index b716630a8..c13b3755a 100644 --- a/src/llama-mmap.cpp +++ b/src/llama-mmap.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef __has_include #if __has_include() diff --git a/src/llama-vocab.cpp b/src/llama-vocab.cpp index 163ff64f7..a708d8b88 100644 --- a/src/llama-vocab.cpp +++ b/src/llama-vocab.cpp @@ -16,6 +16,7 @@ #include #include #include +#include // // helpers From a057897ad4e48e3df0354256e0cc80dadcb57595 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Wed, 5 Mar 2025 06:30:31 +0100 Subject: [PATCH 29/87] llama : add xcframework build script (#11996) * llama : add xcframework build script This commit adds a script to build an XCFramework for Apple ios, macos, visionos, and tvos platforms. The generated XCFramework can then be added to a project and used in the same way as a regular framework. The llama.swiftui example project has been updated to use the XCFramework and can be started using the following command: ```console $ open examples/llama.swiftui/llama.swiftui.xcodeproj/ ``` Refs: https://github.com/ggml-org/llama.cpp/issues/10747 * examples : remove llama.cpp (source dir ref) from project.pbxproj This commit removes the reference to llama.cpp from the project.pbxproj file since Package.swift has been removed. * ci : updated build.yml to use build-xcframework.sh * ci : add xcframework build to github releases This commit adds the ability to create a GitHub release with the xcframework build artifact. * scripts : add apple app validation scripts This commit adds scripts that can validate the iOS, macOS, tvOS, and VisionOS applications. The scripts create a simple test app project, copy the llama.xcframework to the test project, build and archive the app, create an IPA from the archive, and validate the IPA using altool. The motivation for this is to provide some basic validation and hopefully avoid having to manually validate apps in Xcode. * llama : remove Package.swift This commit removes the Package.swift file, as we are now building an XCFramework for the project. * llama : remove Sources and spm-headers directories * llama : use TargetConditionals.h for visionOS/tvOS --- .github/workflows/build.yml | 33 +- Package.swift | 19 - Sources/llama/llama.h | 4 - Sources/llama/module.modulemap | 5 - build-xcframework.sh | 519 +++++++++++ examples/llama.swiftui/README.md | 15 + .../llama.swiftui.xcodeproj/project.pbxproj | 30 +- scripts/apple/validate-apps.sh | 5 + scripts/apple/validate-ios.sh | 820 ++++++++++++++++++ scripts/apple/validate-macos.sh | 781 +++++++++++++++++ scripts/apple/validate-tvos.sh | 813 +++++++++++++++++ scripts/apple/validate-visionos.sh | 811 +++++++++++++++++ spm-headers/ggml-alloc.h | 1 - spm-headers/ggml-backend.h | 1 - spm-headers/ggml-cpp.h | 1 - spm-headers/ggml-cpu.h | 1 - spm-headers/ggml-metal.h | 1 - spm-headers/ggml.h | 1 - spm-headers/llama.h | 1 - src/llama-mmap.cpp | 11 +- 20 files changed, 3822 insertions(+), 51 deletions(-) delete mode 100644 Package.swift delete mode 100644 Sources/llama/llama.h delete mode 100644 Sources/llama/module.modulemap create mode 100755 build-xcframework.sh create mode 100755 scripts/apple/validate-apps.sh create mode 100755 scripts/apple/validate-ios.sh create mode 100755 scripts/apple/validate-macos.sh create mode 100755 scripts/apple/validate-tvos.sh create mode 100755 scripts/apple/validate-visionos.sh delete mode 120000 spm-headers/ggml-alloc.h delete mode 120000 spm-headers/ggml-backend.h delete mode 120000 spm-headers/ggml-cpp.h delete mode 120000 spm-headers/ggml-cpu.h delete mode 120000 spm-headers/ggml-metal.h delete mode 120000 spm-headers/ggml.h delete mode 120000 spm-headers/llama.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b96e1f50a..b0c180f26 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -710,12 +710,36 @@ jobs: -DLLAMA_BUILD_SERVER=OFF \ -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" cmake --build build --config Release -j $(sysctl -n hw.logicalcpu) - sudo cmake --install build --config Release - name: xcodebuild for swift package id: xcodebuild run: | - xcodebuild -scheme llama-Package -destination "${{ matrix.destination }}" + ./build-xcframework.sh + + - name: Determine tag name + id: tag + shell: bash + run: | + BUILD_NUMBER="$(git rev-list --count HEAD)" + SHORT_HASH="$(git rev-parse --short=7 HEAD)" + if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then + echo "name=b${BUILD_NUMBER}" >> $GITHUB_OUTPUT + else + SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-') + echo "name=${SAFE_NAME}-b${BUILD_NUMBER}-${SHORT_HASH}" >> $GITHUB_OUTPUT + fi + + - name: Pack artifacts + id: pack_artifacts + if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} + run: | + zip -r llama-${{ steps.tag.outputs.name }}-xcframework.zip build-apple/llama.xcframework + + - name: Upload artifacts + if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} + uses: actions/upload-artifact@v4 + with: + path: llama-${{ steps.tag.outputs.name }}-xcframework.zip windows-msys2: runs-on: windows-latest @@ -1336,15 +1360,14 @@ jobs: -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \ -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=ggml cmake --build build --config Release -j $(sysctl -n hw.logicalcpu) -- CODE_SIGNING_ALLOWED=NO - sudo cmake --install build --config Release - name: xcodebuild for swift package id: xcodebuild run: | - xcodebuild -scheme llama-Package -destination 'generic/platform=iOS' + ./build-xcframework.sh - name: Build Xcode project - run: xcodebuild -project examples/llama.swiftui/llama.swiftui.xcodeproj -scheme llama.swiftui -sdk iphoneos CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= -destination 'generic/platform=iOS' build + run: xcodebuild -project examples/llama.swiftui/llama.swiftui.xcodeproj -scheme llama.swiftui -sdk iphoneos CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= -destination 'generic/platform=iOS' FRAMEWORK_FOLDER_PATH=./build-ios build android-build: runs-on: ubuntu-latest diff --git a/Package.swift b/Package.swift deleted file mode 100644 index 01c996d24..000000000 --- a/Package.swift +++ /dev/null @@ -1,19 +0,0 @@ -// swift-tools-version:5.5 - -import PackageDescription - -let package = Package( - name: "llama", - platforms: [ - .macOS(.v12), - .iOS(.v14), - .watchOS(.v4), - .tvOS(.v14) - ], - products: [ - .library(name: "llama", targets: ["llama"]), - ], - targets: [ - .systemLibrary(name: "llama", pkgConfig: "llama"), - ] -) diff --git a/Sources/llama/llama.h b/Sources/llama/llama.h deleted file mode 100644 index 41725880e..000000000 --- a/Sources/llama/llama.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include - diff --git a/Sources/llama/module.modulemap b/Sources/llama/module.modulemap deleted file mode 100644 index d010555b1..000000000 --- a/Sources/llama/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -module llama [system] { - header "llama.h" - link "llama" - export * -} diff --git a/build-xcframework.sh b/build-xcframework.sh new file mode 100755 index 000000000..37833dc4e --- /dev/null +++ b/build-xcframework.sh @@ -0,0 +1,519 @@ +#!/bin/bash +# +# Options +IOS_MIN_OS_VERSION=16.4 +MACOS_MIN_OS_VERSION=13.3 +VISIONOS_MIN_OS_VERSION=1.0 +TVOS_MIN_OS_VERSION=16.4 + +BUILD_SHARED_LIBS=OFF +LLAMA_BUILD_EXAMPLES=OFF +LLAMA_BUILD_TESTS=OFF +LLAMA_BUILD_SERVER=OFF +GGML_METAL=ON +GGML_METAL_EMBED_LIBRARY=ON +GGML_BLAS_DEFAULT=ON +GGML_METAL_USE_BF16=ON +GGML_OPENMP=OFF + +COMMON_C_FLAGS="-Wno-macro-redefined -Wno-shorten-64-to-32 -Wno-unused-command-line-argument -g" +COMMON_CXX_FLAGS="-Wno-macro-redefined -Wno-shorten-64-to-32 -Wno-unused-command-line-argument -g" + +# Common options for all builds +COMMON_CMAKE_ARGS=( + -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=NO + -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY="" + -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO + -DCMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT="dwarf-with-dsym" + -DCMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS=YES + -DCMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP=NO + -DCMAKE_XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT=NO + -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=ggml + -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} + -DLLAMA_BUILD_EXAMPLES=${LLAMA_BUILD_EXAMPLES} + -DLLAMA_BUILD_TESTS=${LLAMA_BUILD_TESTS} + -DLLAMA_BUILD_SERVER=${LLAMA_BUILD_SERVER} + -DGGML_METAL_EMBED_LIBRARY=${GGML_METAL_EMBED_LIBRARY} + -DGGML_BLAS_DEFAULT=${GGML_BLAS_DEFAULT} + -DGGML_METAL=${GGML_METAL} + -DGGML_METAL_USE_BF16=${GGML_METAL_USE_BF16} + -DGGML_NATIVE=OFF + -DGGML_OPENMP=${GGML_OPENMP} +) + +check_required_tool() { + local tool=$1 + local install_message=$2 + + if ! command -v $tool &> /dev/null; then + echo "Error: $tool is required but not found." + echo "$install_message" + exit 1 + fi +} +echo "Checking for required tools..." +check_required_tool "cmake" "Please install CMake 3.28.0 or later (brew install cmake)" +check_required_tool "xcodebuild" "Please install Xcode and Xcode Command Line Tools (xcode-select --install)" +check_required_tool "libtool" "Please install libtool which should be available with Xcode Command Line Tools (CLT). Make sure Xcode CLT is installed (xcode-select --install)" +check_required_tool "dsymutil" "Please install Xcode and Xcode Command Line Tools (xcode-select --install)" + +set -e + +## Clean up previous builds +rm -rf build-apple +rm -rf build-ios-sim +rm -rf build-ios-device +rm -rf build-macos +rm -rf build-visionos +rm -rf build-visionos-sim +rm -rf build-tvos-sim +rm -rf build-tvos-device + +# Setup the xcframework build directory structure +setup_framework_structure() { + local build_dir=$1 + local min_os_version=$2 + local platform=$3 # "ios", "macos", "visionos", or "tvos" + local framework_name="llama" + + echo "Creating ${platform}-style framework structure for ${build_dir}" + + if [[ "$platform" == "macos" ]]; then + # macOS versioned structure uses versioned directories + mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Headers + mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Modules + mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Resources + + # Create symbolic links + ln -sf A ${build_dir}/framework/${framework_name}.framework/Versions/Current + ln -sf Versions/Current/Headers ${build_dir}/framework/${framework_name}.framework/Headers + ln -sf Versions/Current/Modules ${build_dir}/framework/${framework_name}.framework/Modules + ln -sf Versions/Current/Resources ${build_dir}/framework/${framework_name}.framework/Resources + ln -sf Versions/Current/${framework_name} ${build_dir}/framework/${framework_name}.framework/${framework_name} + + # Set header and module paths + local header_path=${build_dir}/framework/${framework_name}.framework/Versions/A/Headers/ + local module_path=${build_dir}/framework/${framework_name}.framework/Versions/A/Modules/ + else + # iOS/VisionOS/tvOS use a flat structure + mkdir -p ${build_dir}/framework/${framework_name}.framework/Headers + mkdir -p ${build_dir}/framework/${framework_name}.framework/Modules + + # Remove any existing structure to ensure clean build + rm -rf ${build_dir}/framework/${framework_name}.framework/Versions + + # Set header and module paths + local header_path=${build_dir}/framework/${framework_name}.framework/Headers/ + local module_path=${build_dir}/framework/${framework_name}.framework/Modules/ + fi + + # Copy all required headers (common for all platforms) + cp include/llama.h ${header_path} + cp ggml/include/ggml.h ${header_path} + cp ggml/include/ggml-alloc.h ${header_path} + cp ggml/include/ggml-backend.h ${header_path} + cp ggml/include/ggml-metal.h ${header_path} + cp ggml/include/ggml-cpu.h ${header_path} + cp ggml/include/ggml-blas.h ${header_path} + cp ggml/include/gguf.h ${header_path} + + # Create module map (common for all platforms) + cat > ${module_path}module.modulemap << EOF +framework module llama { + header "llama.h" + header "ggml.h" + header "ggml-alloc.h" + header "ggml-backend.h" + header "ggml-metal.h" + header "ggml-cpu.h" + header "ggml-blas.h" + header "gguf.h" + + link "c++" + link framework "Accelerate" + link framework "Metal" + link framework "Foundation" + + export * +} +EOF + + # Platform-specific settings for Info.plist + local platform_name="" + local sdk_name="" + local supported_platform="" + + case "$platform" in + "ios") + platform_name="iphoneos" + sdk_name="iphoneos${min_os_version}" + supported_platform="iPhoneOS" + local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist" + local device_family=' UIDeviceFamily + + 1 + 2 + ' + ;; + "macos") + platform_name="macosx" + sdk_name="macosx${min_os_version}" + supported_platform="MacOSX" + local plist_path="${build_dir}/framework/${framework_name}.framework/Versions/A/Resources/Info.plist" + local device_family="" + ;; + "visionos") + platform_name="xros" + sdk_name="xros${min_os_version}" + supported_platform="XRPlatform" + local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist" + local device_family="" + ;; + "tvos") + platform_name="appletvos" + sdk_name="appletvos${min_os_version}" + supported_platform="AppleTVOS" + local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist" + local device_family=' UIDeviceFamily + + 3 + ' + ;; + esac + + # Create Info.plist + cat > ${plist_path} << EOF + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + llama + CFBundleIdentifier + org.ggml.llama + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + llama + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + MinimumOSVersion + ${min_os_version} + CFBundleSupportedPlatforms + + ${supported_platform} + ${device_family} + DTPlatformName + ${platform_name} + DTSDKName + ${sdk_name} + + +EOF +} + +# Create dynamic libraries from static libraries. +combine_static_libraries() { + local build_dir="$1" + local release_dir="$2" + local platform="$3" # "ios", "macos", "visionos", or "tvos" + local is_simulator="$4" + local base_dir="$(pwd)" + local framework_name="llama" + + # Determine output path based on platform + local output_lib="" + if [[ "$platform" == "macos" ]]; then + # macOS uses versioned structure + output_lib="${build_dir}/framework/${framework_name}.framework/Versions/A/${framework_name}" + else + # iOS, visionOS, and tvOS use a directory flat structure + output_lib="${build_dir}/framework/${framework_name}.framework/${framework_name}" + fi + + local libs=( + "${base_dir}/${build_dir}/src/${release_dir}/libllama.a" + "${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml.a" + "${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml-base.a" + "${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml-cpu.a" + "${base_dir}/${build_dir}/ggml/src/ggml-metal/${release_dir}/libggml-metal.a" + "${base_dir}/${build_dir}/ggml/src/ggml-blas/${release_dir}/libggml-blas.a" + ) + + # Create temporary directory for processing + local temp_dir="${base_dir}/${build_dir}/temp" + mkdir -p "${temp_dir}" + + # Since we have multiple architectures libtool will find object files that do not + # match the target architecture. We suppress these warnings. + libtool -static -o "${temp_dir}/combined.a" "${libs[@]}" 2> /dev/null + + # Determine SDK, architectures, and install_name based on platform and simulator flag. + local sdk="" + local archs="" + local min_version_flag="" + local install_name="" + + case "$platform" in + "ios") + if [[ "$is_simulator" == "true" ]]; then + sdk="iphonesimulator" + archs="arm64 x86_64" + min_version_flag="-mios-simulator-version-min=${IOS_MIN_OS_VERSION}" + else + sdk="iphoneos" + archs="arm64" + min_version_flag="-mios-version-min=${IOS_MIN_OS_VERSION}" + fi + install_name="@rpath/llama.framework/llama" + ;; + "macos") + sdk="macosx" + archs="arm64 x86_64" + min_version_flag="-mmacosx-version-min=${MACOS_MIN_OS_VERSION}" + install_name="@rpath/llama.framework/Versions/Current/llama" + ;; + "visionos") + if [[ "$is_simulator" == "true" ]]; then + sdk="xrsimulator" + archs="arm64 x86_64" + min_version_flag="-mtargetos=xros${VISIONOS_MIN_OS_VERSION}-simulator" + else + sdk="xros" + archs="arm64" + min_version_flag="-mtargetos=xros${VISIONOS_MIN_OS_VERSION}" + fi + # Use flat structure for visionOS, same as iOS + install_name="@rpath/llama.framework/llama" + ;; + "tvos") + if [[ "$is_simulator" == "true" ]]; then + sdk="appletvsimulator" + archs="arm64 x86_64" + min_version_flag="-mtvos-simulator-version-min=${TVOS_MIN_OS_VERSION}" + else + sdk="appletvos" + archs="arm64" + min_version_flag="-mtvos-version-min=${TVOS_MIN_OS_VERSION}" + fi + install_name="@rpath/llama.framework/llama" + ;; + esac + + # Build architecture flags + local arch_flags="" + for arch in $archs; do + arch_flags+=" -arch $arch" + done + + # Create dynamic library + echo "Creating dynamic library for ${platform}." + xcrun -sdk $sdk clang++ -dynamiclib \ + -isysroot $(xcrun --sdk $sdk --show-sdk-path) \ + $arch_flags \ + $min_version_flag \ + -Wl,-force_load,"${temp_dir}/combined.a" \ + -framework Foundation -framework Metal -framework Accelerate \ + -install_name "$install_name" \ + -o "${base_dir}/${output_lib}" + + # Platform-specific post-processing for device builds + if [[ "$is_simulator" == "false" ]]; then + if command -v vtool &>/dev/null; then + case "$platform" in + "ios") + echo "Marking binary as a framework binary for iOS..." + vtool -set-build-version ios ${IOS_MIN_OS_VERSION} ${IOS_MIN_OS_VERSION} -replace \ + -output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}" + ;; + "visionos") + echo "Marking binary as a framework binary for visionOS..." + vtool -set-build-version xros ${VISIONOS_MIN_OS_VERSION} ${VISIONOS_MIN_OS_VERSION} -replace \ + -output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}" + ;; + "tvos") + echo "Marking binary as a framework binary for tvOS..." + vtool -set-build-version tvos ${TVOS_MIN_OS_VERSION} ${TVOS_MIN_OS_VERSION} -replace \ + -output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}" + ;; + esac + else + echo "Warning: vtool not found. Binary may not pass App Store validation." + fi + fi + + echo "Creating properly formatted dSYM..." + # Create a separate directory for dSYMs for all platforms + mkdir -p "${base_dir}/${build_dir}/dSYMs" + + # iOS and visionOS style dSYM (flat structure) + if [[ "$platform" == "ios" || "$platform" == "visionos" || "$platform" == "tvos" ]]; then + # Generate dSYM in the dSYMs directory + xcrun dsymutil "${base_dir}/${output_lib}" -o "${base_dir}/${build_dir}/dSYMs/llama.dSYM" + + # Create a copy of the binary that will be stripped + cp "${base_dir}/${output_lib}" "${temp_dir}/binary_to_strip" + + # Strip debug symbols from the copy + xcrun strip -S "${temp_dir}/binary_to_strip" -o "${temp_dir}/stripped_lib" + + # Replace the original with the stripped version + mv "${temp_dir}/stripped_lib" "${base_dir}/${output_lib}" + else + # macOS style dSYM + # First strip debug info to a separate file + xcrun strip -S "${base_dir}/${output_lib}" -o "${temp_dir}/stripped_lib" + + # Generate dSYM in the dSYMs directory + xcrun dsymutil "${base_dir}/${output_lib}" -o "${base_dir}/${build_dir}/dSYMs/llama.dSYM" + + # Replace original binary with stripped version + mv "${temp_dir}/stripped_lib" "${base_dir}/${output_lib}" + fi + + # Remove any automatically generated dSYM files in the framework structure as they will + # otherwise case Invalid Bundle Structure validation errors. + if [ -d "${base_dir}/${output_lib}.dSYM" ]; then + echo "Removing generated dSYM file in framework structure: ${base_dir}/${output_lib}.dSYM" + rm -rf "${base_dir}/${output_lib}.dSYM" + fi + + # Clean up + rm -rf "${temp_dir}" +} + +echo "Building for iOS simulator..." +cmake -B build-ios-sim -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${IOS_MIN_OS_VERSION} \ + -DIOS=ON \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT=iphonesimulator \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=iphonesimulator \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-ios-sim --config Release -- -quiet + +echo "Building for iOS devices..." +cmake -B build-ios-device -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${IOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_SYSROOT=iphoneos \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=iphoneos \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-ios-device --config Release -- -quiet + +echo "Building for macOS..." +cmake -B build-macos -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-macos --config Release -- -quiet + +echo "Building for visionOS..." +cmake -B build-visionos -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${VISIONOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -DCMAKE_SYSTEM_NAME=visionOS \ + -DCMAKE_OSX_SYSROOT=xros \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=xros \ + -DCMAKE_C_FLAGS="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-visionos --config Release -- -quiet + +echo "Building for visionOS simulator..." +cmake -B build-visionos-sim -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${VISIONOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_SYSTEM_NAME=visionOS \ + -DCMAKE_OSX_SYSROOT=xrsimulator \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=xrsimulator \ + -DCMAKE_C_FLAGS="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-visionos-sim --config Release -- -quiet + +# Add tvOS builds (might need the same u_int definitions as watchOS and visionOS) +echo "Building for tvOS simulator..." +cmake -B build-tvos-sim -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${TVOS_MIN_OS_VERSION} \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_SYSROOT=appletvsimulator \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DGGML_METAL=ON \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=appletvsimulator \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-tvos-sim --config Release -- -quiet + +echo "Building for tvOS devices..." +cmake -B build-tvos-device -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${TVOS_MIN_OS_VERSION} \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_SYSROOT=appletvos \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -DGGML_METAL=ON \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=appletvos \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-tvos-device --config Release -- -quiet + +# Setup frameworks and copy binaries and headers +echo "Setting up framework structures..." +setup_framework_structure "build-ios-sim" ${IOS_MIN_OS_VERSION} "ios" +setup_framework_structure "build-ios-device" ${IOS_MIN_OS_VERSION} "ios" +setup_framework_structure "build-macos" ${MACOS_MIN_OS_VERSION} "macos" +setup_framework_structure "build-visionos" ${VISIONOS_MIN_OS_VERSION} "visionos" +setup_framework_structure "build-visionos-sim" ${VISIONOS_MIN_OS_VERSION} "visionos" +setup_framework_structure "build-tvos-sim" ${TVOS_MIN_OS_VERSION} "tvos" +setup_framework_structure "build-tvos-device" ${TVOS_MIN_OS_VERSION} "tvos" + +# Create dynamic libraries from static libraries +echo "Creating dynamic libraries from static libraries..." +combine_static_libraries "build-ios-sim" "Release-iphonesimulator" "ios" "true" +combine_static_libraries "build-ios-device" "Release-iphoneos" "ios" "false" +combine_static_libraries "build-macos" "Release" "macos" "false" +combine_static_libraries "build-visionos" "Release-xros" "visionos" "false" +combine_static_libraries "build-visionos-sim" "Release-xrsimulator" "visionos" "true" +combine_static_libraries "build-tvos-sim" "Release-appletvsimulator" "tvos" "true" +combine_static_libraries "build-tvos-device" "Release-appletvos" "tvos" "false" + +# Create XCFramework with correct debug symbols paths +echo "Creating XCFramework..." +xcodebuild -create-xcframework \ + -framework $(pwd)/build-ios-sim/framework/llama.framework \ + -debug-symbols $(pwd)/build-ios-sim/dSYMs/llama.dSYM \ + -framework $(pwd)/build-ios-device/framework/llama.framework \ + -debug-symbols $(pwd)/build-ios-device/dSYMs/llama.dSYM \ + -framework $(pwd)/build-macos/framework/llama.framework \ + -debug-symbols $(pwd)/build-macos/dSYMS/llama.dSYM \ + -framework $(pwd)/build-visionos/framework/llama.framework \ + -debug-symbols $(pwd)/build-visionos/dSYMs/llama.dSYM \ + -framework $(pwd)/build-visionos-sim/framework/llama.framework \ + -debug-symbols $(pwd)/build-visionos-sim/dSYMs/llama.dSYM \ + -framework $(pwd)/build-tvos-device/framework/llama.framework \ + -debug-symbols $(pwd)/build-tvos-device/dSYMs/llama.dSYM \ + -framework $(pwd)/build-tvos-sim/framework/llama.framework \ + -debug-symbols $(pwd)/build-tvos-sim/dSYMs/llama.dSYM \ + -output $(pwd)/build-apple/llama.xcframework diff --git a/examples/llama.swiftui/README.md b/examples/llama.swiftui/README.md index f717886d6..5b0ee9472 100644 --- a/examples/llama.swiftui/README.md +++ b/examples/llama.swiftui/README.md @@ -5,6 +5,21 @@ point for more advanced projects. For usage instructions and performance stats, check the following discussion: https://github.com/ggml-org/llama.cpp/discussions/4508 + +### Building +First llama.cpp need to be built and a XCFramework needs to be created. This can be done by running +the following script from the llama.cpp project root: +```console +$ ./build-xcframework.sh +``` +Open `llama.swiftui.xcodeproj` project in Xcode and you should be able to build and run the app on +a simulator or a real device. + +To use the framework with a different project, the XCFramework can be added to the project by +adding `build-ios/llama.xcframework` by dragging and dropping it into the project navigator, or +by manually selecting the framework in the "Frameworks, Libraries, and Embedded Content" section +of the project settings. + ![image](https://github.com/ggml-org/llama.cpp/assets/1991296/2b40284f-8421-47a2-b634-74eece09a299) Video demonstration: diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj index ff3d108b2..6f08fe220 100644 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 1809696D2D05A39F00400EE8 /* llama in Frameworks */ = {isa = PBXBuildFile; productRef = 1809696C2D05A39F00400EE8 /* llama */; }; 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549479CA2AC9E16000E0F78B /* Metal.framework */; }; 79E1D9CD2B4CD16E005F8E46 /* InputButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E1D9CC2B4CD16E005F8E46 /* InputButton.swift */; }; 7FA3D2B32B2EA2F600543F92 /* DownloadButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FA3D2B22B2EA2F600543F92 /* DownloadButton.swift */; }; @@ -18,9 +17,25 @@ 8A3F84242AC4C891005E2EE8 /* models in Resources */ = {isa = PBXBuildFile; fileRef = 8A3F84232AC4C891005E2EE8 /* models */; }; 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A907F322AC7134E006146EA /* LibLlama.swift */; }; 8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */; }; + DD84C9FD2D747FED007778EC /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD84C9FC2D747FED007778EC /* llama.xcframework */; }; + DD84C9FE2D747FED007778EC /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD84C9FC2D747FED007778EC /* llama.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F1FE20E22B465ECA00B45541 /* LoadCustomButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1FE20E12B465EC900B45541 /* LoadCustomButton.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + DD84C9FF2D747FED007778EC /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + DD84C9FE2D747FED007778EC /* llama.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 549479CA2AC9E16000E0F78B /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 79E1D9CC2B4CD16E005F8E46 /* InputButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputButton.swift; sourceTree = ""; }; @@ -33,6 +48,7 @@ 8A3F84232AC4C891005E2EE8 /* models */ = {isa = PBXFileReference; lastKnownFileType = folder; name = models; path = llama.swiftui/Resources/models; sourceTree = ""; }; 8A907F322AC7134E006146EA /* LibLlama.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibLlama.swift; sourceTree = ""; }; 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LlamaState.swift; sourceTree = ""; }; + DD84C9FC2D747FED007778EC /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = llama.xcframework; path = "../../build-apple/llama.xcframework"; sourceTree = ""; }; DF2D2FE72B4A59BE00FCB72D /* llama.cpp */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = llama.cpp; path = ../..; sourceTree = ""; }; F1FE20E12B465EC900B45541 /* LoadCustomButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadCustomButton.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -42,9 +58,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1809696D2D05A39F00400EE8 /* llama in Frameworks */, 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */, 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */, + DD84C9FD2D747FED007778EC /* llama.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -86,6 +102,7 @@ 8A39BE082AC7601000BFEB40 /* Frameworks */ = { isa = PBXGroup; children = ( + DD84C9FC2D747FED007778EC /* llama.xcframework */, 549479CA2AC9E16000E0F78B /* Metal.framework */, 8A39BE092AC7601000BFEB40 /* Accelerate.framework */, ); @@ -144,6 +161,7 @@ 8A1C836F2AC328BD0096AF73 /* Sources */, 8A1C83702AC328BD0096AF73 /* Frameworks */, 8A1C83712AC328BD0096AF73 /* Resources */, + DD84C9FF2D747FED007778EC /* Embed Frameworks */, ); buildRules = ( ); @@ -151,7 +169,6 @@ ); name = llama.swiftui; packageProductDependencies = ( - 1809696C2D05A39F00400EE8 /* llama */, ); productName = llama.swiftui; productReference = 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */; @@ -427,13 +444,6 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - -/* Begin XCSwiftPackageProductDependency section */ - 1809696C2D05A39F00400EE8 /* llama */ = { - isa = XCSwiftPackageProductDependency; - productName = llama; - }; -/* End XCSwiftPackageProductDependency section */ }; rootObject = 8A1C836B2AC328BD0096AF73 /* Project object */; } diff --git a/scripts/apple/validate-apps.sh b/scripts/apple/validate-apps.sh new file mode 100755 index 000000000..a571aa6fc --- /dev/null +++ b/scripts/apple/validate-apps.sh @@ -0,0 +1,5 @@ +#!/bin/bash +./scripts/apple/validate-ios.sh +./scripts/apple/validate-macos.sh +./scripts/apple/validate-visionos.sh +./scripts/apple/validate-tvos.sh diff --git a/scripts/apple/validate-ios.sh b/scripts/apple/validate-ios.sh new file mode 100755 index 000000000..7bda1b972 --- /dev/null +++ b/scripts/apple/validate-ios.sh @@ -0,0 +1,820 @@ +#!/bin/bash +# validate-ios.sh - Validate iOS Application with embedded llama.xcframework using SwiftUI + +# Authentication options (optional) (can be set via environment variables) +# To use: export APPLE_ID=your.email@example.com +# export APPLE_PASSWORD=your-app-specific-password +# ./validate-ios.sh +APPLE_ID=${APPLE_ID:-""} +APPLE_PASSWORD=${APPLE_PASSWORD:-""} + +# Ensure the script exits on error +set -e + +# Function to print usage instructions +print_usage() { + echo "Usage: ./validate-ios.sh [OPTIONS]" + echo "" + echo "Options:" + echo " --help Show this help message" + echo " --apple-id EMAIL Apple ID email for validation" + echo " --apple-password PWD App-specific password for Apple ID" + echo "" + echo "Environment variables:" + echo " APPLE_ID Apple ID email for validation" + echo " APPLE_PASSWORD App-specific password for Apple ID" + echo "" + echo "Notes:" + echo " - Command line options take precedence over environment variables" + echo " - Authentication is optional. If not provided, alternative validation will be performed" + echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --help) + print_usage + exit 0 + ;; + --apple-id) + APPLE_ID="$2" + shift 2 + ;; + --apple-password) + APPLE_PASSWORD="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + print_usage + exit 1 + ;; + esac +done + +# Function to clean up in case of error +cleanup() { + # Don't clean up temp files on error to help with debugging + echo "===== iOS Validation Process Failed =====" + exit 1 +} + +# Set up trap to call cleanup function on error +trap cleanup ERR + +set -e # Exit on any error + +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" +BUILD_DIR="${ROOT_DIR}/validation-builds/ios" + +# Configuration +APP_NAME="iOSLlamaTest" +BUNDLE_ID="org.ggml.iOSLlamaTest" +XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework" +TEMP_DIR="${BUILD_DIR}/temp" +ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive" +IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa" +VALIDATION_DIR="${BUILD_DIR}/validation" + +# Create necessary directories +mkdir -p "${BUILD_DIR}" +mkdir -p "${TEMP_DIR}" +mkdir -p "${VALIDATION_DIR}" + +echo "===== iOS Validation Process Started =====" + +# 1. Create a simple test app project +echo "Creating test iOS app project..." +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${APP_NAME} + CFBundleIdentifier + ${BUNDLE_ID} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${APP_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchScreen + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + + +EOF + +# Create SwiftUI app files +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources" + +# Create App.swift +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF +import SwiftUI +import llama + +@main +struct LlamaTestApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +EOF + +# Create ContentView.swift +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF +import SwiftUI +import llama + +struct ContentView: View { + // Test that we can initialize a llama context params struct + let params = llama_context_default_params() + + var body: some View { + VStack(spacing: 20) { + Text("Llama Framework Test") + .font(.largeTitle) + .padding() + + Text("llama_context_default_params() created successfully") + .font(.headline) + .multilineTextAlignment(.center) + .padding() + + // Display some param values to confirm the framework is working + Text("n_ctx: \(params.n_ctx)") + .font(.body) + + Text("n_batch: \(params.n_batch)") + .font(.body) + + Spacer() + } + .padding() + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} +EOF + +# Create project.pbxproj, fixing the framework search paths issues +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; }; + 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; }; + 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 88888888888888888888888 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; + 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = ""; }; +/* End PBXFileReference section */ +EOF + +# Add the rest of the project file with fixed framework search paths +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXFrameworksBuildPhase section */ + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 55555555555555555555555 /* llama.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = { + isa = PBXGroup; + children = ( + 99999999999999999999999 /* ${APP_NAME}.app */, + ); + name = Products; + sourceTree = ""; + }; +EOF + +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 66666666666666666666666 /* llama.xcframework */, + ); + name = Frameworks; + sourceTree = ""; + }; + EEEEEEEEEEEEEEEEEEEEEEEE = { + isa = PBXGroup; + children = ( + FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */, + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */, + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */, + ); + sourceTree = ""; + }; + FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */ = { + isa = PBXGroup; + children = ( + 1111111111111111111111AA /* Sources */, + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */, + ); + path = "iOSLlamaTest"; + sourceTree = ""; + }; + 1111111111111111111111AA /* Sources */ = { + isa = PBXGroup; + children = ( + 22222222222222222222222 /* App.swift */, + 44444444444444444444444 /* ContentView.swift */, + ); + path = Sources; + sourceTree = ""; + }; +/* End PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin PBXNativeTarget section */ + 3333333333333333333333AA /* ${APP_NAME} */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */; + buildPhases = ( + 5555555555555555555555AA /* Sources */, + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */, + 6666666666666666666666AA /* Resources */, + 88888888888888888888888 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "${APP_NAME}"; + productName = "${APP_NAME}"; + productReference = 99999999999999999999999 /* ${APP_NAME}.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7777777777777777777777AA /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; + TargetAttributes = { + 3333333333333333333333AA = { + CreatedOnToolsVersion = 12.4; + }; + }; + }; + buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE; + productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3333333333333333333333AA /* ${APP_NAME} */, + ); + }; +/* End PBXProject section */ +EOF + +# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXResourcesBuildPhase section */ + 6666666666666666666666AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5555555555555555555555AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33333333333333333333333 /* ContentView.swift in Sources */, + 11111111111111111111111 /* App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 9999999999999999999999AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)"; + INFOPLIST_FILE = "iOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = "iOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ +EOF + +# Finish the project.pbxproj file +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin XCConfigurationList section */ + 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9999999999999999999999AA /* Debug */, + AAAAAAAAAAAAAAAAAAAAABBB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */, + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7777777777777777777777AA /* Project object */; +} +EOF + +# 2. Copy XCFramework to test project +echo "Copying XCFramework to test project..." +cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/" + +# 3. Build and archive the app +echo "Building and archiving test app..." +cd "${TEMP_DIR}/${APP_NAME}" + +# Create a simple xcscheme file to avoid xcodebuild scheme issues +mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes" +cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + +# Now use xcodebuild with an explicitly defined product name +xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk iphoneos -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet + +# 4. Create IPA from archive +echo "Creating IPA from archive..." +mkdir -p "${TEMP_DIR}/Payload" +cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/" + +# Check and log app structure before zipping +echo "App structure:" +ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/" +echo "Frameworks:" +ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found" + +cd "${TEMP_DIR}" +zip -r "${IPA_PATH}" Payload + +# Check embedded provisioning profile +echo "Checking provisioning profile (if any)..." +PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null) +if [ -n "$PROVISIONING_PROFILE" ]; then + echo "Found embedded provisioning profile:" + security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile" +else + echo "No embedded provisioning profile found (expected for ad-hoc builds)" +fi + +# 5. Validate the IPA +echo "Validating IPA..." +VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt" + +# Check if authentication credentials are provided +AUTH_ARGS="" +if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then + echo "Using Apple ID authentication for validation..." + AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\"" +else + echo "No authentication credentials provided. Will perform basic validation." + echo "To use your personal developer account, you can run the script with:" + echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-ios.sh" + echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage" +fi + +# Run validation with detailed output +echo "Running validation with altool..." +if [ -n "$AUTH_ARGS" ]; then + # Use eval to properly handle the quoted arguments + eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type ios --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}" +else + xcrun altool --validate-app -f "${IPA_PATH}" --type ios --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}" +fi +VALIDATION_RESULT=$? + +# Final validation result +FINAL_VALIDATION_RESULT=0 + +# Check if validation failed because the app isn't in App Store Connect +if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then + echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect" + echo "This is expected for apps that haven't been registered in App Store Connect yet." + echo "This doesn't indicate a problem with the build or framework." + + # Perform alternative validation + echo "Performing alternative validation checks..." + + # Check if IPA was created successfully + if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then + echo "✅ IPA file created successfully" + else + echo "❌ IPA file not created or empty" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if app binary exists and is executable + if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then + echo "✅ App binary exists and is executable" + else + echo "❌ App binary missing or not executable" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if framework was properly embedded + if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then + echo "✅ llama.framework properly embedded" + else + echo "❌ llama.framework not properly embedded" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if framework binary exists + if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then + echo "✅ Framework binary exists" + + # Further validate framework by checking architecture + ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|armv7\\|x86_64" | tr '\n' ' ') + if [ -n "$ARCHS" ]; then + echo "✅ Framework architecture(s): $ARCHS" + else + echo "⚠️ Could not determine framework architecture" + fi + else + echo "❌ Framework binary missing" + FINAL_VALIDATION_RESULT=1 + fi + + if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + echo "✅ Alternative validation PASSED: App built successfully with embedded framework" + else + echo "❌ Alternative validation FAILED: Issues found with the app or framework" + fi +elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then + echo "✅ iOS Validation PASSED: IPA successfully validated" + echo "Results saved to ${VALIDATION_OUTPUT}" +else + echo "❌ iOS Validation FAILED: IPA validation found issues" + echo "See validation output at ${VALIDATION_OUTPUT}" + echo "" + echo "==== VALIDATION ERRORS ====" + + # Try to extract specific errors from the output + if grep -q "Error" "${VALIDATION_OUTPUT}"; then + grep -A 5 "Error" "${VALIDATION_OUTPUT}" + else + # If no specific error found, show the whole log + cat "${VALIDATION_OUTPUT}" + fi + + # Additional debugging: check IPA contents + echo "" + echo "==== IPA CONTENTS ====" + mkdir -p "${TEMP_DIR}/ipa_contents" + unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents" + ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/" + + # Check for code signing issues + echo "" + echo "==== CODE SIGNING INFO ====" + codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed" + + # Check embedded frameworks + echo "" + echo "==== FRAMEWORK INFO ====" + ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found" +fi + +# Don't clean up on error to allow inspection +if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then + echo "" + echo "Temporary files kept for inspection at: ${TEMP_DIR}" + echo "===== iOS Validation Process Failed =====" + exit 1 +fi + +# Clean up temporary files but keep build artifacts +if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + echo "Cleaning up temporary files..." + #rm -rf "${TEMP_DIR}" +fi + +echo "===== iOS Validation Process Completed =====" +exit $FINAL_VALIDATION_RESULT diff --git a/scripts/apple/validate-macos.sh b/scripts/apple/validate-macos.sh new file mode 100755 index 000000000..6dc28e694 --- /dev/null +++ b/scripts/apple/validate-macos.sh @@ -0,0 +1,781 @@ +#!/bin/bash +# validate-macos.sh - Validate macOS Application with embedded llama.xcframework using SwiftUI + +# Authentication options (optional) (can be set via environment variables) +# To use: export APPLE_ID=your.email@example.com +# export APPLE_PASSWORD=your-app-specific-password +# ./validate-macos.sh +APPLE_ID=${APPLE_ID:-""} +APPLE_PASSWORD=${APPLE_PASSWORD:-""} + +# Ensure the script exits on error +set -e + +# Function to print usage instructions +print_usage() { + echo "Usage: ./validate-macos.sh [OPTIONS]" + echo "" + echo "Options:" + echo " --help Show this help message" + echo " --apple-id EMAIL Apple ID email for validation" + echo " --apple-password PWD App-specific password for Apple ID" + echo "" + echo "Environment variables:" + echo " APPLE_ID Apple ID email for validation" + echo " APPLE_PASSWORD App-specific password for Apple ID" + echo "" + echo "Notes:" + echo " - Command line options take precedence over environment variables" + echo " - Authentication is optional. If not provided, alternative validation will be performed" + echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --help) + print_usage + exit 0 + ;; + --apple-id) + APPLE_ID="$2" + shift 2 + ;; + --apple-password) + APPLE_PASSWORD="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + print_usage + exit 1 + ;; + esac +done + +# Function to clean up in case of error +cleanup() { + # Don't clean up temp files on error to help with debugging + echo "===== macOS Validation Process Failed =====" + exit 1 +} + +# Set up trap to call cleanup function on error +trap cleanup ERR + +set -e # Exit on any error + +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" +BUILD_DIR="${ROOT_DIR}/validation-builds/ios" + +# Configuration +APP_NAME="MacOSLlamaTest" +BUNDLE_ID="org.ggml.MacOSLlamaTest" +XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework" +TEMP_DIR="${BUILD_DIR}/temp" +ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive" +APP_PATH="${BUILD_DIR}/${APP_NAME}.app" +ZIP_PATH="${BUILD_DIR}/${APP_NAME}.zip" +VALIDATION_DIR="${BUILD_DIR}/validation" + +# Create necessary directories +mkdir -p "${BUILD_DIR}" +mkdir -p "${TEMP_DIR}" +mkdir -p "${VALIDATION_DIR}" + +echo "===== macOS Validation Process Started =====" + +# 1. Create a simple test app project +echo "Creating test macOS app project..." +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${APP_NAME} + CFBundleIdentifier + ${BUNDLE_ID} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${APP_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + 12.0 + NSHumanReadableCopyright + Copyright © 2025 GGML. All rights reserved. + NSPrincipalClass + NSApplication + + +EOF + +# Create SwiftUI app files +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources" + +# Create App.swift +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF +import SwiftUI +import llama + +@main +struct LlamaTestApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +EOF + +# Create ContentView.swift with macOS specific elements +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF +import SwiftUI +import llama + +struct ContentView: View { + // Test that we can initialize a llama context params struct + let params = llama_context_default_params() + + var body: some View { + VStack(spacing: 20) { + Text("Llama Framework Test on macOS") + .font(.largeTitle) + .padding() + + Text("llama_context_default_params() created successfully") + .font(.headline) + .multilineTextAlignment(.center) + .padding() + + // Display some param values to confirm the framework is working + Text("n_ctx: \(params.n_ctx)") + .font(.body) + + Text("n_batch: \(params.n_batch)") + .font(.body) + + Spacer() + } + .padding() + .frame(width: 600, height: 400) + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} +EOF + +# Create project.pbxproj, fixing the framework search paths issues +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; }; + 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; }; + 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 88888888888888888888888 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; + 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = ""; }; +/* End PBXFileReference section */ +EOF + +# Add the rest of the project file with fixed framework search paths +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXFrameworksBuildPhase section */ + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 55555555555555555555555 /* llama.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = { + isa = PBXGroup; + children = ( + 99999999999999999999999 /* ${APP_NAME}.app */, + ); + name = Products; + sourceTree = ""; + }; +EOF + +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 66666666666666666666666 /* llama.xcframework */, + ); + name = Frameworks; + sourceTree = ""; + }; + EEEEEEEEEEEEEEEEEEEEEEEE = { + isa = PBXGroup; + children = ( + FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSLlamaTest */, + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */, + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */, + ); + sourceTree = ""; + }; + FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSLlamaTest */ = { + isa = PBXGroup; + children = ( + 1111111111111111111111AA /* Sources */, + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */, + ); + path = "MacOSLlamaTest"; + sourceTree = ""; + }; + 1111111111111111111111AA /* Sources */ = { + isa = PBXGroup; + children = ( + 22222222222222222222222 /* App.swift */, + 44444444444444444444444 /* ContentView.swift */, + ); + path = Sources; + sourceTree = ""; + }; +/* End PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin PBXNativeTarget section */ + 3333333333333333333333AA /* ${APP_NAME} */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */; + buildPhases = ( + 5555555555555555555555AA /* Sources */, + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */, + 6666666666666666666666AA /* Resources */, + 88888888888888888888888 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "${APP_NAME}"; + productName = "${APP_NAME}"; + productReference = 99999999999999999999999 /* ${APP_NAME}.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7777777777777777777777AA /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; + TargetAttributes = { + 3333333333333333333333AA = { + CreatedOnToolsVersion = 12.4; + }; + }; + }; + buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE; + productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3333333333333333333333AA /* ${APP_NAME} */, + ); + }; +/* End PBXProject section */ +EOF + +# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS and macOS settings +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXResourcesBuildPhase section */ + 6666666666666666666666AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5555555555555555555555AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33333333333333333333333 /* ContentView.swift in Sources */, + 11111111111111111111111 /* App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 9999999999999999999999AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)"; + INFOPLIST_FILE = "MacOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = "MacOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ +EOF + +# Finish the project.pbxproj file +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin XCConfigurationList section */ + 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9999999999999999999999AA /* Debug */, + AAAAAAAAAAAAAAAAAAAAABBB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */, + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7777777777777777777777AA /* Project object */; +} +EOF + +# 2. Copy XCFramework to test project +echo "Copying XCFramework to test project..." +cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/" + +# 3. Build and archive the app +echo "Building and archiving test app..." +cd "${TEMP_DIR}/${APP_NAME}" + +# Create a simple xcscheme file to avoid xcodebuild scheme issues +mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes" +cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + +# Now use xcodebuild with an explicitly defined product name for macOS +xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk macosx -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet + +# 4. Create a package for distribution +echo "Creating distributable package from archive..." +cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${APP_PATH}" + +# Check and log app structure +echo "App structure:" +ls -la "${APP_PATH}" +echo "Frameworks:" +ls -la "${APP_PATH}/Contents/Frameworks/" 2>/dev/null || echo "No Frameworks directory found" + +# Create a zip file for potential distribution +cd "${BUILD_DIR}" +zip -r "${ZIP_PATH}" "${APP_NAME}.app" + +# Check embedded provisioning profile +echo "Checking provisioning profile (if any)..." +PROVISIONING_PROFILE=$(find "${APP_PATH}/Contents" -name "embedded.provisionprofile" 2>/dev/null) +if [ -n "$PROVISIONING_PROFILE" ]; then + echo "Found embedded provisioning profile:" + security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile" +else + echo "No embedded provisioning profile found (expected for ad-hoc builds)" +fi + +# 5. Validate the app +echo "Validating macOS app..." +VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt" + +# Check if authentication credentials are provided +AUTH_ARGS="" +if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then + echo "Using Apple ID authentication for validation..." + AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\"" +else + echo "No authentication credentials provided. Will perform basic validation." + echo "To use your personal developer account, you can run the script with:" + echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-macos.sh" + echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage" +fi + +# For macOS we need to use notarytool or alternative checks because altool doesn't support macOS apps in the same way +echo "Note: For macOS, formal notarization process would require Apple Developer credentials." +echo "Performing alternative validation checks..." + +# Final validation result +FINAL_VALIDATION_RESULT=0 + +# Check if app was created successfully +if [ -d "${APP_PATH}" ] && [ -s "${APP_PATH}/Contents/MacOS/${APP_NAME}" ]; then + echo "✅ App package created successfully" +else + echo "❌ App package not created or binary missing" + FINAL_VALIDATION_RESULT=1 +fi + +# Check if app binary exists and is executable +if [ -f "${APP_PATH}/Contents/MacOS/${APP_NAME}" ] && [ -x "${APP_PATH}/Contents/MacOS/${APP_NAME}" ]; then + echo "✅ App binary exists and is executable" +else + echo "❌ App binary missing or not executable" + FINAL_VALIDATION_RESULT=1 +fi + +# Check if framework was properly embedded +if [ -d "${APP_PATH}/Contents/Frameworks/llama.framework" ]; then + echo "✅ llama.framework properly embedded" +else + echo "❌ llama.framework not properly embedded" + FINAL_VALIDATION_RESULT=1 +fi + +# Check if framework binary exists +if [ -f "${APP_PATH}/Contents/Frameworks/llama.framework/Versions/A/llama" ]; then + echo "✅ Framework binary exists" + + # Further validate framework by checking architecture + ARCHS=$(lipo -info "${APP_PATH}/Contents/Frameworks/llama.framework/Versions/A/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ') + if [ -n "$ARCHS" ]; then + echo "✅ Framework architecture(s): $ARCHS" + else + echo "⚠️ Could not determine framework architecture" + fi +else + echo "❌ Framework binary missing" + FINAL_VALIDATION_RESULT=1 +fi + +# Check code signing +echo "" +echo "==== CODE SIGNING INFO ====" +codesign -vv -d "${APP_PATH}" 2>&1 || echo "Code signing verification not available (expected for ad-hoc builds)" + +if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + if [ -n "$AUTH_ARGS" ]; then + echo "" + echo "To notarize this app with Apple (requires Apple Developer account):" + echo "xcrun notarytool submit \"${ZIP_PATH}\" --apple-id \"your-apple-id\" --password \"your-app-specific-password\" --team-id \"your-team-id\" --wait" + echo "" + fi + echo "✅ Validation PASSED: macOS app built successfully with embedded framework" +else + echo "❌ Validation FAILED: Issues found with the app or framework" +fi + +# Don't clean up on error to allow inspection +if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then + echo "" + echo "Temporary files kept for inspection at: ${TEMP_DIR}" + echo "===== macOS Validation Process Failed =====" + exit 1 +fi + +# Clean up temporary files but keep build artifacts +if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + echo "Cleaning up temporary files..." + #rm -rf "${TEMP_DIR}" +fi + +echo "===== macOS Validation Process Completed =====" +echo "App package available at: ${APP_PATH}" +echo "Zipped app available at: ${ZIP_PATH}" +exit $FINAL_VALIDATION_RESULT diff --git a/scripts/apple/validate-tvos.sh b/scripts/apple/validate-tvos.sh new file mode 100755 index 000000000..6120189e8 --- /dev/null +++ b/scripts/apple/validate-tvos.sh @@ -0,0 +1,813 @@ +#!/bin/bash +# validate-tvos.sh - Validate tvOS Application with embedded llama.xcframework using SwiftUI + +# Authentication options (optional) (can be set via environment variables) +# To use: export APPLE_ID=your.email@example.com +# export APPLE_PASSWORD=your-app-specific-password +# ./validate-tvos.sh +APPLE_ID=${APPLE_ID:-""} +APPLE_PASSWORD=${APPLE_PASSWORD:-""} + +# Ensure the script exits on error +set -e + +# Function to print usage instructions +print_usage() { + echo "Usage: ./validate-tvos.sh [OPTIONS]" + echo "" + echo "Options:" + echo " --help Show this help message" + echo " --apple-id EMAIL Apple ID email for validation" + echo " --apple-password PWD App-specific password for Apple ID" + echo "" + echo "Environment variables:" + echo " APPLE_ID Apple ID email for validation" + echo " APPLE_PASSWORD App-specific password for Apple ID" + echo "" + echo "Notes:" + echo " - Command line options take precedence over environment variables" + echo " - Authentication is optional. If not provided, alternative validation will be performed" + echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --help) + print_usage + exit 0 + ;; + --apple-id) + APPLE_ID="$2" + shift 2 + ;; + --apple-password) + APPLE_PASSWORD="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + print_usage + exit 1 + ;; + esac +done + +# Function to clean up in case of error +cleanup() { + # Don't clean up temp files on error to help with debugging + echo "===== tvOS Validation Process Failed =====" + exit 1 +} + +# Set up trap to call cleanup function on error +trap cleanup ERR + +set -e # Exit on any error + +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" +BUILD_DIR="${ROOT_DIR}/validation-builds/ios" + +# Configuration +APP_NAME="TVOSLlamaTest" +BUNDLE_ID="org.ggml.TVOSLlamaTest" +XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework" +TEMP_DIR="${BUILD_DIR}/temp" +ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive" +IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa" +VALIDATION_DIR="${BUILD_DIR}/validation" + +# Create necessary directories +mkdir -p "${BUILD_DIR}" +mkdir -p "${TEMP_DIR}" +mkdir -p "${VALIDATION_DIR}" + +echo "===== tvOS Validation Process Started =====" + +# 1. Create a simple test app project +echo "Creating test tvOS app project..." +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${APP_NAME} + CFBundleIdentifier + ${BUNDLE_ID} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${APP_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UIRequiredDeviceCapabilities + + arm64 + + + +EOF + +# Create SwiftUI app files +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources" + +# Create App.swift +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF +import SwiftUI +import llama + +@main +struct LlamaTestApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +EOF + +# Create ContentView.swift with tvOS specific elements +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF +import SwiftUI +import llama + +struct ContentView: View { + // Test that we can initialize a llama context params struct + let params = llama_context_default_params() + + var body: some View { + VStack(spacing: 40) { + Text("Llama Framework Test on tvOS") + .font(.largeTitle) + .padding() + + Text("llama_context_default_params() created successfully") + .font(.headline) + .multilineTextAlignment(.center) + .padding() + + // Display some param values to confirm the framework is working + Text("n_ctx: \(params.n_ctx)") + .font(.title2) + + Text("n_batch: \(params.n_batch)") + .font(.title2) + + Spacer() + } + .padding(50) + // Larger size suitable for TV display + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} +EOF + +# Create project.pbxproj, fixing the framework search paths issues +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; }; + 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; }; + 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 88888888888888888888888 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; + 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = ""; }; +/* End PBXFileReference section */ +EOF + +# Add the rest of the project file with fixed framework search paths +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXFrameworksBuildPhase section */ + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 55555555555555555555555 /* llama.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = { + isa = PBXGroup; + children = ( + 99999999999999999999999 /* ${APP_NAME}.app */, + ); + name = Products; + sourceTree = ""; + }; +EOF + +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 66666666666666666666666 /* llama.xcframework */, + ); + name = Frameworks; + sourceTree = ""; + }; + EEEEEEEEEEEEEEEEEEEEEEEE = { + isa = PBXGroup; + children = ( + FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSLlamaTest */, + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */, + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */, + ); + sourceTree = ""; + }; + FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSLlamaTest */ = { + isa = PBXGroup; + children = ( + 1111111111111111111111AA /* Sources */, + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */, + ); + path = "TVOSLlamaTest"; + sourceTree = ""; + }; + 1111111111111111111111AA /* Sources */ = { + isa = PBXGroup; + children = ( + 22222222222222222222222 /* App.swift */, + 44444444444444444444444 /* ContentView.swift */, + ); + path = Sources; + sourceTree = ""; + }; +/* End PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin PBXNativeTarget section */ + 3333333333333333333333AA /* ${APP_NAME} */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */; + buildPhases = ( + 5555555555555555555555AA /* Sources */, + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */, + 6666666666666666666666AA /* Resources */, + 88888888888888888888888 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "${APP_NAME}"; + productName = "${APP_NAME}"; + productReference = 99999999999999999999999 /* ${APP_NAME}.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7777777777777777777777AA /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; + TargetAttributes = { + 3333333333333333333333AA = { + CreatedOnToolsVersion = 12.4; + }; + }; + }; + buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE; + productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3333333333333333333333AA /* ${APP_NAME} */, + ); + }; +/* End PBXProject section */ +EOF + +# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS and tvOS settings +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXResourcesBuildPhase section */ + 6666666666666666666666AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5555555555555555555555AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33333333333333333333333 /* ContentView.swift in Sources */, + 11111111111111111111111 /* App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 9999999999999999999999AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + TVOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = appletvos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + TVOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = appletvos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)"; + INFOPLIST_FILE = "TVOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = "TVOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ +EOF + +# Finish the project.pbxproj file +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin XCConfigurationList section */ + 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9999999999999999999999AA /* Debug */, + AAAAAAAAAAAAAAAAAAAAABBB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */, + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7777777777777777777777AA /* Project object */; +} +EOF + +# 2. Copy XCFramework to test project +echo "Copying XCFramework to test project..." +cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/" + +# 3. Build and archive the app +echo "Building and archiving test app..." +cd "${TEMP_DIR}/${APP_NAME}" + +# Create a simple xcscheme file to avoid xcodebuild scheme issues +mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes" +cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + +# Now use xcodebuild with an explicitly defined product name for tvOS +xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk appletvos -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet + +# 4. Create IPA from archive +echo "Creating IPA from archive..." +mkdir -p "${TEMP_DIR}/Payload" +cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/" + +# Check and log app structure before zipping +echo "App structure:" +ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/" +echo "Frameworks:" +ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found" + +cd "${TEMP_DIR}" +zip -r "${IPA_PATH}" Payload + +# Check embedded provisioning profile +echo "Checking provisioning profile (if any)..." +PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null) +if [ -n "$PROVISIONING_PROFILE" ]; then + echo "Found embedded provisioning profile:" + security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile" +else + echo "No embedded provisioning profile found (expected for ad-hoc builds)" +fi + +# 5. Validate the IPA +echo "Validating IPA..." +VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt" + +# Check if authentication credentials are provided +AUTH_ARGS="" +if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then + echo "Using Apple ID authentication for validation..." + AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\"" +else + echo "No authentication credentials provided. Will perform basic validation." + echo "To use your personal developer account, you can run the script with:" + echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-tvos.sh" + echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage" +fi + +# Run validation with detailed output +echo "Running validation with altool..." +if [ -n "$AUTH_ARGS" ]; then + # Use eval to properly handle the quoted arguments + eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type tvos --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}" +else + xcrun altool --validate-app -f "${IPA_PATH}" --type tvos --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}" +fi +VALIDATION_RESULT=$? + +# Final validation result +FINAL_VALIDATION_RESULT=0 + +# Check if validation failed because the app isn't in App Store Connect +if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then + echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect" + echo "This is expected for apps that haven't been registered in App Store Connect yet." + echo "This doesn't indicate a problem with the build or framework." + + # Perform alternative validation + echo "Performing alternative validation checks..." + + # Check if IPA was created successfully + if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then + echo "✅ IPA file created successfully" + else + echo "❌ IPA file not created or empty" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if app binary exists and is executable + if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then + echo "✅ App binary exists and is executable" + else + echo "❌ App binary missing or not executable" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if framework was properly embedded + if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then + echo "✅ llama.framework properly embedded" + else + echo "❌ llama.framework not properly embedded" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if framework binary exists + if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then + echo "✅ Framework binary exists" + + # Further validate framework by checking architecture + ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ') + if [ -n "$ARCHS" ]; then + echo "✅ Framework architecture(s): $ARCHS" + else + echo "⚠️ Could not determine framework architecture" + fi + else + echo "❌ Framework binary missing" + FINAL_VALIDATION_RESULT=1 + fi + + if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + echo "✅ Alternative validation PASSED: App built successfully with embedded framework" + else + echo "❌ Alternative validation FAILED: Issues found with the app or framework" + fi +elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then + echo "✅ tvOS Validation PASSED: IPA successfully validated" + echo "Results saved to ${VALIDATION_OUTPUT}" +else + echo "❌ tvOS Validation FAILED: IPA validation found issues" + echo "See validation output at ${VALIDATION_OUTPUT}" + echo "" + echo "==== VALIDATION ERRORS ====" + + # Try to extract specific errors from the output + if grep -q "Error" "${VALIDATION_OUTPUT}"; then + grep -A 5 "Error" "${VALIDATION_OUTPUT}" + else + # If no specific error found, show the whole log + cat "${VALIDATION_OUTPUT}" + fi + + # Additional debugging: check IPA contents + echo "" + echo "==== IPA CONTENTS ====" + mkdir -p "${TEMP_DIR}/ipa_contents" + unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents" + ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/" + + # Check for code signing issues + echo "" + echo "==== CODE SIGNING INFO ====" + codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed" + + # Check embedded frameworks + echo "" + echo "==== FRAMEWORK INFO ====" + ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found" +fi + +# Don't clean up on error to allow inspection +if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then + echo "" + echo "Temporary files kept for inspection at: ${TEMP_DIR}" + echo "===== tvOS Validation Process Failed =====" + exit 1 +fi + +# Clean up temporary files but keep build artifacts +if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + echo "Cleaning up temporary files..." + #rm -rf "${TEMP_DIR}" +fi + +echo "===== tvOS Validation Process Completed =====" +exit $FINAL_VALIDATION_RESULT diff --git a/scripts/apple/validate-visionos.sh b/scripts/apple/validate-visionos.sh new file mode 100755 index 000000000..a18ddcce4 --- /dev/null +++ b/scripts/apple/validate-visionos.sh @@ -0,0 +1,811 @@ +#!/bin/bash +# validate-visionos.sh - Validate visionOS Application with embedded llama.xcframework using SwiftUI + +# Authentication options (optional) (can be set via environment variables) +# To use: export APPLE_ID=your.email@example.com +# export APPLE_PASSWORD=your-app-specific-password +# ./validate-visionos.sh +APPLE_ID=${APPLE_ID:-""} +APPLE_PASSWORD=${APPLE_PASSWORD:-""} + +# Ensure the script exits on error +set -e + +# Function to print usage instructions +print_usage() { + echo "Usage: ./validate-visionos.sh [OPTIONS]" + echo "" + echo "Options:" + echo " --help Show this help message" + echo " --apple-id EMAIL Apple ID email for validation" + echo " --apple-password PWD App-specific password for Apple ID" + echo "" + echo "Environment variables:" + echo " APPLE_ID Apple ID email for validation" + echo " APPLE_PASSWORD App-specific password for Apple ID" + echo "" + echo "Notes:" + echo " - Command line options take precedence over environment variables" + echo " - Authentication is optional. If not provided, alternative validation will be performed" + echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --help) + print_usage + exit 0 + ;; + --apple-id) + APPLE_ID="$2" + shift 2 + ;; + --apple-password) + APPLE_PASSWORD="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + print_usage + exit 1 + ;; + esac +done + +# Function to clean up in case of error +cleanup() { + # Don't clean up temp files on error to help with debugging + echo "===== visionOS Validation Process Failed =====" + exit 1 +} + +# Set up trap to call cleanup function on error +trap cleanup ERR + +set -e # Exit on any error + +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" +BUILD_DIR="${ROOT_DIR}/validation-builds/visionos" + +# Configuration +APP_NAME="VisionOSLlamaTest" +BUNDLE_ID="org.ggml.VisionOSLlamaTest" +XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework" +TEMP_DIR="${BUILD_DIR}/temp" +ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive" +IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa" +VALIDATION_DIR="${BUILD_DIR}/validation" + +# Create necessary directories +mkdir -p "${BUILD_DIR}" +mkdir -p "${TEMP_DIR}" +mkdir -p "${VALIDATION_DIR}" + +echo "===== visionOS Validation Process Started =====" + +# 1. Create a simple test app project +echo "Creating test visionOS app project..." +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${APP_NAME} + CFBundleIdentifier + ${BUNDLE_ID} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${APP_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + +EOF + +# Create SwiftUI app files +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources" + +# Create App.swift +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF +import SwiftUI +import llama + +@main +struct LlamaTestApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +EOF + +# Create ContentView.swift with visionOS specific elements +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF +import SwiftUI +import llama + +struct ContentView: View { + // Test that we can initialize a llama context params struct + let params = llama_context_default_params() + + var body: some View { + VStack(spacing: 20) { + Text("Llama Framework Test on visionOS") + .font(.largeTitle) + .padding() + + Text("llama_context_default_params() created successfully") + .font(.headline) + .multilineTextAlignment(.center) + .padding() + + // Display some param values to confirm the framework is working + Text("n_ctx: \(params.n_ctx)") + .font(.body) + + Text("n_batch: \(params.n_batch)") + .font(.body) + + Spacer() + } + .padding() + .frame(width: 500, height: 400) + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} +EOF + +# Create project.pbxproj, fixing the framework search paths issues +mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj" +cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; }; + 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; }; + 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 88888888888888888888888 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 77777777777777777777777 /* llama.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; + 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = ""; }; +/* End PBXFileReference section */ +EOF + +# Add the rest of the project file with fixed framework search paths +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXFrameworksBuildPhase section */ + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 55555555555555555555555 /* llama.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = { + isa = PBXGroup; + children = ( + 99999999999999999999999 /* ${APP_NAME}.app */, + ); + name = Products; + sourceTree = ""; + }; +EOF + +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 66666666666666666666666 /* llama.xcframework */, + ); + name = Frameworks; + sourceTree = ""; + }; + EEEEEEEEEEEEEEEEEEEEEEEE = { + isa = PBXGroup; + children = ( + FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSLlamaTest */, + CCCCCCCCCCCCCCCCCCCCCCCC /* Products */, + DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */, + ); + sourceTree = ""; + }; + FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSLlamaTest */ = { + isa = PBXGroup; + children = ( + 1111111111111111111111AA /* Sources */, + AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */, + ); + path = "VisionOSLlamaTest"; + sourceTree = ""; + }; + 1111111111111111111111AA /* Sources */ = { + isa = PBXGroup; + children = ( + 22222222222222222222222 /* App.swift */, + 44444444444444444444444 /* ContentView.swift */, + ); + path = Sources; + sourceTree = ""; + }; +/* End PBXGroup section */ +EOF + +# Continue with the project.pbxproj file, using the APP_NAME variable appropriately +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin PBXNativeTarget section */ + 3333333333333333333333AA /* ${APP_NAME} */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */; + buildPhases = ( + 5555555555555555555555AA /* Sources */, + BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */, + 6666666666666666666666AA /* Resources */, + 88888888888888888888888 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "${APP_NAME}"; + productName = "${APP_NAME}"; + productReference = 99999999999999999999999 /* ${APP_NAME}.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7777777777777777777777AA /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1510; + LastUpgradeCheck = 1510; + TargetAttributes = { + 3333333333333333333333AA = { + CreatedOnToolsVersion = 15.1; + }; + }; + }; + buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */; + compatibilityVersion = "Xcode 15.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE; + productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3333333333333333333333AA /* ${APP_NAME} */, + ); + }; +/* End PBXProject section */ +EOF + +# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF' +/* Begin PBXResourcesBuildPhase section */ + 6666666666666666666666AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5555555555555555555555AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33333333333333333333333 /* ContentView.swift in Sources */, + 11111111111111111111111 /* App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 9999999999999999999999AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = xros; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Debug; + }; + AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = xros; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Release; + }; + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)"; + INFOPLIST_FILE = "VisionOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SUPPORTED_PLATFORMS = "xros xrsimulator"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + }; + name = Debug; + }; + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + INFOPLIST_FILE = "VisionOSLlamaTest/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSLlamaTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SUPPORTED_PLATFORMS = "xros xrsimulator"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ +EOF + +# Finish the project.pbxproj file +cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF +/* Begin XCConfigurationList section */ + 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9999999999999999999999AA /* Debug */, + AAAAAAAAAAAAAAAAAAAAABBB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */, + CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7777777777777777777777AA /* Project object */; +} +EOF + +# 2. Copy XCFramework to test project +echo "Copying XCFramework to test project..." +cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/" + +# 3. Build and archive the app +echo "Building and archiving test app..." +cd "${TEMP_DIR}/${APP_NAME}" + +# Create a simple xcscheme file to avoid xcodebuild scheme issues +mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes" +cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + +# Now use xcodebuild with an explicitly defined product name for visionOS +xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk xros -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet + +# 4. Create IPA from archive +echo "Creating IPA from archive..." +mkdir -p "${TEMP_DIR}/Payload" +cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/" + +# Check and log app structure before zipping +echo "App structure:" +ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/" +echo "Frameworks:" +ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found" + +cd "${TEMP_DIR}" +zip -r "${IPA_PATH}" Payload + +# Check embedded provisioning profile +echo "Checking provisioning profile (if any)..." +PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null) +if [ -n "$PROVISIONING_PROFILE" ]; then + echo "Found embedded provisioning profile:" + security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile" +else + echo "No embedded provisioning profile found (expected for ad-hoc builds)" +fi + +# 5. Validate the IPA +echo "Validating IPA..." +VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt" + +# Check if authentication credentials are provided +AUTH_ARGS="" +if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then + echo "Using Apple ID authentication for validation..." + AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\"" +else + echo "No authentication credentials provided. Will perform basic validation." + echo "To use your personal developer account, you can run the script with:" + echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-visionos.sh" + echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage" +fi + +# Run validation with detailed output +echo "Running validation with altool..." +if [ -n "$AUTH_ARGS" ]; then + # Use eval to properly handle the quoted arguments + eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type visionos --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}" +else + xcrun altool --validate-app -f "${IPA_PATH}" --type visionos --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}" +fi +VALIDATION_RESULT=$? + +# Final validation result +FINAL_VALIDATION_RESULT=0 + +# Check if validation failed because the app isn't in App Store Connect +if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then + echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect" + echo "This is expected for apps that haven't been registered in App Store Connect yet." + echo "This doesn't indicate a problem with the build or framework." + + # Perform alternative validation + echo "Performing alternative validation checks..." + + # Check if IPA was created successfully + if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then + echo "✅ IPA file created successfully" + else + echo "❌ IPA file not created or empty" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if app binary exists and is executable + if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then + echo "✅ App binary exists and is executable" + else + echo "❌ App binary missing or not executable" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if framework was properly embedded + if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then + echo "✅ llama.framework properly embedded" + else + echo "❌ llama.framework not properly embedded" + FINAL_VALIDATION_RESULT=1 + fi + + # Check if framework binary exists + if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then + echo "✅ Framework binary exists" + + # Further validate framework by checking architecture + ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ') + if [ -n "$ARCHS" ]; then + echo "✅ Framework architecture(s): $ARCHS" + else + echo "⚠️ Could not determine framework architecture" + fi + else + echo "❌ Framework binary missing" + FINAL_VALIDATION_RESULT=1 + fi + + if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + echo "✅ Alternative validation PASSED: App built successfully with embedded framework" + else + echo "❌ Alternative validation FAILED: Issues found with the app or framework" + fi +elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then + echo "✅ visionOS Validation PASSED: IPA successfully validated" + echo "Results saved to ${VALIDATION_OUTPUT}" +else + echo "❌ visionOS Validation FAILED: IPA validation found issues" + echo "See validation output at ${VALIDATION_OUTPUT}" + echo "" + echo "==== VALIDATION ERRORS ====" + + # Try to extract specific errors from the output + if grep -q "Error" "${VALIDATION_OUTPUT}"; then + grep -A 5 "Error" "${VALIDATION_OUTPUT}" + else + # If no specific error found, show the whole log + cat "${VALIDATION_OUTPUT}" + fi + + # Additional debugging: check IPA contents + echo "" + echo "==== IPA CONTENTS ====" + mkdir -p "${TEMP_DIR}/ipa_contents" + unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents" + ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/" + + # Check for code signing issues + echo "" + echo "==== CODE SIGNING INFO ====" + codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed" + + # Check embedded frameworks + echo "" + echo "==== FRAMEWORK INFO ====" + ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found" +fi + +# Don't clean up on error to allow inspection +if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then + echo "" + echo "Temporary files kept for inspection at: ${TEMP_DIR}" + echo "===== visionOS Validation Process Failed =====" + exit 1 +fi + +# Clean up temporary files but keep build artifacts +if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then + echo "Cleaning up temporary files..." + #rm -rf "${TEMP_DIR}" +fi + +echo "===== visionOS Validation Process Completed =====" +exit $FINAL_VALIDATION_RESULT diff --git a/spm-headers/ggml-alloc.h b/spm-headers/ggml-alloc.h deleted file mode 120000 index 0361ffc38..000000000 --- a/spm-headers/ggml-alloc.h +++ /dev/null @@ -1 +0,0 @@ -../ggml/include/ggml-alloc.h \ No newline at end of file diff --git a/spm-headers/ggml-backend.h b/spm-headers/ggml-backend.h deleted file mode 120000 index 7295f0f0d..000000000 --- a/spm-headers/ggml-backend.h +++ /dev/null @@ -1 +0,0 @@ -../ggml/include/ggml-backend.h \ No newline at end of file diff --git a/spm-headers/ggml-cpp.h b/spm-headers/ggml-cpp.h deleted file mode 120000 index 8a8604cc2..000000000 --- a/spm-headers/ggml-cpp.h +++ /dev/null @@ -1 +0,0 @@ -../ggml/include/ggml-cpp.h \ No newline at end of file diff --git a/spm-headers/ggml-cpu.h b/spm-headers/ggml-cpu.h deleted file mode 120000 index 66e629607..000000000 --- a/spm-headers/ggml-cpu.h +++ /dev/null @@ -1 +0,0 @@ -../ggml/include/ggml-cpu.h \ No newline at end of file diff --git a/spm-headers/ggml-metal.h b/spm-headers/ggml-metal.h deleted file mode 120000 index aefad5fa0..000000000 --- a/spm-headers/ggml-metal.h +++ /dev/null @@ -1 +0,0 @@ -../ggml/include/ggml-metal.h \ No newline at end of file diff --git a/spm-headers/ggml.h b/spm-headers/ggml.h deleted file mode 120000 index 0bdfeacbd..000000000 --- a/spm-headers/ggml.h +++ /dev/null @@ -1 +0,0 @@ -../ggml/include/ggml.h \ No newline at end of file diff --git a/spm-headers/llama.h b/spm-headers/llama.h deleted file mode 120000 index b31388f0d..000000000 --- a/spm-headers/llama.h +++ /dev/null @@ -1 +0,0 @@ -../include/llama.h \ No newline at end of file diff --git a/src/llama-mmap.cpp b/src/llama-mmap.cpp index c13b3755a..3970b7485 100644 --- a/src/llama-mmap.cpp +++ b/src/llama-mmap.cpp @@ -35,6 +35,10 @@ #include #endif +#if defined(__APPLE__) +#include +#endif + // TODO: consider moving to llama-impl.h if needed in more places #if defined(_WIN32) static std::string llama_format_win_err(DWORD err) { @@ -472,7 +476,11 @@ struct llama_mlock::impl { char* errmsg = std::strerror(errno); bool suggest = (errno == ENOMEM); - +#if defined(TARGET_OS_VISION) || defined(TARGET_OS_TV) + // visionOS/tvOS dont't support RLIMIT_MEMLOCK + // Skip resource limit checks on visionOS/tvOS + suggest = false; +#else struct rlimit lock_limit; if (suggest && getrlimit(RLIMIT_MEMLOCK, &lock_limit)) { suggest = false; @@ -480,6 +488,7 @@ struct llama_mlock::impl { if (suggest && (lock_limit.rlim_max > lock_limit.rlim_cur + size)) { suggest = false; } +#endif LLAMA_LOG_WARN("warning: failed to mlock %zu-byte buffer (after previously locking %zu bytes): %s\n%s", size, this->size, errmsg, suggest ? MLOCK_SUGGESTION : ""); From 06a92a193a07afe445929607be9d5e4d033956fb Mon Sep 17 00:00:00 2001 From: Clauszy Date: Wed, 5 Mar 2025 15:25:45 +0800 Subject: [PATCH 30/87] server : fix cache reuse logic (#12161) The first kv shift offsets the positions of all tokens after head_c. When using llama_kv_cache_seq_rm next, using head_c will remove the valid tokens because their positions have already been offset. --- examples/server/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/server/server.cpp b/examples/server/server.cpp index 2306dc26f..e4f7e43fd 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -3003,7 +3003,7 @@ struct server_context { const int64_t kv_shift = (int64_t) head_p - (int64_t) head_c; llama_kv_cache_seq_rm (ctx, slot.id, head_p, head_c); - llama_kv_cache_seq_add(ctx, slot.id, head_c, -1, kv_shift); + llama_kv_cache_seq_add(ctx, slot.id, head_c, head_c + n_match, kv_shift); for (size_t i = 0; i < n_match; i++) { slot.cache_tokens[head_p + i] = slot.cache_tokens[head_c + i]; From 3ccbfe5a71c74ac574b00607067d0aa0a49df04c Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Wed, 5 Mar 2025 08:34:02 +0100 Subject: [PATCH 31/87] ci : remove xframework upload (#12190) * ci : remove xframework upload This commit removes the upload of the xframework zip file as an artifact. The motivation for this change is that the xframework zip file is currently being uploaded as part of strategy and will therefore be attempted to be uploaded multiple times and will fail the build. The uploading should be moved to somewhere else in the build to avoid this. * ci : add xcframework upload to macos-latest job --- .github/workflows/build.yml | 50 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b0c180f26..ad6b33d9b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -716,31 +716,6 @@ jobs: run: | ./build-xcframework.sh - - name: Determine tag name - id: tag - shell: bash - run: | - BUILD_NUMBER="$(git rev-list --count HEAD)" - SHORT_HASH="$(git rev-parse --short=7 HEAD)" - if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then - echo "name=b${BUILD_NUMBER}" >> $GITHUB_OUTPUT - else - SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-') - echo "name=${SAFE_NAME}-b${BUILD_NUMBER}-${SHORT_HASH}" >> $GITHUB_OUTPUT - fi - - - name: Pack artifacts - id: pack_artifacts - if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} - run: | - zip -r llama-${{ steps.tag.outputs.name }}-xcframework.zip build-apple/llama.xcframework - - - name: Upload artifacts - if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} - uses: actions/upload-artifact@v4 - with: - path: llama-${{ steps.tag.outputs.name }}-xcframework.zip - windows-msys2: runs-on: windows-latest @@ -1369,6 +1344,31 @@ jobs: - name: Build Xcode project run: xcodebuild -project examples/llama.swiftui/llama.swiftui.xcodeproj -scheme llama.swiftui -sdk iphoneos CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= -destination 'generic/platform=iOS' FRAMEWORK_FOLDER_PATH=./build-ios build + - name: Determine tag name + id: tag + shell: bash + run: | + BUILD_NUMBER="$(git rev-list --count HEAD)" + SHORT_HASH="$(git rev-parse --short=7 HEAD)" + if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then + echo "name=b${BUILD_NUMBER}" >> $GITHUB_OUTPUT + else + SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-') + echo "name=${SAFE_NAME}-b${BUILD_NUMBER}-${SHORT_HASH}" >> $GITHUB_OUTPUT + fi + + - name: Pack artifacts + id: pack_artifacts + if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} + run: | + zip -r llama-${{ steps.tag.outputs.name }}-xcframework.zip build-apple/llama.xcframework + + - name: Upload artifacts + if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }} + uses: actions/upload-artifact@v4 + with: + path: llama-${{ steps.tag.outputs.name }}-xcframework.zip + android-build: runs-on: ubuntu-latest From fa31c438e0e709242ab7334d26fc3be3dcda07a0 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Wed, 5 Mar 2025 10:22:29 +0100 Subject: [PATCH 32/87] ci : fix xcframework artifact tag (#12191) The commit add the name parameter to the upload-artifact action to ensure that the artifact is uploaded with the correct name. The motivation for this is that currently the uploaded xcframework is named as llama-b1-xcframework.zip. With this change the name of this artifact should contain the build number like the other artifacts. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ad6b33d9b..65f068a9b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1368,6 +1368,7 @@ jobs: uses: actions/upload-artifact@v4 with: path: llama-${{ steps.tag.outputs.name }}-xcframework.zip + name: llama-${{ steps.tag.outputs.name }}-xcframework android-build: runs-on: ubuntu-latest From 669912d9a5bf927312c553332ff997f0a99da8fb Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Wed, 5 Mar 2025 13:05:13 +0000 Subject: [PATCH 33/87] `tool-call`: fix Qwen 2.5 Coder support, add micro benchmarks, support trigger patterns for lazy grammars (#12034) * sampler: turn lazy grammar trigger words to regexes * add scripts/tool_bench.sh & .py * constrain llama json output regardless of function name if matches at beginning * update relaxed newline space rule in grammar tests * support add_generation_prompt query parameter (useful for /apply_template) * Update src/llama-grammar.cpp Co-authored-by: Georgi Gerganov --------- Co-authored-by: Georgi Gerganov --- README.md | 2 +- common/chat.cpp | 437 ++++++++++++------ common/common.cpp | 28 +- common/common.h | 21 +- common/json-schema-to-grammar.cpp | 9 +- common/json-schema-to-grammar.h | 1 - common/sampling.cpp | 51 +- examples/json_schema_to_grammar.py | 2 +- .../public_legacy/json-schema-to-grammar.mjs | 2 +- examples/server/server.cpp | 62 +-- examples/server/tests/unit/test_tool_call.py | 236 ++++++---- examples/server/tests/utils.py | 20 +- examples/server/utils.hpp | 6 +- include/llama.h | 22 +- models/templates/README.md | 2 +- requirements.txt | 1 + requirements/requirements-all.txt | 1 + requirements/requirements-tool_bench.txt | 12 + scripts/fetch_server_test_models.py | 2 +- scripts/tool_bench.py | 368 +++++++++++++++ scripts/tool_bench.sh | 66 +++ src/llama-grammar.cpp | 44 +- src/llama-grammar.h | 15 +- src/llama-sampling.cpp | 53 ++- tests/test-chat.cpp | 133 +++++- tests/test-json-schema-to-grammar.cpp | 126 ++--- 26 files changed, 1314 insertions(+), 408 deletions(-) mode change 100644 => 100755 examples/server/tests/unit/test_tool_call.py create mode 100644 requirements/requirements-tool_bench.txt create mode 100755 scripts/tool_bench.py create mode 100755 scripts/tool_bench.sh diff --git a/README.md b/README.md index ffb59a422..d73b0495d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Inference of Meta's [LLaMA](https://arxiv.org/abs/2302.13971) model (and others) - **How to use [MTLResidencySet](https://developer.apple.com/documentation/metal/mtlresidencyset?language=objc) to keep the GPU memory active?** https://github.com/ggml-org/llama.cpp/pull/11427 - **VS Code extension for FIM completions:** https://github.com/ggml-org/llama.vscode -- Universal tool call support in `llama-server`: https://github.com/ggml-org/llama.cpp/pull/9639 +- Universal [tool call support](./docs/function-calling.md) in `llama-server` https://github.com/ggml-org/llama.cpp/pull/9639 - Vim/Neovim plugin for FIM completions: https://github.com/ggml-org/llama.vim - Introducing GGUF-my-LoRA https://github.com/ggml-org/llama.cpp/discussions/10123 - Hugging Face Inference Endpoints now support GGUF out of the box! https://github.com/ggml-org/llama.cpp/discussions/9669 diff --git a/common/chat.cpp b/common/chat.cpp index 9ebe4c578..1b10219cc 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -449,12 +449,6 @@ std::string common_chat_format_name(common_chat_format format) { } } -const common_grammar_options grammar_options { - /* .dotall = */ false, - /* .compact_spaces = */ false, - // /* .compact_spaces = */ true, -}; - static bool parse_json(std::string::const_iterator & it, const std::string::const_iterator & end, json & out) { // // https://json.nlohmann.me/features/parsing/sax_interface/ struct json_error_locator : public nlohmann::json_sax { @@ -500,6 +494,34 @@ static bool parse_json(std::string::const_iterator & it, const std::string::cons } } +static bool parse_literal(std::string::const_iterator & it, const std::string::const_iterator & end, const std::string & expected) { + auto expected_it = expected.begin(); + auto tmp_it = it; + while (tmp_it != end && expected_it != expected.end() && *tmp_it == *expected_it) { + ++tmp_it; + ++expected_it; + } + if (expected_it == expected.end()) { + it = tmp_it; + return true; + } + return false; +} + +static std::optional parse_pattern(std::string::const_iterator & it, const std::string::const_iterator & end, const std::regex & expected) { + std::smatch match; + if (std::regex_match(it, end, match, expected)) { + it = match.suffix().first; + return match; + } + return std::nullopt; +} + +static void consume_spaces(std::string::const_iterator & it, const std::string::const_iterator & end) { + while (it != end && std::isspace(*it)) { + ++it; + } +} /** * Takes a prefix regex that must have 1 group to capture the function name, a closing suffix, and expects json parameters in between. @@ -509,7 +531,8 @@ static common_chat_msg parse_json_tool_calls( const std::string& input, const std::optional & trigger_opt, const std::regex & function_regex, - const std::regex & close_regex) { + const std::regex & close_regex, + bool allow_raw_python = false) { std::smatch match; common_chat_msg result; @@ -540,14 +563,19 @@ static common_chat_msg parse_json_tool_calls( it = rit->suffix().first; json arguments; - if (!parse_json(it, end, arguments)) { + if (parse_json(it, end, arguments)) { + if (!std::regex_search(it, end, match, close_regex)) { + throw std::runtime_error("Malformed input, missing closing pattern: " + input); + } + it = match.suffix().first; + result.tool_calls.push_back({name, arguments.is_string() ? arguments.get() : arguments.dump(), /* id= */ ""}); + } else { + if (allow_raw_python && name == "python") { + result.tool_calls.push_back({name, json({{"code", std::string(it, end)}}).dump(), /* id= */ ""}); + break; + } throw std::runtime_error("Failed to parse json tool call arguments: " + input); } - if (!std::regex_search(it, end, match, close_regex)) { - throw std::runtime_error("Malformed input, missing closing pattern: " + input); - } - it = match.suffix().first; - result.tool_calls.push_back({name, arguments.is_string() ? arguments.get() : arguments.dump(), /* id= */ ""}); } if (!result.tool_calls.empty()) { @@ -559,29 +587,29 @@ static common_chat_msg parse_json_tool_calls( return result; } +static common_chat_tool_call process_tool_call(const json & tool_call) { + const auto & arguments = tool_call.at("arguments"); + return { + /* .name = */ tool_call.at("name"), + /* .arguments = */ arguments.is_string() ? arguments.get() : arguments.dump(), + /* .id = */ tool_call.contains("id") ? tool_call.at("id") : "", + }; +} static common_chat_msg parse_prefixed_json_tool_call_array(const std::string& input, const std::string & prefix, size_t rstrip_prefix = 0) { auto content_end = input.find(prefix); size_t tc_start = std::string::npos; common_chat_msg result; result.role = "assistant"; - const auto process_tool_calls = [&](const json & tool_calls) { - for (const auto & tool_call : tool_calls) { - const auto & arguments = tool_call.at("arguments"); - result.tool_calls.push_back({ - tool_call.at("name"), - arguments.is_string() ? arguments.get() : arguments.dump(), - tool_call.contains("id") ? tool_call.at("id") : "", - }); - } - }; if (content_end == std::string::npos) { result.content = input; } else { tc_start = content_end + prefix.size() - rstrip_prefix; result.content = input.substr(0, content_end); auto tool_calls = json::parse(input.substr(tc_start)); - process_tool_calls(tool_calls); + for (const auto & tool_call : tool_calls) { + result.tool_calls.emplace_back(process_tool_call(tool_call)); + } } return result; } @@ -700,7 +728,7 @@ static common_chat_params common_chat_params_init_generic(const common_chat_temp data.grammar_lazy = false; data.grammar = build_grammar([&](const common_grammar_builder & builder) { builder.add_schema("root", schema); - }, grammar_options); + }); auto tweaked_messages = common_chat_template::add_system( inputs.messages, @@ -770,8 +798,11 @@ static common_chat_params common_chat_params_init_mistral_nemo(const common_chat schema["maxItems"] = 1; } builder.add_rule("root", "\"[TOOL_CALLS]\" " + builder.add_schema("tool_calls", schema)); - }, grammar_options); - data.grammar_triggers.push_back({"[TOOL_CALLS]", /* .at_start = */ true}); + }); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "[TOOL_CALLS]"}); + data.preserved_tokens = { + "[TOOL_CALLS]", + }; data.prompt = apply(tmpl, inputs.messages, inputs.tools.empty() ? json() : inputs.tools, inputs.add_generation_prompt); data.format = COMMON_CHAT_FORMAT_MISTRAL_NEMO; return data; @@ -813,14 +844,18 @@ static common_chat_params common_chat_params_init_command_r7b(const common_chat_ schema["maxItems"] = 1; } builder.add_rule("root", "\"<|START_ACTION|>\" " + builder.add_schema("tool_calls", schema) + " \"<|END_ACTION|>\""); - }, grammar_options); - data.grammar_triggers.push_back({"<|START_ACTION|>", /* .at_start = */ false}); + }); + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_WORD, + "<|START_ACTION|>", + }); data.preserved_tokens = { + "<|START_ACTION|>", + "<|END_ACTION|>", "<|START_RESPONSE|>", "<|END_RESPONSE|>", "<|START_THINKING|>", "<|END_THINKING|>", - "<|END_ACTION|>", }; auto adjusted_messages = json::array(); for (const auto & msg : inputs.messages) { @@ -840,9 +875,9 @@ static common_chat_params common_chat_params_init_command_r7b(const common_chat_ return data; } static common_chat_msg common_chat_parse_command_r7b(const std::string & input, bool extract_reasoning) { - static std::regex thought_regex("(<\\|START_THINKING\\|>([\\s\\S\\n\\r]*?)<\\|END_THINKING\\|>)([\\s\\S\\n\\r]*)"); - static std::regex action_regex("<\\|START_ACTION\\|>([\\s\\S\\n\\r]*?)<\\|END_ACTION\\|>"); - static std::regex response_regex("(?:<\\|START_RESPONSE\\|>)?([\\s\\S\\n\\r]*?)<\\|END_RESPONSE\\|>"); + static std::regex thought_regex("(<\\|START_THINKING\\|>([\\s\\S]*?)<\\|END_THINKING\\|>)([\\s\\S]*)"); + static std::regex action_regex("<\\|START_ACTION\\|>([\\s\\S]*?)<\\|END_ACTION\\|>"); + static std::regex response_regex("(?:<\\|START_RESPONSE\\|>)?([\\s\\S]*?)<\\|END_RESPONSE\\|>"); std::smatch match; @@ -945,23 +980,23 @@ static common_chat_params common_chat_params_init_llama_3_1_tool_calls(const com builder.add_rule( name + "-call", "\"{\" space " - "( \"\\\"type\\\":\" space \"\\\"function\\\",\" space )? " - "\"\\\"name\\\": \\\"" + name + "\\\", \\\"parameters\\\": \" " + - builder.add_schema(name + "-args", parameters) + - " \"}\"")); - data.grammar_triggers.push_back({"{\"name\": \"" + name + "\"", /* .at_start = */ true}); + "( \"\\\"type\\\"\" space \":\" space \"\\\"function\\\"\" space \",\" space )? " + " \"\\\"name\\\"\" space \":\" space \"\\\"" + name + "\\\"\" space \",\" space " + " \"\\\"parameters\\\"\" space \":\" space " + builder.add_schema(name + "-args", parameters) + " " + "\"}\" space")); + }); + // Small models may hallucinate function names so we match anything (*at the start*) that looks like the JSON of a function call, regardless of the name. + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_START, + "\\{\\s*(?:\"type\"\\s*:\\s*\"function\"\\s*,\\s*)?\"name\"\\s*:\\s*\"", // + name + "\"[\\s\\S]*", }); - data.grammar_triggers.push_back({"{\"name\":", /* .at_start = */ true}); - data.grammar_triggers.push_back({"{\n \"name\":", /* .at_start = */ true}); - data.grammar_triggers.push_back({"{\n \"name\":", /* .at_start = */ true}); - data.grammar_triggers.push_back({"{\"type\": \"function\"", /* .at_start = */ true}); - data.grammar_triggers.push_back({"{\n \"type\": \"function\"", /* .at_start = */ true}); - data.grammar_triggers.push_back({"{\n \"type\": \"function\"", /* .at_start = */ true}); if (!builtin_tools.empty()) { - data.grammar_triggers.push_back({"<|python_tag|>", /* .at_start = */ false}); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "<|python_tag|>"}); + data.preserved_tokens.push_back("<|python_tag|>"); } + // Allow a few empty lines on top of the usual constrained json schema space rule. builder.add_rule("root", string_join(tool_rules, " | ")); - }, grammar_options); + }); data.additional_stops.push_back("<|eom_id|>"); data.prompt = apply(tmpl, inputs.messages, inputs.tools.empty() ? json() : inputs.tools, inputs.add_generation_prompt, { {"tools_in_user_message", false}, @@ -974,33 +1009,33 @@ static common_chat_params common_chat_params_init_llama_3_1_tool_calls(const com } static common_chat_msg common_chat_parse_llama_3_1(const std::string & input, bool with_builtin_tools = false) { // TODO: tighten & simplify the parser, don't accept leading text context. - static std::regex function_regex("\\{[\\s\\n\\r]*(?:\"type\"[\\s\\n\\r]*:[\\s\\n\\r]*\"function\"[\\s\\n\\r]*,[\\s\\n\\r]*|[\\s\\n\\r]*)\"name\"[\\s\\n\\r]*:[\\s\\n\\r]*\"([^\"]+)\"[\\s\\n\\r]*,[\\s\\n\\r]*\"parameters\": "); - static std::regex close_regex("\\}"); - static std::regex builtin_call_regex("<\\|python_tag\\|>([^.(]+)\\.call\\((.*)\\)"); + static std::regex function_regex( + "\\s*\\{\\s*(?:\"type\"\\s*:\\s*\"function\"\\s*,\\s*)?\"name\"\\s*:\\s*\"([^\"]+)\"\\s*,\\s*\"parameters\"\\s*: "); + static std::regex close_regex("\\}\\s*"); + static std::regex builtin_call_regex("<\\|python_tag\\|>\\s*([^.(]+)\\s*\\.\\s*call\\s*\\(\\s*([\\w]+)\\s*=\\s*([\\s\\S]*?)\\)"); if (with_builtin_tools) { std::smatch match; if (std::regex_match(input, match, builtin_call_regex)) { - auto name = match[1].str(); - auto raw_args = match[2].str(); + try { + auto name = match[1].str(); + auto arg_name = match[2].str(); + auto arg_value_str = match[3].str(); + auto arg_value = json::parse(arg_value_str); - // TODO: if/when builtin tools start accepting more than 1 argument, use parse_json for real parsing. - auto it_eq = raw_args.find('='); - auto arg_name = raw_args.substr(0, it_eq); - auto arg_value_str = raw_args.substr(it_eq + 1); - auto arg_value = json::parse(arg_value_str); - - common_chat_msg msg; - msg.role = "assistant"; - msg.content = match.prefix().str(); - msg.tool_calls.push_back({ - /* .name = */ name, - /* .arguments = */ (json { - {arg_name, arg_value}, - }).dump(), - /* .id = */ "", - }); - return msg; + common_chat_msg msg; + msg.role = "assistant"; + msg.tool_calls.push_back({ + /* .name = */ name, + /* .arguments = */ (json { + {arg_name, arg_value}, + }).dump(), + /* .id = */ "", + }); + return msg; + } catch (const std::exception & e) { + LOG_WRN("Failed to parse builtin tool call arguments (%s): %s", e.what(), input.c_str()); + } } } return parse_json_tool_calls(input, std::nullopt, function_regex, close_regex); @@ -1017,10 +1052,10 @@ static common_chat_params common_chat_params_init_deepseek_r1(const common_chat_ std::string name = function.at("name"); auto parameters = function.at("parameters"); builder.resolve_refs(parameters); - auto args_rule = builder.add_schema(name + "-args", parameters); tool_rules.push_back(builder.add_rule(name + "-call", "\"<|tool▁call▁begin|>function<|tool▁sep|>" + name + "\\n" - "```json\\n\" " + args_rule + " \"```<|tool▁call▁end|>\"")); + "```json\\n\" " + builder.add_schema(name + "-args", parameters) + " " + "\"```<|tool▁call▁end|>\"")); }); // Distill Qwen 7B & 32B models seem confused re/ syntax of their tool call opening tag, // so we accept common variants (then it's all constrained) @@ -1029,18 +1064,20 @@ static common_chat_params common_chat_params_init_deepseek_r1(const common_chat_ "(" + string_join(tool_rules, " | ") + ")" + (inputs.parallel_tool_calls ? "*" : "") + " " "\"<|tool▁calls▁end|>\"" " space"); - data.grammar_triggers.push_back({"<|tool▁calls▁begin|>", /* .at_start = */ false}); - data.grammar_triggers.push_back({"<|tool_calls_begin|>", /* .at_start = */ false}); - data.grammar_triggers.push_back({"<|tool calls begin|>", /* .at_start = */ false}); - data.grammar_triggers.push_back({"<|tool\\_calls\\_begin|>", /* .at_start = */ false}); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "<|tool▁calls▁begin|>"}); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "<|tool_calls_begin|>"}); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "<|tool calls begin|>"}); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "<|tool\\_calls\\_begin|>"}); data.preserved_tokens = { "", "", + "<|tool▁calls▁begin|>", + "<|tool▁call▁begin|>", "<|tool▁sep|>", - "<|tool▁calls▁end|", "<|tool▁call▁end|>", + "<|tool▁calls▁end|", }; - }, grammar_options); + }); } auto prompt = apply(tmpl, inputs.messages, inputs.tools.empty() ? json() : inputs.tools, inputs.add_generation_prompt); @@ -1129,8 +1166,11 @@ static common_chat_params common_chat_params_init_firefunction_v2(const common_c schema["maxItems"] = 1; } builder.add_rule("root", "\" functools\"? " + builder.add_schema("tool_calls", schema)); - }, grammar_options); - data.grammar_triggers.push_back({" functools[", /* .at_start = */ false}); + }); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, " functools["}); + data.preserved_tokens = { + " functools[", + }; data.format = COMMON_CHAT_FORMAT_FIREFUNCTION_V2; } else { data.format = COMMON_CHAT_FORMAT_CONTENT_ONLY; @@ -1158,11 +1198,28 @@ static common_chat_params common_chat_params_init_functionary_v3_2(const common_ auto parameters = function.at("parameters"); builder.resolve_refs(parameters); auto args_rule = builder.add_schema(name + "-args", parameters); - first_tool_rules.push_back(builder.add_rule(name + "-call", "\"" + name + "\\n\" " + args_rule)); + first_tool_rules.push_back(builder.add_rule(name + "-call", "( \"assistant<|end_header_id|>\\n\" )? \"" + name + "\\n\" " + args_rule)); subsequent_tool_rules.push_back(builder.add_rule(name + "-call2", "\">>>" + name + "\\n\" " + args_rule)); - data.grammar_triggers.push_back({name, /* .at_start = */ true}); - data.grammar_triggers.push_back({">>>" + name, /* .at_start = */ false}); + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_START, + regex_escape(name + "\n"), + }); + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_START, + regex_escape("assistant<|end_header_id|>\n" + name + "\n"), + }); + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_WORD, + regex_escape(">>>" + name + "\n"), + }); + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_WORD, + ">>>assistant<|end_header_id|>\n" + name, + }); }); + data.preserved_tokens = { + "<|end_header_id|>", + }; auto first_rule = first_tool_rules.empty() ? "" : builder.add_rule("first_tool_call", string_join(first_tool_rules, " | ")) + " space"; if (inputs.parallel_tool_calls) { auto subsequent_rule = builder.add_rule("subsequent_tool_call", string_join(subsequent_tool_rules, " | ")) + " space"; @@ -1171,34 +1228,20 @@ static common_chat_params common_chat_params_init_functionary_v3_2(const common_ builder.add_rule("root", first_rule); } - }, grammar_options); + }); } return data; } -static bool consume(std::string::const_iterator & it, const std::string::const_iterator & end, const std::string & expected) { - auto expected_it = expected.begin(); - auto tmp_it = it; - while (tmp_it != end && expected_it != expected.end() && *tmp_it == *expected_it) { - ++tmp_it; - ++expected_it; - } - if (expected_it == expected.end()) { - it = tmp_it; - return true; - } - return false; -} - static common_chat_msg common_chat_parse_functionary_v3_2(const std::string & input) { - static std::regex function_regex(R"((?:>>>)?(\w+)\n)"); + static std::regex function_regex(R"((?:>>>)?(?:assistant<|end_header_id|>\n)?(\w+)\n)"); static std::regex close_regex(R"($|(?=>>>))"); std::string content; auto it = input.begin(); const auto end = input.end(); - if (consume(it, end, "all\n")) { + if (parse_literal(it, end, "all\n")) { std::smatch match; if (std::regex_search(it, end, match, function_regex)) { auto fun_it = match.prefix().second; @@ -1213,7 +1256,7 @@ static common_chat_msg common_chat_parse_functionary_v3_2(const std::string & in } // TODO: tighten & simplify. try { - auto res = parse_json_tool_calls(std::string(it, end), std::nullopt, function_regex, close_regex); + auto res = parse_json_tool_calls(std::string(it, end), std::nullopt, function_regex, close_regex, /* allow_raw_python= */ true); res.content = content + res.content; return res; } catch (const std::exception & e) { @@ -1266,12 +1309,13 @@ static common_chat_params common_chat_params_init_functionary_v3_1_llama_3_1(con }); if (has_raw_python) { tool_rules.push_back(builder.add_rule("python-call", "\"<|python_tag|>\" .*")); - data.grammar_triggers.push_back({"<|python_tag|>", /* .at_start = */ false}); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "<|python_tag|>"}); + data.preserved_tokens.push_back("<|python_tag|>"); } auto tool_call = builder.add_rule("tool_call", string_join(tool_rules, " | ")) + " space"; builder.add_rule("root", inputs.parallel_tool_calls ? "(" + tool_call + ")+" : tool_call); - data.grammar_triggers.push_back({"\" space " + + builder.add_schema(name + "-args", parameters) + " " + "\"\" space")); + + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_WORD, + "", + }); + auto escaped_name = regex_escape(name); + data.grammar_triggers.push_back({ + COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN, + "\" space " + builder.add_rule("tool_call", string_join(tool_rules, " | ")) + " \"\" space"; + auto any_tool_call = builder.add_rule("any_tool_call", "( " + string_join(tool_rules, " | ") + " ) space"); + std::vector alt_tags { + any_tool_call, + "\"\" space " + any_tool_call + " \"\"", + // The rest is just to accommodate common "good bad" outputs. + "\"\" space " + any_tool_call + " \"\"", + "\"\" space " + any_tool_call + " \"\"", + "\"\" space " + any_tool_call + " \"\"", + "\"\" space " + any_tool_call + " \"\"", + "\"\" space " + any_tool_call + " \"\"", + "\"\" space " + any_tool_call + " \"\"", + }; + auto wrappable_tool_call = builder.add_rule("wrappable_tool_call", "( " + string_join(alt_tags, " | ") + " ) space"); + tool_call_alts.push_back(wrappable_tool_call); + tool_call_alts.push_back( + "( \"```\\n\" | \"```json\\n\" | \"```xml\\n\" ) space " + wrappable_tool_call + " space \"```\" space "); + auto tool_call = builder.add_rule("tool_call", string_join(tool_call_alts, " | ")); builder.add_rule("root", inputs.parallel_tool_calls ? "(" + tool_call + ")+" : tool_call); - data.grammar_triggers.push_back({"", /* .at_start = */ false}); - data.preserved_tokens = { "" }; - }, grammar_options); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, ""}); + data.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, "|||)?\\s*\\{\\s*\"", //name\"\\s*:\\s*\"" + escaped_name + "\"", + }); + data.preserved_tokens = { + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "```", + "```json", + "```xml", + }; + }); data.prompt = apply(tmpl, inputs.messages, inputs.tools.empty() ? json() : inputs.tools, inputs.add_generation_prompt); data.format = COMMON_CHAT_FORMAT_HERMES_2_PRO; return data; } -static common_chat_msg common_chat_parse_hermes_2_pro(const std::string & input) { +static common_chat_msg common_chat_parse_hermes_2_pro(const std::string& input) { + const static std::regex open_regex( + "(?:" + "(```(?:xml|json)?\\n\\s*)?" // match 1 (block_start) + "(" // match 2 (open_tag) + "|" + "|" + "|" + "|" + "|" + "|" + "|" + ")?" + "(\\s*\\{\\s*\"name\"\\s*:[\\s\\S]*)" // match 3 (named tool call + rest) + ")" + "|" + "(?:]+)>" // match 4 (function name) + "|)" // match 5 (function name again) + "([\\s\\S]*)" // match 6 (function arguments + rest)})" + ); + try { - std::regex start_pattern(R"([\n\s]*)"); - std::regex middle_pattern(R"([\n\s]*[\n\s]*)"); - std::regex end_pattern(R"([\n\s]*[\n\s]*$)"); common_chat_msg msg; msg.role = "assistant"; - auto end = input.end(); - std::sregex_iterator rend; - std::sregex_iterator rit(input.begin(), end, start_pattern); - if (rit == rend) { - msg.content = input; - return msg; - } + std::string::const_iterator it = input.begin(); + const std::string::const_iterator end = input.end(); + std::smatch match; - msg.content = rit->prefix(); - - auto it = rit->suffix().first; while (it != end) { - json call; - if (!parse_json(it, end, call)) { - throw std::runtime_error("Failed to parse json tool call"); - } - const auto & arguments = call.at("arguments"); - msg.tool_calls.push_back({ - call.at("name"), - arguments.dump(), - // arguments.is_string() ? arguments.get() : arguments.dump(), - /* id= */ "", - }); - rit = {it, end, middle_pattern}; - if (rit != rend) { - it = rit->suffix().first; - } else { - rit = {it, end, end_pattern}; - if (rit == rend) { - throw std::runtime_error("Malformed input, missing "); + if (std::regex_search(it, end, match, open_regex)) { + // Add content before the match + msg.content += std::string(it, match[0].first); + + auto block_start = match[1].str(); + std::string block_end = block_start.empty() ? "" : "```"; + + auto open_tag = match[2].str(); + std::string close_tag; + + if (match[3].matched) { + close_tag = open_tag.empty() ? "" : ""; + // Start parsing from after the opening tags + auto json_it = match[6].first; + json arguments; + if (parse_json(json_it, end, arguments)) { + msg.tool_calls.emplace_back(process_tool_call({ + {"name", function_name}, + {"arguments", arguments}, + })); + it = json_it; // Move iterator past parsed JSON + + // Handle close tags + consume_spaces(it, end); + if (!close_tag.empty() && !parse_literal(it, end, close_tag)) { + throw std::runtime_error("Failed to parse closing tag"); + } + consume_spaces(it, end); + if (!block_end.empty() && !parse_literal(it, end, block_end)) { + throw std::runtime_error("Failed to parse block end"); + } + consume_spaces(it, end); + } else { + // Not a valid tool call, treat as content + msg.content += std::string(match[0].first, match[0].second); + it = match[0].second; + } } + } else { + // Add remaining content + msg.content += std::string(it, end); break; } } diff --git a/common/common.cpp b/common/common.cpp index d2b0d50e3..6448b7b03 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -10,7 +10,6 @@ // Change JSON_ASSERT from assert() to GGML_ASSERT: #define JSON_ASSERT GGML_ASSERT #include "json.hpp" -#include "json-schema-to-grammar.h" #include "llama.h" #include @@ -483,6 +482,11 @@ void string_replace_all(std::string & s, const std::string & search, const std:: s = std::move(builder); } +std::string regex_escape(const std::string & s) { + static const std::regex special_chars("[.^$|()*+?\\[\\]{}\\\\]"); + return std::regex_replace(s, special_chars, "\\$0"); +} + std::string string_join(const std::vector & values, const std::string & separator) { std::ostringstream result; for (size_t i = 0; i < values.size(); ++i) { @@ -2026,3 +2030,25 @@ common_control_vector_data common_control_vector_load(const std::vector +json common_grammar_trigger::to_json() const { + json out { + {"type", (int) type}, + {"value", value}, + }; + if (type == COMMON_GRAMMAR_TRIGGER_TYPE_TOKEN) { + out["token"] = (int) token; + } + return out; +} + +template <> +common_grammar_trigger common_grammar_trigger::from_json(const json & in) { + common_grammar_trigger out; + out.type = (common_grammar_trigger_type) in.at("type").get(); + out.value = in.at("value").get(); + if (out.type == COMMON_GRAMMAR_TRIGGER_TYPE_TOKEN) { + out.token = (llama_token) in.at("token").get(); + } + return out; +} diff --git a/common/common.h b/common/common.h index f4b4a96fb..733f7f1c8 100644 --- a/common/common.h +++ b/common/common.h @@ -110,9 +110,21 @@ enum common_conversation_mode { COMMON_CONVERSATION_MODE_AUTO = 2, }; +enum common_grammar_trigger_type { + COMMON_GRAMMAR_TRIGGER_TYPE_TOKEN, + COMMON_GRAMMAR_TRIGGER_TYPE_WORD, + COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN, + COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_START, +}; + struct common_grammar_trigger { - std::string word; - bool at_start; + common_grammar_trigger_type type; + std::string value; + llama_token token = LLAMA_TOKEN_NULL; + + // T can only be nlohmann::ordered_json + template T to_json() const; + template static common_grammar_trigger from_json(const T & in); }; // sampling parameters @@ -163,8 +175,7 @@ struct common_params_sampling { std::string grammar; // optional BNF-like grammar to constrain sampling bool grammar_lazy = false; - std::vector grammar_trigger_words; // optional trigger words to trigger lazy grammar - std::vector grammar_trigger_tokens; // optional trigger tokens to trigger lazy grammar and print trigger special tokens. + std::vector grammar_triggers; // optional triggers (for lazy grammars) std::set preserved_tokens; std::vector logit_bias; // logit biases to apply @@ -458,6 +469,8 @@ std::string string_repeat(const std::string & str, size_t n); void string_replace_all(std::string & s, const std::string & search, const std::string & replace); +std::string regex_escape(const std::string & s); + template static std::vector string_split(const std::string & str, char delim) { static_assert(!std::is_same::value, "Please use the specialized version for std::string"); diff --git a/common/json-schema-to-grammar.cpp b/common/json-schema-to-grammar.cpp index 3ebcc3d9f..906798225 100644 --- a/common/json-schema-to-grammar.cpp +++ b/common/json-schema-to-grammar.cpp @@ -264,7 +264,7 @@ static void _build_min_max_int(int min_value, int max_value, std::stringstream & throw std::runtime_error("At least one of min_value or max_value must be set"); } -const std::string SPACE_RULE = "| \" \" | \"\\n\" [ \\t]{0,20}"; +const std::string SPACE_RULE = "| \" \" | \"\\n\"{1,2} [ \\t]{0,20}"; struct BuiltinRule { std::string content; @@ -764,11 +764,10 @@ private: public: SchemaConverter( const std::function & fetch_json, - bool dotall, - bool compact_spaces) + bool dotall) : _fetch_json(fetch_json), _dotall(dotall) { - _rules["space"] = compact_spaces ? "\" \"?" : SPACE_RULE; + _rules["space"] = SPACE_RULE; } void resolve_refs(json & schema, const std::string & url) { @@ -1007,7 +1006,7 @@ std::string json_schema_to_grammar(const json & schema, bool force_gbnf) { } std::string build_grammar(const std::function & cb, const common_grammar_options & options) { - SchemaConverter converter([&](const std::string &) { return json(); }, options.dotall, options.compact_spaces); + SchemaConverter converter([&](const std::string &) { return json(); }, options.dotall); common_grammar_builder builder { /* .add_rule = */ [&](const std::string & name, const std::string & rule) { return converter._add_rule(name, rule); diff --git a/common/json-schema-to-grammar.h b/common/json-schema-to-grammar.h index 62a3b0a44..4613f5d9f 100644 --- a/common/json-schema-to-grammar.h +++ b/common/json-schema-to-grammar.h @@ -16,7 +16,6 @@ struct common_grammar_builder { struct common_grammar_options { bool dotall = false; - bool compact_spaces = false; }; std::string build_grammar(const std::function & cb, const common_grammar_options & options = {}); diff --git a/common/sampling.cpp b/common/sampling.cpp index 972fbe9da..baf22066d 100644 --- a/common/sampling.cpp +++ b/common/sampling.cpp @@ -160,16 +160,53 @@ struct common_sampler * common_sampler_init(const struct llama_model * model, co GGML_ABORT("llguidance (cmake -DLLAMA_LLGUIDANCE=ON) is not enabled"); #endif // LLAMA_USE_LLGUIDANCE } else { - std::vector trigger_words; - trigger_words.reserve(params.grammar_trigger_words.size()); - for (const auto & str : params.grammar_trigger_words) { - trigger_words.push_back(str.word.c_str()); + std::vector patterns_at_start; + std::vector patterns_anywhere; + std::vector trigger_tokens; + for (const auto & trigger : params.grammar_triggers) { + switch (trigger.type) { + case COMMON_GRAMMAR_TRIGGER_TYPE_WORD: + { + const auto & word = trigger.value; + patterns_anywhere.push_back(regex_escape(word)); + break; + } + case COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN: + case COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_START: + { + const auto & pattern = trigger.value; + (trigger.type == COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_START ? patterns_at_start : patterns_anywhere).push_back(pattern); + break; + } + case COMMON_GRAMMAR_TRIGGER_TYPE_TOKEN: + { + const auto token = trigger.token; + trigger_tokens.push_back(token); + break; + } + default: + GGML_ASSERT(false && "unknown trigger type"); + } + } + + std::vector trigger_patterns; + if (!patterns_at_start.empty()) { + trigger_patterns.push_back("^(" + string_join(patterns_at_start, "|") + ")[\\s\\S]*"); + } + if (!patterns_anywhere.empty()) { + trigger_patterns.push_back("^[\\s\\S]*?(" + string_join(patterns_anywhere, "|") + ")[\\s\\S]*"); + } + + std::vector trigger_patterns_c; + trigger_patterns_c.reserve(trigger_patterns.size()); + for (const auto & regex : trigger_patterns) { + trigger_patterns_c.push_back(regex.c_str()); } grmr = params.grammar_lazy - ? llama_sampler_init_grammar_lazy(vocab, params.grammar.c_str(), "root", - trigger_words.data(), trigger_words.size(), - params.grammar_trigger_tokens.data(), params.grammar_trigger_tokens.size()) + ? llama_sampler_init_grammar_lazy_patterns(vocab, params.grammar.c_str(), "root", + trigger_patterns_c.data(), trigger_patterns_c.size(), + trigger_tokens.data(), trigger_tokens.size()) : llama_sampler_init_grammar(vocab, params.grammar.c_str(), "root"); } diff --git a/examples/json_schema_to_grammar.py b/examples/json_schema_to_grammar.py index fc9f0097f..55f94c0b0 100755 --- a/examples/json_schema_to_grammar.py +++ b/examples/json_schema_to_grammar.py @@ -195,7 +195,7 @@ class BuiltinRule: self.deps = deps or [] # Constraining spaces to prevent model "running away". -SPACE_RULE = '| " " | "\\n" [ \\t]{0,20}' +SPACE_RULE = '| " " | "\\n"{1,2} [ \\t]{0,20}' PRIMITIVE_RULES = { 'boolean' : BuiltinRule('("true" | "false") space', []), diff --git a/examples/server/public_legacy/json-schema-to-grammar.mjs b/examples/server/public_legacy/json-schema-to-grammar.mjs index e67bb15c1..f767ce7b7 100644 --- a/examples/server/public_legacy/json-schema-to-grammar.mjs +++ b/examples/server/public_legacy/json-schema-to-grammar.mjs @@ -1,5 +1,5 @@ // WARNING: This file was ported from json_schema_to_grammar.py, please fix bugs / add features there first. -const SPACE_RULE = '| " " | "\\n" [ \\t]{0,20}'; +const SPACE_RULE = '| " " | "\\n"{1,2} [ \\t]{0,20}'; function _buildRepetition(itemRule, minItems, maxItems, opts={}) { if (minItems === 0 && maxItems === 1) { diff --git a/examples/server/server.cpp b/examples/server/server.cpp index e4f7e43fd..2a526b0e7 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -131,9 +131,9 @@ struct slot_params { lora.push_back({{"id", i}, {"scale", this->lora[i].scale}}); } - std::vector grammar_trigger_words; - for (const auto & trigger : sampling.grammar_trigger_words) { - grammar_trigger_words.push_back(trigger.word); + auto grammar_triggers = json::array(); + for (const auto & trigger : sampling.grammar_triggers) { + grammar_triggers.push_back(trigger.to_json()); } return json { @@ -170,8 +170,8 @@ struct slot_params { {"n_probs", sampling.n_probs}, {"min_keep", sampling.min_keep}, {"grammar", sampling.grammar}, - {"grammar_trigger_words", grammar_trigger_words}, - {"grammar_trigger_tokens", sampling.grammar_trigger_tokens}, + {"grammar_lazy", sampling.grammar_lazy}, + {"grammar_triggers", grammar_triggers}, {"preserved_tokens", sampling.preserved_tokens}, {"chat_format", common_chat_format_name(oaicompat_chat_format)}, {"samplers", samplers}, @@ -356,24 +356,6 @@ struct server_task { } { - const auto grammar_triggers = data.find("grammar_triggers"); - if (grammar_triggers != data.end()) { - for (const auto & t : *grammar_triggers) { - common_grammar_trigger trigger; - trigger.word = t.at("word"); - trigger.at_start = t.at("at_start"); - - auto ids = common_tokenize(vocab, trigger.word, /* add_special= */ false, /* parse_special= */ true); - if (ids.size() == 1) { - SRV_DBG("Grammar trigger token: %d (`%s`)\n", ids[0], trigger.word.c_str()); - params.sampling.grammar_trigger_tokens.push_back(ids[0]); - params.sampling.preserved_tokens.insert(ids[0]); - continue; - } - SRV_DBG("Grammar trigger word: `%s`\n", trigger.word.c_str()); - params.sampling.grammar_trigger_words.push_back(trigger); - } - } const auto preserved_tokens = data.find("preserved_tokens"); if (preserved_tokens != data.end()) { for (const auto & t : *preserved_tokens) { @@ -383,12 +365,38 @@ struct server_task { params.sampling.preserved_tokens.insert(ids[0]); } else { // This may happen when using a tool call style meant for a model with special tokens to preserve on a model without said tokens. - SRV_WRN("Not preserved because more than 1 token (wrong chat template override?): %s\n", t.get().c_str()); + SRV_DBG("Not preserved because more than 1 token: %s\n", t.get().c_str()); } } } - if (params.sampling.grammar_lazy) { - GGML_ASSERT(params.sampling.grammar_trigger_tokens.size() > 0 || params.sampling.grammar_trigger_words.size() > 0); + const auto grammar_triggers = data.find("grammar_triggers"); + if (grammar_triggers != data.end()) { + for (const auto & t : *grammar_triggers) { + auto ct = common_grammar_trigger::from_json(t); + if (ct.type == COMMON_GRAMMAR_TRIGGER_TYPE_WORD) { + const auto & word = ct.value; + auto ids = common_tokenize(vocab, word, /* add_special= */ false, /* parse_special= */ true); + if (ids.size() == 1) { + auto token = ids[0]; + if (std::find(params.sampling.preserved_tokens.begin(), params.sampling.preserved_tokens.end(), (llama_token) token) == params.sampling.preserved_tokens.end()) { + throw std::runtime_error("Grammar trigger word should be marked as preserved token: " + word); + } + SRV_DBG("Grammar trigger token: %d (`%s`)\n", token, word.c_str()); + common_grammar_trigger trigger; + trigger.type = COMMON_GRAMMAR_TRIGGER_TYPE_TOKEN; + trigger.value = (llama_token) token; + params.sampling.grammar_triggers.push_back(trigger); + } else { + SRV_DBG("Grammar trigger word: `%s`\n", word.c_str()); + params.sampling.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, word}); + } + } else { + params.sampling.grammar_triggers.push_back(ct); + } + } + } + if (params.sampling.grammar_lazy && params.sampling.grammar_triggers.empty()) { + throw std::runtime_error("Error: no triggers set for lazy grammar!"); } } @@ -2045,7 +2053,7 @@ struct server_context { if (slot.n_predict > 0 && slot.params.n_predict > slot.n_predict) { // Might be better to reject the request with a 400 ? - SLT_WRN(slot, "n_predict = %d exceeds server configuration, setting to %d", slot.params.n_predict, slot.n_predict); + SLT_WRN(slot, "n_predict = %d exceeds server configuration, setting to %d\n", slot.params.n_predict, slot.n_predict); slot.params.n_predict = slot.n_predict; } diff --git a/examples/server/tests/unit/test_tool_call.py b/examples/server/tests/unit/test_tool_call.py old mode 100644 new mode 100755 index a91a2f333..25bddbaee --- a/examples/server/tests/unit/test_tool_call.py +++ b/examples/server/tests/unit/test_tool_call.py @@ -1,4 +1,12 @@ +#!/usr/bin/env python import pytest + +# ensure grandparent path is in sys.path +from pathlib import Path +import sys +path = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(path)) + from utils import * server: ServerProcess @@ -66,15 +74,8 @@ WEATHER_TOOL = { } -def do_test_completion_with_required_tool_tiny(template_name: str, tool: dict, argument_key: str | None): - global server - n_predict = 512 - # server = ServerPreset.stories15m_moe() - server.jinja = True - server.n_predict = n_predict - server.chat_template_file = f'../../../models/templates/{template_name}.jinja' - server.start(timeout_seconds=TIMEOUT_SERVER_START) - res = server.make_request("POST", "/chat/completions", data={ +def do_test_completion_with_required_tool_tiny(server: ServerProcess, tool: dict, argument_key: str | None, n_predict, **kwargs): + res = server.make_request("POST", "/v1/chat/completions", data={ "max_tokens": n_predict, "messages": [ {"role": "system", "content": "You are a coding assistant."}, @@ -83,16 +84,14 @@ def do_test_completion_with_required_tool_tiny(template_name: str, tool: dict, a "tool_choice": "required", "tools": [tool], "parallel_tool_calls": False, - "temperature": 0.0, - "top_k": 1, - "top_p": 1.0, + **kwargs, }) assert res.status_code == 200, f"Expected status code 200, got {res.status_code}" choice = res.body["choices"][0] tool_calls = choice["message"].get("tool_calls") assert tool_calls and len(tool_calls) == 1, f'Expected 1 tool call in {choice["message"]}' tool_call = tool_calls[0] - assert choice["message"].get("content") is None, f'Expected no content in {choice["message"]}' + assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' expected_function_name = "python" if tool["type"] == "code_interpreter" else tool["function"]["name"] assert expected_function_name == tool_call["function"]["name"] actual_arguments = tool_call["function"]["arguments"] @@ -108,7 +107,14 @@ def do_test_completion_with_required_tool_tiny(template_name: str, tool: dict, a ("meta-llama-Llama-3.3-70B-Instruct", PYTHON_TOOL, "code"), ]) def test_completion_with_required_tool_tiny_fast(template_name: str, tool: dict, argument_key: str | None): - do_test_completion_with_required_tool_tiny(template_name, tool, argument_key) + global server + n_predict = 512 + # server = ServerPreset.stories15m_moe() + server.jinja = True + server.n_predict = n_predict + server.chat_template_file = f'../../../models/templates/{template_name}.jinja' + server.start(timeout_seconds=TIMEOUT_SERVER_START) + do_test_completion_with_required_tool_tiny(server, tool, argument_key, n_predict, temperature=0.0, top_k=1, top_p=1.0) @pytest.mark.slow @@ -130,10 +136,17 @@ def test_completion_with_required_tool_tiny_fast(template_name: str, tool: dict, ("deepseek-ai-DeepSeek-R1-Distill-Llama-8B", TEST_TOOL, "success"), ("deepseek-ai-DeepSeek-R1-Distill-Llama-8B", PYTHON_TOOL, "code"), ("fireworks-ai-llama-3-firefunction-v2", TEST_TOOL, "success"), - ("fireworks-ai-llama-3-firefunction-v2", PYTHON_TOOL, "code"), + # ("fireworks-ai-llama-3-firefunction-v2", PYTHON_TOOL, "code"), ]) def test_completion_with_required_tool_tiny_slow(template_name: str, tool: dict, argument_key: str | None): - do_test_completion_with_required_tool_tiny(template_name, tool, argument_key) + global server + n_predict = 512 + # server = ServerPreset.stories15m_moe() + server.jinja = True + server.n_predict = n_predict + server.chat_template_file = f'../../../models/templates/{template_name}.jinja' + server.start(timeout_seconds=TIMEOUT_SERVER_START) + do_test_completion_with_required_tool_tiny(server, tool, argument_key, n_predict) @pytest.mark.slow @@ -142,25 +155,33 @@ def test_completion_with_required_tool_tiny_slow(template_name: str, tool: dict, (PYTHON_TOOL, "code", "bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", None), (PYTHON_TOOL, "code", "bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", "chatml"), - # Note: gemma-2-2b-it knows itself as "model", not "assistant", so we don't test the ill-suited chatml on it. (TEST_TOOL, "success", "bartowski/gemma-2-2b-it-GGUF:Q4_K_M", None), (PYTHON_TOOL, "code", "bartowski/gemma-2-2b-it-GGUF:Q4_K_M", None), + (PYTHON_TOOL, "code", "bartowski/gemma-2-2b-it-GGUF:Q4_K_M", "chatml"), (TEST_TOOL, "success", "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), (PYTHON_TOOL, "code", "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), (PYTHON_TOOL, "code", "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", "chatml"), + (TEST_TOOL, "success", "bartowski/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M", None), + (PYTHON_TOOL, "code", "bartowski/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M", None), + (PYTHON_TOOL, "code", "bartowski/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M", "chatml"), + + (TEST_TOOL, "success", "bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M", None), + (PYTHON_TOOL, "code", "bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M", None), + (PYTHON_TOOL, "code", "bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M", "chatml"), + (TEST_TOOL, "success", "bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", None), (PYTHON_TOOL, "code", "bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", None), (PYTHON_TOOL, "code", "bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", "chatml"), (TEST_TOOL, "success", "bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-2-Pro-Llama-3-8B", "tool_use")), (PYTHON_TOOL, "code", "bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-2-Pro-Llama-3-8B", "tool_use")), - # (PYTHON_TOOL, "code", "bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", "chatml"), + (PYTHON_TOOL, "code", "bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", "chatml"), (TEST_TOOL, "success", "bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-3-Llama-3.1-8B", "tool_use")), (PYTHON_TOOL, "code", "bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-3-Llama-3.1-8B", "tool_use")), - # (PYTHON_TOOL, "code", "bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", "chatml"), + (PYTHON_TOOL, "code", "bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", "chatml"), (TEST_TOOL, "success", "bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", None), (PYTHON_TOOL, "code", "bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", None), @@ -176,10 +197,10 @@ def test_completion_with_required_tool_tiny_slow(template_name: str, tool: dict, (TEST_TOOL, "success", "bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", ("meta-llama/Llama-3.2-3B-Instruct", None)), (PYTHON_TOOL, "code", "bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", ("meta-llama/Llama-3.2-3B-Instruct", None)), - # (PYTHON_TOOL, "code", "bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", "chatml"), - # TODO: fix these - # (TEST_TOOL, "success", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), - # (PYTHON_TOOL, "code", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), + (PYTHON_TOOL, "code", "bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", "chatml"), + + (TEST_TOOL, "success", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), + (PYTHON_TOOL, "code", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), ]) def test_completion_with_required_tool_real_model(tool: dict, argument_key: str | None, hf_repo: str, template_override: str | Tuple[str, str | None] | None): global server @@ -197,7 +218,7 @@ def test_completion_with_required_tool_real_model(tool: dict, argument_key: str elif isinstance(template_override, str): server.chat_template = template_override server.start(timeout_seconds=TIMEOUT_SERVER_START) - res = server.make_request("POST", "/chat/completions", data={ + res = server.make_request("POST", "/v1/chat/completions", data={ "max_tokens": n_predict, "messages": [ {"role": "system", "content": "You are a coding assistant."}, @@ -215,7 +236,7 @@ def test_completion_with_required_tool_real_model(tool: dict, argument_key: str tool_calls = choice["message"].get("tool_calls") assert tool_calls and len(tool_calls) == 1, f'Expected 1 tool call in {choice["message"]}' tool_call = tool_calls[0] - assert choice["message"].get("content") is None, f'Expected no content in {choice["message"]}' + # assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' expected_function_name = "python" if tool["type"] == "code_interpreter" else tool["function"]["name"] assert expected_function_name == tool_call["function"]["name"] actual_arguments = tool_call["function"]["arguments"] @@ -225,13 +246,8 @@ def test_completion_with_required_tool_real_model(tool: dict, argument_key: str assert argument_key in actual_arguments, f"tool arguments: {json.dumps(actual_arguments)}, expected: {argument_key}" -def do_test_completion_without_tool_call(template_name: str, n_predict: int, tools: list[dict], tool_choice: str | None): - global server - server.jinja = True - server.n_predict = n_predict - server.chat_template_file = f'../../../models/templates/{template_name}.jinja' - server.start(timeout_seconds=TIMEOUT_SERVER_START) - res = server.make_request("POST", "/chat/completions", data={ +def do_test_completion_without_tool_call(server: ServerProcess, n_predict: int, tools: list[dict], tool_choice: str | None, **kwargs): + res = server.make_request("POST", "/v1/chat/completions", data={ "max_tokens": n_predict, "messages": [ {"role": "system", "content": "You are a coding assistant."}, @@ -239,9 +255,7 @@ def do_test_completion_without_tool_call(template_name: str, n_predict: int, too ], "tools": tools if tools else None, "tool_choice": tool_choice, - "temperature": 0.0, - "top_k": 1, - "top_p": 1.0, + **kwargs, }, timeout=TIMEOUT_HTTP_REQUEST) assert res.status_code == 200, f"Expected status code 200, got {res.status_code}" choice = res.body["choices"][0] @@ -254,7 +268,12 @@ def do_test_completion_without_tool_call(template_name: str, n_predict: int, too ("meta-llama-Llama-3.3-70B-Instruct", 128, [PYTHON_TOOL], 'none'), ]) def test_completion_without_tool_call_fast(template_name: str, n_predict: int, tools: list[dict], tool_choice: str | None): - do_test_completion_without_tool_call(template_name, n_predict, tools, tool_choice) + global server + server.jinja = True + server.n_predict = n_predict + server.chat_template_file = f'../../../models/templates/{template_name}.jinja' + server.start(timeout_seconds=TIMEOUT_SERVER_START) + do_test_completion_without_tool_call(server, n_predict, tools, tool_choice) @pytest.mark.slow @@ -270,7 +289,12 @@ def test_completion_without_tool_call_fast(template_name: str, n_predict: int, t ("meta-llama-Llama-3.2-3B-Instruct", 256, [PYTHON_TOOL], 'none'), ]) def test_completion_without_tool_call_slow(template_name: str, n_predict: int, tools: list[dict], tool_choice: str | None): - do_test_completion_without_tool_call(template_name, n_predict, tools, tool_choice) + global server + server.jinja = True + server.n_predict = n_predict + server.chat_template_file = f'../../../models/templates/{template_name}.jinja' + server.start(timeout_seconds=TIMEOUT_SERVER_START) + do_test_completion_without_tool_call(server, n_predict, tools, tool_choice) @pytest.mark.slow @@ -281,6 +305,12 @@ def test_completion_without_tool_call_slow(template_name: str, n_predict: int, t ("bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), ("bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", "chatml"), + ("bartowski/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M", None), + ("bartowski/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M", "chatml"), + + ("bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M", None), + ("bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M", "chatml"), + ("bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", None), ("bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", "chatml"), @@ -324,48 +354,52 @@ def test_weather(hf_repo: str, template_override: str | Tuple[str, str | None] | elif isinstance(template_override, str): server.chat_template = template_override server.start(timeout_seconds=TIMEOUT_SERVER_START) - res = server.make_request("POST", "/chat/completions", data={ - "max_tokens": n_predict, + do_test_weather(server, max_tokens=n_predict) + + +def do_test_weather(server: ServerProcess, **kwargs): + res = server.make_request("POST", "/v1/chat/completions", data={ "messages": [ {"role": "system", "content": "You are a chatbot that uses tools/functions. Dont overthink things."}, {"role": "user", "content": "What is the weather in Istanbul?"}, ], "tools": [WEATHER_TOOL], + **kwargs, }, timeout=TIMEOUT_HTTP_REQUEST) assert res.status_code == 200, f"Expected status code 200, got {res.status_code}" choice = res.body["choices"][0] tool_calls = choice["message"].get("tool_calls") assert tool_calls and len(tool_calls) == 1, f'Expected 1 tool call in {choice["message"]}' tool_call = tool_calls[0] - assert choice["message"].get("content") is None, f'Expected no content in {choice["message"]}' - assert tool_call["function"]["name"] == WEATHER_TOOL["function"]["name"] + # assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' + assert tool_call["function"]["name"] == WEATHER_TOOL["function"]["name"], f'Expected weather tool call, got {tool_call["function"]["name"]}' actual_arguments = json.loads(tool_call["function"]["arguments"]) assert 'location' in actual_arguments, f"location not found in {json.dumps(actual_arguments)}" location = actual_arguments["location"] assert isinstance(location, str), f"Expected location to be a string, got {type(location)}: {json.dumps(location)}" - assert re.match('^Istanbul(, (TR|Turkey|Türkiye))?$', location), f'Expected Istanbul for location, got {location}' + assert re.match('^Istanbul(( |, ?)(TR|Turkey|Türkiye))?$', location), f'Expected Istanbul for location, got {location}' @pytest.mark.slow @pytest.mark.parametrize("result_override,n_predict,hf_repo,template_override", [ (None, 128, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", "chatml"), - (None, 128, "bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", None), + (None, 128, "bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M", None), + (None, 128, "bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M", "chatml"), (None, 128, "bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", "chatml"), (None, 128, "bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-2-Pro-Llama-3-8B", "tool_use")), (None, 128, "bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-3-Llama-3.1-8B", "tool_use")), (None, 128, "bartowski/functionary-small-v3.2-GGUF:Q8_0", ("meetkai/functionary-medium-v3.2", None)), - (None, 128, "bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", None), (None, 128, "bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", None), (None, 128, "bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", "chatml"), (None, 128, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), + ("[\\s\\S]*?\\*\\*\\s*0.5($|\\*\\*)", 8192, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", ("llama-cpp-deepseek-r1", None)), # TODO: fix these (wrong results, either didn't respect decimal instruction or got wrong value) - ("[\\s\\S]*?\\*\\*\\s*0.5($|\\*\\*)", 8192, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), - # ("[\\s\\S]*?\\*\\*\\s*0.5($|\\*\\*)", 8192, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", ("llama-cpp-deepseek-r1", None)), + # (None, 128, "bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", None), + # ("[\\s\\S]*?\\*\\*\\s*0.5($|\\*\\*)", 8192, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), ]) def test_calc_result(result_override: str | None, n_predict: int, hf_repo: str, template_override: str | Tuple[str, str | None] | None): global server - # n_predict = 512 server.n_slots = 1 server.jinja = True server.n_ctx = 8192 * 2 @@ -379,10 +413,14 @@ def test_calc_result(result_override: str | None, n_predict: int, hf_repo: str, elif isinstance(template_override, str): server.chat_template = template_override server.start(timeout_seconds=TIMEOUT_SERVER_START) - res = server.make_request("POST", "/chat/completions", data={ + do_test_calc_result(server, result_override, n_predict) + + +def do_test_calc_result(server: ServerProcess, result_override: str | None, n_predict: int, **kwargs): + res = server.make_request("POST", "/v1/chat/completions", data={ "max_tokens": n_predict, "messages": [ - {"role": "system", "content": "You are a chatbot that uses tools/functions. Dont overthink things, and provide very concise answers. Do not explain your reasoning to the user. Provide any numerical values back to the user with at most two decimals."}, + {"role": "system", "content": "You are a tools-calling assistant. You express numerical values with at most two decimals."}, {"role": "user", "content": "What's the y coordinate of a point on the unit sphere at angle 30 degrees?"}, { "role": "assistant", @@ -423,7 +461,8 @@ def test_calc_result(result_override: str | None, n_predict: int, hf_repo: str, } } } - ] + ], + **kwargs, }, timeout=TIMEOUT_HTTP_REQUEST) assert res.status_code == 200, f"Expected status code 200, got {res.status_code}" choice = res.body["choices"][0] @@ -434,19 +473,19 @@ def test_calc_result(result_override: str | None, n_predict: int, hf_repo: str, if result_override is not None: assert re.match(result_override, content), f'Expected {result_override}, got {content}' else: - assert re.match('^[\\s\\S]*?The (y[ -])?coordinate [\\s\\S]*?is (approximately )?0\\.56\\b|^0\\.56$', content), \ + assert re.match('^[\\s\\S]*?((That\'s|\\bis) (approximately )?)?\\b0\\.(5\\b|56\\b|556)', content), \ f'Expected something like "The y coordinate is 0.56.", got {content}' @pytest.mark.slow @pytest.mark.parametrize("n_predict,reasoning_format,expect_content,expect_reasoning_content,hf_repo,template_override", [ - (128, 'deepseek', "^The sum of 102 and 7 is 109.*", None, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), - (128, None, "^The sum of 102 and 7 is 109.*", None, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), + (128, 'deepseek', "^The sum of 102 and 7 is 109[\\s\\S]*", None, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), + (128, None, "^The sum of 102 and 7 is 109[\\s\\S]*", None, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), - (1024, 'deepseek', "To find the sum of.*", "I need to calculate the sum of 102 and 7.*", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), - (1024, 'none', "^I need[\\s\\S]*?\n?To find.*", None, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), + (1024, 'deepseek', "To find the sum of[\\s\\S]*", "I need to calculate the sum of 102 and 7[\\s\\S]*", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), + (1024, 'none', "^(\\s*)?I need[\\s\\S]*?\\s*To find[\\s\\S]*", None, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), - (1024, 'deepseek', "To find the sum of.*", "First, I [\\s\\S]*", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", ("llama-cpp-deepseek-r1", None)), + (1024, 'deepseek', "To find the sum of[\\s\\S]*", "First, I [\\s\\S]*", "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", ("llama-cpp-deepseek-r1", None)), ]) def test_thoughts(n_predict: int, reasoning_format: Literal['deepseek', 'none'] | None, expect_content: str | None, expect_reasoning_content: str | None, hf_repo: str, template_override: str | Tuple[str, str | None] | None): global server @@ -464,7 +503,7 @@ def test_thoughts(n_predict: int, reasoning_format: Literal['deepseek', 'none'] elif isinstance(template_override, str): server.chat_template = template_override server.start(timeout_seconds=TIMEOUT_SERVER_START) - res = server.make_request("POST", "/chat/completions", data={ + res = server.make_request("POST", "/v1/chat/completions", data={ "max_tokens": n_predict, "messages": [ {"role": "user", "content": "What's the sum of 102 and 7?"}, @@ -476,7 +515,7 @@ def test_thoughts(n_predict: int, reasoning_format: Literal['deepseek', 'none'] content = choice["message"].get("content") if expect_content is None: - assert content is None, f'Expected no content in {choice["message"]}' + assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' else: assert re.match(expect_content, content), f'Expected {expect_content}, got {content}' @@ -488,46 +527,46 @@ def test_thoughts(n_predict: int, reasoning_format: Literal['deepseek', 'none'] @pytest.mark.slow -@pytest.mark.parametrize("expected_arguments_override,hf_repo,template_override", [ - (None, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), - # (None, "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", "chatml"), +@pytest.mark.parametrize("hf_repo,template_override", [ + ("bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q4_K_M", None), - (None, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), - (None, "bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", "chatml"), + ("bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", None), + ("bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M", "chatml"), - (None, "bartowski/functionary-small-v3.2-GGUF:Q8_0", ("meetkai-functionary-medium-v3.2", None)), - (None, "bartowski/functionary-small-v3.2-GGUF:Q8_0", "chatml"), + ("bartowski/functionary-small-v3.2-GGUF:Q8_0", ("meetkai-functionary-medium-v3.2", None)), + ("bartowski/functionary-small-v3.2-GGUF:Q8_0", "chatml"), - ('{"code":"print("}', "bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", None), - (None, "bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", "chatml"), + # ("bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", None), + ("bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M", "chatml"), - (None, "bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", ("meta-llama-Llama-3.2-3B-Instruct", None)), - (None, "bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", "chatml"), + ("bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", ("meta-llama-Llama-3.2-3B-Instruct", None)), + ("bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M", None), - ('{"code":"print("}', "bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M", ("meta-llama-Llama-3.2-3B-Instruct", None)), - (None, "bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M", "chatml"), + ("bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M", ("meta-llama-Llama-3.2-3B-Instruct", None)), + ("bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M", None), - (None, "bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", None), - (None, "bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", "chatml"), + ("bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", None), + ("bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M", "chatml"), - (None, "bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-2-Pro-Llama-3-8B", "tool_use")), - (None, "bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", "chatml"), + ("bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", ("NousResearch/Hermes-2-Pro-Llama-3-8B", "tool_use")), + ("bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M", "chatml"), - (None, "bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", ("NousResearch-Hermes-3-Llama-3.1-8B", "tool_use")), - (None, "bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", "chatml"), + ("bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", ("NousResearch-Hermes-3-Llama-3.1-8B", "tool_use")), + ("bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M", "chatml"), - (None, "bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", None), - (None, "bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", "chatml"), + ("bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", None), + ("bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M", "chatml"), - # Note: gemma-2-2b-it knows itself as "model", not "assistant", so we don't test the ill-suited chatml on it. - (None, "bartowski/gemma-2-2b-it-GGUF:Q4_K_M", None), + ("bartowski/gemma-2-2b-it-GGUF:Q4_K_M", None), + ("bartowski/gemma-2-2b-it-GGUF:Q4_K_M", "chatml"), ]) -def test_hello_world(expected_arguments_override: str | None, hf_repo: str, template_override: str | Tuple[str, str | None] | None): +def test_hello_world(hf_repo: str, template_override: str | Tuple[str, str | None] | None): global server + n_predict = 512 # High because of DeepSeek R1 server.n_slots = 1 server.jinja = True server.n_ctx = 8192 - server.n_predict = 512 # High because of DeepSeek R1 + server.n_predict = n_predict server.model_hf_repo = hf_repo server.model_hf_file = None if isinstance(template_override, tuple): @@ -537,31 +576,28 @@ def test_hello_world(expected_arguments_override: str | None, hf_repo: str, temp elif isinstance(template_override, str): server.chat_template = template_override server.start(timeout_seconds=TIMEOUT_SERVER_START) - res = server.make_request("POST", "/chat/completions", data={ - "max_tokens": 256, + + do_test_hello_world(server, max_tokens=n_predict) + + +def do_test_hello_world(server: ServerProcess, **kwargs): + res = server.make_request("POST", "/v1/chat/completions", data={ "messages": [ - {"role": "system", "content": "You are a coding assistant."}, + {"role": "system", "content": "You are a tool-calling agent."}, {"role": "user", "content": "say hello world with python"}, ], "tools": [PYTHON_TOOL], - # Note: without these greedy params, Functionary v3.2 writes `def hello_world():\n print("Hello, World!")\nhello_world()` which is correct but a pain to test. - "temperature": 0.0, - "top_k": 1, - "top_p": 1.0, + **kwargs, }, timeout=TIMEOUT_HTTP_REQUEST) assert res.status_code == 200, f"Expected status code 200, got {res.status_code}" choice = res.body["choices"][0] tool_calls = choice["message"].get("tool_calls") assert tool_calls and len(tool_calls) == 1, f'Expected 1 tool call in {choice["message"]}' tool_call = tool_calls[0] - assert choice["message"].get("content") is None, f'Expected no content in {choice["message"]}' + # assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' assert tool_call["function"]["name"] == PYTHON_TOOL["function"]["name"] - actual_arguments = tool_call["function"]["arguments"] - if expected_arguments_override is not None: - assert actual_arguments == expected_arguments_override - else: - actual_arguments = json.loads(actual_arguments) - assert 'code' in actual_arguments, f"code not found in {json.dumps(actual_arguments)}" - code = actual_arguments["code"] - assert isinstance(code, str), f"Expected code to be a string, got {type(code)}: {json.dumps(code)}" - assert re.match(r'''print\(("[Hh]ello,? [Ww]orld!?"|'[Hh]ello,? [Ww]orld!?')\)''', code), f'Expected hello world, got {code}' + actual_arguments = json.loads(tool_call["function"]["arguments"]) + assert 'code' in actual_arguments, f"code not found in {json.dumps(actual_arguments)}" + code = actual_arguments["code"] + assert isinstance(code, str), f"Expected code to be a string, got {type(code)}: {json.dumps(code)}" + assert re.match(r'''print\(("[Hh]ello,? [Ww]orld!?"|'[Hh]ello,? [Ww]orld!?')\)''', code), f'Expected hello world, got {code}' diff --git a/examples/server/tests/utils.py b/examples/server/tests/utils.py index f32a439f6..ec2d8ec55 100644 --- a/examples/server/tests/utils.py +++ b/examples/server/tests/utils.py @@ -67,6 +67,9 @@ class ServerProcess: id_slot: int | None = None cache_prompt: bool | None = None n_slots: int | None = None + ctk: str | None = None + ctv: str | None = None + fa: bool | None = None server_continuous_batching: bool | None = False server_embeddings: bool | None = False server_reranking: bool | None = False @@ -84,6 +87,7 @@ class ServerProcess: reasoning_format: Literal['deepseek', 'none'] | None = None chat_template: str | None = None chat_template_file: str | None = None + server_path: str | None = None # session variables process: subprocess.Popen | None = None @@ -97,7 +101,9 @@ class ServerProcess: self.server_port = int(os.environ["PORT"]) def start(self, timeout_seconds: int | None = DEFAULT_HTTP_TIMEOUT) -> None: - if "LLAMA_SERVER_BIN_PATH" in os.environ: + if self.server_path is not None: + server_path = self.server_path + elif "LLAMA_SERVER_BIN_PATH" in os.environ: server_path = os.environ["LLAMA_SERVER_BIN_PATH"] elif os.name == "nt": server_path = "../../../build/bin/Release/llama-server.exe" @@ -151,6 +157,12 @@ class ServerProcess: server_args.extend(["--ctx-size", self.n_ctx]) if self.n_slots: server_args.extend(["--parallel", self.n_slots]) + if self.ctk: + server_args.extend(["-ctk", self.ctk]) + if self.ctv: + server_args.extend(["-ctv", self.ctv]) + if self.fa is not None: + server_args.append("-fa") if self.n_predict: server_args.extend(["--n-predict", self.n_predict]) if self.slot_save_path: @@ -184,7 +196,7 @@ class ServerProcess: server_args.extend(["--chat-template-file", self.chat_template_file]) args = [str(arg) for arg in [server_path, *server_args]] - print(f"bench: starting server with: {' '.join(args)}") + print(f"tests: starting server with: {' '.join(args)}") flags = 0 if "nt" == os.name: @@ -215,6 +227,10 @@ class ServerProcess: return # server is ready except Exception as e: pass + # Check if process died + if self.process.poll() is not None: + raise RuntimeError(f"Server process died with return code {self.process.returncode}") + print(f"Waiting for server to start...") time.sleep(0.5) raise TimeoutError(f"Server did not start within {timeout_seconds} seconds") diff --git a/examples/server/utils.hpp b/examples/server/utils.hpp index 144d914c2..393e3927c 100644 --- a/examples/server/utils.hpp +++ b/examples/server/utils.hpp @@ -607,6 +607,7 @@ static json oaicompat_completion_params_parse( inputs.use_jinja = use_jinja; inputs.parallel_tool_calls = json_value(body, "parallel_tool_calls", false); inputs.extract_reasoning = reasoning_format != COMMON_REASONING_FORMAT_NONE; + inputs.add_generation_prompt = json_value(body, "add_generation_prompt", true); if (!inputs.tools.empty() && inputs.tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE && body.contains("grammar")) { throw std::runtime_error("Cannot use custom grammar constraints with tools."); } @@ -620,10 +621,7 @@ static json oaicompat_completion_params_parse( llama_params["grammar_lazy"] = chat_params.grammar_lazy; auto grammar_triggers = json::array(); for (const auto & trigger : chat_params.grammar_triggers) { - grammar_triggers.push_back({ - {"word", trigger.word}, - {"at_start", trigger.at_start}, - }); + grammar_triggers.push_back(trigger.to_json()); } llama_params["grammar_triggers"] = grammar_triggers; llama_params["preserved_tokens"] = chat_params.preserved_tokens; diff --git a/include/llama.h b/include/llama.h index ee6e73915..d62792c0a 100644 --- a/include/llama.h +++ b/include/llama.h @@ -1205,17 +1205,29 @@ extern "C" { const char * grammar_str, const char * grammar_root); - /// @details Lazy grammar sampler, introduced in https://github.com/ggml-org/llama.cpp/pull/9639 - /// @param trigger_words A list of words that will trigger the grammar sampler. This may be updated to a loose regex syntax (w/ ^) in a near future. - /// @param trigger_tokens A list of tokens that will trigger the grammar sampler. - LLAMA_API struct llama_sampler * llama_sampler_init_grammar_lazy( + DEPRECATED(LLAMA_API struct llama_sampler * llama_sampler_init_grammar_lazy( const struct llama_vocab * vocab, const char * grammar_str, const char * grammar_root, const char ** trigger_words, size_t num_trigger_words, const llama_token * trigger_tokens, - size_t num_trigger_tokens); + size_t num_trigger_tokens), + "use llama_sampler_init_grammar_lazy_patterns instead"); + + + /// @details Lazy grammar sampler, introduced in https://github.com/ggml-org/llama.cpp/pull/9639 + /// @param trigger_patterns A list of patterns that will trigger the grammar sampler. Pattern will be matched from the start of the generation output, and grammar sampler will be fed content starting from its first match group. + /// @param trigger_tokens A list of tokens that will trigger the grammar sampler. Grammar sampler will be fed content starting from the trigger token included. + LLAMA_API struct llama_sampler * llama_sampler_init_grammar_lazy_patterns( + const struct llama_vocab * vocab, + const char * grammar_str, + const char * grammar_root, + const char ** trigger_patterns, + size_t num_trigger_patterns, + const llama_token * trigger_tokens, + size_t num_trigger_tokens); + /// NOTE: Avoid using on the full vocabulary as searching for repeated tokens can become slow. For example, apply top-k or top-p sampling first. LLAMA_API struct llama_sampler * llama_sampler_init_penalties( diff --git a/models/templates/README.md b/models/templates/README.md index 72c30d1e1..e4fd104fc 100644 --- a/models/templates/README.md +++ b/models/templates/README.md @@ -9,7 +9,7 @@ These templates can be updated with the following commands: ./scripts/get_chat_template.py deepseek-ai/DeepSeek-R1-Distill-Qwen-32B > models/templates/deepseek-ai-DeepSeek-R1-Distill-Qwen-32B.jinja ./scripts/get_chat_template.py fireworks-ai/llama-3-firefunction-v2 > models/templates/fireworks-ai-llama-3-firefunction-v2.jinja ./scripts/get_chat_template.py google/gemma-2-2b-it > models/templates/google-gemma-2-2b-it.jinja -./scripts/get_chat_template.py meetkai/functionary-medium-v3. > models/templates/meetkai-functionary-medium-v3.jinja +./scripts/get_chat_template.py meetkai/functionary-medium-v3.1 > models/templates/meetkai-functionary-medium-v3.1.jinja ./scripts/get_chat_template.py meetkai/functionary-medium-v3.2 > models/templates/meetkai-functionary-medium-v3.2.jinja ./scripts/get_chat_template.py meta-llama/Llama-3.1-8B-Instruct > models/templates/meta-llama-Llama-3.1-8B-Instruct.jinja ./scripts/get_chat_template.py meta-llama/Llama-3.2-3B-Instruct > models/templates/meta-llama-Llama-3.2-3B-Instruct.jinja diff --git a/requirements.txt b/requirements.txt index 9e190ae27..f2a18d628 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ -r ./requirements/requirements-convert_hf_to_gguf_update.txt -r ./requirements/requirements-convert_llama_ggml_to_gguf.txt -r ./requirements/requirements-convert_lora_to_gguf.txt +-r ./requirements/requirements-tool_bench.txt diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index 94de59d7e..439db8886 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -10,3 +10,4 @@ -r ./requirements-convert_hf_to_gguf_update.txt -r ./requirements-convert_legacy_llama.txt -r ./requirements-convert_llama_ggml_to_gguf.txt +-r ./requirements-tool_bench.txt diff --git a/requirements/requirements-tool_bench.txt b/requirements/requirements-tool_bench.txt new file mode 100644 index 000000000..b94521fc7 --- /dev/null +++ b/requirements/requirements-tool_bench.txt @@ -0,0 +1,12 @@ +aiohttp~=3.9.3 +pytest~=8.3.3 +huggingface_hub~=0.23.2 +matplotlib~=3.10.0 +numpy~=1.26.4 +openai~=1.55.3 +pandas~=2.2.3 +prometheus-client~=0.20.0 +requests~=2.32.3 +wget~=3.2 +typer~=0.15.1 +seaborn~=0.13.2 diff --git a/scripts/fetch_server_test_models.py b/scripts/fetch_server_test_models.py index 05690b138..e6775bfc5 100755 --- a/scripts/fetch_server_test_models.py +++ b/scripts/fetch_server_test_models.py @@ -75,7 +75,7 @@ if __name__ == '__main__': logging.info(f' - {m.hf_repo} / {m.hf_file}') cli_path = os.environ.get( - 'LLAMA_SERVER_BIN_PATH', + 'LLAMA_CLI_BIN_PATH', os.path.join( os.path.dirname(__file__), '../build/bin/Release/llama-cli.exe' if os.name == 'nt' else '../build/bin/llama-cli')) diff --git a/scripts/tool_bench.py b/scripts/tool_bench.py new file mode 100755 index 000000000..0f406bc42 --- /dev/null +++ b/scripts/tool_bench.py @@ -0,0 +1,368 @@ +#!/usr/bin/env uv run +''' + Simplistic tool call benchmarks for llama-server and ollama. + + Essentially runs the tests at server/examples/server/tests/unit/test_tool_call.py N times, at different temperatures and on different backends (current llama-server, baseline llama-server and ollama), + and plots the results of multiple runs (from same .jsonl file or multiple ones) as a success rate heatmap. + + Simple usage example: + + cmake -B build -DLLAMA_CURL=1 && cmake --build build --config Release -j -t llama-server + + export LLAMA_SERVER_BIN_PATH=$PWD/build/bin/llama-server + export LLAMA_CACHE=${LLAMA_CACHE:-$HOME/Library/Caches/llama.cpp} + + ./scripts/tool_bench.py run --n 30 --temp -1 --temp 0 --temp 1 --model "Qwen 2.5 1.5B Q4_K_M" --output qwen1.5b.jsonl --hf bartowski/Qwen2.5-1.5B-Instruct-GGUF --ollama qwen2.5:1.5b-instruct-q4_K_M + ./scripts/tool_bench.py run --n 30 --temp -1 --temp 0 --temp 1 --model "Qwen 2.5 Coder 7B Q4_K_M" --output qwenc7b.jsonl --hf bartowski/Qwen2.5-Coder-7B-Instruct-GGUF --ollama qwen2.5-coder:7b + + ./scripts/tool_bench.py plot *.jsonl # Opens window w/ heatmap + ./scripts/tool_bench.py plot qwen*.jsonl --output qwen.png # Saves heatmap to qwen.png + + (please see ./scripts/tool_bench.sh for a more complete example) +''' +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "pytest", +# "pandas", +# "matplotlib", +# "seaborn", +# "requests", +# "wget", +# "typer", +# ] +# /// +from contextlib import contextmanager +from pathlib import Path +import re +from statistics import mean, median +from typing import Annotated, Dict, List, Optional, Tuple +import atexit +import json +import logging +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import seaborn as sns +import subprocess +import sys +import time +import typer + +sys.path.insert(0, Path(__file__).parent.parent.as_posix()) +if True: + from examples.server.tests.utils import ServerProcess + from examples.server.tests.unit.test_tool_call import TIMEOUT_SERVER_START, do_test_calc_result, do_test_hello_world, do_test_weather + + +@contextmanager +def scoped_server(sp: ServerProcess): + def stop(): + nonlocal sp + if sp is not None: + sp.stop() + sp = None # type: ignore + atexit.register(stop) + yield sp + stop() + + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s' +) +logger = logging.getLogger(__name__) + +app = typer.Typer() + + +@app.command() +def plot(files: List[Path], output: Optional[Path] = None, test_regex: Optional[str] = None, server_regex: Optional[str] = None): + + lines: List[Dict] = [] + for file in files: + if not file.exists(): + logger.error(f"File not found: {file}") + continue + + try: + with file.open() as f: + raw_data = f.read() + logger.info(f"Reading {file} ({len(raw_data)} bytes)") + + for line_num, line in enumerate(raw_data.split('\n'), 1): + line = line.strip() + if not line: + continue + try: + record = json.loads(line) + lines.append(record) + except json.JSONDecodeError as e: + logger.warning(f"Invalid JSON at {file}:{line_num} - {e}") + except Exception as e: + logger.error(f"Error processing {file}: {e}") + + if not lines: + raise Exception("No valid data was loaded") + + data_dict: Dict[Tuple, float] = {} + models: List[str] = [] + temps = set() + tests = set() + server_names = set() + total_counts = set() + for rec in lines: + try: + model = rec["model"] + temp = rec["temp"] + server_name = rec["server_name"] + test = rec["test"] + success = rec["success_ratio"] + success_count = rec["success_count"] + failure_count = rec["failure_count"] + total_count = success_count + failure_count + total_counts.add(total_count) + + if test_regex and not re.search(test_regex, test): + continue + + if server_regex and not re.search(server_regex, server_name): + continue + + data_dict[(model, temp, server_name, test)] = success + + if model not in models: + models.append(model) + temps.add(temp) + tests.add(test) + server_names.add(server_name) + + except KeyError as e: + logger.warning(f"Missing required field in record: {e}") + + if len(total_counts) > 1: + logger.warning(f"Total counts are not consistent: {total_counts}") + + # Sort the collected values + temps = list(sorted(temps, key=lambda x: x if x is not None else -1)) + tests = list(sorted(tests)) + server_names = list(sorted(server_names)) + + logger.info(f"Processed {len(lines)} lines") + logger.info(f"Found {len(data_dict)} valid data points") + logger.info(f"Models: {models}") + logger.info(f"Temperatures: {temps}") + logger.info(f"Tests: {tests}") + logger.info(f"Servers: {server_names}") + + matrix: list[list[float]] = [] + index: list[str] = [] + + all_cols = [ + (server_name, test) + for server_name in server_names + for test in tests + ] + for model in models: + for temp in temps: + index.append(f"{model} @ {temp}") + row_vals = [ + data_dict.get((model, temp, server_name, test), np.nan) + for server_name, test in all_cols + ] + matrix.append(row_vals) + + columns: list[str] = [f"{server_name}\n{test}" for server_name, test in all_cols] + + df = pd.DataFrame(matrix, index=np.array(index), columns=np.array(columns)) + + plt.figure(figsize=(12, 6)) + + sns.heatmap( + df, annot=True, cmap="RdYlGn", vmin=0.0, vmax=1.0, cbar=True, fmt=".2f", center=0.5, square=True, linewidths=0.5, + cbar_kws={"label": "Success Ratio"}, + ) + + plt.title(f"Tool Call Bench (n = {str(min(total_counts)) if len(total_counts) == 1 else f'{min(total_counts)}-{max(total_counts)}'})\nSuccess Ratios by Server & Test", pad=20) + plt.xlabel("Server & Test", labelpad=10) + plt.ylabel("Model @ Temperature", labelpad=10) + + plt.xticks(rotation=45, ha='right') + plt.yticks(rotation=0) + + plt.tight_layout() + + if output: + plt.savefig(output, dpi=300, bbox_inches='tight') + logger.info(f"Plot saved to {output}") + else: + plt.show() + + +@app.command() +def run( + output: Annotated[Path, typer.Option(help="Output JSON file")], + model: Annotated[Optional[str], typer.Option(help="Name of the model to test (server agnostic)")] = None, + hf: Annotated[Optional[str], typer.Option(help="GGUF huggingface model repo id (+ optional quant) to test w/ llama-server")] = None, + chat_template: Annotated[Optional[str], typer.Option(help="Chat template override for llama-server")] = None, + ollama: Annotated[Optional[str], typer.Option(help="Ollama model tag to test")] = None, + llama_baseline: Annotated[Optional[str], typer.Option(help="llama-server baseline binary path to use as baseline")] = None, + n: Annotated[int, typer.Option(help="Number of times to run each test")] = 10, + temp: Annotated[Optional[List[float]], typer.Option(help="Set of temperatures to test")] = None, + top_p: Annotated[Optional[float], typer.Option(help="top_p")] = None, + top_k: Annotated[Optional[int], typer.Option(help="top_k")] = None, + ctk: Annotated[Optional[str], typer.Option(help="ctk")] = None, + ctv: Annotated[Optional[str], typer.Option(help="ctv")] = None, + fa: Annotated[Optional[bool], typer.Option(help="fa")] = None, + seed: Annotated[Optional[int], typer.Option(help="Random seed")] = None, + port: Annotated[int, typer.Option(help="llama-server port")] = 8084, + force: Annotated[bool, typer.Option(help="Force overwrite of output file")] = False, + append: Annotated[bool, typer.Option(help="Append to output file")] = False, + + test_hello_world: Annotated[bool, typer.Option(help="Whether to run the hello world test")] = True, + test_weather: Annotated[bool, typer.Option(help="Whether to run the weather test")] = True, + test_calc_result: Annotated[bool, typer.Option(help="Whether to run the calc result test")] = False, +): + # Check only one of output and append + + n_predict = 512 # High because of DeepSeek R1 + # n_ctx = 8192 + n_ctx = 2048 + + assert force or append or not output.exists(), f"Output file already exists: {output}; use --force to overwrite" + + with output.open('a' if append else 'w') as output_file: + + def run(server: ServerProcess, *, server_name: str, model_id: str, temp: Optional[float] = None, output_kwargs={}, request_kwargs={}): + request_kwargs = {**request_kwargs} + if temp is not None: + request_kwargs['temperature'] = temp + if top_p is not None: + request_kwargs['top_p'] = top_p + if top_k is not None: + request_kwargs['top_k'] = top_k + if seed is not None: + request_kwargs['seed'] = seed + + request_kwargs['cache_prompt'] = False + + tests = {} + if test_hello_world: + tests["hello world"] = lambda server: do_test_hello_world(server, **request_kwargs) + if test_weather: + tests["weather"] = lambda server: do_test_weather(server, **request_kwargs) + if test_calc_result: + tests["calc result"] = lambda server: do_test_calc_result(server, None, 512, **request_kwargs) + + for test_name, test in tests.items(): + success_count = 0 + failure_count = 0 + failures = [] + success_times = [] + failure_times = [] + logger.info(f"Running {test_name} ({server_name}, {model}): ") + for i in range(n): + start_time = time.time() + + def elapsed(): + return time.time() - start_time + + try: + test(server) + success_times.append(elapsed()) + success_count += 1 + logger.info('success') + except Exception as e: + logger.error(f'failure: {e}') + failure_count += 1 + failure_times.append(elapsed()) + failures.append(str(e)) + # import traceback + # traceback.print_exc() + output_file.write(json.dumps({**output_kwargs, **dict( + model=model, + server_name=server_name, + model_id=model_id, + test=test_name, + temp=t, + top_p=top_p, + top_k=top_k, + ctk=ctk, + ctv=ctv, + seed=seed, + success_ratio=float(success_count) / n, + avg_time=mean(success_times + failure_times), + median_time=median(success_times + failure_times), + success_count=success_count, + success_times=success_times, + failure_count=failure_count, + failure_times=failure_times, + failures=list(set(failures)), + )}) + '\n') + output_file.flush() + + for t in [None] if temp is None else [t if t >= 0 else None for t in temp]: + if hf is not None: + + servers: list[Tuple[str, Optional[str]]] = [('llama-server', None)] + if llama_baseline is not None: + servers.append(('llama-server (baseline)', llama_baseline)) + + for server_name, server_path in servers: + server = ServerProcess() + server.n_ctx = n_ctx + server.n_slots = 1 + server.jinja = True + server.ctk = ctk + server.ctv = ctv + server.fa = fa + server.n_predict = n_predict + server.model_hf_repo = hf + server.model_hf_file = None + server.chat_template = chat_template + server.server_path = server_path + if port is not None: + server.server_port = port + # server.debug = True + + with scoped_server(server): + server.start(timeout_seconds=TIMEOUT_SERVER_START) + for ignore_chat_grammar in [False]: + run( + server, + server_name=server_name, + model_id=hf, + temp=t, + output_kwargs=dict( + chat_template=chat_template, + ), + request_kwargs=dict( + ignore_chat_grammar=ignore_chat_grammar, + ), + ) + + if ollama is not None: + server = ServerProcess() + server.server_port = 11434 + server.server_host = "localhost" + subprocess.check_call(["ollama", "pull", ollama]) + + with scoped_server(server): + run( + server, + server_name="ollama", + model_id=ollama, + temp=t, + output_kwargs=dict( + chat_template=None, + ), + request_kwargs=dict( + model=ollama, + max_tokens=n_predict, + num_ctx = n_ctx, + ), + ) + + +if __name__ == "__main__": + app() diff --git a/scripts/tool_bench.sh b/scripts/tool_bench.sh new file mode 100755 index 000000000..6c7616a88 --- /dev/null +++ b/scripts/tool_bench.sh @@ -0,0 +1,66 @@ +#!/bin/bash +set -euo pipefail + +cmake --build build -j + +export LLAMA_CACHE=${LLAMA_CACHE:-$HOME/Library/Caches/llama.cpp} +export LLAMA_SERVER_BIN_PATH=$PWD/build/bin/llama-server + +if [ ! -x "$LLAMA_SERVER_BIN_PATH" ]; then + echo "Could not find llama-server binary at $LLAMA_SERVER_BIN_PATH" + exit 1 +fi +if [ ! -d "$LLAMA_CACHE" ]; then + echo "Could not find llama cache at $LLAMA_CACHE, please set LLAMA_CACHE explicitly." + exit 1 +fi + +export ARGS=( + --llama-baseline="$(which llama-server)" + --n 30 + --temp -1 # Leaves temperature parameter unset (use the server's default, e.g. 0.6 for ollama) + --temp 0 + --temp 0.5 + --temp 0.75 + --temp 1 + --temp 1.5 + --temp 2 + --temp 5 + "$@" +) + +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 Coder 0.5B Q4_K_M" --output ../qwenc0.5b.jsonl --hf bartowski/Qwen2.5-Coder-0.5B-Instruct-GGUF:Q4_K_M --ollama qwen2.5-coder:0.5b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 Coder 1.5B Q4_K_M" --output ../qwenc1.5b.jsonl --hf bartowski/Qwen2.5-Coder-1.5B-Instruct-GGUF:Q4_K_M --ollama qwen2.5-coder:1.5b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 Coder 3B Q4_K_M" --output ../qwenc3b.jsonl --hf bartowski/Qwen2.5-Coder-3B-Instruct-GGUF:Q4_K_M --ollama qwen2.5-coder:3b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 Coder 7B Q4_K_M" --output ../qwenc7b.jsonl --hf bartowski/Qwen2.5-Coder-7B-Instruct-GGUF:Q4_K_M --ollama qwen2.5-coder:7b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 Coder 32B Q4_K_M" --output ../qwenc32b.jsonl --hf bartowski/Qwen2.5-Coder-32B-Instruct-GGUF:Q4_K_M --ollama qwen2.5-coder:32B-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 1.5B Q4_K_M" --output ../qwen1.5b.jsonl --hf bartowski/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M --ollama qwen2.5:1.5b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 3B Q4_K_M" --output ../qwen3b.jsonl --hf bartowski/Qwen2.5-3B-Instruct-GGUF:Q4_K_M --ollama qwen2.5:3b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Qwen 2.5 7B Q4_K_M" --output ../qwen7b.jsonl --hf bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M --ollama qwen2.5:7b-instruct-q4_K_M + +./scripts/tool_bench.py run ${ARGS[@]} --model "Llama 3.2 Instruct 1B Q4_K_M" --output ../llama1b.jsonl --hf bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_K_M --ollama llama3.2:1b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Llama 3.2 Instruct 3B Q4_K_M" --output ../llama3b.jsonl --hf bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M --ollama llama3.2:3b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Llama 3.1 Instruct 8B Q4_K_M" --output ../llama8b.jsonl --hf bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M --ollama llama3.1:8b-instruct-q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "Llama 3.3 70B Q4_K_M" --output ../llama70b.jsonl --hf bartowski/Llama-3.3-70B-Instruct-GGUF:Q4_K_M + +./scripts/tool_bench.py run ${ARGS[@]} --model "Mistral Nemo Q4_K_M" --output ../nemo.jsonl --hf bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q4_K_M --ollama mistral-nemo:12b-instruct-2407-q4_K_M + +./scripts/tool_bench.py run ${ARGS[@]} --model "Hermes 3 Llama 3.1 8B Q4_K_M" --output ../hermes3.jsonl --hf bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M --ollama hermes3:8b-llama3.1-q4_K_M --chat-template-file <( python scripts/get_chat_template.py NousResearch/Hermes-3-Llama-3.1-8B tool_use ) +./scripts/tool_bench.py run ${ARGS[@]} --model "Hermes 2 Pro Llama 3 8B Q4_K_M" --output ../hermes2.jsonl --hf bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M --ollama hermes2:8b-llama3-q4_K_M --chat-template-file <( python scripts/get_chat_template.py NousResearch/Hermes-2-Pro-Llama-3-8B tool_use ) + +./scripts/tool_bench.py run ${ARGS[@]} --model "Functionary Small V3.2 Q4_K_M" --output ../funct3.2.jsonl --hf bartowski/functionary-small-v3.2-GGUF:Q4_K_M +./scripts/tool_bench.py run ${ARGS[@]} --model "FireFunction V2 IQ1_M" --output ../firef2.jsonl --hf bartowski/firefunction-v2-GGUF:IQ1_M --chat-template-file <( python scripts/get_chat_template.py fireworks-ai/llama-3-firefunction-v2 tool_use ) + +./scripts/tool_bench.py run ${ARGS[@]} --model "Command R7B 12-2024 Q6_K_L" --output ../c4ai.jsonl --hf bartowski/c4ai-command-r7b-12-2024-GGUF:Q6_K_L --chat-template-file <( python scripts/get_chat_template.py CohereForAI/c4ai-command-r7b-12-2024 tool_use ) + +./scripts/tool_bench.py run ${ARGS[@]} --model "Gemma 2 2B Q8_0" --output ../gemma2.jsonl --hf bartowski/gemma-2-2b-it-GGUF:Q8_0 +./scripts/tool_bench.py run ${ARGS[@]} --model "Phi 4 Instruct Q4_K_M" --output ../phi4.jsonl --hf bartowski/phi-4-GGUF:Q4_K_M # --ollama phi4 +./scripts/tool_bench.py run ${ARGS[@]} --model "Phi 3.5 Mini Instruct Q4_K_M" --output ../phi3.5.jsonl --hf bartowski/Phi-3.5-mini-instruct-GGUF:Q4_K_M # --ollama phi3.5:3.8b-mini-instruct-q4_K_M + +# ./scripts/tool_bench.py run ${ARGS[@]} --model "DeepSeek R1 Distill Qwen 7B Q6_K_L" --output ../dsqw7.jsonl --hf bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q6_K_L --chat-template-file <( python scripts/get_chat_template.py NousResearch/DeepSeek-R1-Distill-Qwen-7B tool_use ) +# ./scripts/tool_bench.py run ${ARGS[@]} --model "DeepSeek R1 Distill Qwen 32B Q4_K_M" --output ../dsqw32.jsonl --hf bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF:Q4_K_M --chat-template-file <( python scripts/get_chat_template.py NousResearch/DeepSeek-R1-Distill-Qwen-32B tool_use ) + + +for f in ../*.jsonl; do + ./scripts/tool_bench.py plot "$f" --output ${f%.jsonl}.png || true +done diff --git a/src/llama-grammar.cpp b/src/llama-grammar.cpp index 98af1ba39..973b47ae0 100644 --- a/src/llama-grammar.cpp +++ b/src/llama-grammar.cpp @@ -969,7 +969,7 @@ struct llama_grammar * llama_grammar_init_impl( /* .awaiting_trigger = */ false, /* .trigger_buffer = */ "", /* .trigger_tokens = */ {}, - /* .trigger_words = */ {}, + /* .trigger_patterns = */ {}, }; } @@ -978,19 +978,15 @@ struct llama_grammar * llama_grammar_init_impl( const char * grammar_str, const char * grammar_root, bool lazy, - const char ** trigger_words, - size_t num_trigger_words, + const char ** trigger_patterns, + size_t num_trigger_patterns, const llama_token * trigger_tokens, size_t num_trigger_tokens) { llama_grammar_parser parser; // if there is a grammar, parse it - if (!parser.parse(grammar_str)) { - return nullptr; - } - - // will be empty (default) if there are parse errors - if (parser.rules.empty()) { + // rules will be empty (default) if there are parse errors + if (!parser.parse(grammar_str) || parser.rules.empty()) { fprintf(stderr, "%s: failed to parse grammar\n", __func__); return nullptr; } @@ -1054,14 +1050,16 @@ struct llama_grammar * llama_grammar_init_impl( } while (true); std::vector vec_trigger_tokens; - std::vector vec_trigger_words; + std::vector vec_trigger_patterns; for (size_t i = 0; i < num_trigger_tokens; i++) { GGML_ASSERT(trigger_tokens != nullptr); vec_trigger_tokens.push_back(trigger_tokens[i]); } - for (size_t i = 0; i < num_trigger_words; i++) { - GGML_ASSERT(trigger_words != nullptr); - vec_trigger_words.push_back(trigger_words[i]); + for (size_t i = 0; i < num_trigger_patterns; i++) { + GGML_ASSERT(trigger_patterns != nullptr); + auto & trigger = vec_trigger_patterns.emplace_back(); + trigger.pattern = trigger_patterns[i]; + trigger.regex = std::regex(trigger.pattern); } // Important: vec_rules has to be moved here, not copied, because stacks contains @@ -1076,7 +1074,7 @@ struct llama_grammar * llama_grammar_init_impl( /* .awaiting_trigger = */ lazy, /* .trigger_buffer = */ "", std::move(vec_trigger_tokens), - std::move(vec_trigger_words), + std::move(vec_trigger_patterns), }; } @@ -1089,7 +1087,7 @@ void llama_grammar_free_impl(struct llama_grammar * grammar) { } struct llama_grammar * llama_grammar_clone_impl(const struct llama_grammar & grammar) { - llama_grammar * result = new llama_grammar { + auto * result = new llama_grammar { grammar.vocab, grammar.rules, grammar.stacks, @@ -1098,7 +1096,7 @@ struct llama_grammar * llama_grammar_clone_impl(const struct llama_grammar & gra grammar.awaiting_trigger, grammar.trigger_buffer, grammar.trigger_tokens, - grammar.trigger_words, + grammar.trigger_patterns, }; // redirect elements in stacks to point to new rules @@ -1173,16 +1171,18 @@ void llama_grammar_accept_impl(struct llama_grammar & grammar, llama_token token LLAMA_LOG_DEBUG("Grammar triggered on token %u (`%s`)", token, piece.c_str()); return; } else { - // TODO: consider a smarter incremental substring search algorithm (store last position to search from). grammar.trigger_buffer += piece; - for (const auto & word : grammar.trigger_words) { - auto pos = grammar.trigger_buffer.find(word); - if (pos != std::string::npos) { + + std::smatch match; + for (const auto & trigger_pattern : grammar.trigger_patterns) { + if (std::regex_match(grammar.trigger_buffer, match, trigger_pattern.regex)) { grammar.awaiting_trigger = false; - auto constrained_str = grammar.trigger_buffer.substr(pos); + // get from the first match to the end of the string + auto constrained_str = grammar.trigger_buffer.substr(match.position(1)); + // std::string constrained_str(match[1].first, grammar.trigger_buffer.end()); grammar.trigger_buffer.clear(); llama_grammar_accept_str(grammar, constrained_str); - LLAMA_LOG_DEBUG("Grammar triggered on word `%s`", word.c_str()); + LLAMA_LOG_DEBUG("Grammar triggered on regex: '%s'\n", constrained_str.c_str()); return; } } diff --git a/src/llama-grammar.h b/src/llama-grammar.h index b143d834c..f8c291de9 100644 --- a/src/llama-grammar.h +++ b/src/llama-grammar.h @@ -3,6 +3,7 @@ #include "llama.h" #include +#include #include #include @@ -105,6 +106,11 @@ struct llama_grammar_parser { void print(FILE * file); }; +struct llama_grammar_trigger_pattern { + std::string pattern; + std::regex regex; +}; + struct llama_grammar { // note: allow null vocab for testing (not great) const llama_vocab * vocab; @@ -122,7 +128,10 @@ struct llama_grammar { bool awaiting_trigger = false; // Initialized to true for lazy grammars only std::string trigger_buffer; // Output buffered by lazy grammar. Will be cleared once trigger is found. std::vector trigger_tokens; // Tokens that trigger a lazy grammar, or tokens to force printing of (even if special). - std::vector trigger_words; + std::vector + trigger_patterns; // Regular expressions that trigger a lazy grammar. Must be a full match of the entire generated + // string, and the grammar will be given the string from the first match group onwards. + }; // @@ -141,8 +150,8 @@ struct llama_grammar * llama_grammar_init_impl( const char * grammar_str, const char * grammar_root, bool lazy, - const char ** trigger_words, - size_t num_trigger_words, + const char ** trigger_patterns, + size_t num_trigger_patterns, const llama_token * trigger_tokens, size_t num_trigger_tokens); diff --git a/src/llama-sampling.cpp b/src/llama-sampling.cpp index f40bf2db8..c25977ca3 100644 --- a/src/llama-sampling.cpp +++ b/src/llama-sampling.cpp @@ -1449,7 +1449,9 @@ static struct llama_sampler * llama_sampler_init_grammar_impl( const char ** trigger_words, size_t num_trigger_words, const llama_token * trigger_tokens, - size_t num_trigger_tokens); + size_t num_trigger_tokens, + const char ** trigger_patterns, + size_t num_trigger_patterns); static void llama_sampler_grammar_reset(struct llama_sampler * smpl) { auto * ctx = (llama_sampler_grammar *) smpl->ctx; @@ -1457,12 +1459,14 @@ static void llama_sampler_grammar_reset(struct llama_sampler * smpl) { return; } - std::vector trigger_words; - for (auto & word : ctx->grammar->trigger_words) { - trigger_words.push_back(word.c_str()); + std::vector trigger_patterns_c; + trigger_patterns_c.reserve(ctx->grammar->trigger_patterns.size()); + for (auto & trigger_pattern : ctx->grammar->trigger_patterns) { + trigger_patterns_c.push_back(trigger_pattern.pattern.c_str()); } + auto * grammar_new = llama_grammar_init_impl(ctx->grammar->vocab, ctx->grammar_str.c_str(), ctx->grammar_root.c_str(), - ctx->grammar->lazy, trigger_words.data(), trigger_words.size(), + ctx->grammar->lazy, trigger_patterns_c.data(), trigger_patterns_c.size(), ctx->grammar->trigger_tokens.data(), ctx->grammar->trigger_tokens.size()); llama_grammar_free_impl(ctx->grammar); @@ -1472,7 +1476,7 @@ static void llama_sampler_grammar_reset(struct llama_sampler * smpl) { static struct llama_sampler * llama_sampler_grammar_clone(const struct llama_sampler * smpl) { const auto * ctx = (const llama_sampler_grammar *) smpl->ctx; - auto * result = llama_sampler_init_grammar_impl(ctx->vocab, nullptr, nullptr, false, nullptr, 0, nullptr, 0); + auto * result = llama_sampler_init_grammar_impl(ctx->vocab, nullptr, nullptr, false, nullptr, 0, nullptr, 0, nullptr, 0); // copy the state { @@ -1516,15 +1520,33 @@ static struct llama_sampler * llama_sampler_init_grammar_impl( const char ** trigger_words, size_t num_trigger_words, const llama_token * trigger_tokens, - size_t num_trigger_tokens) { + size_t num_trigger_tokens, + const char ** trigger_patterns, + size_t num_trigger_patterns) { auto * ctx = new llama_sampler_grammar; if (grammar_str != nullptr && grammar_str[0] != '\0') { + // TODO: remove trigger_words support. + if (trigger_words != nullptr && num_trigger_words > 0) { + GGML_ASSERT(trigger_patterns == nullptr && num_trigger_patterns == 0); + std::string trigger_pattern("[\\s\\S]*?("); + for (size_t i = 0; i < num_trigger_words; ++i) { + static const std::regex special_chars("[.^$|()*+?\\[\\]{}\\\\]"); + if (i > 0) { + trigger_pattern += "|"; + } + trigger_pattern += std::regex_replace(trigger_words[i], special_chars, "\\$0"); + } + trigger_pattern += ")[\\s\\S]*"; + auto trigger_pattern_c = trigger_pattern.c_str(); + trigger_patterns = &trigger_pattern_c; + num_trigger_patterns = 1; + } *ctx = { /* .vocab = */ vocab, /* .grammar_str = */ grammar_str, /* .grammar_root = */ grammar_root, - /* .grammar = */ llama_grammar_init_impl(vocab, grammar_str, grammar_root, lazy, trigger_words, num_trigger_words, trigger_tokens, num_trigger_tokens), + /* .grammar = */ llama_grammar_init_impl(vocab, grammar_str, grammar_root, lazy, trigger_patterns, num_trigger_patterns, trigger_tokens, num_trigger_tokens), }; } else { *ctx = { @@ -1545,7 +1567,7 @@ struct llama_sampler * llama_sampler_init_grammar( const struct llama_vocab * vocab, const char * grammar_str, const char * grammar_root) { - return llama_sampler_init_grammar_impl(vocab, grammar_str, grammar_root, /* lazy= */ false, nullptr, 0, nullptr, 0); + return llama_sampler_init_grammar_impl(vocab, grammar_str, grammar_root, /* lazy= */ false, nullptr, 0, nullptr, 0, nullptr, 0); } struct llama_sampler * llama_sampler_init_grammar_lazy( @@ -1556,7 +1578,18 @@ struct llama_sampler * llama_sampler_init_grammar_lazy( size_t num_trigger_words, const llama_token * trigger_tokens, size_t num_trigger_tokens) { - return llama_sampler_init_grammar_impl(vocab, grammar_str, grammar_root, /* lazy= */ true, trigger_words, num_trigger_words, trigger_tokens, num_trigger_tokens); + return llama_sampler_init_grammar_impl(vocab, grammar_str, grammar_root, /* lazy= */ true, trigger_words, num_trigger_words, trigger_tokens, num_trigger_tokens, nullptr, 0); +} + +struct llama_sampler * llama_sampler_init_grammar_lazy_patterns( + const struct llama_vocab * vocab, + const char * grammar_str, + const char * grammar_root, + const char ** trigger_patterns, + size_t num_trigger_patterns, + const llama_token * trigger_tokens, + size_t num_trigger_tokens) { + return llama_sampler_init_grammar_impl(vocab, grammar_str, grammar_root, /* lazy= */ true, nullptr, 0, trigger_tokens, num_trigger_tokens, trigger_patterns, num_trigger_patterns); } // penalties diff --git a/tests/test-chat.cpp b/tests/test-chat.cpp index 643592305..35a307c63 100644 --- a/tests/test-chat.cpp +++ b/tests/test-chat.cpp @@ -237,12 +237,35 @@ static void test_templates(const struct common_chat_templates * tmpls, const std auto earliest_trigger_pos = std::string::npos; auto constrained = data.delta; for (const auto & trigger : data.params.grammar_triggers) { - auto pos = constrained.find(trigger.word); - if (pos == std::string::npos) { - continue; + size_t pos = std::string::npos; + std::smatch match; + switch (trigger.type) { + case COMMON_GRAMMAR_TRIGGER_TYPE_WORD: + { + const auto & word = trigger.value; + pos = constrained.find(word); + break; + } + case COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN: + { + const auto & pattern = trigger.value; + if (std::regex_search(constrained, match, std::regex(pattern))) { + pos = match.position(); + } + break; + } + case COMMON_GRAMMAR_TRIGGER_TYPE_PATTERN_START: + { + const auto & pattern = trigger.value; + if (std::regex_search(constrained, match, std::regex(pattern)) && match.position() == 0) { + pos = 0; + } + break; + } + default: + throw std::runtime_error("Unknown trigger type"); } - if (pos > 0 && trigger.at_start) { - fprintf(stderr, "Trigger %s not at start of message, skipping:\n\n%s\n\n", trigger.word.c_str(), constrained.c_str()); + if (pos == std::string::npos) { continue; } if (earliest_trigger_pos == std::string::npos || pos < earliest_trigger_pos) { @@ -260,7 +283,8 @@ static void test_templates(const struct common_chat_templates * tmpls, const std if (grammar_triggered && test_grammar_if_triggered && !match_string(constrained, grammar.get())) { throw std::runtime_error("Failed to match delta against grammar:\n\n" + data.delta + - "\n\nGrammar: " + data.params.grammar); + "\n\nConstrained: " + constrained + + "\n\nGrammar: " + data.params.grammar); } } } @@ -640,6 +664,93 @@ static void test_template_output_parsers() { inputs_tools) .format); + // Test parsing + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + "{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "{\"arg1\": 1}", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + "{\"arg1\": 1}\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "```xml\n" + "\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "\n" + "```", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "```xml\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "```", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "```\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "```", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "```\n" + "{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "```", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "```json\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "```", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "```json\n" + "\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}} \n" + " \n" + "``` ", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + " {\n" + " \"name\": \"special_function\", \"arguments\": {\"arg1\": 1}\n" + " }\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "\n" + " {\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}\n" + "", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "{\"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_call, common_chat_parse( + "{\n \"name\": \"special_function\", \"arguments\": {\"arg1\": 1}}", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + test_templates(tmpls.get(), end_tokens, message_assist, tools, "Hello, world!\nWhat's up?", /* expect_grammar_triggered= */ false); test_templates(tmpls.get(), end_tokens, message_assist_call, tools, "\n" @@ -789,7 +900,7 @@ static void test_template_output_parsers() { } int main(int argc, char ** argv) { - try { + // try { #ifndef _WIN32 if (argc > 1) { common_chat_templates_inputs inputs; @@ -827,8 +938,8 @@ int main(int argc, char ** argv) { std::cout << "\n[chat] All tests passed!" << '\n'; } return 0; - } catch (const std::exception & e) { - std::cerr << "Error: " << e.what() << '\n'; - return 1; - } + // } catch (const std::exception & e) { + // std::cerr << "Error: " << e.what() << '\n'; + // return 1; + // } } diff --git a/tests/test-json-schema-to-grammar.cpp b/tests/test-json-schema-to-grammar.cpp index f38994c92..4d78e9142 100755 --- a/tests/test-json-schema-to-grammar.cpp +++ b/tests/test-json-schema-to-grammar.cpp @@ -91,7 +91,7 @@ static void test_all(const std::string & lang, std::function Date: Wed, 5 Mar 2025 14:16:40 +0100 Subject: [PATCH 34/87] ci : add fetch-depth to xcframework upload (#12195) This commit adds the fetch-depth: 0 option to the checkout action in the build.yml workflow file (0 meaning that it fetches the complete history). The default value is 1 when not specified which only fetches the latest commit. This is necessary to ensure that `git rev-list --count HEAD` counts the total number of commits in the history. Currently because the default is being used the name of the xcframework artifact is always llama-b1-xcframework. --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65f068a9b..b653b1f82 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1320,6 +1320,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Build id: cmake_build From 16e4b22c5e58ee200ede913fd7b7b8ba92132ce8 Mon Sep 17 00:00:00 2001 From: Plamen Minev Date: Wed, 5 Mar 2025 17:16:01 +0200 Subject: [PATCH 35/87] ggml : fix GGMLMetalClass ODR (#12200) -- it might happen if ggml is loaded from 2 separate libraries since each one of them will expose the class. This is more of a guard since we want to use only Metal as embedded library and don't care about the other case. --- ggml/src/ggml-metal/ggml-metal.m | 49 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/ggml/src/ggml-metal/ggml-metal.m b/ggml/src/ggml-metal/ggml-metal.m index 9eb9a0db6..1f45ebad1 100644 --- a/ggml/src/ggml-metal/ggml-metal.m +++ b/ggml/src/ggml-metal/ggml-metal.m @@ -467,11 +467,13 @@ struct ggml_backend_metal_context { // for now it is easier to work in a separate file // static NSString * const msl_library_source = @"see metal.metal"; +#if !GGML_METAL_EMBED_LIBRARY // Here to assist with NSBundle Path Hack @interface GGMLMetalClass : NSObject @end @implementation GGMLMetalClass @end +#endif static void * ggml_metal_host_malloc(size_t n) { void * data = NULL; @@ -520,7 +522,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de ctx->d_queue = dispatch_queue_create("ggml-metal", DISPATCH_QUEUE_CONCURRENT); - id metal_library; + id metal_library = nil; // load library // @@ -529,19 +531,23 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de // - if not found, load the source and compile it // - if that fails, return NULL { - NSBundle * bundle = nil; -#ifdef SWIFT_PACKAGE - bundle = SWIFTPM_MODULE_BUNDLE; -#else - bundle = [NSBundle bundleForClass:[GGMLMetalClass class]]; -#endif - NSError * error = nil; + NSString * src = nil; #if GGML_METAL_EMBED_LIBRARY - const bool try_metallib = false; + GGML_LOG_INFO("%s: using embedded metal library\n", __func__); + + extern const char ggml_metallib_start[]; + extern const char ggml_metallib_end[]; + + src = [[NSString alloc] initWithBytes:ggml_metallib_start length:(ggml_metallib_end-ggml_metallib_start) encoding:NSUTF8StringEncoding]; + #else - const bool try_metallib = true; + +#ifdef SWIFT_PACKAGE + NSBundle * bundle = SWIFTPM_MODULE_BUNDLE; +#else + NSBundle * bundle = [NSBundle bundleForClass:[GGMLMetalClass class]]; #endif NSString * path_lib = [bundle pathForResource:@"default" ofType:@"metallib"]; @@ -574,7 +580,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de path_lib = default_metallib_path; } - if (try_metallib && path_lib != nil) { + if (path_lib != nil) { // pre-compiled library found NSURL * libURL = [NSURL fileURLWithPath:path_lib]; GGML_LOG_INFO("%s: loading '%s'\n", __func__, [path_lib UTF8String]); @@ -585,14 +591,6 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de return NULL; } } else { -#if GGML_METAL_EMBED_LIBRARY - GGML_LOG_INFO("%s: using embedded metal library\n", __func__); - - extern const char ggml_metallib_start[]; - extern const char ggml_metallib_end[]; - - NSString * src = [[NSString alloc] initWithBytes:ggml_metallib_start length:(ggml_metallib_end-ggml_metallib_start) encoding:NSUTF8StringEncoding]; -#else GGML_LOG_INFO("%s: default.metallib not found, loading from source\n", __func__); NSString * path_source; @@ -613,13 +611,15 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de GGML_LOG_INFO("%s: loading '%s'\n", __func__, [path_source UTF8String]); - NSString * src = [NSString stringWithContentsOfFile:path_source encoding:NSUTF8StringEncoding error:&error]; + src = [NSString stringWithContentsOfFile:path_source encoding:NSUTF8StringEncoding error:&error]; if (error) { GGML_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]); return NULL; } -#endif // GGML_METAL_EMBED_LIBRARY + } +#endif + if (!metal_library) { @autoreleasepool { // dictionary of preprocessor macros NSMutableDictionary * prep = [NSMutableDictionary dictionary]; @@ -647,10 +647,11 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de [options release]; #endif } -#if GGML_METAL_EMBED_LIBRARY - [src release]; -#endif // GGML_METAL_EMBED_LIBRARY } + +#if GGML_METAL_EMBED_LIBRARY + [src release]; +#endif // GGML_METAL_EMBED_LIBRARY } // print MTL GPU family: From 5e43f104cca1a14874e980326a506b44fde022b8 Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Wed, 5 Mar 2025 21:28:23 +0530 Subject: [PATCH 36/87] SYCL: Disable f16 Unary OPs as not supported by the kernels (#12201) --- ggml/src/ggml-sycl/ggml-sycl.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ggml/src/ggml-sycl/ggml-sycl.cpp b/ggml/src/ggml-sycl/ggml-sycl.cpp index e7304947f..6977b705e 100644 --- a/ggml/src/ggml-sycl/ggml-sycl.cpp +++ b/ggml/src/ggml-sycl/ggml-sycl.cpp @@ -41,6 +41,7 @@ #include "ggml-sycl/gemm.hpp" #include "ggml-sycl/sycl_hw.hpp" #include "ggml-sycl/getrows.hpp" +#include "ggml.h" static bool g_sycl_loaded = false; int g_ggml_sycl_debug = 0; @@ -3864,7 +3865,7 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_TANH: case GGML_UNARY_OP_EXP: - return ggml_is_contiguous(op->src[0]); + return ggml_is_contiguous(op->src[0]) && (op->src[0]->type == GGML_TYPE_F32); default: return false; } @@ -3981,23 +3982,24 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g case GGML_OP_VIEW: case GGML_OP_PERMUTE: case GGML_OP_TRANSPOSE: + return true; case GGML_OP_ADD: case GGML_OP_ADD1: - case GGML_OP_LOG: case GGML_OP_SUB: case GGML_OP_MUL: case GGML_OP_DIV: - return true; - case GGML_OP_NORM: - case GGML_OP_RMS_NORM: - case GGML_OP_GROUP_NORM: - return ggml_is_contiguous(op->src[0]); - case GGML_OP_SCALE: case GGML_OP_SQR: case GGML_OP_SQRT: case GGML_OP_SIN: case GGML_OP_COS: case GGML_OP_CLAMP: + case GGML_OP_LOG: + return (op->src[0]->type == GGML_TYPE_F32); + case GGML_OP_NORM: + case GGML_OP_RMS_NORM: + case GGML_OP_GROUP_NORM: + return ggml_is_contiguous(op->src[0]); + case GGML_OP_SCALE: return true; case GGML_OP_CONT: return op->src[0]->type != GGML_TYPE_BF16; From 07d15723470a0a5b15d8ccad1aff5b20354ffbe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20O?= Date: Thu, 6 Mar 2025 02:26:10 +0100 Subject: [PATCH 37/87] ggml-cpu: Faster IQ1 mul_mat_vec on AVX2 using BMI2 instructions (#12154) * ggml-cpu: Faster IQ1 mul_mat_vec on AVX2 using BMI2 instructions * cmake: Add GGML_BMI2 build option * ggml: enable BMI2 on relevant CPU variants * ggml-cpu: include BMI2 in backend score * ggml-cpu: register BMI2 in ggml_backend_cpu_get_features * ggml-cpu: add __BMI2__ define when using MSVC --- ggml/CMakeLists.txt | 1 + ggml/include/ggml-cpu.h | 1 + ggml/src/CMakeLists.txt | 12 +++---- ggml/src/ggml-cpu/CMakeLists.txt | 8 +++++ ggml/src/ggml-cpu/cpu-feats-x86.cpp | 4 +++ ggml/src/ggml-cpu/ggml-cpu-quants.c | 49 ++++++++++++++++++++++------- ggml/src/ggml-cpu/ggml-cpu.c | 8 +++++ ggml/src/ggml-cpu/ggml-cpu.cpp | 3 ++ 8 files changed, 68 insertions(+), 18 deletions(-) diff --git a/ggml/CMakeLists.txt b/ggml/CMakeLists.txt index 92a62ea6f..412d294dc 100644 --- a/ggml/CMakeLists.txt +++ b/ggml/CMakeLists.txt @@ -106,6 +106,7 @@ option(GGML_CPU_KLEIDIAI "ggml: use KleidiAI optimized kernels if applicable option(GGML_AVX "ggml: enable AVX" ${INS_ENB}) option(GGML_AVX_VNNI "ggml: enable AVX-VNNI" OFF) option(GGML_AVX2 "ggml: enable AVX2" ${INS_ENB}) +option(GGML_BMI2 "ggml: enable BMI2" ${INS_ENB}) option(GGML_AVX512 "ggml: enable AVX512F" OFF) option(GGML_AVX512_VBMI "ggml: enable AVX512-VBMI" OFF) option(GGML_AVX512_VNNI "ggml: enable AVX512-VNNI" OFF) diff --git a/ggml/include/ggml-cpu.h b/ggml/include/ggml-cpu.h index b48cc560e..f5e11f1e1 100644 --- a/ggml/include/ggml-cpu.h +++ b/ggml/include/ggml-cpu.h @@ -80,6 +80,7 @@ extern "C" { GGML_BACKEND_API int ggml_cpu_has_avx (void); GGML_BACKEND_API int ggml_cpu_has_avx_vnni (void); GGML_BACKEND_API int ggml_cpu_has_avx2 (void); + GGML_BACKEND_API int ggml_cpu_has_bmi2 (void); GGML_BACKEND_API int ggml_cpu_has_f16c (void); GGML_BACKEND_API int ggml_cpu_has_fma (void); GGML_BACKEND_API int ggml_cpu_has_avx512 (void); diff --git a/ggml/src/CMakeLists.txt b/ggml/src/CMakeLists.txt index fcb354e16..cfd4ac54c 100644 --- a/ggml/src/CMakeLists.txt +++ b/ggml/src/CMakeLists.txt @@ -289,7 +289,7 @@ function(ggml_add_cpu_backend_variant tag_name) set(GGML_CPU_TAG_NAME ${tag_name}) # other: OPENMP LLAMAFILE CPU_HBM foreach (feat NATIVE - AVX AVX2 AVX_VNNI FMA F16C + AVX AVX2 BMI2 AVX_VNNI FMA F16C AVX512 AVX512_VBMI AVX512_VNNI AVX512_BF16 AMX_TILE AMX_INT8 AMX_BF16) set(GGML_${feat} OFF) @@ -309,13 +309,13 @@ if (GGML_CPU_ALL_VARIANTS) message(FATAL_ERROR "GGML_CPU_ALL_VARIANTS requires GGML_BACKEND_DL") endif() ggml_add_cpu_backend_variant(sandybridge AVX) - ggml_add_cpu_backend_variant(haswell AVX F16C AVX2 FMA) - ggml_add_cpu_backend_variant(skylakex AVX F16C AVX2 FMA AVX512) - ggml_add_cpu_backend_variant(icelake AVX F16C AVX2 FMA AVX512 AVX512_VBMI AVX512_VNNI) - ggml_add_cpu_backend_variant(alderlake AVX F16C AVX2 FMA AVX_VNNI) + ggml_add_cpu_backend_variant(haswell AVX F16C AVX2 BMI2 FMA) + ggml_add_cpu_backend_variant(skylakex AVX F16C AVX2 BMI2 FMA AVX512) + ggml_add_cpu_backend_variant(icelake AVX F16C AVX2 BMI2 FMA AVX512 AVX512_VBMI AVX512_VNNI) + ggml_add_cpu_backend_variant(alderlake AVX F16C AVX2 BMI2 FMA AVX_VNNI) if (NOT MSVC) # MSVC doesn't support AMX - ggml_add_cpu_backend_variant(sapphirerapids AVX F16C AVX2 FMA AVX512 AVX512_VBMI AVX512_VNNI AVX512_BF16 AMX_TILE AMX_INT8) + ggml_add_cpu_backend_variant(sapphirerapids AVX F16C AVX2 BMI2 FMA AVX512 AVX512_VBMI AVX512_VNNI AVX512_BF16 AMX_TILE AMX_INT8) endif() elseif (GGML_CPU) ggml_add_cpu_backend_variant_impl("") diff --git a/ggml/src/ggml-cpu/CMakeLists.txt b/ggml/src/ggml-cpu/CMakeLists.txt index f8836ed61..d6c4a9c29 100644 --- a/ggml/src/ggml-cpu/CMakeLists.txt +++ b/ggml/src/ggml-cpu/CMakeLists.txt @@ -219,6 +219,10 @@ function(ggml_add_cpu_backend_variant_impl tag_name) if (GGML_AVX_VNNI) list(APPEND ARCH_DEFINITIONS __AVXVNNI__ GGML_AVX_VNNI) endif() + if (GGML_BMI2) + # MSVC does not define macro __BMI2__ + list(APPEND ARCH_DEFINITIONS __BMI2__ GGML_BMI2) + endif() else () if (GGML_NATIVE) list(APPEND ARCH_FLAGS -march=native) @@ -233,6 +237,10 @@ function(ggml_add_cpu_backend_variant_impl tag_name) list(APPEND ARCH_FLAGS -mfma) list(APPEND ARCH_DEFINITIONS GGML_FMA) endif() + if (GGML_BMI2) + list(APPEND ARCH_FLAGS -mbmi2) + list(APPEND ARCH_DEFINITIONS GGML_BMI2) + endif() if (GGML_AVX) list(APPEND ARCH_FLAGS -mavx) list(APPEND ARCH_DEFINITIONS GGML_AVX) diff --git a/ggml/src/ggml-cpu/cpu-feats-x86.cpp b/ggml/src/ggml-cpu/cpu-feats-x86.cpp index e8133d411..902ee4346 100644 --- a/ggml/src/ggml-cpu/cpu-feats-x86.cpp +++ b/ggml/src/ggml-cpu/cpu-feats-x86.cpp @@ -278,6 +278,10 @@ static int ggml_backend_cpu_x86_score() { if (!is.SSE42()) { return 0; } score += 1<<2; #endif +#ifdef GGML_BMI2 + if (!is.BMI2()) { return 0; } + score += 1<<3; +#endif #ifdef GGML_AVX if (!is.AVX()) { return 0; } score += 1<<4; diff --git a/ggml/src/ggml-cpu/ggml-cpu-quants.c b/ggml/src/ggml-cpu/ggml-cpu-quants.c index c30ac0318..2ae66591d 100644 --- a/ggml/src/ggml-cpu/ggml-cpu-quants.c +++ b/ggml/src/ggml-cpu/ggml-cpu-quants.c @@ -11362,10 +11362,19 @@ void ggml_vec_dot_iq1_s_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const __m256i sumi = _mm256_setzero_si256(); int sumi1 = 0; for (int ib = 0; ib < QK_K/32; ib += 2) { +#ifdef __BMI2__ + const uint64_t packed_idx1 = _pdep_u64(*(const uint32_t *)qs, 0x00ff00ff00ff00ffULL) | _pdep_u64(qh[ib], 0x700070007000700ULL); + const uint64_t packed_idx2 = _pdep_u64(*(const uint32_t *)(qs + 4), 0x00ff00ff00ff00ffULL) | _pdep_u64(qh[ib + 1], 0x700070007000700ULL); + const uint16_t *idx1 = (const uint16_t *)(&packed_idx1); + const uint16_t *idx2 = (const uint16_t *)(&packed_idx2); + const __m256i q1b_1 = _mm256_set_epi64x(iq1s_grid[idx1[3]], iq1s_grid[idx1[2]], iq1s_grid[idx1[1]], iq1s_grid[idx1[0]]); + const __m256i q1b_2 = _mm256_set_epi64x(iq1s_grid[idx2[3]], iq1s_grid[idx2[2]], iq1s_grid[idx2[1]], iq1s_grid[idx2[0]]); +#else const __m256i q1b_1 = _mm256_set_epi64x(iq1s_grid[qs[3] | ((qh[ib+0] >> 1) & 0x700)], iq1s_grid[qs[2] | ((qh[ib+0] << 2) & 0x700)], iq1s_grid[qs[1] | ((qh[ib+0] << 5) & 0x700)], iq1s_grid[qs[0] | ((qh[ib+0] << 8) & 0x700)]); const __m256i q1b_2 = _mm256_set_epi64x(iq1s_grid[qs[7] | ((qh[ib+1] >> 1) & 0x700)], iq1s_grid[qs[6] | ((qh[ib+1] << 2) & 0x700)], iq1s_grid[qs[5] | ((qh[ib+1] << 5) & 0x700)], iq1s_grid[qs[4] | ((qh[ib+1] << 8) & 0x700)]); +#endif qs += 8; const __m256i q8b_1 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32; const __m256i q8b_2 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32; @@ -11709,8 +11718,9 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const #elif defined __AVX2__ - const __m256i mask = _mm256_set1_epi16(0x7); + const __m256i mask = _mm256_set1_epi16(2 * 0x7); const __m256i mone = _mm256_set1_epi16(1); + const __m256i mone8 = _mm256_set1_epi8(1); __m256 accum1 = _mm256_setzero_ps(); __m256 accum2 = _mm256_setzero_ps(); @@ -11726,6 +11736,21 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const __m256i sumi1 = _mm256_setzero_si256(); __m256i sumi2 = _mm256_setzero_si256(); for (int ib = 0; ib < QK_K/32; ib += 2) { +#ifdef __BMI2__ + const uint64_t packed_idx1 = _pdep_u64(*(const uint32_t *)qs, 0x00ff00ff00ff00ffULL) + | _pdep_u64(*(const uint16_t*)(qh) & 0x7777, 0xf000f000f000f00ULL); + const uint64_t packed_idx2 = _pdep_u64(*(const uint32_t *)(qs + 4), 0x00ff00ff00ff00ffULL) + | _pdep_u64(*(const uint16_t*)(qh + 2) & 0x7777, 0xf000f000f000f00ULL); + const uint16_t *idx1 = (const uint16_t *)(&packed_idx1); + const uint16_t *idx2 = (const uint16_t *)(&packed_idx2); + const __m256i q1b_1 = _mm256_set_epi64x(iq1s_grid[idx1[3]], iq1s_grid[idx1[2]], iq1s_grid[idx1[1]], iq1s_grid[idx1[0]]); + const __m256i q1b_2 = _mm256_set_epi64x(iq1s_grid[idx2[3]], iq1s_grid[idx2[2]], iq1s_grid[idx2[1]], iq1s_grid[idx2[0]]); + + // Convert signs to bytes 0x81 (negative) or 0x01 (positive) + const uint64_t delta_sign = _pdep_u64(*(const uint32_t*)(qh) & 0x88888888, 0xf0f0f0f0f0f0f0f0ULL); + const __m256i delta1 = _mm256_or_si256(mone8, _mm256_cvtepi8_epi64(_mm_set1_epi32(delta_sign))); + const __m256i delta2 = _mm256_or_si256(mone8, _mm256_cvtepi8_epi64(_mm_set1_epi32(delta_sign >> 32))); +#else const __m256i q1b_1 = _mm256_set_epi64x( iq1s_grid[qs[3] | (((uint16_t)qh[1] << 4) & 0x700)], iq1s_grid[qs[2] | (((uint16_t)qh[1] << 8) & 0x700)], iq1s_grid[qs[1] | (((uint16_t)qh[0] << 4) & 0x700)], iq1s_grid[qs[0] | (((uint16_t)qh[0] << 8) & 0x700)] @@ -11734,11 +11759,6 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const iq1s_grid[qs[7] | (((uint16_t)qh[3] << 4) & 0x700)], iq1s_grid[qs[6] | (((uint16_t)qh[3] << 8) & 0x700)], iq1s_grid[qs[5] | (((uint16_t)qh[2] << 4) & 0x700)], iq1s_grid[qs[4] | (((uint16_t)qh[2] << 8) & 0x700)] ); - const __m256i q8b_1 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32; - const __m256i q8b_2 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32; - - const __m256i dot1 = mul_add_epi8(q1b_1, q8b_1); - const __m256i dot2 = mul_add_epi8(q1b_2, q8b_2); const __m256i delta1 = _mm256_set_epi64x(qh[1] & 0x80 ? 0xffffffffffffffff : 0x0101010101010101, qh[1] & 0x08 ? 0xffffffffffffffff : 0x0101010101010101, @@ -11748,15 +11768,20 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const qh[3] & 0x08 ? 0xffffffffffffffff : 0x0101010101010101, qh[2] & 0x80 ? 0xffffffffffffffff : 0x0101010101010101, qh[2] & 0x08 ? 0xffffffffffffffff : 0x0101010101010101); +#endif + const __m256i q8b_1 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32; + const __m256i q8b_2 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32; - const __m256i dot3 = mul_add_epi8(delta1, q8b_1); - const __m256i dot4 = mul_add_epi8(delta2, q8b_2); + const __m256i dot1 = mul_add_epi8(q1b_1, q8b_1); + const __m256i dot2 = mul_add_epi8(q1b_2, q8b_2); + const __m256i dot3 = _mm256_maddubs_epi16(mone8, _mm256_sign_epi8(q8b_1, delta1)); + const __m256i dot4 = _mm256_maddubs_epi16(mone8, _mm256_sign_epi8(q8b_2, delta2)); - __m256i scale1 = MM256_SET_M128I(_mm_set1_epi16(sc[ib/2] >> 3), _mm_set1_epi16(sc[ib/2] >> 0)); - __m256i scale2 = MM256_SET_M128I(_mm_set1_epi16(sc[ib/2] >> 9), _mm_set1_epi16(sc[ib/2] >> 6)); + __m256i scale1 = MM256_SET_M128I(_mm_set1_epi16(sc[ib/2] >> 2), _mm_set1_epi16(sc[ib/2] << 1)); + __m256i scale2 = MM256_SET_M128I(_mm_set1_epi16(sc[ib/2] >> 8), _mm_set1_epi16(sc[ib/2] >> 5)); - scale1 = _mm256_add_epi16(_mm256_slli_epi16(_mm256_and_si256(scale1, mask), 1), mone); - scale2 = _mm256_add_epi16(_mm256_slli_epi16(_mm256_and_si256(scale2, mask), 1), mone); + scale1 = _mm256_add_epi16(_mm256_and_si256(scale1, mask), mone); + scale2 = _mm256_add_epi16(_mm256_and_si256(scale2, mask), mone); const __m256i p1 = _mm256_madd_epi16(dot1, scale1); const __m256i p2 = _mm256_madd_epi16(dot2, scale2); const __m256i p3 = _mm256_madd_epi16(dot3, scale1); diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c index 2a5463fdf..c67fdd045 100644 --- a/ggml/src/ggml-cpu/ggml-cpu.c +++ b/ggml/src/ggml-cpu/ggml-cpu.c @@ -15440,6 +15440,14 @@ int ggml_cpu_has_amx_int8(void) { #endif } +int ggml_cpu_has_bmi2(void) { +#if defined(__BMI2__) + return 1; +#else + return 0; +#endif +} + int ggml_cpu_has_fma(void) { #if defined(__FMA__) return 1; diff --git a/ggml/src/ggml-cpu/ggml-cpu.cpp b/ggml/src/ggml-cpu/ggml-cpu.cpp index a84203f29..09f8382b9 100644 --- a/ggml/src/ggml-cpu/ggml-cpu.cpp +++ b/ggml/src/ggml-cpu/ggml-cpu.cpp @@ -511,6 +511,9 @@ static ggml_backend_feature * ggml_backend_cpu_get_features(ggml_backend_reg_t r if (ggml_cpu_has_fma()) { features.push_back({ "FMA", "1" }); } + if (ggml_cpu_has_bmi2()) { + features.push_back({ "BMI2", "1" }); + } if (ggml_cpu_has_avx512()) { features.push_back({ "AVX512", "1" }); } From ed4ce0dda24986c80d58e2ce112049af00f632f4 Mon Sep 17 00:00:00 2001 From: simon886212 <37953122+simon886212@users.noreply.github.com> Date: Thu, 6 Mar 2025 09:30:05 +0800 Subject: [PATCH 38/87] opencl : fix profile-related errors (#12095) Co-authored-by: ubuntu --- ggml/src/ggml-opencl/ggml-opencl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ggml/src/ggml-opencl/ggml-opencl.cpp b/ggml/src/ggml-opencl/ggml-opencl.cpp index dc9a718f7..9a76da43b 100644 --- a/ggml/src/ggml-opencl/ggml-opencl.cpp +++ b/ggml/src/ggml-opencl/ggml-opencl.cpp @@ -278,7 +278,7 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { cl_int err; -#ifdef GGML_PROFILE_OPENCL +#ifdef GGML_OPENCL_PROFILING GGML_LOG_INFO("ggml_opencl: OpenCL profiling enabled\n"); #endif @@ -3023,6 +3023,7 @@ static void ggml_cl_mul_mat(ggml_backend_t backend, const ggml_tensor * src0, co // enqueue kernel with profiling // <--------------------------------------------> // #ifdef GGML_OPENCL_PROFILING + cl_event evt; CL_CHECK(clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global_work_size, local_work_size, 0, NULL, &evt)); g_profiling_info.emplace_back(); From f79243992cd31e4e4844d5158d2f3325b1d2d811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henry=20Linjam=C3=A4ki?= Date: Thu, 6 Mar 2025 03:31:14 +0200 Subject: [PATCH 39/87] opencl : fix `ulong` kernel args were set from `int` variables (#12174) ... which left garbage bits in the upper half of the kernel args. This caused segmentation faults when running PoCL. --- ggml/src/ggml-opencl/ggml-opencl.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ggml/src/ggml-opencl/ggml-opencl.cpp b/ggml/src/ggml-opencl/ggml-opencl.cpp index 9a76da43b..340284086 100644 --- a/ggml/src/ggml-opencl/ggml-opencl.cpp +++ b/ggml/src/ggml-opencl/ggml-opencl.cpp @@ -3765,10 +3765,10 @@ static void ggml_cl_rope(ggml_backend_t backend, const ggml_tensor * src0, const const int ne02 = src0 ? src0->ne[2] : 0; const int ne03 = src0 ? src0->ne[3] : 0; - const int nb00 = src0 ? src0->nb[0] : 0; - const int nb01 = src0 ? src0->nb[1] : 0; - const int nb02 = src0 ? src0->nb[2] : 0; - const int nb03 = src0 ? src0->nb[3] : 0; + const cl_ulong nb00 = src0 ? src0->nb[0] : 0; + const cl_ulong nb01 = src0 ? src0->nb[1] : 0; + const cl_ulong nb02 = src0 ? src0->nb[2] : 0; + const cl_ulong nb03 = src0 ? src0->nb[3] : 0; const int ne10 = src1 ? src1->ne[0] : 0; const int ne11 = src1 ? src1->ne[1] : 0; UNUSED(ne11); @@ -3780,10 +3780,10 @@ static void ggml_cl_rope(ggml_backend_t backend, const ggml_tensor * src0, const const int ne2 = dst ? dst->ne[2] : 0; const int ne3 = dst ? dst->ne[3] : 0; - const int nb0 = dst ? dst->nb[0] : 0; - const int nb1 = dst ? dst->nb[1] : 0; - const int nb2 = dst ? dst->nb[2] : 0; - const int nb3 = dst ? dst->nb[3] : 0; + const cl_ulong nb0 = dst ? dst->nb[0] : 0; + const cl_ulong nb1 = dst ? dst->nb[1] : 0; + const cl_ulong nb2 = dst ? dst->nb[2] : 0; + const cl_ulong nb3 = dst ? dst->nb[3] : 0; GGML_ASSERT(ne10 % ne02 == 0); GGML_ASSERT(ne10 >= ne02); From 94bb63e4f0f6135579b88e5700ed40cefa374e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henry=20Linjam=C3=A4ki?= Date: Thu, 6 Mar 2025 03:33:40 +0200 Subject: [PATCH 40/87] opencl : fix buffer alignment (#12197) Fix the following error: ``` ggml-alloc.c:99: not enough space in the buffer ggml_tallocr_alloc: not enough space in the buffer to allocate blk.17.ffn_down.weight (needed 27525120, available 27521024) ``` which occurs when `ggml_backend_opencl_context::alignment` is larger than `cl_ptr_base` (hard-coded to `0x1000`). Also, fix `ggml_backend_opencl_context::alignment` was set to `CL_DEVICE_MEM_BASE_ADDR_ALIGN` which was treated as bytes but the value is reported in bits. --- ggml/src/ggml-opencl/ggml-opencl.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ggml/src/ggml-opencl/ggml-opencl.cpp b/ggml/src/ggml-opencl/ggml-opencl.cpp index 340284086..bc2ea06b5 100644 --- a/ggml/src/ggml-opencl/ggml-opencl.cpp +++ b/ggml/src/ggml-opencl/ggml-opencl.cpp @@ -524,7 +524,10 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { return backend_ctx; } - CL_CHECK(clGetDeviceInfo(device, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(cl_uint), &backend_ctx->alignment, NULL)); + cl_uint base_align_in_bits; + CL_CHECK(clGetDeviceInfo(device, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(cl_uint), &base_align_in_bits, NULL)); + GGML_ASSERT(base_align_in_bits % 8u == 0); + backend_ctx->alignment = base_align_in_bits / 8u; GGML_LOG_INFO("ggml_opencl: mem base addr align: %u\n", backend_ctx->alignment); clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(size_t), &backend_ctx->max_alloc_size, NULL); @@ -1198,17 +1201,14 @@ struct ggml_backend_opencl_buffer_context { std::string name; }; -static void * const cl_ptr_base = (void *)(uintptr_t) 0x1000; - static void ggml_backend_opencl_buffer_free_buffer(ggml_backend_buffer_t buffer) { ggml_backend_opencl_buffer_context * ctx = (ggml_backend_opencl_buffer_context *) buffer->context; delete ctx; } static void * ggml_backend_opencl_buffer_get_base(ggml_backend_buffer_t buffer) { - return cl_ptr_base; - - GGML_UNUSED(buffer); + ggml_backend_opencl_context * backend_ctx = ggml_cl2_init(buffer->buft->device); + return (void *) (uintptr_t) backend_ctx->alignment; } static enum ggml_status ggml_backend_opencl_buffer_init_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor) { @@ -1241,7 +1241,7 @@ static enum ggml_status ggml_backend_opencl_buffer_init_tensor(ggml_backend_buff tensor->extra = view_extra; } else { { - size_t offset = (char *)tensor->data - (char *)cl_ptr_base; + size_t offset = (char *) tensor->data - (char *) ggml_backend_opencl_buffer_get_base(buffer); ggml_tensor_extra_cl * extra = ctx->ggml_opencl_alloc_temp_tensor_extra(); extra->offset = offset; From 57b6abf85acb1f697913a44e5e105e333d894b78 Mon Sep 17 00:00:00 2001 From: Han Yin Date: Wed, 5 Mar 2025 22:22:49 -0800 Subject: [PATCH 41/87] android : fix KV cache log message condition (#12212) --- examples/llama.android/llama/src/main/cpp/llama-android.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/llama.android/llama/src/main/cpp/llama-android.cpp b/examples/llama.android/llama/src/main/cpp/llama-android.cpp index 2a73983a9..0de61ce77 100644 --- a/examples/llama.android/llama/src/main/cpp/llama-android.cpp +++ b/examples/llama.android/llama/src/main/cpp/llama-android.cpp @@ -361,7 +361,7 @@ Java_android_llama_cpp_LLamaAndroid_completion_1init( const auto tokens_list = common_tokenize(context, text, true, parse_special); auto n_ctx = llama_n_ctx(context); - auto n_kv_req = tokens_list.size() + (n_len - tokens_list.size()); + auto n_kv_req = tokens_list.size() + n_len; LOGi("n_len = %d, n_ctx = %d, n_kv_req = %d", n_len, n_ctx, n_kv_req); From e721c05c9336a72fbb59d5c75967360bc67036c6 Mon Sep 17 00:00:00 2001 From: uvos Date: Thu, 6 Mar 2025 08:20:52 +0100 Subject: [PATCH 42/87] HIP/CUDA: set the paramerter value in maintain_cuda_graph instead of replaceing it. (#12209) This avoids conflict with internal cuda/hip runtimes memory managment behavior. --- ggml/src/ggml-cuda/ggml-cuda.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ggml/src/ggml-cuda/ggml-cuda.cu b/ggml/src/ggml-cuda/ggml-cuda.cu index b5d2c8411..497de37be 100644 --- a/ggml/src/ggml-cuda/ggml-cuda.cu +++ b/ggml/src/ggml-cuda/ggml-cuda.cu @@ -2571,7 +2571,7 @@ static void maintain_cuda_graph(ggml_backend_cuda_context * cuda_ctx, std::vecto for (size_t i = 0; i < cuda_ctx->cuda_graph->num_nodes; i++) { if(count(ggml_cuda_cpy_fn_ptrs.begin(), ggml_cuda_cpy_fn_ptrs.end(), cuda_ctx->cuda_graph->params[i].func) > 0) { char ** updated_kernel_arg_ptr = cuda_ctx->cuda_graph->updated_kernel_arg.at(k++); - cuda_ctx->cuda_graph->params[i].kernelParams[1] = updated_kernel_arg_ptr; + *(void**)cuda_ctx->cuda_graph->params[i].kernelParams[1] = *(void**)updated_kernel_arg_ptr; CUDA_CHECK(cudaGraphKernelNodeSetParams(cuda_ctx->cuda_graph->nodes[i], &cuda_ctx->cuda_graph->params[i])); } } From e9b2f84f145fbd458dcb98f227bd09370918be6e Mon Sep 17 00:00:00 2001 From: Aaron Teo <57927438+taronaeo@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:33:21 +0800 Subject: [PATCH 43/87] llava: add big-endian conversion for image encoder (#12218) Signed-off-by: Aaron Teo --- examples/llava/convert_image_encoder_to_gguf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/llava/convert_image_encoder_to_gguf.py b/examples/llava/convert_image_encoder_to_gguf.py index de29687ec..2949faec4 100644 --- a/examples/llava/convert_image_encoder_to_gguf.py +++ b/examples/llava/convert_image_encoder_to_gguf.py @@ -89,6 +89,7 @@ def bytes_to_unicode(): ap = argparse.ArgumentParser() ap.add_argument("-m", "--model-dir", help="Path to model directory cloned from HF Hub", required=True) ap.add_argument("--use-f32", action="store_true", default=False, help="Use f32 instead of f16") +ap.add_argument('--bigendian', action="store_true", default=False, help="Model is executed on big-endian machine") ap.add_argument("--text-only", action="store_true", required=False, help="Save a text-only model. It can't be used to encode images") ap.add_argument("--vision-only", action="store_true", required=False, @@ -191,7 +192,7 @@ output_dir = args.output_dir if args.output_dir is not None else dir_model os.makedirs(output_dir, exist_ok=True) output_prefix = os.path.basename(output_dir).replace("ggml_", "") fname_out = os.path.join(output_dir, f"{fname_middle}model-{ftype_str[ftype]}.gguf") -fout = GGUFWriter(path=fname_out, arch="clip") +fout = GGUFWriter(path=fname_out, arch="clip", endianess=GGUFEndian.LITTLE if not args.bigendian else GGUFEndian.BIG) fout.add_bool("clip.has_text_encoder", has_text_encoder) fout.add_bool("clip.has_vision_encoder", has_vision_encoder) From 42994048a34b0bddd72b57c26f8ae2c7d417946d Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Thu, 6 Mar 2025 09:03:31 +0000 Subject: [PATCH 44/87] update function-calling.md w/ template override for functionary-small-v3.2 (#12214) --- docs/function-calling.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/function-calling.md b/docs/function-calling.md index 92cb6531a..c3873c3fa 100644 --- a/docs/function-calling.md +++ b/docs/function-calling.md @@ -287,30 +287,32 @@ Here are some models known to work (w/ chat template override when needed): llama-server --jinja -fa -hf bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M llama-server --jinja -fa -hf bartowski/Mistral-Nemo-Instruct-2407-GGUF:Q6_K_L -llama-server --jinja -fa -hf bartowski/functionary-small-v3.2-GGUF:Q4_K_M llama-server --jinja -fa -hf bartowski/Llama-3.3-70B-Instruct-GGUF:Q4_K_M -# Native support for DeepSeek R1 works best w/ our own template (official template buggy) +# Native support for DeepSeek R1 works best w/ our template override (official template is buggy, although we do work around it) llama-server --jinja -fa -hf bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF:Q6_K_L \ ---chat-template-file models/templates/llama-cpp-deepseek-r1.jinja + --chat-template-file models/templates/llama-cpp-deepseek-r1.jinja llama-server --jinja -fa -hf bartowski/DeepSeek-R1-Distill-Qwen-32B-GGUF:Q4_K_M \ ---chat-template-file models/templates/llama-cpp-deepseek-r1.jinja + --chat-template-file models/templates/llama-cpp-deepseek-r1.jinja # Native support requires the right template for these GGUFs: +llama-server --jinja -fa -hf bartowski/functionary-small-v3.2-GGUF:Q4_K_M + --chat-template-file models/templates/meetkai-functionary-medium-v3.2.jinja + llama-server --jinja -fa -hf bartowski/Hermes-2-Pro-Llama-3-8B-GGUF:Q4_K_M \ ---chat-template-file <( python scripts/get_chat_template.py NousResearch/Hermes-2-Pro-Llama-3-8B tool_use ) + --chat-template-file models/templates/NousResearch-Hermes-2-Pro-Llama-3-8B-tool_use.jinja llama-server --jinja -fa -hf bartowski/Hermes-3-Llama-3.1-8B-GGUF:Q4_K_M \ ---chat-template-file <( python scripts/get_chat_template.py NousResearch/Hermes-3-Llama-3.1-8B tool_use ) + --chat-template-file models/templates/NousResearch-Hermes-3-Llama-3.1-8B-tool_use.jinja llama-server --jinja -fa -hf bartowski/firefunction-v2-GGUF -hff firefunction-v2-IQ1_M.gguf \ ---chat-template-file <( python scripts/get_chat_template.py fireworks-ai/llama-3-firefunction-v2 tool_use ) + --chat-template-file models/templates/fireworks-ai-llama-3-firefunction-v2.jinja llama-server --jinja -fa -hf bartowski/c4ai-command-r7b-12-2024-GGUF:Q6_K_L \ ---chat-template-file <( python scripts/get_chat_template.py CohereForAI/c4ai-command-r7b-12-2024 tool_use ) + --chat-template-file models/templates/CohereForAI-c4ai-command-r7b-12-2024-tool_use.jinja # Generic format support llama-server --jinja -fa -hf bartowski/phi-4-GGUF:Q4_0 @@ -318,6 +320,8 @@ llama-server --jinja -fa -hf bartowski/gemma-2-2b-it-GGUF:Q8_0 llama-server --jinja -fa -hf bartowski/c4ai-command-r-v01-GGUF:Q2_K ``` +To get the official template from original HuggingFace repos, you can use [scripts/get_chat_template.py](../scripts/get_chat_template.py) (see examples invocations in [models/templates/README.md](../models/templates/README.md)) + > [!TIP] > If there is no official `tool_use` Jinja template, you may want to set `--chat-template chatml` to use a default that works with many models (YMMV!), or write your own (e.g. we provide a custom [llama-cpp-deepseek-r1.jinja](../models/templates/llama-cpp-deepseek-r1.jinja) for DeepSeek R1 distills) From 3ffbbd5ce130859be91909e9b77d4c1962a6be2c Mon Sep 17 00:00:00 2001 From: David Huang <1969802+hjc4869@users.noreply.github.com> Date: Thu, 6 Mar 2025 21:14:11 +0800 Subject: [PATCH 45/87] HIP: rocWMMA documentation and enabling in workflow builds (#12179) * Enable rocWMMA for Windows CI build * Enable for Ubuntu * GGML_HIP_ROCWMMA_FATTN documentation work --- .github/workflows/build.yml | 16 ++++++++++++++++ docs/build.md | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b653b1f82..7e4596ab2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -467,6 +467,7 @@ jobs: run: | cmake -B build -S . \ -DCMAKE_HIP_COMPILER="$(hipconfig -l)/clang" \ + -DGGML_HIP_ROCWMMA_FATTN=ON \ -DGGML_HIP=ON cmake --build build --config Release -j $(nproc) @@ -476,6 +477,7 @@ jobs: cmake -B build2 -S . \ -DCMAKE_C_COMPILER=hipcc \ -DCMAKE_CXX_COMPILER=hipcc \ + -DGGML_HIP_ROCWMMA_FATTN=ON \ -DGGML_HIP=ON cmake --build build2 --config Release -j $(nproc) @@ -1202,6 +1204,11 @@ jobs: id: checkout uses: actions/checkout@v4 + - name: Clone rocWMMA repository + id: clone_rocwmma + run: | + git clone https://github.com/rocm/rocwmma --branch rocm-6.2.4 --depth 1 + - name: Install id: depends run: | @@ -1231,8 +1238,10 @@ jobs: cmake -G "Unix Makefiles" -B build -S . ` -DCMAKE_C_COMPILER="${env:HIP_PATH}\bin\clang.exe" ` -DCMAKE_CXX_COMPILER="${env:HIP_PATH}\bin\clang++.exe" ` + -DCMAKE_CXX_FLAGS="-Irocwmma/library/include/" ` -DCMAKE_BUILD_TYPE=Release ` -DGGML_HIP=ON ` + -DGGML_HIP_ROCWMMA_FATTN=ON ` -DGGML_RPC=ON cmake --build build -j ${env:NUMBER_OF_PROCESSORS} @@ -1251,6 +1260,11 @@ jobs: with: fetch-depth: 0 + - name: Clone rocWMMA repository + id: clone_rocwmma + run: | + git clone https://github.com/rocm/rocwmma --branch rocm-6.2.4 --depth 1 + - name: ccache uses: hendrikmuhs/ccache-action@v1.2.16 with: @@ -1280,8 +1294,10 @@ jobs: cmake -G "Unix Makefiles" -B build -S . ` -DCMAKE_C_COMPILER="${env:HIP_PATH}\bin\clang.exe" ` -DCMAKE_CXX_COMPILER="${env:HIP_PATH}\bin\clang++.exe" ` + -DCMAKE_CXX_FLAGS="-Irocwmma/library/include/" ` -DCMAKE_BUILD_TYPE=Release ` -DAMDGPU_TARGETS=${{ matrix.gpu_target }} ` + -DGGML_HIP_ROCWMMA_FATTN=ON ` -DGGML_HIP=ON ` -DGGML_RPC=ON cmake --build build -j ${env:NUMBER_OF_PROCESSORS} diff --git a/docs/build.md b/docs/build.md index b3ecf043d..3d8333328 100644 --- a/docs/build.md +++ b/docs/build.md @@ -235,6 +235,12 @@ You can download it from your Linux distro's package manager or from here: [ROCm On Linux it is also possible to use unified memory architecture (UMA) to share main memory between the CPU and integrated GPU by setting `-DGGML_HIP_UMA=ON`. However, this hurts performance for non-integrated GPUs (but enables working with integrated GPUs). + To enhance flash attention performance on RDNA3+ or CDNA architectures, you can utilize the rocWMMA library by enabling the `-DGGML_HIP_ROCWMMA_FATTN=ON` option. This requires rocWMMA headers to be installed on the build system. + + The rocWMMA library is included by default when installing the ROCm SDK using the `rocm` meta package provided by AMD. Alternatively, if you are not using the meta package, you can install the library using the `rocwmma-dev` or `rocwmma-devel` package, depending on your system's package manager. + + As an alternative, you can manually install the library by cloning it from the official [GitHub repository](https://github.com/ROCm/rocWMMA), checkout the corresponding version tag (e.g. `rocm-6.2.4`) and set `-DCMAKE_CXX_FLAGS="-I/library/include/"` in CMake. This also works under Windows despite not officially supported by AMD. + Note that if you get the following error: ``` clang: error: cannot find ROCm device library; provide its path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to build without ROCm device library From 5220a16d18563d3ffc509002f0514415fdda4036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=A4=C3=9Fler?= Date: Thu, 6 Mar 2025 18:45:09 +0100 Subject: [PATCH 46/87] CUDA: fix FA logic for PTX 7.0 and CC >= 7.5 (#12222) --- ggml/src/ggml-cuda/fattn.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ggml/src/ggml-cuda/fattn.cu b/ggml/src/ggml-cuda/fattn.cu index 24f973056..2e72fc8fd 100644 --- a/ggml/src/ggml-cuda/fattn.cu +++ b/ggml/src/ggml-cuda/fattn.cu @@ -310,7 +310,7 @@ void ggml_cuda_flash_attn_ext(ggml_backend_cuda_context & ctx, ggml_tensor * dst } // The MMA implementation needs Turing or newer, use the old WMMA code for Volta: - if (cc == GGML_CUDA_CC_VOLTA) { + if (fp16_mma_available(cc) && !new_mma_available(cc)) { ggml_cuda_flash_attn_ext_wmma_f16(ctx, dst); return; } From 3d652bfddfba09022525067e672c3c145c074649 Mon Sep 17 00:00:00 2001 From: Lucas Moura Belo Date: Thu, 6 Mar 2025 16:15:13 -0300 Subject: [PATCH 47/87] readme : update bindings (#12229) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d73b0495d..e371c44ed 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ Instructions for adding support for new models: [HOWTO-add-model.md](docs/develo - Guile Scheme: [guile_llama_cpp](https://savannah.nongnu.org/projects/guile-llama-cpp) - Swift [srgtuszy/llama-cpp-swift](https://github.com/srgtuszy/llama-cpp-swift) - Swift [ShenghaiWang/SwiftLlama](https://github.com/ShenghaiWang/SwiftLlama) +- Delphi [Embarcadero/llama-cpp-delphi](https://github.com/Embarcadero/llama-cpp-delphi) From 776f9e59cc8a85e840d1d4af8540d199c77190ac Mon Sep 17 00:00:00 2001 From: xiaofei Date: Fri, 7 Mar 2025 06:58:25 +0800 Subject: [PATCH 48/87] cmake : fix undefined reference errors for std::filesystem in ggml (#12092) (#12094) Signed-off-by: Ray Lee Co-authored-by: Ray Lee --- ggml/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ggml/src/CMakeLists.txt b/ggml/src/CMakeLists.txt index cfd4ac54c..52817510f 100644 --- a/ggml/src/CMakeLists.txt +++ b/ggml/src/CMakeLists.txt @@ -236,7 +236,7 @@ add_library(ggml target_link_libraries(ggml PUBLIC ggml-base) if (CMAKE_SYSTEM_NAME MATCHES "Linux") - target_link_libraries(ggml PRIVATE dl) + target_link_libraries(ggml PRIVATE dl stdc++fs) endif() function(ggml_add_backend_library backend) From d76a86d967ef491d530400b08bc8ef8a14807936 Mon Sep 17 00:00:00 2001 From: lhez Date: Thu, 6 Mar 2025 16:20:35 -0800 Subject: [PATCH 49/87] opencl: Noncontiguous `norm`, `rms_norm`, disable `fp16` for some ops (#12217) * opencl: support noncontiguous `norm` * opencl: support noncontiguous `rms_norm` * opencl: disable fp16 for `ADD`, `MUL`, `SCALE`, `RELU`, `GELU`, `SILU`, `CLAMP` --- ggml/src/ggml-opencl/ggml-opencl.cpp | 70 +++++++++++++-------- ggml/src/ggml-opencl/kernels/ggml-opencl.cl | 26 ++++++-- 2 files changed, 65 insertions(+), 31 deletions(-) diff --git a/ggml/src/ggml-opencl/ggml-opencl.cpp b/ggml/src/ggml-opencl/ggml-opencl.cpp index bc2ea06b5..b85a895c4 100644 --- a/ggml/src/ggml-opencl/ggml-opencl.cpp +++ b/ggml/src/ggml-opencl/ggml-opencl.cpp @@ -1007,17 +1007,18 @@ static bool ggml_opencl_supports_op(ggml_backend_dev_t dev, const struct ggml_te case GGML_OP_ADD: case GGML_OP_SCALE: case GGML_OP_MUL: - return true; + return op->src[0]->type == GGML_TYPE_F32; case GGML_OP_UNARY: switch (ggml_get_unary_op(op)) { case GGML_UNARY_OP_GELU: case GGML_UNARY_OP_SILU: case GGML_UNARY_OP_RELU: - return ggml_is_contiguous(op->src[0]); + return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32; default: return false; } case GGML_OP_CLAMP: + return op->src[0]->type == GGML_TYPE_F32; case GGML_OP_SOFT_MAX: case GGML_OP_NORM: case GGML_OP_RMS_NORM: @@ -2573,26 +2574,33 @@ static void ggml_cl_norm(ggml_backend_t backend, const ggml_tensor * src0, const memcpy(&eps, dst->op_params, sizeof(float)); const int ne00 = src0 ? src0->ne[0] : 0; - const cl_ulong nb01 = src0 ? src0->nb[1] : 0; + const int ne01 = src0 ? src0->ne[1] : 0; + const int ne02 = src0 ? src0->ne[2] : 0; + const int ne03 = src0 ? src0->ne[3] : 0; - GGML_ASSERT(ggml_is_contiguous_1(src0)); + const cl_ulong nb01 = src0 ? src0->nb[1] : 0; + const cl_ulong nb02 = src0 ? src0->nb[2] : 0; + const cl_ulong nb03 = src0 ? src0->nb[3] : 0; const int nth = MIN(64, ne00); cl_kernel kernel = backend_ctx->kernel_norm; - CL_CHECK(clSetKernelArg(kernel, 0, sizeof(cl_mem), &extra0->data_device)); - CL_CHECK(clSetKernelArg(kernel, 1, sizeof(cl_ulong), &offset0)); - CL_CHECK(clSetKernelArg(kernel, 2, sizeof(cl_mem), &extrad->data_device)); - CL_CHECK(clSetKernelArg(kernel, 3, sizeof(cl_ulong), &offsetd)); - CL_CHECK(clSetKernelArg(kernel, 4, sizeof(int), &ne00)); - CL_CHECK(clSetKernelArg(kernel, 5, sizeof(cl_ulong), &nb01)); - CL_CHECK(clSetKernelArg(kernel, 6, sizeof(float), &eps)); - CL_CHECK(clSetKernelArg(kernel, 7, sizeof(float)*nth, NULL)); + CL_CHECK(clSetKernelArg(kernel, 0, sizeof(cl_mem), &extra0->data_device)); + CL_CHECK(clSetKernelArg(kernel, 1, sizeof(cl_ulong), &offset0)); + CL_CHECK(clSetKernelArg(kernel, 2, sizeof(cl_mem), &extrad->data_device)); + CL_CHECK(clSetKernelArg(kernel, 3, sizeof(cl_ulong), &offsetd)); + CL_CHECK(clSetKernelArg(kernel, 4, sizeof(int), &ne00)); + CL_CHECK(clSetKernelArg(kernel, 5, sizeof(int), &ne01)); + CL_CHECK(clSetKernelArg(kernel, 6, sizeof(int), &ne02)); + CL_CHECK(clSetKernelArg(kernel, 7, sizeof(int), &ne03)); + CL_CHECK(clSetKernelArg(kernel, 8, sizeof(cl_ulong), &nb01)); + CL_CHECK(clSetKernelArg(kernel, 9, sizeof(cl_ulong), &nb02)); + CL_CHECK(clSetKernelArg(kernel, 10, sizeof(cl_ulong), &nb03)); + CL_CHECK(clSetKernelArg(kernel, 11, sizeof(float), &eps)); + CL_CHECK(clSetKernelArg(kernel, 12, sizeof(float)*nth, NULL)); - const int64_t nrows = ggml_nrows(src0); - - size_t global_work_size[] = {(size_t)nrows*nth, 1, 1}; + size_t global_work_size[] = {(size_t)ne01*nth, (size_t)ne02, (size_t)ne03}; size_t local_work_size[] = {(size_t)nth, 1, 1}; #ifdef GGML_OPENCL_PROFILING @@ -2630,16 +2638,19 @@ static void ggml_cl_rms_norm(ggml_backend_t backend, const ggml_tensor * src0, c memcpy(&eps, dst->op_params, sizeof(float)); const int ne00 = src0 ? src0->ne[0] : 0; + const int ne01 = src0 ? src0->ne[1] : 0; + const int ne02 = src0 ? src0->ne[2] : 0; + const int ne03 = src0 ? src0->ne[3] : 0; + const cl_ulong nb01 = src0 ? src0->nb[1] : 0; + const cl_ulong nb02 = src0 ? src0->nb[2] : 0; + const cl_ulong nb03 = src0 ? src0->nb[3] : 0; GGML_ASSERT(ne00 % 4 == 0); - GGML_ASSERT(ggml_is_contiguous_1(src0)); const int nth = MIN(64, ne00); - const int64_t nrows = ggml_nrows(src0); - - size_t global_work_size[] = {(size_t)nrows*nth, 1, 1}; + size_t global_work_size[] = {(size_t)ne01*nth, (size_t)ne02, (size_t)ne03}; size_t local_work_size[] = {(size_t)nth, 1, 1}; cl_kernel kernel = backend_ctx->kernel_rms_norm; @@ -2654,15 +2665,20 @@ static void ggml_cl_rms_norm(ggml_backend_t backend, const ggml_tensor * src0, c sizeof(local_work_size), local_work_size, sizeof(size_t), &sgs, NULL)); - CL_CHECK(clSetKernelArg(kernel, 0, sizeof(cl_mem), &extra0->data_device)); - CL_CHECK(clSetKernelArg(kernel, 1, sizeof(cl_ulong), &offset0)); - CL_CHECK(clSetKernelArg(kernel, 2, sizeof(cl_mem), &extrad->data_device)); - CL_CHECK(clSetKernelArg(kernel, 3, sizeof(cl_ulong), &offsetd)); - CL_CHECK(clSetKernelArg(kernel, 4, sizeof(int), &ne00)); - CL_CHECK(clSetKernelArg(kernel, 5, sizeof(cl_ulong), &nb01)); - CL_CHECK(clSetKernelArg(kernel, 6, sizeof(float), &eps)); + CL_CHECK(clSetKernelArg(kernel, 0, sizeof(cl_mem), &extra0->data_device)); + CL_CHECK(clSetKernelArg(kernel, 1, sizeof(cl_ulong), &offset0)); + CL_CHECK(clSetKernelArg(kernel, 2, sizeof(cl_mem), &extrad->data_device)); + CL_CHECK(clSetKernelArg(kernel, 3, sizeof(cl_ulong), &offsetd)); + CL_CHECK(clSetKernelArg(kernel, 4, sizeof(int), &ne00)); + CL_CHECK(clSetKernelArg(kernel, 5, sizeof(int), &ne01)); + CL_CHECK(clSetKernelArg(kernel, 6, sizeof(int), &ne02)); + CL_CHECK(clSetKernelArg(kernel, 7, sizeof(int), &ne03)); + CL_CHECK(clSetKernelArg(kernel, 8, sizeof(cl_ulong), &nb01)); + CL_CHECK(clSetKernelArg(kernel, 9, sizeof(cl_ulong), &nb02)); + CL_CHECK(clSetKernelArg(kernel, 10, sizeof(cl_ulong), &nb03)); + CL_CHECK(clSetKernelArg(kernel, 11, sizeof(float), &eps)); // This is local memory - the size depends on subgroup size. - CL_CHECK(clSetKernelArg(kernel, 7, sizeof(float)*nth/sgs, NULL)); + CL_CHECK(clSetKernelArg(kernel, 12, sizeof(float)*nth/sgs, NULL)); #ifdef GGML_OPENCL_PROFILING cl_event evt; diff --git a/ggml/src/ggml-opencl/kernels/ggml-opencl.cl b/ggml/src/ggml-opencl/kernels/ggml-opencl.cl index 8882a8c9c..1d43642a9 100644 --- a/ggml/src/ggml-opencl/kernels/ggml-opencl.cl +++ b/ggml/src/ggml-opencl/kernels/ggml-opencl.cl @@ -506,14 +506,23 @@ kernel void kernel_norm( global float * dst, ulong offsetd, int ne00, + int ne01, + int ne02, + int ne03, ulong nb01, + ulong nb02, + ulong nb03, float eps, local float * sum ) { src0 = (global void*)((global char*)src0 + offset0); dst = (global void*)((global char*)dst + offsetd); - global float * x = (global float *) ((global char *) src0 + get_group_id(0)*nb01); + int i03 = get_group_id(2); + int i02 = get_group_id(1); + int i01 = get_group_id(0); + + global float * x = (global float *) ((global char *) src0 + i03*nb03 + i02*nb02 + i01*nb01); // MEAN // parallel sum @@ -533,7 +542,7 @@ kernel void kernel_norm( // recenter and VARIANCE barrier(CLK_LOCAL_MEM_FENCE); - global float * y = dst + get_group_id(0)*ne00; + global float * y = dst + i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00; sum[get_local_id(0)] = 0.0f; for (int i00 = get_local_id(0); i00 < ne00; i00 += get_local_size(0)) { y[i00] = x[i00] - mean; @@ -566,14 +575,23 @@ kernel void kernel_rms_norm( global float * dst, ulong offsetd, int ne00, + int ne01, + int ne02, + int ne03, ulong nb01, + ulong nb02, + ulong nb03, float eps, local float * sum // Note, the size depends on number of subgroups ) { src0 = (global void*)((global char*)src0 + offset0); dst = (global float*)((global char*)dst + offsetd); - global float4 * x = (global float4 *) ((global char *) src0 + get_group_id(0)*nb01); + int i03 = get_group_id(2); + int i02 = get_group_id(1); + int i01 = get_group_id(0); + + global float4 * x = (global float4 *) ((global char *) src0 + i03*nb03 + i02*nb02 + i01*nb01); global float * x_scalar = (global float *) x; float4 sumf = 0; float all_sum = 0; @@ -607,7 +625,7 @@ kernel void kernel_rms_norm( const float mean = sum[0]; const float scale = 1.0f/sqrt(mean + eps); - global float4 * y = (global float4 *) (dst + get_group_id(0)*ne00); + global float4 * y = (global float4 *) (dst + i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00); global float * y_scalar = (global float *) y; for (int i00 = get_local_id(0); i00 < ne00/4; i00 += get_local_size(0)) { y[i00] = x[i00] * scale; From d6c95b0740510231b3797b80d6d3440d8fe188b6 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Fri, 7 Mar 2025 06:23:16 +0100 Subject: [PATCH 50/87] metal : fix default.metallib build (#12224) This commit updates the custom command to build the default.metallib file to use the correct path to ../ggml-common.h by using the variable METALLIB_COMMON. The motivation for this change is that currently when building and specifying GGML_METAL_EMBED_LIBRARY=OFF the following error is generated: ```console [ 11%] Linking CXX shared library ../../bin/libggml.dylib [ 11%] Built target ggml make[2]: *** No rule to make target `ggml/src/ggml-metal/ggml-common.h', needed by `bin/default.metallib'. Stop. make[1]: *** [ggml/src/ggml-metal/CMakeFiles/ggml-metal-lib.dir/all] Error 2 ``` With the above change the build could progress but there was a follow on error about not being able to find the ggml-common.h file in ggml-metal.metal where is was included as a relative path: ```console [ 11%] Compiling Metal kernels /Users/danbev/work/llama.cpp/build/bin/ggml-metal.metal:6:10: error: '../ggml-common.h' file not found, did you mean 'ggml-common.h'? ^~~~~~~~~~~~~~~~~~ "ggml-common.h" 1 error generated. ``` Removing the relative path then allowed the build to complete successfully. --- ggml/src/ggml-metal/CMakeLists.txt | 4 ++-- ggml/src/ggml-metal/ggml-metal.metal | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ggml/src/ggml-metal/CMakeLists.txt b/ggml/src/ggml-metal/CMakeLists.txt index 89fcde2fa..be3fb3fa9 100644 --- a/ggml/src/ggml-metal/CMakeLists.txt +++ b/ggml/src/ggml-metal/CMakeLists.txt @@ -27,12 +27,12 @@ configure_file(../ggml-common.h ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-common.h configure_file(ggml-metal.metal ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal COPYONLY) configure_file(ggml-metal-impl.h ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal-impl.h COPYONLY) +set(METALLIB_COMMON "${CMAKE_CURRENT_SOURCE_DIR}/../ggml-common.h") if (GGML_METAL_EMBED_LIBRARY) enable_language(ASM) add_compile_definitions(GGML_METAL_EMBED_LIBRARY) - set(METALLIB_COMMON "${CMAKE_CURRENT_SOURCE_DIR}/../ggml-common.h") set(METALLIB_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/ggml-metal.metal") set(METALLIB_IMPL "${CMAKE_CURRENT_SOURCE_DIR}/ggml-metal-impl.h") @@ -93,7 +93,7 @@ else() COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.air COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-common.h COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal - DEPENDS ggml-metal.metal ggml-common.h + DEPENDS ggml-metal.metal ${METALLIB_COMMON} COMMENT "Compiling Metal kernels" ) diff --git a/ggml/src/ggml-metal/ggml-metal.metal b/ggml/src/ggml-metal/ggml-metal.metal index d092a1690..c46a13050 100644 --- a/ggml/src/ggml-metal/ggml-metal.metal +++ b/ggml/src/ggml-metal/ggml-metal.metal @@ -3,8 +3,7 @@ #if defined(GGML_METAL_EMBED_LIBRARY) __embed_ggml-common.h__ #else -// TODO: this should not be a relative path, but can't figure out how to set Metal include paths in Package.swift -#include "../ggml-common.h" +#include "ggml-common.h" #endif #include "ggml-metal-impl.h" From f1648e91cf6c52e9593810aa70857e412d474c09 Mon Sep 17 00:00:00 2001 From: David Huang <1969802+hjc4869@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:06:08 +0800 Subject: [PATCH 51/87] HIP: fix rocWMMA build flags under Windows (#12230) --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e4596ab2..f2c81c0c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1238,7 +1238,7 @@ jobs: cmake -G "Unix Makefiles" -B build -S . ` -DCMAKE_C_COMPILER="${env:HIP_PATH}\bin\clang.exe" ` -DCMAKE_CXX_COMPILER="${env:HIP_PATH}\bin\clang++.exe" ` - -DCMAKE_CXX_FLAGS="-Irocwmma/library/include/" ` + -DCMAKE_CXX_FLAGS="-I$($PWD.Path.Replace('\', '/'))/rocwmma/library/include/" ` -DCMAKE_BUILD_TYPE=Release ` -DGGML_HIP=ON ` -DGGML_HIP_ROCWMMA_FATTN=ON ` @@ -1294,7 +1294,7 @@ jobs: cmake -G "Unix Makefiles" -B build -S . ` -DCMAKE_C_COMPILER="${env:HIP_PATH}\bin\clang.exe" ` -DCMAKE_CXX_COMPILER="${env:HIP_PATH}\bin\clang++.exe" ` - -DCMAKE_CXX_FLAGS="-Irocwmma/library/include/" ` + -DCMAKE_CXX_FLAGS="-I$($PWD.Path.Replace('\', '/'))/rocwmma/library/include/" ` -DCMAKE_BUILD_TYPE=Release ` -DAMDGPU_TARGETS=${{ matrix.gpu_target }} ` -DGGML_HIP_ROCWMMA_FATTN=ON ` From 5e2d57b2b2e43eadbe6d66ba3e873a824b95e725 Mon Sep 17 00:00:00 2001 From: BB-fat <45072480+BB-fat@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:35:57 +0800 Subject: [PATCH 52/87] metal : simplify kernel arguments using a struct (#3229) (#12194) * metal : refactor im2col parameters into a struct * metal: Change im2col offset types from int32_t to uint64_t to support larger memory offsets * metal : refactor sum_rows parameters into a struct * metal : refactor soft_max parameters into a struct * metal : refactor diag_mask_inf parameters into a struct * metal : refactor ssm_conv parameters into a struct * metal : refactor ssm_scan parameters into a struct * metal : refactor get_rows parameters into a struct * metal : refactor group_norm parameters into a struct * metal : refactor conv_transpose_1d parameters into a struct * metal : refactor upscale parameters into a struct * metal : refactor pad parameters into a struct * metal : refactor pad_reflect_1d parameters into a struct * metal : refactor arange parameters into a struct * metal : refactor timestep_embedding parameters into a struct * metal : refactor argsort parameters into a struct * metal : refactor leaky_relu parameters into a struct * metal : refactor pool_2d parameters into a struct * metal : fix trailing whitespace --------- Co-authored-by: alexju --- ggml/src/ggml-metal/ggml-metal-impl.h | 235 ++++++++++ ggml/src/ggml-metal/ggml-metal.m | 466 ++++++++++--------- ggml/src/ggml-metal/ggml-metal.metal | 627 ++++++++------------------ 3 files changed, 685 insertions(+), 643 deletions(-) diff --git a/ggml/src/ggml-metal/ggml-metal-impl.h b/ggml/src/ggml-metal/ggml-metal-impl.h index e3dc25f16..a58c474eb 100644 --- a/ggml/src/ggml-metal/ggml-metal-impl.h +++ b/ggml/src/ggml-metal/ggml-metal-impl.h @@ -285,4 +285,239 @@ typedef struct { float eps; } ggml_metal_kargs_rms_norm; +typedef struct { + int64_t ne00; + int64_t ne01; + int64_t ne02; + uint64_t nb00; + uint64_t nb01; + uint64_t nb02; + int32_t n_groups; + float eps; +} ggml_metal_kargs_group_norm; + +typedef struct { + int32_t IC; + int32_t IL; + int32_t K; + int32_t s0; + uint64_t nb0; + uint64_t nb1; +} ggml_metal_kargs_conv_transpose_1d; + +typedef struct { + uint64_t ofs0; + uint64_t ofs1; + int32_t IW; + int32_t IH; + int32_t CHW; + int32_t s0; + int32_t s1; + int32_t p0; + int32_t p1; + int32_t d0; + int32_t d1; + int32_t N; + int32_t KH; + int32_t KW; + int32_t KHW; // KH * KW, pre-computed on CPU to save GPU resources +} ggml_metal_kargs_im2col; + +typedef struct { + int64_t ne00; + int64_t ne01; + int64_t ne02; + int64_t ne03; + uint64_t nb00; + uint64_t nb01; + uint64_t nb02; + uint64_t nb03; + int64_t ne10; + int64_t ne11; + int64_t ne12; + int64_t ne13; + uint64_t nb10; + uint64_t nb11; + uint64_t nb12; + uint64_t nb13; + int64_t ne0; + int64_t ne1; + int64_t ne2; + int64_t ne3; + uint64_t nb0; + uint64_t nb1; + uint64_t nb2; + uint64_t nb3; +} ggml_metal_kargs_sum_rows; + +typedef struct { + int64_t ne00; + int64_t ne01; + int64_t ne02; + float scale; + float max_bias; + float m0; + float m1; + uint32_t n_head_log2; +} ggml_metal_kargs_soft_max; + +typedef struct { + int64_t ne00; + int64_t ne01; + int n_past; +} ggml_metal_kargs_diag_mask_inf; + +typedef struct { + int64_t ne00; + int64_t ne01; + int64_t ne02; + uint64_t nb00; + uint64_t nb01; + uint64_t nb02; + int64_t ne10; + int64_t ne11; + uint64_t nb10; + uint64_t nb11; + int64_t ne0; + int64_t ne1; + int64_t ne2; + uint64_t nb0; + uint64_t nb1; + uint64_t nb2; +} ggml_metal_kargs_ssm_conv; + +typedef struct { + int64_t d_state; + int64_t d_inner; + int64_t n_seq_tokens; + int64_t n_seqs; + uint64_t nb00; + uint64_t nb01; + uint64_t nb02; + uint64_t nb10; + uint64_t nb11; + uint64_t nb12; + uint64_t nb13; + uint64_t nb20; + uint64_t nb21; + uint64_t nb22; + uint64_t nb30; + uint64_t nb31; + uint64_t nb40; + uint64_t nb41; + uint64_t nb42; + uint64_t nb50; + uint64_t nb51; + uint64_t nb52; +} ggml_metal_kargs_ssm_scan; + +typedef struct { + int64_t ne00; + uint64_t nb01; + uint64_t nb02; + int64_t ne10; + uint64_t nb10; + uint64_t nb11; + uint64_t nb1; + uint64_t nb2; +} ggml_metal_kargs_get_rows; + +typedef struct { + int64_t ne00; + int64_t ne01; + int64_t ne02; + int64_t ne03; + uint64_t nb00; + uint64_t nb01; + uint64_t nb02; + uint64_t nb03; + int64_t ne0; + int64_t ne1; + int64_t ne2; + int64_t ne3; + uint64_t nb0; + uint64_t nb1; + uint64_t nb2; + uint64_t nb3; + float sf0; + float sf1; + float sf2; + float sf3; +} ggml_metal_kargs_upscale; + +typedef struct { + int64_t ne00; + int64_t ne01; + int64_t ne02; + int64_t ne03; + uint64_t nb00; + uint64_t nb01; + uint64_t nb02; + uint64_t nb03; + int64_t ne0; + int64_t ne1; + int64_t ne2; + int64_t ne3; + uint64_t nb0; + uint64_t nb1; + uint64_t nb2; + uint64_t nb3; +} ggml_metal_kargs_pad; + +typedef struct { + int64_t ne00; + int64_t ne01; + int64_t ne02; + int64_t ne03; + uint64_t nb00; + uint64_t nb01; + uint64_t nb02; + uint64_t nb03; + int64_t ne0; + int64_t ne1; + int64_t ne2; + int64_t ne3; + uint64_t nb0; + uint64_t nb1; + uint64_t nb2; + uint64_t nb3; + int32_t p0; + int32_t p1; +} ggml_metal_kargs_pad_reflect_1d; + +typedef struct { + uint64_t nb1; + int dim; + int max_period; +} ggml_metal_kargs_timestep_embedding; + +typedef struct { + float slope; +} ggml_metal_kargs_leaky_relu; + +typedef struct { + int64_t ncols; + int64_t ncols_pad; +} ggml_metal_kargs_argsort; + +typedef struct { + int64_t ne0; + float start; + float step; +} ggml_metal_kargs_arange; + +typedef struct { + int32_t k0; + int32_t k1; + int32_t s0; + int32_t s1; + int32_t p0; + int32_t p1; + int64_t IH; + int64_t IW; + int64_t OH; + int64_t OW; + int64_t parallel_elements; +} ggml_metal_kargs_pool_2d; + #endif // GGML_METAL_IMPL diff --git a/ggml/src/ggml-metal/ggml-metal.m b/ggml/src/ggml-metal/ggml-metal.m index 1f45ebad1..1158b285c 100644 --- a/ggml/src/ggml-metal/ggml-metal.m +++ b/ggml/src/ggml-metal/ggml-metal.m @@ -1945,34 +1945,38 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_SUM_ROWS].pipeline; - // TODO: add ggml_metal_kargs struct + + ggml_metal_kargs_sum_rows args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.ne02 =*/ ne02, + /*.ne03 =*/ ne03, + /*.nb00 =*/ nb00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.nb03 =*/ nb03, + /*.ne10 =*/ ne10, + /*.ne11 =*/ ne11, + /*.ne12 =*/ ne12, + /*.ne13 =*/ ne13, + /*.nb10 =*/ nb10, + /*.nb11 =*/ nb11, + /*.nb12 =*/ nb12, + /*.nb13 =*/ nb13, + /*.ne0 =*/ ne0, + /*.ne1 =*/ ne1, + /*.ne2 =*/ ne2, + /*.ne3 =*/ ne3, + /*.nb0 =*/ nb0, + /*.nb1 =*/ nb1, + /*.nb2 =*/ nb2, + /*.nb3 =*/ nb3, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:2]; - [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:3]; - [encoder setBytes:&ne02 length:sizeof(ne02) atIndex:4]; - [encoder setBytes:&ne03 length:sizeof(ne03) atIndex:5]; - [encoder setBytes:&nb00 length:sizeof(nb00) atIndex:6]; - [encoder setBytes:&nb01 length:sizeof(nb01) atIndex:7]; - [encoder setBytes:&nb02 length:sizeof(nb02) atIndex:8]; - [encoder setBytes:&nb03 length:sizeof(nb03) atIndex:9]; - [encoder setBytes:&ne10 length:sizeof(ne10) atIndex:10]; - [encoder setBytes:&ne11 length:sizeof(ne11) atIndex:11]; - [encoder setBytes:&ne12 length:sizeof(ne12) atIndex:12]; - [encoder setBytes:&ne13 length:sizeof(ne13) atIndex:13]; - [encoder setBytes:&nb10 length:sizeof(nb10) atIndex:14]; - [encoder setBytes:&nb11 length:sizeof(nb11) atIndex:15]; - [encoder setBytes:&nb12 length:sizeof(nb12) atIndex:16]; - [encoder setBytes:&nb13 length:sizeof(nb13) atIndex:17]; - [encoder setBytes:&ne0 length:sizeof(ne0) atIndex:18]; - [encoder setBytes:&ne1 length:sizeof(ne1) atIndex:19]; - [encoder setBytes:&ne2 length:sizeof(ne2) atIndex:20]; - [encoder setBytes:&ne3 length:sizeof(ne3) atIndex:21]; - [encoder setBytes:&nb0 length:sizeof(nb0) atIndex:22]; - [encoder setBytes:&nb1 length:sizeof(nb1) atIndex:23]; - [encoder setBytes:&nb2 length:sizeof(nb2) atIndex:24]; - [encoder setBytes:&nb3 length:sizeof(nb3) atIndex:25]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; [encoder dispatchThreadgroups:MTLSizeMake(ne01, ne02, ne03) threadsPerThreadgroup:MTLSizeMake(1, 1, 1)]; } break; @@ -2021,8 +2025,17 @@ static void ggml_metal_encode_node( const float m0 = powf(2.0f, -(max_bias ) / n_head_log2); const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2); - // TODO: add ggml_metal_kargs struct - // TODO: optimize (see https://github.com/ggml-org/llama.cpp/pull/10238/commits/7941b6b9ec29a2866fec6fa6c51612515ca509f6) + ggml_metal_kargs_soft_max args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.ne02 =*/ ne02, + /*.scale =*/ scale, + /*.max_bias =*/ max_bias, + /*.m0 =*/ m0, + /*.m1 =*/ m1, + /*.n_head_log2 =*/ n_head_log2, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; if (id_src1) { @@ -2031,14 +2044,7 @@ static void ggml_metal_encode_node( [encoder setBuffer:id_src0 offset:offs_src0 atIndex:1]; } [encoder setBuffer:id_dst offset:offs_dst atIndex:2]; - [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:3]; - [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:4]; - [encoder setBytes:&ne02 length:sizeof(ne02) atIndex:5]; - [encoder setBytes:&scale length:sizeof(scale) atIndex:6]; - [encoder setBytes:&max_bias length:sizeof(max_bias) atIndex:7]; - [encoder setBytes:&m0 length:sizeof(m0) atIndex:8]; - [encoder setBytes:&m1 length:sizeof(m1) atIndex:9]; - [encoder setBytes:&n_head_log2 length:sizeof(n_head_log2) atIndex:10]; + [encoder setBytes:&args length:sizeof(args) atIndex:3]; [encoder setThreadgroupMemoryLength:32*sizeof(float) atIndex:0]; @@ -2056,13 +2062,16 @@ static void ggml_metal_encode_node( pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_DIAG_MASK_INF].pipeline; } - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_diag_mask_inf args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.n_past =*/ n_past, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:2]; - [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:3]; - [encoder setBytes:&n_past length:sizeof(int) atIndex:4]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; if (ne00%8 == 0) { [encoder dispatchThreadgroups:MTLSizeMake(ne00*ne01*ne02/8, 1, 1) threadsPerThreadgroup:MTLSizeMake(1, 1, 1)]; @@ -2081,27 +2090,30 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_SSM_CONV_F32].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_ssm_conv args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.ne02 =*/ ne02, + /*.nb00 =*/ nb00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.ne10 =*/ ne10, + /*.ne11 =*/ ne11, + /*.nb10 =*/ nb10, + /*.nb11 =*/ nb11, + /*.ne0 =*/ ne0, + /*.ne1 =*/ ne1, + /*.ne2 =*/ ne2, + /*.nb0 =*/ nb0, + /*.nb1 =*/ nb1, + /*.nb2 =*/ nb2, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_src1 offset:offs_src1 atIndex:1]; [encoder setBuffer:id_dst offset:offs_dst atIndex:2]; - [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:3]; - [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:4]; - [encoder setBytes:&ne02 length:sizeof(ne02) atIndex:5]; - [encoder setBytes:&nb00 length:sizeof(nb00) atIndex:6]; - [encoder setBytes:&nb01 length:sizeof(nb01) atIndex:7]; - [encoder setBytes:&nb02 length:sizeof(nb02) atIndex:8]; - [encoder setBytes:&ne10 length:sizeof(ne10) atIndex:9]; - [encoder setBytes:&ne11 length:sizeof(ne11) atIndex:10]; - [encoder setBytes:&nb10 length:sizeof(nb10) atIndex:11]; - [encoder setBytes:&nb11 length:sizeof(nb11) atIndex:12]; - [encoder setBytes:&ne0 length:sizeof(ne0) atIndex:13]; - [encoder setBytes:&ne1 length:sizeof(ne1) atIndex:14]; - [encoder setBytes:&ne2 length:sizeof(ne2) atIndex:15]; - [encoder setBytes:&nb0 length:sizeof(nb0) atIndex:16]; - [encoder setBytes:&nb1 length:sizeof(nb1) atIndex:17]; - [encoder setBytes:&nb2 length:sizeof(nb2) atIndex:18]; + [encoder setBytes:&args length:sizeof(args) atIndex:3]; [encoder dispatchThreadgroups:MTLSizeMake(ne01, ne1, ne02) threadsPerThreadgroup:MTLSizeMake(1, 1, 1)]; } break; @@ -2152,7 +2164,31 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_SSM_SCAN_F32].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_ssm_scan args = { + /*.d_state =*/ d_state, + /*.d_inner =*/ d_inner, + /*.n_seq_tokens =*/ n_seq_tokens, + /*.n_seqs =*/ n_seqs, + /*.nb00 =*/ nb00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.nb10 =*/ nb10, + /*.nb11 =*/ nb11, + /*.nb12 =*/ nb12, + /*.nb13 =*/ nb13, + /*.nb20 =*/ nb20, + /*.nb21 =*/ nb21, + /*.nb22 =*/ nb22, + /*.nb30 =*/ nb30, + /*.nb31 =*/ nb31, + /*.nb40 =*/ nb40, + /*.nb41 =*/ nb41, + /*.nb42 =*/ nb42, + /*.nb50 =*/ nb50, + /*.nb51 =*/ nb51, + /*.nb52 =*/ nb52, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_src1 offset:offs_src1 atIndex:1]; @@ -2161,30 +2197,7 @@ static void ggml_metal_encode_node( [encoder setBuffer:id_src4 offset:offs_src4 atIndex:4]; [encoder setBuffer:id_src5 offset:offs_src5 atIndex:5]; [encoder setBuffer:id_dst offset:offs_dst atIndex:6]; - - [encoder setBytes:&d_state length:sizeof(d_state) atIndex:7]; - [encoder setBytes:&d_inner length:sizeof(d_inner) atIndex:8]; - [encoder setBytes:&n_seq_tokens length:sizeof(n_seq_tokens) atIndex:9]; - [encoder setBytes:&n_seqs length:sizeof(n_seqs) atIndex:10]; - - [encoder setBytes:&nb00 length:sizeof(nb00) atIndex:11]; - [encoder setBytes:&nb01 length:sizeof(nb01) atIndex:12]; - [encoder setBytes:&nb02 length:sizeof(nb02) atIndex:13]; - [encoder setBytes:&nb10 length:sizeof(nb10) atIndex:14]; - [encoder setBytes:&nb11 length:sizeof(nb11) atIndex:15]; - [encoder setBytes:&nb12 length:sizeof(nb12) atIndex:16]; - [encoder setBytes:&nb13 length:sizeof(nb13) atIndex:17]; - [encoder setBytes:&nb20 length:sizeof(nb20) atIndex:18]; - [encoder setBytes:&nb21 length:sizeof(nb21) atIndex:19]; - [encoder setBytes:&nb22 length:sizeof(nb22) atIndex:20]; - [encoder setBytes:&nb30 length:sizeof(nb30) atIndex:21]; - [encoder setBytes:&nb31 length:sizeof(nb31) atIndex:22]; - [encoder setBytes:&nb40 length:sizeof(nb40) atIndex:23]; - [encoder setBytes:&nb41 length:sizeof(nb41) atIndex:24]; - [encoder setBytes:&nb42 length:sizeof(nb42) atIndex:25]; - [encoder setBytes:&nb50 length:sizeof(nb50) atIndex:26]; - [encoder setBytes:&nb51 length:sizeof(nb51) atIndex:27]; - [encoder setBytes:&nb52 length:sizeof(nb52) atIndex:28]; + [encoder setBytes:&args length:sizeof(args) atIndex:7]; [encoder dispatchThreadgroups:MTLSizeMake(d_inner, n_seqs, 1) threadsPerThreadgroup:MTLSizeMake(1, 1, 1)]; } break; @@ -3041,19 +3054,22 @@ static void ggml_metal_encode_node( default: GGML_ABORT("not implemented"); } - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_get_rows args = { + /*.ne00 =*/ ne00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.ne10 =*/ ne10, + /*.nb10 =*/ nb10, + /*.nb11 =*/ nb11, + /*.nb1 =*/ nb1, + /*.nb2 =*/ nb2, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_src1 offset:offs_src1 atIndex:1]; [encoder setBuffer:id_dst offset:offs_dst atIndex:2]; - [encoder setBytes:&ne00 length:sizeof( int64_t) atIndex:3]; - [encoder setBytes:&nb01 length:sizeof(uint64_t) atIndex:4]; - [encoder setBytes:&nb02 length:sizeof(uint64_t) atIndex:5]; - [encoder setBytes:&ne10 length:sizeof( int64_t) atIndex:6]; - [encoder setBytes:&nb10 length:sizeof( int64_t) atIndex:7]; - [encoder setBytes:&nb11 length:sizeof( int64_t) atIndex:8]; - [encoder setBytes:&nb1 length:sizeof(uint64_t) atIndex:9]; - [encoder setBytes:&nb2 length:sizeof(uint64_t) atIndex:10]; + [encoder setBytes:&args length:sizeof(args) atIndex:3]; [encoder dispatchThreadgroups:MTLSizeMake(ne10, ne11, 1) threadsPerThreadgroup:MTLSizeMake(32, 1, 1)]; } break; @@ -3110,18 +3126,21 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GROUP_NORM].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_group_norm args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.ne02 =*/ ne02, + /*.nb00 =*/ nb00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.n_groups =*/ n_groups, + /*.eps =*/ eps, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ne00 length:sizeof( int64_t) atIndex:2]; - [encoder setBytes:&ne01 length:sizeof( int64_t) atIndex:3]; - [encoder setBytes:&ne02 length:sizeof( int64_t) atIndex:4]; - [encoder setBytes:&nb00 length:sizeof(uint64_t) atIndex:5]; - [encoder setBytes:&nb01 length:sizeof(uint64_t) atIndex:6]; - [encoder setBytes:&nb02 length:sizeof(uint64_t) atIndex:7]; - [encoder setBytes:&n_groups length:sizeof( int32_t) atIndex:8]; - [encoder setBytes:&eps length:sizeof( float) atIndex:9]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; [encoder setThreadgroupMemoryLength:32*sizeof(float) atIndex:0]; [encoder dispatchThreadgroups:MTLSizeMake(n_groups, 1, 1) threadsPerThreadgroup:MTLSizeMake(nth, 1, 1)]; @@ -3279,8 +3298,8 @@ static void ggml_metal_encode_node( const int32_t CHW = IC * KH * KW; - const int32_t ofs0 = src1->nb[is_2D ? 3 : 2] / 4; - const int32_t ofs1 = src1->nb[is_2D ? 2 : 1] / 4; + const uint64_t ofs0 = src1->nb[is_2D ? 3 : 2] / 4; + const uint64_t ofs1 = src1->nb[is_2D ? 2 : 1] / 4; id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_IM2COL_F32].pipeline; @@ -3302,27 +3321,30 @@ static void ggml_metal_encode_node( default: GGML_ABORT("fatal error"); }; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_im2col args = { + /*.ofs0 =*/ ofs0, + /*.ofs1 =*/ ofs1, + /*.IW =*/ IW, + /*.IH =*/ IH, + /*.CHW =*/ CHW, + /*.s0 =*/ s0, + /*.s1 =*/ s1, + /*.p0 =*/ p0, + /*.p1 =*/ p1, + /*.d0 =*/ d0, + /*.d1 =*/ d1, + /*.N =*/ N, + /*.KH =*/ KH, + /*.KW =*/ KW, + /*.KHW =*/ KH * KW, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src1 offset:offs_src1 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ofs0 length:sizeof(int32_t) atIndex:2]; - [encoder setBytes:&ofs1 length:sizeof(int32_t) atIndex:3]; - [encoder setBytes:&IW length:sizeof(int32_t) atIndex:4]; - [encoder setBytes:&IH length:sizeof(int32_t) atIndex:5]; - [encoder setBytes:&CHW length:sizeof(int32_t) atIndex:6]; - [encoder setBytes:&s0 length:sizeof(int32_t) atIndex:7]; - [encoder setBytes:&s1 length:sizeof(int32_t) atIndex:8]; - [encoder setBytes:&p0 length:sizeof(int32_t) atIndex:9]; - [encoder setBytes:&p1 length:sizeof(int32_t) atIndex:10]; - [encoder setBytes:&d0 length:sizeof(int32_t) atIndex:11]; - [encoder setBytes:&d1 length:sizeof(int32_t) atIndex:12]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; if (is_gt_mttpt) { - [encoder setBytes:&N length:sizeof(int32_t) atIndex:13]; - [encoder setBytes:&KH length:sizeof(int32_t) atIndex:14]; - [encoder setBytes:&KW length:sizeof(int32_t) atIndex:15]; - const uint64_t n_threads = MIN(pipeline.maxTotalThreadsPerThreadgroup, (uint64_t)N); const int64_t quotient = N / n_threads + (N % n_threads > 0 ? 1 : 0); @@ -3362,16 +3384,20 @@ static void ggml_metal_encode_node( default: GGML_ABORT("fatal error"); }; + ggml_metal_kargs_conv_transpose_1d args = { + /*.IC =*/ IC, + /*.IL =*/ IL, + /*.K =*/ K, + /*.s0 =*/ s0, + /*.nb0 =*/ nb0, + /*.nb1 =*/ nb1, + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_src1 offset:offs_src1 atIndex:1]; [encoder setBuffer:id_dst offset:offs_dst atIndex:2]; - [encoder setBytes:&IC length:sizeof( int32_t) atIndex:3]; - [encoder setBytes:&IL length:sizeof( int32_t) atIndex:4]; - [encoder setBytes:&K length:sizeof( int32_t) atIndex:5]; - [encoder setBytes:&s0 length:sizeof( int32_t) atIndex:6]; - [encoder setBytes:&nb0 length:sizeof(uint64_t) atIndex:7]; - [encoder setBytes:&nb1 length:sizeof(uint64_t) atIndex:8]; + [encoder setBytes:&args length:sizeof(args) atIndex:3]; [encoder dispatchThreadgroups:MTLSizeMake(OL, OC, 1) threadsPerThreadgroup:MTLSizeMake(1, 1, 1)]; } break; @@ -3386,30 +3412,33 @@ static void ggml_metal_encode_node( const id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_UPSCALE_F32].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_upscale args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.ne02 =*/ ne02, + /*.ne03 =*/ ne03, + /*.nb00 =*/ nb00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.nb03 =*/ nb03, + /*.ne0 =*/ ne0, + /*.ne1 =*/ ne1, + /*.ne2 =*/ ne2, + /*.ne3 =*/ ne3, + /*.nb0 =*/ nb0, + /*.nb1 =*/ nb1, + /*.nb2 =*/ nb2, + /*.nb3 =*/ nb3, + /*.sf0 =*/ sf0, + /*.sf1 =*/ sf1, + /*.sf2 =*/ sf2, + /*.sf3 =*/ sf3 + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:2]; - [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:3]; - [encoder setBytes:&ne02 length:sizeof(ne02) atIndex:4]; - [encoder setBytes:&ne03 length:sizeof(ne03) atIndex:5]; - [encoder setBytes:&nb00 length:sizeof(nb00) atIndex:6]; - [encoder setBytes:&nb01 length:sizeof(nb01) atIndex:7]; - [encoder setBytes:&nb02 length:sizeof(nb02) atIndex:8]; - [encoder setBytes:&nb03 length:sizeof(nb03) atIndex:9]; - [encoder setBytes:&ne0 length:sizeof(ne0) atIndex:10]; - [encoder setBytes:&ne1 length:sizeof(ne1) atIndex:11]; - [encoder setBytes:&ne2 length:sizeof(ne2) atIndex:12]; - [encoder setBytes:&ne3 length:sizeof(ne3) atIndex:13]; - [encoder setBytes:&nb0 length:sizeof(nb0) atIndex:14]; - [encoder setBytes:&nb1 length:sizeof(nb1) atIndex:15]; - [encoder setBytes:&nb2 length:sizeof(nb2) atIndex:16]; - [encoder setBytes:&nb3 length:sizeof(nb3) atIndex:17]; - [encoder setBytes:&sf0 length:sizeof(sf0) atIndex:18]; - [encoder setBytes:&sf1 length:sizeof(sf1) atIndex:19]; - [encoder setBytes:&sf2 length:sizeof(sf2) atIndex:20]; - [encoder setBytes:&sf3 length:sizeof(sf3) atIndex:21]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; const int nth = MIN((int) pipeline.maxTotalThreadsPerThreadgroup, ne0); @@ -3421,26 +3450,29 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_PAD_F32].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_pad args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.ne02 =*/ ne02, + /*.ne03 =*/ ne03, + /*.nb00 =*/ nb00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.nb03 =*/ nb03, + /*.ne0 =*/ ne0, + /*.ne1 =*/ ne1, + /*.ne2 =*/ ne2, + /*.ne3 =*/ ne3, + /*.nb0 =*/ nb0, + /*.nb1 =*/ nb1, + /*.nb2 =*/ nb2, + /*.nb3 =*/ nb3 + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:2]; - [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:3]; - [encoder setBytes:&ne02 length:sizeof(ne02) atIndex:4]; - [encoder setBytes:&ne03 length:sizeof(ne03) atIndex:5]; - [encoder setBytes:&nb00 length:sizeof(nb00) atIndex:6]; - [encoder setBytes:&nb01 length:sizeof(nb01) atIndex:7]; - [encoder setBytes:&nb02 length:sizeof(nb02) atIndex:8]; - [encoder setBytes:&nb03 length:sizeof(nb03) atIndex:9]; - [encoder setBytes:&ne0 length:sizeof(ne0) atIndex:10]; - [encoder setBytes:&ne1 length:sizeof(ne1) atIndex:11]; - [encoder setBytes:&ne2 length:sizeof(ne2) atIndex:12]; - [encoder setBytes:&ne3 length:sizeof(ne3) atIndex:13]; - [encoder setBytes:&nb0 length:sizeof(nb0) atIndex:14]; - [encoder setBytes:&nb1 length:sizeof(nb1) atIndex:15]; - [encoder setBytes:&nb2 length:sizeof(nb2) atIndex:16]; - [encoder setBytes:&nb3 length:sizeof(nb3) atIndex:17]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; const int nth = MIN(1024, ne0); @@ -3455,24 +3487,31 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_PAD_REFLECT_1D_F32].pipeline; + ggml_metal_kargs_pad_reflect_1d args = { + /*.ne00 =*/ ne00, + /*.ne01 =*/ ne01, + /*.ne02 =*/ ne02, + /*.ne03 =*/ ne03, + /*.nb00 =*/ nb00, + /*.nb01 =*/ nb01, + /*.nb02 =*/ nb02, + /*.nb03 =*/ nb03, + /*.ne0 =*/ ne0, + /*.ne1 =*/ ne1, + /*.ne2 =*/ ne2, + /*.ne3 =*/ ne3, + /*.nb0 =*/ nb0, + /*.nb1 =*/ nb1, + /*.nb2 =*/ nb2, + /*.nb3 =*/ nb3, + /*.p0 =*/ p0, + /*.p1 =*/ p1 + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ne00 length:sizeof(ne00) atIndex:2]; - [encoder setBytes:&ne01 length:sizeof(ne01) atIndex:3]; - [encoder setBytes:&ne02 length:sizeof(ne02) atIndex:4]; - [encoder setBytes:&ne03 length:sizeof(ne03) atIndex:5]; - [encoder setBytes:&ne0 length:sizeof(ne0) atIndex:6]; - [encoder setBytes:&nb00 length:sizeof(nb00) atIndex:7]; - [encoder setBytes:&nb01 length:sizeof(nb01) atIndex:8]; - [encoder setBytes:&nb02 length:sizeof(nb02) atIndex:9]; - [encoder setBytes:&nb03 length:sizeof(nb03) atIndex:10]; - [encoder setBytes:&nb0 length:sizeof(nb0) atIndex:11]; - [encoder setBytes:&nb1 length:sizeof(nb1) atIndex:12]; - [encoder setBytes:&nb2 length:sizeof(nb2) atIndex:13]; - [encoder setBytes:&nb3 length:sizeof(nb3) atIndex:14]; - [encoder setBytes:&p0 length:sizeof(p0) atIndex:15]; - [encoder setBytes:&p1 length:sizeof(p1) atIndex:16]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; const int nth = MIN(1024, ne0); @@ -3490,12 +3529,15 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_ARANGE_F32].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_arange args = { + /*.ne0 =*/ ne0, + /*.start =*/ start, + /*.step =*/ step + }; + [encoder setComputePipelineState:pipeline]; - [encoder setBuffer:id_dst offset:offs_dst atIndex:0]; - [encoder setBytes:&ne0 length:sizeof(ne0) atIndex:1]; - [encoder setBytes:&start length:sizeof(start) atIndex:2]; - [encoder setBytes:&step length:sizeof(step) atIndex:3]; + [encoder setBuffer:id_dst offset:offs_dst atIndex:0]; + [encoder setBytes:&args length:sizeof(args) atIndex:1]; const int nth = MIN(1024, ne0); @@ -3512,13 +3554,16 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_TIMESTEP_EMBEDDING_F32].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_timestep_embedding args = { + /*.nb1 =*/ nb1, + /*.dim =*/ dim, + /*.max_period =*/ max_period + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&nb1 length:sizeof(nb1) atIndex:2]; - [encoder setBytes:&dim length:sizeof(dim) atIndex:3]; - [encoder setBytes:&max_period length:sizeof(max_period) atIndex:4]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; const int nth = MIN(1024, half); @@ -3551,12 +3596,15 @@ static void ggml_metal_encode_node( default: GGML_ABORT("fatal error"); }; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_argsort args = { + /*.ncols =*/ ne00, + /*.ncols_pad =*/ ne00_padded + }; + [encoder setComputePipelineState:pipeline]; - [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; - [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&ne00 length:sizeof( int64_t) atIndex:2]; - [encoder setBytes:&ne00_padded length:sizeof( int64_t) atIndex:3]; + [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; + [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; [encoder setThreadgroupMemoryLength:mem_size atIndex:0]; [encoder dispatchThreadgroups:MTLSizeMake(1, nrows, 1) threadsPerThreadgroup:MTLSizeMake(ne00_padded, 1, 1)]; @@ -3570,11 +3618,14 @@ static void ggml_metal_encode_node( id pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_LEAKY_RELU_F32].pipeline; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_leaky_relu args = { + /*.slope =*/ slope + }; + [encoder setComputePipelineState:pipeline]; [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&slope length:sizeof(slope) atIndex:2]; + [encoder setBytes:&args length:sizeof(args) atIndex:2]; const int64_t n = ggml_nelements(dst); @@ -4150,21 +4201,24 @@ static void ggml_metal_encode_node( const int64_t n_threads = MIN((int64_t)[pipeline maxTotalThreadsPerThreadgroup], parallel_elements); const int64_t n_tg = (parallel_elements + n_threads - 1) / n_threads; - // TODO: add ggml_metal_kargs struct + ggml_metal_kargs_pool_2d args_pool_2d = { + /* .k0 = */ k0, + /* .k1 = */ k1, + /* .s0 = */ s0, + /* .s1 = */ s1, + /* .p0 = */ p0, + /* .p1 = */ p1, + /* .IH = */ IH, + /* .IW = */ IW, + /* .OH = */ OH, + /* .OW = */ OW, + /* .parallel_elements = */ parallel_elements + }; + [encoder setComputePipelineState:pipeline]; - [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; - [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; - [encoder setBytes:&k0 length:sizeof(int32_t) atIndex:2]; - [encoder setBytes:&k1 length:sizeof(int32_t) atIndex:3]; - [encoder setBytes:&s0 length:sizeof(int32_t) atIndex:4]; - [encoder setBytes:&s1 length:sizeof(int32_t) atIndex:5]; - [encoder setBytes:&p0 length:sizeof(int32_t) atIndex:6]; - [encoder setBytes:&p1 length:sizeof(int32_t) atIndex:7]; - [encoder setBytes:&IH length:sizeof(int64_t) atIndex:8]; - [encoder setBytes:&IW length:sizeof(int64_t) atIndex:9]; - [encoder setBytes:&OH length:sizeof(int64_t) atIndex:10]; - [encoder setBytes:&OW length:sizeof(int64_t) atIndex:11]; - [encoder setBytes:¶llel_elements length:sizeof(int64_t) atIndex:12]; + [encoder setBuffer:id_src0 offset:offs_src0 atIndex:0]; + [encoder setBuffer:id_dst offset:offs_dst atIndex:1]; + [encoder setBytes:&args_pool_2d length:sizeof(args_pool_2d) atIndex:2]; [encoder dispatchThreadgroups:MTLSizeMake(n_tg, 1, 1) threadsPerThreadgroup:MTLSizeMake(n_threads, 1, 1)]; } break; diff --git a/ggml/src/ggml-metal/ggml-metal.metal b/ggml/src/ggml-metal/ggml-metal.metal index c46a13050..ad9d42a3e 100644 --- a/ggml/src/ggml-metal/ggml-metal.metal +++ b/ggml/src/ggml-metal/ggml-metal.metal @@ -947,45 +947,22 @@ kernel void kernel_cos( kernel void kernel_sum_rows( device const float * src0, device float * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant int64_t & ne03, - constant uint64_t & nb00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant uint64_t & nb03, - constant int64_t & ne10, - constant int64_t & ne11, - constant int64_t & ne12, - constant int64_t & ne13, - constant uint64_t & nb10, - constant uint64_t & nb11, - constant uint64_t & nb12, - constant uint64_t & nb13, - constant int64_t & ne0, - constant int64_t & ne1, - constant int64_t & ne2, - constant int64_t & ne3, - constant uint64_t & nb0, - constant uint64_t & nb1, - constant uint64_t & nb2, - constant uint64_t & nb3, + constant ggml_metal_kargs_sum_rows & args, uint3 tpig[[thread_position_in_grid]]) { int64_t i3 = tpig.z; int64_t i2 = tpig.y; int64_t i1 = tpig.x; - if (i3 >= ne03 || i2 >= ne02 || i1 >= ne01) { + if (i3 >= args.ne03 || i2 >= args.ne02 || i1 >= args.ne01) { return; } - device const float * src_row = (device const float *) ((device const char *) src0 + i1*nb01 + i2*nb02 + i3*nb03); - device float * dst_row = (device float *) ((device char *) dst + i1*nb1 + i2*nb2 + i3*nb3); + device const float * src_row = (device const float *) ((device const char *) src0 + i1*args.nb01 + i2*args.nb02 + i3*args.nb03); + device float * dst_row = (device float *) ((device char *) dst + i1*args.nb1 + i2*args.nb2 + i3*args.nb3); float row_sum = 0; - for (int64_t i0 = 0; i0 < ne00; i0++) { + for (int64_t i0 = 0; i0 < args.ne00; i0++) { row_sum += src_row[i0]; } @@ -997,36 +974,29 @@ kernel void kernel_soft_max( device const char * src0, device const char * src1, device char * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant float & scale, - constant float & max_bias, - constant float & m0, - constant float & m1, - constant uint32_t & n_head_log2, + constant ggml_metal_kargs_soft_max & args, threadgroup float * buf [[threadgroup(0)]], uint tgpig[[threadgroup_position_in_grid]], uint tpitg[[thread_position_in_threadgroup]], uint sgitg[[simdgroup_index_in_threadgroup]], uint tiisg[[thread_index_in_simdgroup]], uint ntg[[threads_per_threadgroup]]) { - const int64_t i03 = (tgpig) / (ne02*ne01); - const int64_t i02 = (tgpig - i03*ne02*ne01) / ne01; - const int64_t i01 = (tgpig - i03*ne02*ne01 - i02*ne01); + const int64_t i03 = (tgpig) / (args.ne02*args.ne01); + const int64_t i02 = (tgpig - i03*args.ne02*args.ne01) / args.ne01; + const int64_t i01 = (tgpig - i03*args.ne02*args.ne01 - i02*args.ne01); - device const float * psrc0 = (device const float *) src0 + (i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00); - device const T * pmask = src1 != src0 ? (device const T *) src1 + i01*ne00 : nullptr; - device float * pdst = (device float *) dst + (i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00); + device const float * psrc0 = (device const float *) src0 + (i03*args.ne02*args.ne01*args.ne00 + i02*args.ne01*args.ne00 + i01*args.ne00); + device const T * pmask = src1 != src0 ? (device const T *) src1 + i01*args.ne00 : nullptr; + device float * pdst = (device float *) dst + (i03*args.ne02*args.ne01*args.ne00 + i02*args.ne01*args.ne00 + i01*args.ne00); float slope = 1.0f; // ALiBi - if (max_bias > 0.0f) { + if (args.max_bias > 0.0f) { const int64_t h = i02; - const float base = h < n_head_log2 ? m0 : m1; - const int exp = h < n_head_log2 ? h + 1 : 2*(h - n_head_log2) + 1; + const float base = h < args.n_head_log2 ? args.m0 : args.m1; + const int exp = h < args.n_head_log2 ? h + 1 : 2*(h - args.n_head_log2) + 1; slope = pow(base, exp); } @@ -1034,8 +1004,8 @@ kernel void kernel_soft_max( // parallel max float lmax = -INFINITY; - for (int i00 = tpitg; i00 < ne00; i00 += ntg) { - lmax = MAX(lmax, psrc0[i00]*scale + (pmask ? slope*pmask[i00] : 0.0f)); + for (int i00 = tpitg; i00 < args.ne00; i00 += ntg) { + lmax = MAX(lmax, psrc0[i00]*args.scale + (pmask ? slope*pmask[i00] : 0.0f)); } // find the max value in the block @@ -1059,8 +1029,8 @@ kernel void kernel_soft_max( // parallel sum float lsum = 0.0f; - for (int i00 = tpitg; i00 < ne00; i00 += ntg) { - const float exp_psrc0 = exp((psrc0[i00]*scale + (pmask ? slope*pmask[i00] : 0.0f)) - max_val); + for (int i00 = tpitg; i00 < args.ne00; i00 += ntg) { + const float exp_psrc0 = exp((psrc0[i00]*args.scale + (pmask ? slope*pmask[i00] : 0.0f)) - max_val); lsum += exp_psrc0; pdst[i00] = exp_psrc0; } @@ -1090,7 +1060,7 @@ kernel void kernel_soft_max( const float inv_sum = 1.0f/sum; - for (int i00 = tpitg; i00 < ne00; i00 += ntg) { + for (int i00 = tpitg; i00 < args.ne00; i00 += ntg) { pdst[i00] *= inv_sum; } } @@ -1100,35 +1070,28 @@ kernel void kernel_soft_max_4( device const char * src0, device const char * src1, device char * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant float & scale, - constant float & max_bias, - constant float & m0, - constant float & m1, - constant uint32_t & n_head_log2, + constant ggml_metal_kargs_soft_max & args, threadgroup float * buf [[threadgroup(0)]], uint tgpig[[threadgroup_position_in_grid]], uint tpitg[[thread_position_in_threadgroup]], uint sgitg[[simdgroup_index_in_threadgroup]], uint tiisg[[thread_index_in_simdgroup]], uint ntg[[threads_per_threadgroup]]) { - const int64_t i03 = (tgpig) / (ne02*ne01); - const int64_t i02 = (tgpig - i03*ne02*ne01) / ne01; - const int64_t i01 = (tgpig - i03*ne02*ne01 - i02*ne01); + const int64_t i03 = (tgpig) / (args.ne02*args.ne01); + const int64_t i02 = (tgpig - i03*args.ne02*args.ne01) / args.ne01; + const int64_t i01 = (tgpig - i03*args.ne02*args.ne01 - i02*args.ne01); - device const float4 * psrc4 = (device const float4 *) src0 + (i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00)/4; - device const T * pmask = src1 != src0 ? (device const T *) src1 + i01*ne00/4 : nullptr; - device float4 * pdst4 = (device float4 *) dst + (i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00)/4; + device const float4 * psrc4 = (device const float4 *) src0 + (i03*args.ne02*args.ne01*args.ne00 + i02*args.ne01*args.ne00 + i01*args.ne00)/4; + device const T * pmask = src1 != src0 ? (device const T *) src1 + i01*args.ne00/4 : nullptr; + device float4 * pdst4 = (device float4 *) dst + (i03*args.ne02*args.ne01*args.ne00 + i02*args.ne01*args.ne00 + i01*args.ne00)/4; float slope = 1.0f; - if (max_bias > 0.0f) { + if (args.max_bias > 0.0f) { const int64_t h = i02; - const float base = h < n_head_log2 ? m0 : m1; - const int exp = h < n_head_log2 ? h + 1 : 2*(h - n_head_log2) + 1; + const float base = h < args.n_head_log2 ? args.m0 : args.m1; + const int exp = h < args.n_head_log2 ? h + 1 : 2*(h - args.n_head_log2) + 1; slope = pow(base, exp); } @@ -1136,8 +1099,8 @@ kernel void kernel_soft_max_4( // parallel max float4 lmax4 = -INFINITY; - for (int i00 = tpitg; i00 < ne00/4; i00 += ntg) { - lmax4 = fmax(lmax4, psrc4[i00]*scale + (float4)((pmask ? slope*pmask[i00] : 0.0f))); + for (int i00 = tpitg; i00 < args.ne00/4; i00 += ntg) { + lmax4 = fmax(lmax4, psrc4[i00]*args.scale + (float4)((pmask ? slope*pmask[i00] : 0.0f))); } const float lmax = MAX(MAX(lmax4[0], lmax4[1]), MAX(lmax4[2], lmax4[3])); @@ -1162,8 +1125,8 @@ kernel void kernel_soft_max_4( // parallel sum float4 lsum4 = 0.0f; - for (int i00 = tpitg; i00 < ne00/4; i00 += ntg) { - const float4 exp_psrc4 = exp((psrc4[i00]*scale + (float4)((pmask ? slope*pmask[i00] : 0.0f))) - max_val); + for (int i00 = tpitg; i00 < args.ne00/4; i00 += ntg) { + const float4 exp_psrc4 = exp((psrc4[i00]*args.scale + (float4)((pmask ? slope*pmask[i00] : 0.0f))) - max_val); lsum4 += exp_psrc4; pdst4[i00] = exp_psrc4; } @@ -1195,7 +1158,7 @@ kernel void kernel_soft_max_4( const float inv_sum = 1.0f/sum; - for (int i00 = tpitg; i00 < ne00/4; i00 += ntg) { + for (int i00 = tpitg; i00 < args.ne00/4; i00 += ntg) { pdst4[i00] *= inv_sum; } } @@ -1211,27 +1174,23 @@ template [[host_name("kernel_soft_max_f32_4")]] kernel kernel_soft_max_4_t kerne kernel void kernel_diag_mask_inf( device const float * src0, device float * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int & n_past, + constant ggml_metal_kargs_diag_mask_inf & args, uint3 tpig[[thread_position_in_grid]]) { const int64_t i02 = tpig[2]; const int64_t i01 = tpig[1]; const int64_t i00 = tpig[0]; - if (i00 > n_past + i01) { - dst[i02*ne01*ne00 + i01*ne00 + i00] = -INFINITY; + if (i00 > args.n_past + i01) { + dst[i02*args.ne01*args.ne00 + i01*args.ne00 + i00] = -INFINITY; } else { - dst[i02*ne01*ne00 + i01*ne00 + i00] = src0[i02*ne01*ne00 + i01*ne00 + i00]; + dst[i02*args.ne01*args.ne00 + i01*args.ne00 + i00] = src0[i02*args.ne01*args.ne00 + i01*args.ne00 + i00]; } } kernel void kernel_diag_mask_inf_8( device const float4 * src0, device float4 * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int & n_past, + constant ggml_metal_kargs_diag_mask_inf & args, uint3 tpig[[thread_position_in_grid]]) { const int64_t i = 2*tpig[0]; @@ -1239,42 +1198,26 @@ kernel void kernel_diag_mask_inf_8( dst[i+0] = src0[i+0]; dst[i+1] = src0[i+1]; int64_t i4 = 4*i; - const int64_t i02 = i4/(ne00*ne01); i4 -= i02*ne00*ne01; - const int64_t i01 = i4/(ne00); i4 -= i01*ne00; + const int64_t i02 = i4/(args.ne00*args.ne01); i4 -= i02*args.ne00*args.ne01; + const int64_t i01 = i4/(args.ne00); i4 -= i01*args.ne00; const int64_t i00 = i4; for (int k = 3; k >= 0; --k) { - if (i00 + 4 + k <= n_past + i01) { + if (i00 + 4 + k <= args.n_past + i01) { break; } dst[i+1][k] = -INFINITY; - if (i00 + k > n_past + i01) { + if (i00 + k > args.n_past + i01) { dst[i][k] = -INFINITY; } } } // ref: ggml.c:ggml_compute_forward_ssm_conv_f32 -// TODO: optimize kernel void kernel_ssm_conv_f32( device const void * src0, device const void * src1, device float * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant uint64_t & nb00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant int64_t & ne10, - constant int64_t & ne11, - constant uint64_t & nb10, - constant uint64_t & nb11, - constant int64_t & ne0, - constant int64_t & ne1, - constant int64_t & ne2, - constant uint64_t & nb0, - constant uint64_t & nb1, - constant uint64_t & nb2, + constant ggml_metal_kargs_ssm_conv & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]], uint3 ntg[[threads_per_threadgroup]]) { @@ -1282,15 +1225,15 @@ kernel void kernel_ssm_conv_f32( const int64_t i2 = tgpig.y; const int64_t i3 = tgpig.z; - const int64_t nc = ne10; - //const int64_t ncs = ne00; - //const int64_t nr = ne01; - //const int64_t n_t = ne1; - //const int64_t n_s = ne2; + const int64_t nc = args.ne10; + //const int64_t ncs = args.ne00; + //const int64_t nr = args.ne01; + //const int64_t n_t = args.ne1; + //const int64_t n_s = args.ne2; - device const float * s = (device const float *) ((device const char *) src0 + ir*nb01 + i2*nb00 + i3*nb02); - device const float * c = (device const float *) ((device const char *) src1 + ir*nb11); - device float * x = (device float *) ((device char *) dst + ir*nb0 + i2*nb1 + i3*nb2); + device const float * s = (device const float *) ((device const char *) src0 + ir*args.nb01 + i2*args.nb00 + i3*args.nb02); + device const float * c = (device const float *) ((device const char *) src1 + ir*args.nb11); + device float * x = (device float *) ((device char *) dst + ir*args.nb0 + i2*args.nb1 + i3*args.nb2); float sumf = 0.0f; @@ -1302,7 +1245,6 @@ kernel void kernel_ssm_conv_f32( } // ref: ggml.c:ggml_compute_forward_ssm_scan_f32 -// TODO: optimize kernel void kernel_ssm_scan_f32( device const void * src0, device const void * src1, @@ -1311,48 +1253,27 @@ kernel void kernel_ssm_scan_f32( device const void * src4, device const void * src5, device float * dst, - constant int64_t & d_state, - constant int64_t & d_inner, - constant int64_t & n_seq_tokens, - constant int64_t & n_seqs, - constant uint64_t & nb00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant uint64_t & nb10, - constant uint64_t & nb11, - constant uint64_t & nb12, - constant uint64_t & nb13, - constant uint64_t & nb20, - constant uint64_t & nb21, - constant uint64_t & nb22, - constant uint64_t & nb30, - constant uint64_t & nb31, - constant uint64_t & nb40, - constant uint64_t & nb41, - constant uint64_t & nb42, - constant uint64_t & nb50, - constant uint64_t & nb51, - constant uint64_t & nb52, + constant ggml_metal_kargs_ssm_scan & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]], uint3 ntg[[threads_per_threadgroup]]) { const int64_t ir = tgpig.x; const int64_t i3 = tgpig.y; - const int64_t nc = d_state; - //const int64_t nr = d_inner; - const int64_t n_t = n_seq_tokens; - //const int64_t n_s = n_seqs; + const int64_t nc = args.d_state; + // const int64_t nr = args.d_inner; + const int64_t n_t = args.n_seq_tokens; + // const int64_t n_s = args.n_seqs; for (int64_t i2 = 0; i2 < n_t; ++i2) { - device const float * s0 = (device const float *) ((device const char *) src0 + ir*nb01 + i3*nb02); - device const float * x = (device const float *) ((device const char *) src1 + ir*nb10 + i2*nb11 + i3*nb12); - device const float * dt = (device const float *) ((device const char *) src2 + ir*nb20 + i2*nb21 + i3*nb22); - device const float * A = (device const float *) ((device const char *) src3 + ir*nb31); - device const float * B = (device const float *) ((device const char *) src4 + i2*nb41 + i3*nb42); - device const float * C = (device const float *) ((device const char *) src5 + i2*nb51 + i3*nb52); - device float * y = (device float *) ((device char *) dst + ir*nb10 + i2*nb11 + i3*nb12); // TODO: do not use src1 strides - device float * s = (device float *) ((device char *) dst + ir*nb01 + i3*nb02 + nb13); + device const float * s0 = (device const float *) ((device const char *) src0 + ir*args.nb01 + i3*args.nb02); + device const float * x = (device const float *) ((device const char *) src1 + ir*args.nb10 + i2*args.nb11 + i3*args.nb12); + device const float * dt = (device const float *) ((device const char *) src2 + ir*args.nb20 + i2*args.nb21 + i3*args.nb22); + device const float * A = (device const float *) ((device const char *) src3 + ir*args.nb31); + device const float * B = (device const float *) ((device const char *) src4 + i2*args.nb41 + i3*args.nb42); + device const float * C = (device const float *) ((device const char *) src5 + i2*args.nb51 + i3*args.nb52); + device float * y = (device float *) ((device char *) dst + ir*args.nb10 + i2*args.nb11 + i3*args.nb12); // TODO: do not use src1 strides + device float * s = (device float *) ((device char *) dst + ir*args.nb01 + i3*args.nb02 + args.nb13); if (i2 > 0) { s0 = s; @@ -1545,22 +1466,15 @@ kernel void kernel_rms_norm( kernel void kernel_group_norm( device const float * src0, device float * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant uint64_t & nb00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant int32_t & n_groups, - constant float & eps, + constant ggml_metal_kargs_group_norm & args, threadgroup float * buf [[threadgroup(0)]], uint tgpig[[threadgroup_position_in_grid]], uint tpitg[[thread_position_in_threadgroup]], uint sgitg[[simdgroup_index_in_threadgroup]], uint tiisg[[thread_index_in_simdgroup]], uint ntg[[threads_per_threadgroup]]) { - const int64_t ne = ne00*ne01*ne02; - const int64_t gs = ne00*ne01*((ne02 + n_groups - 1) / n_groups); + const int64_t ne = args.ne00*args.ne01*args.ne02; + const int64_t gs = args.ne00*args.ne01*((args.ne02 + args.n_groups - 1) / args.n_groups); int start = tgpig * gs; int end = start + gs; @@ -1624,7 +1538,7 @@ kernel void kernel_group_norm( } const float variance = tmp / gs; - const float scale = 1.0f/sqrt(variance + eps); + const float scale = 1.0f/sqrt(variance + args.eps); for (int j = start; j < end; j += ntg) { dst[j] *= scale; } @@ -2588,17 +2502,7 @@ template [[host_name("kernel_rope_neox_f16")]] kernel kernel_rope_neox_t kernel_ typedef void (im2col_t)( device const float * x, device char * dst, - constant int32_t & ofs0, - constant int32_t & ofs1, - constant int32_t & IW, - constant int32_t & IH, - constant int32_t & CHW, - constant int32_t & s0, - constant int32_t & s1, - constant int32_t & p0, - constant int32_t & p1, - constant int32_t & d0, - constant int32_t & d1, + constant ggml_metal_kargs_im2col & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]], uint3 tpitg[[thread_position_in_threadgroup]], @@ -2608,17 +2512,7 @@ template kernel void kernel_im2col( device const float * x, device char * dst, - constant int32_t & ofs0, - constant int32_t & ofs1, - constant int32_t & IW, - constant int32_t & IH, - constant int32_t & CHW, - constant int32_t & s0, - constant int32_t & s1, - constant int32_t & p0, - constant int32_t & p1, - constant int32_t & d0, - constant int32_t & d1, + constant ggml_metal_kargs_im2col & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]], uint3 tpitg[[thread_position_in_threadgroup]], @@ -2639,17 +2533,17 @@ kernel void kernel_im2col( const int64_t ioh = tgpig[1]; const int64_t iow = tgpig[2]; - const int64_t iiw = iow*s0 + ikw*d0 - p0; - const int64_t iih = ioh*s1 + ikh*d1 - p1; + const int64_t iiw = iow*args.s0 + ikw*args.d0 - args.p0; + const int64_t iih = ioh*args.s1 + ikh*args.d1 - args.p1; - const int64_t offset_dst = (in*OH*OW + ioh*OW + iow)*CHW + (iic*(KH*KW) + ikh*KW + ikw); + const int64_t offset_dst = (in*OH*OW + ioh*OW + iow)*args.CHW + (iic*(KH*KW) + ikh*KW + ikw); device T * pdst = (device T *) (dst); - if (iih < 0 || iih >= IH || iiw < 0 || iiw >= IW) { + if (iih < 0 || iih >= args.IH || iiw < 0 || iiw >= args.IW) { pdst[offset_dst] = 0.0f; } else { - const int64_t offset_src = in*ofs0 + iic*ofs1 + iih*IW + iiw; + const int64_t offset_src = in*args.ofs0 + iic*args.ofs1 + iih*args.IW + iiw; pdst[offset_dst] = x[offset_src]; } } @@ -2660,20 +2554,7 @@ template [[host_name("kernel_im2col_f16")]] kernel im2col_t kernel_im2col; typedef void (im2col_ext_t)( device const float * x, device char * dst, - constant int32_t & ofs0, - constant int32_t & ofs1, - constant int32_t & IW, - constant int32_t & IH, - constant int32_t & CHW, - constant int32_t & s0, - constant int32_t & s1, - constant int32_t & p0, - constant int32_t & p1, - constant int32_t & d0, - constant int32_t & d1, - constant int32_t & N, - constant int32_t & KH, - constant int32_t & KW, + constant ggml_metal_kargs_im2col & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]], uint3 tpitg[[thread_position_in_threadgroup]], @@ -2683,53 +2564,40 @@ template kernel void kernel_im2col_ext( device const float * x, device char * dst, - constant int32_t & ofs0, - constant int32_t & ofs1, - constant int32_t & IW, - constant int32_t & IH, - constant int32_t & CHW, - constant int32_t & s0, - constant int32_t & s1, - constant int32_t & p0, - constant int32_t & p1, - constant int32_t & d0, - constant int32_t & d1, - constant int32_t & N, - constant int32_t & KH, - constant int32_t & KW, + constant ggml_metal_kargs_im2col & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]], // tgpg[0] = D x IC x KH x KW, CHW = IC x KH x KW uint3 tpitg[[thread_position_in_threadgroup]], uint3 ntg[[threads_per_threadgroup]]) { // [M, 1, 1] - const int64_t KHW = KH * KW; // KHW == ntg[1] * ntg[2], KW == ntg[2] + const int64_t KHW = (int64_t)args.KHW; - const int64_t d = tgpig[0] / CHW; - const int64_t chw = tgpig[0] % CHW; + const int64_t d = tgpig[0] / args.CHW; + const int64_t chw = tgpig[0] % args.CHW; const int64_t tgpig_0 = chw / KHW; // 0 ~ (IC - 1) const int64_t HW = tgpig[0] % KHW; const int64_t tpitg_0 = (d * ntg[0]) + tpitg[0]; - if (tpitg_0 >= N) { + if (tpitg_0 >= args.N) { return; } - const int64_t tpitg_1 = HW / KW; - const int64_t tpitg_2 = HW % KW; + const int64_t tpitg_1 = HW / args.KW; + const int64_t tpitg_2 = HW % args.KW; - const int64_t iiw = tgpig[2] * s0 + tpitg_2 * d0 - p0; - const int64_t iih = tgpig[1] * s1 + tpitg_1 * d1 - p1; + const int64_t iiw = tgpig[2] * args.s0 + tpitg_2 * args.d0 - args.p0; + const int64_t iih = tgpig[1] * args.s1 + tpitg_1 * args.d1 - args.p1; const int64_t offset_dst = - (tpitg_0 * tgpg[1] * tgpg[2] + tgpig[1] * tgpg[2] + tgpig[2]) * CHW + - (tgpig_0 * KHW + tpitg_1 * KW + tpitg_2); + (tpitg_0 * tgpg[1] * tgpg[2] + tgpig[1] * tgpg[2] + tgpig[2]) * args.CHW + + (tgpig_0 * KHW + tpitg_1 * args.KW + tpitg_2); device T * pdst = (device T *) (dst); - if (iih < 0 || iih >= IH || iiw < 0 || iiw >= IW) { + if (iih < 0 || iih >= args.IH || iiw < 0 || iiw >= args.IW) { pdst[offset_dst] = 0.0f; } else { - const int64_t offset_src = tpitg_0 * ofs0 + tgpig_0 * ofs1; - pdst[offset_dst] = x[offset_src + iih * IW + iiw]; + const int64_t offset_src = tpitg_0 * args.ofs0 + tgpig_0 * args.ofs1; + pdst[offset_dst] = x[offset_src + iih * args.IW + iiw]; } } @@ -2740,12 +2608,7 @@ typedef void (conv_transpose_1d_t)( device const float * src0, device const float * src1, device char * dst, - constant int32_t & IC, - constant int32_t & IL, - constant int32_t & K, - constant int32_t & s0, - constant uint64_t & nb0, - constant uint64_t & nb1, + constant ggml_metal_kargs_conv_transpose_1d & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]]); @@ -2754,29 +2617,24 @@ kernel void kernel_conv_transpose_1d( device const T * src0, device const float * src1, device char * dst, - constant int32_t & IC, - constant int32_t & IL, - constant int32_t & K, - constant int32_t & s0, - constant uint64_t & nb0, - constant uint64_t & nb1, + constant ggml_metal_kargs_conv_transpose_1d & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]]) { float v = 0.0f; - for (int64_t c = 0; c < IC; c++) { - const int32_t kernel_offset = c * tgpg[1] * K + K * tgpig[1]; - const int32_t input_offset = c * IL; + for (int64_t c = 0; c < args.IC; c++) { + const int32_t kernel_offset = c * tgpg[1] * args.K + args.K * tgpig[1]; + const int32_t input_offset = c * args.IL; - for (int64_t i = 0; i < IL; i++) { - if (tgpig[0] >= i * s0 && tgpig[0] < i * s0 + K) { - v += src0[kernel_offset + tgpig[0] - i * s0] * src1[input_offset + i]; + for (int64_t i = 0; i < args.IL; i++) { + if (tgpig[0] >= i * args.s0 && tgpig[0] < i * args.s0 + args.K) { + v += src0[kernel_offset + tgpig[0] - i * args.s0] * src1[input_offset + i]; } } } - device float * dst_ptr = (device float *) (dst + tgpig[0] * nb0 + tgpig[1] * nb1); + device float * dst_ptr = (device float *) (dst + tgpig[0] * args.nb0 + tgpig[1] * args.nb1); dst_ptr[0] = v; } @@ -2786,12 +2644,7 @@ kernel void kernel_conv_transpose_1d( device const float * src0, device const float * src1, device char * dst, - constant int32_t & IC, - constant int32_t & IL, - constant int32_t & K, - constant int32_t & s0, - constant uint64_t & nb0, - constant uint64_t & nb1, + constant ggml_metal_kargs_conv_transpose_1d & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]]); @@ -2800,38 +2653,14 @@ kernel void kernel_conv_transpose_1d( device const half * src0, device const float * src1, device char * dst, - constant int32_t & IC, - constant int32_t & IL, - constant int32_t & K, - constant int32_t & s0, - constant uint64_t & nb0, - constant uint64_t & nb1, + constant ggml_metal_kargs_conv_transpose_1d & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]]); kernel void kernel_upscale_f32( device const char * src0, device char * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant int64_t & ne03, - constant uint64_t & nb00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant uint64_t & nb03, - constant int64_t & ne0, - constant int64_t & ne1, - constant int64_t & ne2, - constant int64_t & ne3, - constant uint64_t & nb0, - constant uint64_t & nb1, - constant uint64_t & nb2, - constant uint64_t & nb3, - constant float & sf0, - constant float & sf1, - constant float & sf2, - constant float & sf3, + constant ggml_metal_kargs_upscale & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]], uint3 ntg[[threads_per_threadgroup]]) { @@ -2840,15 +2669,15 @@ kernel void kernel_upscale_f32( const int64_t i2 = tgpig.y; const int64_t i1 = tgpig.x; - const int64_t i03 = i3/sf3; - const int64_t i02 = i2/sf2; - const int64_t i01 = i1/sf1; + const int64_t i03 = i3/args.sf3; + const int64_t i02 = i2/args.sf2; + const int64_t i01 = i1/args.sf1; - for (int i0 = tpitg.x; i0 < ne0; i0 += ntg.x) { - const int64_t i00 = i0/sf0; + for (int i0 = tpitg.x; i0 < args.ne0; i0 += ntg.x) { + const int64_t i00 = i0/args.sf0; - device const float * src0_ptr = (device const float *) (src0 + i03*nb03 + i02*nb02 + i01*nb01 + i00*nb00); - device float * dst_ptr = (device float *) (dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0); + device const float * src0_ptr = (device const float *) (src0 + i03*args.nb03 + i02*args.nb02 + i01*args.nb01 + i00*args.nb00); + device float * dst_ptr = (device float *) (dst + i3*args.nb3 + i2*args.nb2 + i1*args.nb1 + i0*args.nb0); dst_ptr[0] = src0_ptr[0]; } @@ -2857,22 +2686,7 @@ kernel void kernel_upscale_f32( kernel void kernel_pad_f32( device const char * src0, device char * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant int64_t & ne03, - constant uint64_t & nb00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant uint64_t & nb03, - constant int64_t & ne0, - constant int64_t & ne1, - constant int64_t & ne2, - constant int64_t & ne3, - constant uint64_t & nb0, - constant uint64_t & nb1, - constant uint64_t & nb2, - constant uint64_t & nb3, + constant ggml_metal_kargs_pad & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]], uint3 ntg[[threads_per_threadgroup]]) { @@ -2885,12 +2699,12 @@ kernel void kernel_pad_f32( const int64_t i02 = i2; const int64_t i01 = i1; - device const float * src0_ptr = (device const float *) (src0 + i03*nb03 + i02*nb02 + i01*nb01); - device float * dst_ptr = (device float *) (dst + i3*nb3 + i2*nb2 + i1*nb1); + device const float * src0_ptr = (device const float *) (src0 + i03*args.nb03 + i02*args.nb02 + i01*args.nb01); + device float * dst_ptr = (device float *) (dst + i3*args.nb3 + i2*args.nb2 + i1*args.nb1); - if (i1 < ne01 && i2 < ne02 && i3 < ne03) { - for (int i0 = tpitg.x; i0 < ne0; i0 += ntg.x) { - if (i0 < ne00) { + if (i1 < args.ne01 && i2 < args.ne02 && i3 < args.ne03) { + for (int i0 = tpitg.x; i0 < args.ne0; i0 += ntg.x) { + if (i0 < args.ne00) { dst_ptr[i0] = src0_ptr[i0]; } else { dst_ptr[i0] = 0.0f; @@ -2900,7 +2714,7 @@ kernel void kernel_pad_f32( return; } - for (int i0 = tpitg.x; i0 < ne0; i0 += ntg.x) { + for (int i0 = tpitg.x; i0 < args.ne0; i0 += ntg.x) { dst_ptr[i0] = 0.0f; } } @@ -2908,21 +2722,7 @@ kernel void kernel_pad_f32( kernel void kernel_pad_reflect_1d_f32( device const char * src0, device char * dst, - constant int64_t & ne00, - constant int64_t & ne01, - constant int64_t & ne02, - constant int64_t & ne03, - constant int64_t & ne0, - constant uint64_t & nb00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant uint64_t & nb03, - constant uint64_t & nb0, - constant uint64_t & nb1, - constant uint64_t & nb2, - constant uint64_t & nb3, - constant int32_t & p0, - constant int32_t & p1, + constant ggml_metal_kargs_pad_reflect_1d & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tgpg[[threadgroups_per_grid]], uint3 tpitg[[thread_position_in_threadgroup]], @@ -2936,17 +2736,17 @@ kernel void kernel_pad_reflect_1d_f32( const int64_t i02 = i2; const int64_t i01 = i1; - device const float * src0_ptr = (device const float *) (src0 + i03*nb03 + i02*nb02 + i01*nb01); - device float * dst_ptr = (device float *) (dst + i3*nb3 + i2*nb2 + i1*nb1); + device const float * src0_ptr = (device const float *) (src0 + i03*args.nb03 + i02*args.nb02 + i01*args.nb01); + device float * dst_ptr = (device float *) (dst + i3*args.nb3 + i2*args.nb2 + i1*args.nb1); - if (i1 < ne01 && i2 < ne02 && i3 < ne03) { - for (int i0 = tpitg.x; i0 < ne0; i0 += ntg.x) { - if (i0 < p0) { - dst_ptr[i0] = src0_ptr[p0 - i0]; - } else if (i0 < ne0 - p1) { - dst_ptr[i0] = src0_ptr[i0 - p0]; + if (i1 < args.ne01 && i2 < args.ne02 && i3 < args.ne03) { + for (int i0 = tpitg.x; i0 < args.ne0; i0 += ntg.x) { + if (i0 < args.p0) { + dst_ptr[i0] = src0_ptr[args.p0 - i0]; + } else if (i0 < args.ne0 - args.p1) { + dst_ptr[i0] = src0_ptr[i0 - args.p0]; } else { - dst_ptr[i0] = src0_ptr[(ne0 - p1 - p0) - (p1 + 1 - (ne0 - i0)) - 1]; + dst_ptr[i0] = src0_ptr[(args.ne0 - args.p1 - args.p0) - (args.p1 + 1 - (args.ne0 - i0)) - 1]; } } } @@ -2954,44 +2754,40 @@ kernel void kernel_pad_reflect_1d_f32( kernel void kernel_arange_f32( device char * dst, - constant int64_t & ne0, - constant float & start, - constant float & step, + constant ggml_metal_kargs_arange & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]], uint3 ntg[[threads_per_threadgroup]]) { device float * dst_ptr = (device float *) dst; - for (int i0 = tpitg.x; i0 < ne0; i0 += ntg.x) { - dst_ptr[i0] = start + step * i0; + for (int i0 = tpitg.x; i0 < args.ne0; i0 += ntg.x) { + dst_ptr[i0] = args.start + args.step * i0; } } kernel void kernel_timestep_embedding_f32( device const char * src0, device char * dst, - constant uint64_t & nb1, - constant int & dim, - constant int & max_period, + constant ggml_metal_kargs_timestep_embedding & args, uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]], uint3 ntg[[threads_per_threadgroup]]) { int i = tgpig.x; - device float * embed_data = (device float *)(dst + i*nb1); + device float * embed_data = (device float *)(dst + i*args.nb1); - int half_ = dim / 2; + int half_ = args.dim / 2; for (int j = tpitg.x; j < half_; j += ntg.x) { float timestep = ((device float *)src0)[i]; - float freq = (float)exp(-log((float)max_period) * j / half_); + float freq = (float)exp(-log((float)args.max_period) * j / half_); float arg = timestep * freq; embed_data[j ] = cos(arg); embed_data[j + half_] = sin(arg); } - if (dim % 2 != 0 && tpitg.x == 0) { - embed_data[dim] = 0.f; + if (args.dim % 2 != 0 && tpitg.x == 0) { + embed_data[args.dim] = 0.f; } } @@ -2999,8 +2795,7 @@ kernel void kernel_timestep_embedding_f32( typedef void (argsort_t)( device const float * x, device int32_t * dst, - constant int64_t & ncols, - constant int64_t & ncols_pad, + constant ggml_metal_kargs_argsort & args, threadgroup int32_t * shared_values [[threadgroup(0)]], uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]]); @@ -3009,8 +2804,7 @@ template kernel void kernel_argsort_f32_i32( device const float * x, device int32_t * dst, - constant int64_t & ncols, - constant int64_t & ncols_pad, + constant ggml_metal_kargs_argsort & args, threadgroup int32_t * shared_values [[threadgroup(0)]], uint3 tgpig[[threadgroup_position_in_grid]], uint3 tpitg[[thread_position_in_threadgroup]]) { @@ -3018,9 +2812,9 @@ kernel void kernel_argsort_f32_i32( int col = tpitg[0]; int row = tgpig[1]; - if (col >= ncols_pad) return; + if (col >= args.ncols_pad) return; - device const float * x_row = x + row * ncols; + device const float * x_row = x + row * args.ncols; threadgroup int32_t * dst_row = shared_values; // initialize indices @@ -3028,21 +2822,21 @@ kernel void kernel_argsort_f32_i32( threadgroup_barrier(mem_flags::mem_threadgroup); - for (int k = 2; k <= ncols_pad; k *= 2) { + for (int k = 2; k <= args.ncols_pad; k *= 2) { for (int j = k / 2; j > 0; j /= 2) { int ixj = col ^ j; if (ixj > col) { if ((col & k) == 0) { - if (dst_row[col] >= ncols || - (dst_row[ixj] < ncols && (order == GGML_SORT_ORDER_ASC ? + if (dst_row[col] >= args.ncols || + (dst_row[ixj] < args.ncols && (order == GGML_SORT_ORDER_ASC ? x_row[dst_row[col]] > x_row[dst_row[ixj]] : x_row[dst_row[col]] < x_row[dst_row[ixj]])) ) { SWAP(dst_row[col], dst_row[ixj]); } } else { - if (dst_row[ixj] >= ncols || - (dst_row[col] < ncols && (order == GGML_SORT_ORDER_ASC ? + if (dst_row[ixj] >= args.ncols || + (dst_row[col] < args.ncols && (order == GGML_SORT_ORDER_ASC ? x_row[dst_row[col]] < x_row[dst_row[ixj]] : x_row[dst_row[col]] > x_row[dst_row[ixj]])) ) { @@ -3055,8 +2849,8 @@ kernel void kernel_argsort_f32_i32( } // copy the result to dst without the padding - if (col < ncols) { - dst[row * ncols + col] = dst_row[col]; + if (col < args.ncols) { + dst[row * args.ncols + col] = dst_row[col]; } } @@ -3066,9 +2860,9 @@ template [[host_name("kernel_argsort_f32_i32_desc")]] kernel argsort_t kernel_ar kernel void kernel_leaky_relu_f32( device const float * src0, device float * dst, - constant float & slope, + constant ggml_metal_kargs_leaky_relu & args, uint tpig[[thread_position_in_grid]]) { - dst[tpig] = src0[tpig] > 0.0f ? src0[tpig] : src0[tpig] * slope; + dst[tpig] = src0[tpig] > 0.0f ? src0[tpig] : src0[tpig] * args.slope; } // ref: https://arxiv.org/pdf/2307.08691.pdf @@ -6009,28 +5803,21 @@ kernel void kernel_get_rows_q( device const void * src0, device const void * src1, device float * dst, - constant int64_t & ne00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant int64_t & ne10, - constant uint64_t & nb10, - constant uint64_t & nb11, - constant uint64_t & nb1, - constant uint64_t & nb2, + constant ggml_metal_kargs_get_rows & args, uint3 tgpig[[threadgroup_position_in_grid]], uint tiitg[[thread_index_in_threadgroup]], uint3 tptg [[threads_per_threadgroup]]) { const int64_t i10 = tgpig.x; const int64_t i11 = tgpig.y; - const int64_t r = ((const device int32_t *) ((const device char *) src1 + i11*nb11 + i10*nb10))[0]; + const int64_t r = ((const device int32_t *) ((const device char *) src1 + i11*args.nb11 + i10*args.nb10))[0]; const int64_t i02 = i11; - for (int64_t ind = tiitg; ind < ne00/16; ind += tptg.x) { + for (int64_t ind = tiitg; ind < args.ne00/16; ind += tptg.x) { float4x4 temp; - dequantize_func(((device const block_q *) ((const device char *) src0 + r*nb01 + i02*nb02)) + ind/nl, ind%nl, temp); - *(((device float4x4 *) ((device char *) dst + i11*nb2 + i10*nb1)) + ind) = temp; + dequantize_func(((device const block_q *) ((const device char *) src0 + r*args.nb01 + i02*args.nb02)) + ind/nl, ind%nl, temp); + *(((device float4x4 *) ((device char *) dst + i11*args.nb2 + i10*args.nb1)) + ind) = temp; } } @@ -6039,27 +5826,20 @@ kernel void kernel_get_rows_f( device const void * src0, device const void * src1, device float * dst, - constant int64_t & ne00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant int64_t & ne10, - constant uint64_t & nb10, - constant uint64_t & nb11, - constant uint64_t & nb1, - constant uint64_t & nb2, + constant ggml_metal_kargs_get_rows & args, uint3 tgpig[[threadgroup_position_in_grid]], uint tiitg[[thread_index_in_threadgroup]], uint3 tptg [[threads_per_threadgroup]]) { const int64_t i10 = tgpig.x; const int64_t i11 = tgpig.y; - const int64_t r = ((const device int32_t *) ((const device char *) src1 + i11*nb11 + i10*nb10))[0]; + const int64_t r = ((const device int32_t *) ((const device char *) src1 + i11*args.nb11 + i10*args.nb10))[0]; const int64_t i02 = i11; - for (int ind = tiitg; ind < ne00; ind += tptg.x) { - (( device float *) (( device char *) dst + i11*nb2 + i10*nb1))[ind] = - ((const device T *) ((const device char *) src0 + i02*nb02 + r*nb01))[ind]; + for (int ind = tiitg; ind < args.ne00; ind += tptg.x) { + (( device float *) (( device char *) dst + i11*args.nb2 + i10*args.nb1))[ind] = + ((const device T *) ((const device char *) src0 + i02*args.nb02 + r*args.nb01))[ind]; } } @@ -6067,27 +5847,20 @@ kernel void kernel_get_rows_i32( device const void * src0, device const void * src1, device int32_t * dst, - constant int64_t & ne00, - constant uint64_t & nb01, - constant uint64_t & nb02, - constant int64_t & ne10, - constant uint64_t & nb10, - constant uint64_t & nb11, - constant uint64_t & nb1, - constant uint64_t & nb2, + constant ggml_metal_kargs_get_rows & args, uint3 tgpig[[threadgroup_position_in_grid]], uint tiitg[[thread_index_in_threadgroup]], uint3 tptg [[threads_per_threadgroup]]) { const int64_t i10 = tgpig.x; const int64_t i11 = tgpig.y; - const int64_t r = ((const device int32_t *) ((const device char *) src1 + i11*nb11 + i10*nb10))[0]; + const int64_t r = ((const device int32_t *) ((const device char *) src1 + i11*args.nb11 + i10*args.nb10))[0]; const int64_t i02 = i11; - for (int ind = tiitg; ind < ne00; ind += tptg.x) { - (( device int32_t *) (( device char *) dst + i11*nb2 + i10*nb1))[ind] = - ((const device int32_t *) ((const device char *) src0 + i02*nb02 + r*nb01))[ind]; + for (int ind = tiitg; ind < args.ne00; ind += tptg.x) { + (( device int32_t *) (( device char *) dst + i11*args.nb2 + i10*args.nb1))[ind] = + ((const device int32_t *) ((const device char *) src0 + i02*args.nb02 + r*args.nb01))[ind]; } } @@ -6689,98 +6462,78 @@ template [[host_name("kernel_mul_mv_id_iq4_xs_f32")]] kernel kernel_mul_mv_id_t kernel void kernel_pool_2d_max_f32( device const float * src0, device float * dst, - constant int32_t & k0, - constant int32_t & k1, - constant int32_t & s0, - constant int32_t & s1, - constant int32_t & p0, - constant int32_t & p1, - constant int64_t & IH, - constant int64_t & IW, - constant int64_t & OH, - constant int64_t & OW, - constant int64_t & parallel_elements, + constant ggml_metal_kargs_pool_2d & args, uint gid[[thread_position_in_grid]]) { - if (gid >= parallel_elements) { + if (gid >= args.parallel_elements) { return; } const int idx = gid; - const int I_HW = IH * IW; - const int O_HW = OH * OW; + const int I_HW = args.IH * args.IW; + const int O_HW = args.OH * args.OW; const int nc = idx / O_HW; - const int cur_oh = idx % O_HW / OW; - const int cur_ow = idx % O_HW % OW; + const int cur_oh = idx % O_HW / args.OW; + const int cur_ow = idx % O_HW % args.OW; device const float * i_ptr = src0 + nc * I_HW; device float * o_ptr = dst + nc * O_HW; - const int start_h = cur_oh * s1 - p1; + const int start_h = cur_oh * args.s1 - args.p1; const int bh = MAX(0, start_h); - const int eh = MIN(IH, start_h + k1); - const int start_w = cur_ow * s0 - p0; + const int eh = MIN(args.IH, start_h + args.k1); + const int start_w = cur_ow * args.s0 - args.p0; const int bw = MAX(0, start_w); - const int ew = MIN(IW, start_w + k0); + const int ew = MIN(args.IW, start_w + args.k0); float res = -INFINITY; for (int i = bh; i < eh; i += 1) { for (int j = bw; j < ew; j += 1) { - res = MAX(res, i_ptr[i * IW + j]); + res = MAX(res, i_ptr[i * args.IW + j]); } } - o_ptr[cur_oh * OW + cur_ow] = res; + o_ptr[cur_oh * args.OW + cur_ow] = res; } kernel void kernel_pool_2d_avg_f32( device const float * src0, device float * dst, - constant int32_t & k0, - constant int32_t & k1, - constant int32_t & s0, - constant int32_t & s1, - constant int32_t & p0, - constant int32_t & p1, - constant int64_t & IH, - constant int64_t & IW, - constant int64_t & OH, - constant int64_t & OW, - constant int64_t & parallel_elements, + constant ggml_metal_kargs_pool_2d & args, uint gid[[thread_position_in_grid]]) { - if (gid >= parallel_elements) { + if (gid >= args.parallel_elements) { return; } const int idx = gid; - const int I_HW = IH * IW; - const int O_HW = OH * OW; + const int I_HW = args.IH * args.IW; + const int O_HW = args.OH * args.OW; const int nc = idx / O_HW; - const int cur_oh = idx % O_HW / OW; - const int cur_ow = idx % O_HW % OW; + const int cur_oh = idx % O_HW / args.OW; + const int cur_ow = idx % O_HW % args.OW; device const float * i_ptr = src0 + nc * I_HW; device float * o_ptr = dst + nc * O_HW; - const int start_h = cur_oh * s1 - p1; + const int start_h = cur_oh * args.s1 - args.p1; const int bh = MAX(0, start_h); - const int eh = MIN(IH, start_h + k1); - const int start_w = cur_ow * s0 - p0; + const int eh = MIN(args.IH, start_h + args.k1); + const int start_w = cur_ow * args.s0 - args.p0; const int bw = MAX(0, start_w); - const int ew = MIN(IW, start_w + k0); + const int ew = MIN(args.IW, start_w + args.k0); // const float scale = 1. / ((eh - bh) * (ew - bw)); - const float scale = 1. / (k0 * k1); + const float scale = 1. / (args.k0 * args.k1); float res = 0; for (int i = bh; i < eh; i += 1) { for (int j = bw; j < ew; j += 1) { - float cur = i_ptr[i * IW + j]; + float cur = i_ptr[i * args.IW + j]; res += cur * scale; } } - o_ptr[cur_oh * OW + cur_ow] = res; + o_ptr[cur_oh * args.OW + cur_ow] = res; } From 7cf64f6beecf54c6ac71503181f154667fd4228a Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Fri, 7 Mar 2025 09:33:37 +0000 Subject: [PATCH 53/87] sync: minja - support QwQ-32B (#12235) https://github.com/google/minja/commit/8a76f7815e8a3ae00bd233c2b5a8b7d4e86564ec --- common/minja/minja.hpp | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/common/minja/minja.hpp b/common/minja/minja.hpp index c58dd66e0..fa4c34d6e 100644 --- a/common/minja/minja.hpp +++ b/common/minja/minja.hpp @@ -1378,13 +1378,27 @@ struct ArgumentsExpression { } }; -static std::string strip(const std::string & s) { - auto start = s.find_first_not_of(" \t\n\r"); +static std::string strip(const std::string & s, const std::string & chars = "", bool left = true, bool right = true) { + auto charset = chars.empty() ? " \t\n\r" : chars; + auto start = left ? s.find_first_not_of(charset) : 0; if (start == std::string::npos) return ""; - auto end = s.find_last_not_of(" \t\n\r"); + auto end = right ? s.find_last_not_of(charset) : s.size() - 1; return s.substr(start, end - start + 1); } +static std::vector split(const std::string & s, const std::string & sep) { + std::vector result; + size_t start = 0; + size_t end = s.find(sep); + while (end != std::string::npos) { + result.push_back(s.substr(start, end - start)); + start = end + sep.length(); + end = s.find(sep, start); + } + result.push_back(s.substr(start)); + return result; +} + static std::string capitalize(const std::string & s) { if (s.empty()) return s; auto result = s; @@ -1467,8 +1481,26 @@ public: } else if (obj.is_string()) { auto str = obj.get(); if (method->get_name() == "strip") { - vargs.expectArgs("strip method", {0, 0}, {0, 0}); - return Value(strip(str)); + vargs.expectArgs("strip method", {0, 1}, {0, 0}); + auto chars = vargs.args.empty() ? "" : vargs.args[0].get(); + return Value(strip(str, chars)); + } else if (method->get_name() == "lstrip") { + vargs.expectArgs("lstrip method", {0, 1}, {0, 0}); + auto chars = vargs.args.empty() ? "" : vargs.args[0].get(); + return Value(strip(str, chars, /* left= */ true, /* right= */ false)); + } else if (method->get_name() == "rstrip") { + vargs.expectArgs("rstrip method", {0, 1}, {0, 0}); + auto chars = vargs.args.empty() ? "" : vargs.args[0].get(); + return Value(strip(str, chars, /* left= */ false, /* right= */ true)); + } else if (method->get_name() == "split") { + vargs.expectArgs("split method", {1, 1}, {0, 0}); + auto sep = vargs.args[0].get(); + auto parts = split(str, sep); + Value result = Value::array(); + for (const auto& part : parts) { + result.push_back(Value(part)); + } + return result; } else if (method->get_name() == "capitalize") { vargs.expectArgs("capitalize method", {0, 0}, {0, 0}); return Value(capitalize(str)); From 8fad3c7a7c54a25a1ca38dfb08244df55288e675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigbj=C3=B8rn=20Skj=C3=A6ret?= Date: Fri, 7 Mar 2025 11:15:33 +0100 Subject: [PATCH 54/87] server : Log original chat template parsing error (#12233) --- examples/server/server.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/server/server.cpp b/examples/server/server.cpp index 2a526b0e7..e1371dbf8 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -1900,6 +1900,7 @@ struct server_context { try { common_chat_format_example(chat_templates.get(), params.use_jinja); } catch (const std::exception & e) { + SRV_WRN("%s: Chat template parsing error: %s\n", __func__, e.what()); SRV_WRN("%s: The chat template that comes with this model is not yet supported, falling back to chatml. This may cause the model to output suboptimal responses\n", __func__); chat_templates = common_chat_templates_init(model, "chatml"); } From ea002810a209246d034d1b6ddac387f778751588 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Fri, 7 Mar 2025 12:19:31 +0200 Subject: [PATCH 55/87] ci : fix save-load test invocations (#12245) --- ci/run.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci/run.sh b/ci/run.sh index 77c32ce00..9fc19c89d 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -352,10 +352,10 @@ function gg_run_open_llama_7b_v2 { (time ./bin/llama-imatrix --model ${model_f16} -f ${wiki_test} -t 1 -ngl 99 -c 2048 -b 512 --chunks 4 ) 2>&1 | tee -a $OUT/${ci}-imatrix.log - (time ./bin/llama-save-load-state--model ${model_q4_0} -ngl 10 -c 0 ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log - (time ./bin/llama-save-load-state--model ${model_q4_0} -ngl 10 -c 0 -fa ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log - (time ./bin/llama-save-load-state--model ${model_q4_0} -ngl 99 -c 0 ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log - (time ./bin/llama-save-load-state--model ${model_q4_0} -ngl 99 -c 0 -fa ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log + (time ./bin/llama-save-load-state --model ${model_q4_0} -ngl 10 -c 0 ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log + (time ./bin/llama-save-load-state --model ${model_q4_0} -ngl 10 -c 0 -fa ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log + (time ./bin/llama-save-load-state --model ${model_q4_0} -ngl 99 -c 0 ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log + (time ./bin/llama-save-load-state --model ${model_q4_0} -ngl 99 -c 0 -fa ) 2>&1 | tee -a $OUT/${ci}-save-load-state.log function check_ppl { qnt="$1" From 68d0027f3d19eb579c1863814c91e37ffa699014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20O?= Date: Fri, 7 Mar 2025 12:54:22 +0100 Subject: [PATCH 56/87] ggml-cpu: faster AVX2 variant for IQ1_M (#12216) --- ggml/src/ggml-cpu/ggml-cpu-quants.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/ggml/src/ggml-cpu/ggml-cpu-quants.c b/ggml/src/ggml-cpu/ggml-cpu-quants.c index 2ae66591d..8c7dbd1cc 100644 --- a/ggml/src/ggml-cpu/ggml-cpu-quants.c +++ b/ggml/src/ggml-cpu/ggml-cpu-quants.c @@ -11718,9 +11718,12 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const #elif defined __AVX2__ - const __m256i mask = _mm256_set1_epi16(2 * 0x7); + const __m256i mask = _mm256_set1_epi16(0x7); const __m256i mone = _mm256_set1_epi16(1); const __m256i mone8 = _mm256_set1_epi8(1); + const __m256i mtwo8 = _mm256_set1_epi8(2); + // VPSHUFB cannot cross 128-bit lanes so odd shifts go to upper half. + const __m256i scales_shift = _mm256_set_epi64x(9, 3, 6, 0); __m256 accum1 = _mm256_setzero_ps(); __m256 accum2 = _mm256_setzero_ps(); @@ -11732,6 +11735,14 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const const uint16_t * sc = (const uint16_t *)x[i].scales; scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000); + // Extract 3-bit scales (16 values) + __m256i scales = _mm256_set1_epi64x(*(const uint64_t*)sc); + scales = _mm256_srlv_epi64(scales, scales_shift); + scales = _mm256_add_epi16(_mm256_slli_epi16(_mm256_and_si256(scales, mask), 1), mone); + + // Indices to repeat each scale 8 times. + __m256i scales_idx1 = _mm256_set1_epi16(0x0100); + __m256i scales_idx2 = _mm256_add_epi8(scales_idx1, _mm256_set1_epi8(8)); __m256i sumi1 = _mm256_setzero_si256(); __m256i sumi2 = _mm256_setzero_si256(); @@ -11777,11 +11788,12 @@ void ggml_vec_dot_iq1_m_q8_K (int n, float * GGML_RESTRICT s, size_t bs, const const __m256i dot3 = _mm256_maddubs_epi16(mone8, _mm256_sign_epi8(q8b_1, delta1)); const __m256i dot4 = _mm256_maddubs_epi16(mone8, _mm256_sign_epi8(q8b_2, delta2)); - __m256i scale1 = MM256_SET_M128I(_mm_set1_epi16(sc[ib/2] >> 2), _mm_set1_epi16(sc[ib/2] << 1)); - __m256i scale2 = MM256_SET_M128I(_mm_set1_epi16(sc[ib/2] >> 8), _mm_set1_epi16(sc[ib/2] >> 5)); + __m256i scale1 = _mm256_shuffle_epi8(scales, scales_idx1); + __m256i scale2 = _mm256_shuffle_epi8(scales, scales_idx2); + + scales_idx1 = _mm256_add_epi8(scales_idx1, mtwo8); + scales_idx2 = _mm256_add_epi8(scales_idx2, mtwo8); - scale1 = _mm256_add_epi16(_mm256_and_si256(scale1, mask), mone); - scale2 = _mm256_add_epi16(_mm256_and_si256(scale2, mask), mone); const __m256i p1 = _mm256_madd_epi16(dot1, scale1); const __m256i p2 = _mm256_madd_epi16(dot2, scale2); const __m256i p3 = _mm256_madd_epi16(dot3, scale1); From d6ae2fa06139e496880cbf65197c84341e9d98e7 Mon Sep 17 00:00:00 2001 From: vmobilis <75476228+vmobilis@users.noreply.github.com> Date: Fri, 7 Mar 2025 11:11:40 +0300 Subject: [PATCH 57/87] ggml : ggml_compute_forward_concat() for arbitrary tensor type (ggml/1118) * ggml_compute_forward_concat() for arbitrary tensor type * Check that tensors' type match * ggml-cpu.c: check type of source tensors * ggml-cpu.c: move tensor type check to ggml_compute_forward_concat() * ggml.c: check concatenated tensor type * Remove tensor type check from ggml_compute_forward_concat() in ggml-cpu.c ..., as it was moved to ggml.c. --- ggml/src/ggml-cpu/ggml-cpu.c | 143 ++++++++++++++++++++++++++++++++++- ggml/src/ggml.c | 1 + 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c index c67fdd045..f2ab4c5d6 100644 --- a/ggml/src/ggml-cpu/ggml-cpu.c +++ b/ggml/src/ggml-cpu/ggml-cpu.c @@ -6648,6 +6648,135 @@ static void ggml_compute_forward_repeat_back( // ggml_compute_forward_concat +static void ggml_compute_forward_concat_any( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + const struct ggml_tensor * src1 = dst->src[1]; + + const size_t len = ggml_type_size(src0->type); + + const int ith = params->ith; + const int nth = params->nth; + + GGML_TENSOR_BINARY_OP_LOCALS + + const int32_t dim = ggml_get_op_params_i32(dst, 0); + + GGML_ASSERT(dim >= 0 && dim < 4); + + int64_t o[4] = {0, 0, 0, 0}; + o[dim] = src0->ne[dim]; + + const char * x; + + // TODO: smarter multi-theading + for (int i3 = 0; i3 < ne3; i3++) { + for (int i2 = ith; i2 < ne2; i2 += nth) { + for (int i1 = 0; i1 < ne1; i1++) { + for (int i0 = 0; i0 < ne0; i0++) { + if (i0 < ne00 && i1 < ne01 && i2 < ne02 && i3 < ne03) { + x = (const char *)src0->data + (i0 )*nb00 + (i1 )*nb01 + (i2 )*nb02 + (i3 )*nb03; + } else { + x = (const char *)src1->data + (i0 - o[0])*nb10 + (i1 - o[1])*nb11 + (i2 - o[2])*nb12 + (i3 - o[3])*nb13; + } + + char * y = (char *)dst->data + i0*nb0 + i1*nb1 + i2*nb2 + i3*nb3; + + memcpy(y, x, len); + } + } + } + } +} + +static void ggml_compute_forward_concat_i8( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + const struct ggml_tensor * src1 = dst->src[1]; + + GGML_ASSERT(ggml_type_size(src0->type) == sizeof(int8_t)); + + const int ith = params->ith; + const int nth = params->nth; + + GGML_TENSOR_BINARY_OP_LOCALS + + const int32_t dim = ggml_get_op_params_i32(dst, 0); + + GGML_ASSERT(dim >= 0 && dim < 4); + + int64_t o[4] = {0, 0, 0, 0}; + o[dim] = src0->ne[dim]; + + const int8_t * x; + + // TODO: smarter multi-theading + for (int i3 = 0; i3 < ne3; i3++) { + for (int i2 = ith; i2 < ne2; i2 += nth) { + for (int i1 = 0; i1 < ne1; i1++) { + for (int i0 = 0; i0 < ne0; i0++) { + if (i0 < ne00 && i1 < ne01 && i2 < ne02 && i3 < ne03) { + x = (const int8_t *) ((const char *)src0->data + (i0 )*nb00 + (i1 )*nb01 + (i2 )*nb02 + (i3 )*nb03); + } else { + x = (const int8_t *) ((const char *)src1->data + (i0 - o[0])*nb10 + (i1 - o[1])*nb11 + (i2 - o[2])*nb12 + (i3 - o[3])*nb13); + } + + int8_t * y = (int8_t *)((char *)dst->data + i0*nb0 + i1*nb1 + i2*nb2 + i3*nb3); + + *y = *x; + } + } + } + } +} + +static void ggml_compute_forward_concat_f16( + const struct ggml_compute_params * params, + struct ggml_tensor * dst) { + + const struct ggml_tensor * src0 = dst->src[0]; + const struct ggml_tensor * src1 = dst->src[1]; + + GGML_ASSERT(ggml_type_size(src0->type) == sizeof(ggml_fp16_t)); + + const int ith = params->ith; + const int nth = params->nth; + + GGML_TENSOR_BINARY_OP_LOCALS + + const int32_t dim = ggml_get_op_params_i32(dst, 0); + + GGML_ASSERT(dim >= 0 && dim < 4); + + int64_t o[4] = {0, 0, 0, 0}; + o[dim] = src0->ne[dim]; + + const ggml_fp16_t * x; + + // TODO: smarter multi-theading + for (int i3 = 0; i3 < ne3; i3++) { + for (int i2 = ith; i2 < ne2; i2 += nth) { + for (int i1 = 0; i1 < ne1; i1++) { + for (int i0 = 0; i0 < ne0; i0++) { + if (i0 < ne00 && i1 < ne01 && i2 < ne02 && i3 < ne03) { + x = (const ggml_fp16_t *) ((const char *)src0->data + (i0 )*nb00 + (i1 )*nb01 + (i2 )*nb02 + (i3 )*nb03); + } else { + x = (const ggml_fp16_t *) ((const char *)src1->data + (i0 - o[0])*nb10 + (i1 - o[1])*nb11 + (i2 - o[2])*nb12 + (i3 - o[3])*nb13); + } + + ggml_fp16_t * y = (ggml_fp16_t *)((char *)dst->data + i0*nb0 + i1*nb1 + i2*nb2 + i3*nb3); + + *y = *x; + } + } + } + } +} + static void ggml_compute_forward_concat_f32( const struct ggml_compute_params * params, struct ggml_tensor * dst) { @@ -6655,7 +6784,7 @@ static void ggml_compute_forward_concat_f32( const struct ggml_tensor * src0 = dst->src[0]; const struct ggml_tensor * src1 = dst->src[1]; - GGML_ASSERT(src0->nb[0] == sizeof(float)); + GGML_ASSERT(ggml_type_size(src0->type) == sizeof(float)); const int ith = params->ith; const int nth = params->nth; @@ -6698,6 +6827,16 @@ static void ggml_compute_forward_concat( const struct ggml_tensor * src0 = dst->src[0]; switch (src0->type) { + case GGML_TYPE_F16: + case GGML_TYPE_BF16: + case GGML_TYPE_I16: + { + ggml_compute_forward_concat_f16(params, dst); + } break; + case GGML_TYPE_I8: + { + ggml_compute_forward_concat_i8(params, dst); + } break; case GGML_TYPE_F32: case GGML_TYPE_I32: { @@ -6705,7 +6844,7 @@ static void ggml_compute_forward_concat( } break; default: { - GGML_ABORT("fatal error"); + ggml_compute_forward_concat_any(params, dst); } } } diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index 084240331..89409bb0e 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -2332,6 +2332,7 @@ struct ggml_tensor * ggml_concat( struct ggml_tensor * b, int dim) { GGML_ASSERT(dim >= 0 && dim < GGML_MAX_DIMS); + GGML_ASSERT(a->type == b->type); int64_t ne[GGML_MAX_DIMS]; for (int d = 0; d < GGML_MAX_DIMS; ++d) { From 102ac1891db32c346a7b6b96145a2a23c1e4c352 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Fri, 7 Mar 2025 14:00:27 +0200 Subject: [PATCH 58/87] sync : ggml ggml-ci --- scripts/sync-ggml.last | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sync-ggml.last b/scripts/sync-ggml.last index 040b53ca3..c7944d1d4 100644 --- a/scripts/sync-ggml.last +++ b/scripts/sync-ggml.last @@ -1 +1 @@ -58ecf6b96d887e408b6869915863fa1126483d51 +c7dfe3d174f98b14801f9ed12f129179d3e7b638 From 7c7f3b7f435f41f2508e0e3010f0013cd8335156 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Fri, 7 Mar 2025 14:15:27 +0100 Subject: [PATCH 59/87] ggml : skip intermediate .air file when compiling .metallib (#12247) This commit updates the compilation of default.metallib to skip the intermediate .air (Apple Intermediate Representation) file. The motivation for this change is to simplify the custom command a little and avoid generating and then removing the .air file. --- ggml/src/ggml-metal/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ggml/src/ggml-metal/CMakeLists.txt b/ggml/src/ggml-metal/CMakeLists.txt index be3fb3fa9..e22232780 100644 --- a/ggml/src/ggml-metal/CMakeLists.txt +++ b/ggml/src/ggml-metal/CMakeLists.txt @@ -88,9 +88,8 @@ else() add_custom_command( OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib - COMMAND xcrun -sdk macosx metal ${XC_FLAGS} -c ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.air - COMMAND xcrun -sdk macosx metallib ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.air -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib - COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.air + COMMAND xcrun -sdk macosx metal ${XC_FLAGS} -c ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal -o - | + xcrun -sdk macosx metallib - -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-common.h COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal DEPENDS ggml-metal.metal ${METALLIB_COMMON} From 7ab364390f92b0b8d83f69821a536b424838f3f8 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Fri, 7 Mar 2025 20:54:30 +0200 Subject: [PATCH 60/87] server : infill gen ends on new line (#12254) --- examples/server/server.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/server/server.cpp b/examples/server/server.cpp index e1371dbf8..8386f4eeb 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -1312,7 +1312,7 @@ struct server_slot { return task_type == SERVER_TASK_TYPE_EMBEDDING || task_type == SERVER_TASK_TYPE_RERANK; } - bool can_batch_with(server_slot & other_slot) { + bool can_batch_with(server_slot & other_slot) const { return is_non_causal() == other_slot.is_non_causal() && are_lora_equal(lora, other_slot.lora); } @@ -2157,14 +2157,6 @@ struct server_context { } if (slot.has_new_line) { - // if we have already seen a new line, we stop after a certain time limit - if (slot.params.t_max_predict_ms > 0 && (ggml_time_us() - slot.t_start_generation > 1000.0f*slot.params.t_max_predict_ms)) { - slot.stop = STOP_TYPE_LIMIT; - slot.has_next_token = false; - - SLT_DBG(slot, "stopped by time limit, n_decoded = %d, t_max_predict_ms = %d ms\n", slot.n_decoded, (int) slot.params.t_max_predict_ms); - } - // require that each new line has a whitespace prefix (i.e. indentation) of at least slot.params.n_indent if (slot.params.n_indent > 0) { // check the current indentation @@ -2203,6 +2195,14 @@ struct server_context { // check if there is a new line in the generated text if (result.text_to_send.find('\n') != std::string::npos) { slot.has_new_line = true; + + // if we have seen a new line, we stop after a certain time limit, but only upon another new line + if (slot.params.t_max_predict_ms > 0 && (ggml_time_us() - slot.t_start_generation > 1000.0f*slot.params.t_max_predict_ms)) { + slot.stop = STOP_TYPE_LIMIT; + slot.has_next_token = false; + + SLT_DBG(slot, "stopped by time limit, n_decoded = %d, t_max_predict_ms = %d ms\n", slot.n_decoded, (int) slot.params.t_max_predict_ms); + } } // if context shift is disabled, we stop when it reaches the context limit From 6fefc05a7a4e676780ae10b0a4d0728e5281f367 Mon Sep 17 00:00:00 2001 From: "Jason C.H" Date: Sun, 9 Mar 2025 00:02:39 +0800 Subject: [PATCH 61/87] ggml-backend : make path_str compatible with C++20 (#12269) --- AUTHORS | 1 + ggml/src/ggml-backend-reg.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/AUTHORS b/AUTHORS index 6796b2941..ddcb15638 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1045,3 +1045,4 @@ zrm 蕭澧邦 <45505768+shou692199@users.noreply.github.com> 谢乃闻 Нияз Гарифзянов <112617865+garrnizon@users.noreply.github.com> +Jason C.H diff --git a/ggml/src/ggml-backend-reg.cpp b/ggml/src/ggml-backend-reg.cpp index d0d68becd..9bedeae78 100644 --- a/ggml/src/ggml-backend-reg.cpp +++ b/ggml/src/ggml-backend-reg.cpp @@ -76,7 +76,14 @@ namespace fs = std::filesystem; static std::string path_str(const fs::path & path) { std::string u8path; try { +#if defined(__cpp_lib_char8_t) + // C++20 and later: u8string() returns std::u8string + std::u8string u8str = path.u8string(); + u8path = std::string(reinterpret_cast(u8str.c_str())); +#else + // C++17: u8string() returns std::string u8path = path.u8string(); +#endif } catch (...) { } return u8path; From 0fd7ca7a210bd4abc995cd728491043491dbdef7 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sat, 8 Mar 2025 18:26:00 +0200 Subject: [PATCH 62/87] authors : update (#12271) --- AUTHORS | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index ddcb15638..0af9f44ad 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ -# date: Tue Feb 4 13:04:05 EET 2025 +# date: Sat Mar 8 18:23:52 EET 2025 # this file is auto-generated by scripts/gen-authors.sh 0cc4m @@ -8,10 +8,12 @@ 3ooabkhxtn <31479382+3ooabkhxtn@users.noreply.github.com> 44670 <44670@users.noreply.github.com> 65a <10104049+65a@users.noreply.github.com> +708-145 <40387547+708-145@users.noreply.github.com> AN Long AT Aarni Koskela Aaron Miller +Aaron Teo <57927438+taronaeo@users.noreply.github.com> Aaryaman Vasishta Abheek Gulati Abhilash Majumder <30946547+abhilash1910@users.noreply.github.com> @@ -20,6 +22,7 @@ Adithya Balaji AdithyanI Adrian Adrian Hesketh +Adrian Kretz Adrien Gallouët Adrien Gallouët Ahmad Tameem <113388789+Tameem-10xE@users.noreply.github.com> @@ -28,15 +31,18 @@ AidanBeltonS <87009434+AidanBeltonS@users.noreply.github.com> AidanBeltonS Aisuko Akarshan Biswas +Akarshan Biswas Akarshan Biswas Al Mochkin <14274697+amochkin@users.noreply.github.com> Albert Jin Alberto <57916483+albbus-stack@users.noreply.github.com> Alberto Cabrera Pérez Alberto Cabrera Pérez +Aleksei Nikiforov <103434461+AlekseiNikiforovIBM@users.noreply.github.com> Alex Alex Azarov Alex Azarov +Alex Brooks Alex Klinkhamer Alex Klinkhamer Alex Nguyen @@ -67,6 +73,7 @@ Andrew Minh Nguyen <40281306+amqdn@users.noreply.github.com> Andy Salerno Andy Tai Anthony Van de Gejuchte +Antoine Viallon Antonis Makropoulos Arik Poznanski Armen Kaleshian @@ -83,6 +90,7 @@ Atsushi Tatsuma Austin <77757836+teleprint-me@users.noreply.github.com> AustinMroz BADR +BB-fat <45072480+BB-fat@users.noreply.github.com> Bach Le Bailey Chittle <39804642+bachittle@users.noreply.github.com> BarfingLemurs <128182951+BarfingLemurs@users.noreply.github.com> @@ -101,6 +109,7 @@ Bert Wagner Billel Mokeddem Bingan <70050083+binganao@users.noreply.github.com> Bjarke Viksøe <164612031+bviksoe@users.noreply.github.com> +Bodhi <3882561+BodhiHu@users.noreply.github.com> Bodo Graumann Bono Lv Borislav Stanimirov @@ -128,6 +137,7 @@ CentricStorm Chad Brewbaker Changyeon Kim Chao Jiang +Charles Duffy Charles Xu <63788048+chaxu01@users.noreply.github.com> Charles Xu Chen Xi @@ -139,12 +149,14 @@ Chris Kuehl Christian Demsar Christian Demsar Christian Falch <875252+chrfalch@users.noreply.github.com> +Christian Fillion Christian Kastner Christian Kögler Christian Köhnenkamp Christian Zhou-Zheng <59622928+christianazinn@users.noreply.github.com> Christopher Nielsen <62156882+mascguy@users.noreply.github.com> Clark Saben <76020733+csaben@users.noreply.github.com> +Clauszy Clint Herron Conrad Kramer Corentin REGAL @@ -163,6 +175,7 @@ Daniel Hiltgen Daniel Illescas Romero Daniel Kleine <53251018+d-kleine@users.noreply.github.com> Daniele <57776841+daniandtheweb@users.noreply.github.com> +Danny Milosavljevic DannyDaemonic Dat Quoc Nguyen <2412555+datquocnguyen@users.noreply.github.com> Dave @@ -170,6 +183,7 @@ Dave Airlie Dave Airlie Dave Della Costa David Friehs +David Huang <1969802+hjc4869@users.noreply.github.com> David Kennedy David Pflug David Renshaw @@ -236,6 +250,7 @@ Felix Finn Voorhees Firat FirstTimeEZ <179362031+FirstTimeEZ@users.noreply.github.com> +Florent BENOIT Folko-Ven <71110216+Folko-Ven@users.noreply.github.com> Foul-Tarnished <107711110+Foul-Tarnished@users.noreply.github.com> Francisco Melo <43780565+francis2tm@users.noreply.github.com> @@ -254,6 +269,7 @@ Gary Mulder Gavin Zhao Genkagaku.GPT Georgi Gerganov +Gian-Carlo Pascutto Gilad S Gilad S. <7817232+giladgd@users.noreply.github.com> Giuseppe Scrivano @@ -267,7 +283,9 @@ Guspan Tanadi <36249910+guspan-tanadi@users.noreply.github.com> Gustavo Rocha Dias <91472747+gustrd@users.noreply.github.com> Haggai Nuchi Halalaluyafail3 <55773281+Halalaluyafail3@users.noreply.github.com> +Hale Chan Hamdoud Hakem <90524568+hamdoudhakem@users.noreply.github.com> +Han Yin HanishKVC Haohui Mai Haoxiang Fei @@ -278,6 +296,7 @@ Haus1 Henk Poley Henri Vasserman Henrik Forstén +Henry Linjamäki Herman Semenov Hesen Peng HimariO @@ -307,6 +326,7 @@ Ivan Ivan Filipov <159561759+vanaka11@users.noreply.github.com> Ivan Komarov Ivan Stepanov +JC <43374599+MrSMlT@users.noreply.github.com> JFLFY2255 JH23X <165871467+JH23X@users.noreply.github.com> Jack Mousseau @@ -325,6 +345,7 @@ Jan Ploski Jannis Schönleber Jared Van Bortel Jared Van Bortel +Jason C.H Jason McCartney Jason Stillerman Jean-Christophe Hoelt @@ -342,6 +363,7 @@ Jiahao Li Jian Liao JidongZhang-THU <1119708529@qq.com> Jinwoo Jeong <33892306+williamjeong2@users.noreply.github.com> +Jinyang He Jiří Podivín <66251151+jpodivin@users.noreply.github.com> Jiří Sejkora Joan Fontanals @@ -379,6 +401,7 @@ Justine Tunney Juuso Alasuutari KASR Kamil Tomšík +Kante Yin Karol Kontny <82021046+kkontny@users.noreply.github.com> Karsten Weiss Karthick @@ -419,6 +442,7 @@ LoganDark Loïc Carrère LostRuins <39025047+LostRuins@users.noreply.github.com> LostRuins Concedo <39025047+LostRuins@users.noreply.github.com> +Lucas Moura Belo Luciano Luo Tian Lyle Dean @@ -463,6 +487,7 @@ Matthew Tejo Matvey Soloviev Max Krasnyansky Max Krasnyansky +Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Maxime <672982+maximegmd@users.noreply.github.com> Maximilian Winter Meng Zhang @@ -494,6 +519,7 @@ Miwa / Ensan <63481257+ensan-hcl@users.noreply.github.com> Mohammadreza Hendiani Mohammadreza Hendiani Molly Sophia +MoonRide303 <130458190+MoonRide303@users.noreply.github.com> MorganRO8 <47795945+MorganRO8@users.noreply.github.com> Murilo Santana Musab Gultekin @@ -524,6 +550,7 @@ Nikolas <127742645+nneubacher@users.noreply.github.com> Nindaleth Nuno OSecret <135510162+OLSecret@users.noreply.github.com> +Oleksandr Kuvshynov <661042+okuvshynov@users.noreply.github.com> Oleksandr Nikitin Oleksii Maryshchenko Olivier Chafik @@ -533,6 +560,7 @@ PAB Pablo Duboue Pascal Patry Patrice Ferlet +Patrick Peng Paul Tsochantaris Pavel Zloi Pavol Rusnak @@ -549,6 +577,7 @@ Pieter Ouwerkerk Plamen Minev Prashant Vithule <119530321+Vithulep@users.noreply.github.com> Przemysław Pawełczyk +PureJourney Qin Yue Chen <71813199+chenqiny@users.noreply.github.com> Qingyou Meng Qu Zongfu <43257352+yancaoweidaode@users.noreply.github.com> @@ -564,14 +593,17 @@ Rand Xie Randall Fitzgerald Random Fly Reinforce-II +Rémy O Rémy Oudompheng Ren Xuancheng Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Reza Kakhki +Reza Rahemtola <49811529+RezaRahemtola@users.noreply.github.com> RhinoDevel Riccardo Orlando Riceball LEE Rich Dougherty +Richard Richard Kiss Richard Roberson Rick G <26732651+TheFlipbook@users.noreply.github.com> @@ -588,6 +620,7 @@ Robert Sung-wook Shin Robey Holderith Robyn Roger Meier +Rohanjames1997 Roland <14355895+rbur0425@users.noreply.github.com> Romain Biessy Romain D <90720+Artefact2@users.noreply.github.com> @@ -610,6 +643,7 @@ Ryan Landay Ryder Wishart Ryuei Rőczey Barnabás <31726601+An0nie@users.noreply.github.com> +SAMI SRHMorris <69468379+SRHMorris@users.noreply.github.com> SXX SakuraUmi @@ -634,6 +668,8 @@ Shane A Shangning Xu <32517059+xushangning@users.noreply.github.com> Shankar Shanshan Shen <467638484@qq.com> +Shelby Jenkins <47464908+ShelbyJenkins@users.noreply.github.com> +Sheldon Robinson Shijie <821898965@qq.com> Shintarou Okada Shouzheng Liu <61452103+lshzh-ww@users.noreply.github.com> @@ -713,18 +749,24 @@ Victor Nogueira Victor Z. Peng Viet-Anh NGUYEN (Andrew) Vinesh Janarthanan <36610342+VJHack@users.noreply.github.com> +Vitali Lovich +Vivian Vlad Vladimir Vladimir Malyutin +Vladimir Vuksanovic <109677816+vvuksanovic@users.noreply.github.com> Vladimir Zorin VoidIsVoid <343750470@qq.com> Volodymyr Vitvitskyi <72226+signalpillar@users.noreply.github.com> +Wagner Bruna Wang Qin <37098874+wangqin0@users.noreply.github.com> Wang Ran (汪然) WangHaoranRobin <56047610+WangHaoranRobin@users.noreply.github.com> Weird Constructor +Weizhao Ouyang Welby Seely Wentai Zhang +Wilken Gottwalt <12194808+wgottwalt@users.noreply.github.com> WillCorticesAI <150854901+WillCorticesAI@users.noreply.github.com> William Tambellini William Tambellini @@ -816,6 +858,8 @@ chaihahaha chiranko <96988916+chiranko@users.noreply.github.com> clibdev <52199778+clibdev@users.noreply.github.com> clyang +cmdr2 +cmdr2 cocktailpeanut <121128867+cocktailpeanut@users.noreply.github.com> codezjx coezbek @@ -835,6 +879,7 @@ deepdiffuser <112834445+deepdiffuser@users.noreply.github.com> devojony <61173062+devojony@users.noreply.github.com> ditsuke divinity76 +dm4 dm4 dotpy314 <33351922+dotpy314@users.noreply.github.com> drbh @@ -849,6 +894,7 @@ fairydreaming <166155368+fairydreaming@users.noreply.github.com> fengerhu1 <2748250768@qq.com> fj-y-saito <85871716+fj-y-saito@users.noreply.github.com> fraxy-v <65565042+fraxy-v@users.noreply.github.com> +fxzjshm <11426482+fxzjshm@users.noreply.github.com> github-actions[bot] gliptic gn64 @@ -873,6 +919,7 @@ hydai iSma iacore <74560659+iacore@users.noreply.github.com> icppWorld <124377669+icppWorld@users.noreply.github.com> +igardev <49397134+igardev@users.noreply.github.com> igarnier intelmatt <61025942+intelmatt@users.noreply.github.com> iohub @@ -880,6 +927,7 @@ issixx <46835150+issixx@users.noreply.github.com> jacobi petrucciani <8117202+jpetrucciani@users.noreply.github.com> jaime-m-p <167997752+jaime-m-p@users.noreply.github.com> jameswu2014 <545426914@qq.com> +jason_w jdomke <28772296+jdomke@users.noreply.github.com> jiahao su jiez <373447296@qq.com> @@ -891,6 +939,7 @@ jon-chuang <9093549+jon-chuang@users.noreply.github.com> jp-x-g jukofyork <69222624+jukofyork@users.noreply.github.com> junchao-loongson <68935141+junchao-loongson@users.noreply.github.com> +junchao-zhao <68935141+junchao-loongson@users.noreply.github.com> jwj7140 <32943891+jwj7140@users.noreply.github.com> k.h.lai kaizau @@ -925,6 +974,7 @@ ltoniazzi <61414566+ltoniazzi@users.noreply.github.com> luoyu-intel m3ndax maddes8cht <55592906+maddes8cht@users.noreply.github.com> +magicse mahorozte <41834471+mahorozte@users.noreply.github.com> makomk manikbhandari @@ -935,6 +985,7 @@ matt23654 matteo mdrokz mgroeber9110 <45620825+mgroeber9110@users.noreply.github.com> +midnight minarchist mj-shifu <77107165+mj-shifu@users.noreply.github.com> mmyjona @@ -958,10 +1009,12 @@ omahs <73983677+omahs@users.noreply.github.com> oobabooga <112222186+oobabooga@users.noreply.github.com> opparco ostix360 <55257054+ostix360@users.noreply.github.com> +pascal-lc <49066376+pascal-lc@users.noreply.github.com> pculliton peidaqi pengxin99 perserk +petterreinholdtsen piDack <104877312+piDack@users.noreply.github.com> pmysl postmasters @@ -983,6 +1036,7 @@ semidark serhii-nakon <57632032+serhii-nakon@users.noreply.github.com> sharpHL <132747147+sharpHL@users.noreply.github.com> shibe2 +simon886212 <37953122+simon886212@users.noreply.github.com> singularity <12184989+singularity-s0@users.noreply.github.com> sjinzh sjxx <63994076+ylsdamxssjxxdd@users.noreply.github.com> @@ -1000,10 +1054,12 @@ tarcey tc-mb <157115220+tc-mb@users.noreply.github.com> texmex76 <40733439+texmex76@users.noreply.github.com> thement <40525767+thement@users.noreply.github.com> +theraininsky <76763719+theraininsky@users.noreply.github.com> thewh1teagle <61390950+thewh1teagle@users.noreply.github.com> tjohnman toyer <2042519524@qq.com> tslmy +tv1wnd <55383215+tv1wnd@users.noreply.github.com> ubik2 uint256_t uint256_t @@ -1014,6 +1070,7 @@ valiray <133289098+valiray@users.noreply.github.com> vb vik viric +vmobilis <75476228+vmobilis@users.noreply.github.com> vodkaslime <646329483@qq.com> vvhg1 <94630311+vvhg1@users.noreply.github.com> vxiiduu <73044267+vxiiduu@users.noreply.github.com> @@ -1028,6 +1085,8 @@ wzy <32936898+Freed-Wu@users.noreply.github.com> xaedes xaedes xctan +xiaobing318 <71554036+xiaobing318@users.noreply.github.com> +xiaofei xloem <0xloem@gmail.com> yangli2 ymcki <84055651+ymcki@users.noreply.github.com> @@ -1045,4 +1104,3 @@ zrm 蕭澧邦 <45505768+shou692199@users.noreply.github.com> 谢乃闻 Нияз Гарифзянов <112617865+garrnizon@users.noreply.github.com> -Jason C.H From 1e2f78a00450593e2dfa458796fcdd9987300dfc Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sun, 9 Mar 2025 19:08:20 +0200 Subject: [PATCH 63/87] server : add speculative decoding presets for FIM (#12287) --- common/arg.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/common/arg.cpp b/common/arg.cpp index 3e549ede0..b96a5678f 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -2571,5 +2571,43 @@ common_params_context common_params_parser_init(common_params & params, llama_ex } ).set_examples({LLAMA_EXAMPLE_SERVER})); + add_opt(common_arg( + {"--fim-qwen-7b-spec"}, + string_format("use Qwen 2.5 Coder 7B + 0.5B draft for speculative decoding (note: can download weights from the internet)"), + [](common_params & params) { + params.hf_repo = "ggml-org/Qwen2.5-Coder-7B-Q8_0-GGUF"; + params.hf_file = "qwen2.5-coder-7b-q8_0.gguf"; + params.speculative.hf_repo = "ggml-org/Qwen2.5-Coder-0.5B-Q8_0-GGUF"; + params.speculative.hf_file = "qwen2.5-coder-0.5b-q8_0.gguf"; + params.speculative.n_gpu_layers = 99; + params.port = 8012; + params.n_gpu_layers = 99; + params.flash_attn = true; + params.n_ubatch = 1024; + params.n_batch = 1024; + params.n_ctx = 0; + params.n_cache_reuse = 256; + } + ).set_examples({LLAMA_EXAMPLE_SERVER})); + + add_opt(common_arg( + {"--fim-qwen-14b-spec"}, + string_format("use Qwen 2.5 Coder 14B + 0.5B draft for speculative decoding (note: can download weights from the internet)"), + [](common_params & params) { + params.hf_repo = "ggml-org/Qwen2.5-Coder-14B-Q8_0-GGUF"; + params.hf_file = "qwen2.5-coder-14b-q8_0.gguf"; + params.speculative.hf_repo = "ggml-org/Qwen2.5-Coder-0.5B-Q8_0-GGUF"; + params.speculative.hf_file = "qwen2.5-coder-0.5b-q8_0.gguf"; + params.speculative.n_gpu_layers = 99; + params.port = 8012; + params.n_gpu_layers = 99; + params.flash_attn = true; + params.n_ubatch = 1024; + params.n_batch = 1024; + params.n_ctx = 0; + params.n_cache_reuse = 256; + } + ).set_examples({LLAMA_EXAMPLE_SERVER})); + return ctx_arg; } From 8352cdc87b207a735d34c431a36c425728cb4586 Mon Sep 17 00:00:00 2001 From: tc-mb <157115220+tc-mb@users.noreply.github.com> Date: Mon, 10 Mar 2025 16:33:24 +0800 Subject: [PATCH 64/87] llava : fix bug in minicpm-v code (#11513) * fix bug in minicpm-v code * update readme of minicpm-v --- examples/llava/README-minicpmo2.6.md | 34 +++---- examples/llava/README-minicpmv2.5.md | 88 ++++------------- examples/llava/README-minicpmv2.6.md | 96 ++++--------------- examples/llava/clip.cpp | 1 + examples/llava/minicpmv-cli.cpp | 35 +++++-- .../minicpmv-convert-image-encoder-to-gguf.py | 1 - 6 files changed, 80 insertions(+), 175 deletions(-) diff --git a/examples/llava/README-minicpmo2.6.md b/examples/llava/README-minicpmo2.6.md index 8f591506d..48c423238 100644 --- a/examples/llava/README-minicpmo2.6.md +++ b/examples/llava/README-minicpmo2.6.md @@ -5,13 +5,25 @@ Currently, this readme only supports minicpm-omni's image capabilities, and we w Download [MiniCPM-o-2_6](https://huggingface.co/openbmb/MiniCPM-o-2_6) PyTorch model from huggingface to "MiniCPM-o-2_6" folder. + +### Build llama.cpp +Readme modification time: 20250206 + +If there are differences in usage, please refer to the official build [documentation](https://github.com/ggerganov/llama.cpp/blob/master/docs/build.md) + Clone llama.cpp: ```bash -git clone git@github.com:OpenBMB/llama.cpp.git +git clone https://github.com/ggerganov/llama.cpp cd llama.cpp -git checkout minicpm-omni ``` +Build llama.cpp using `CMake`: +```bash +cmake -B build +cmake --build build --config Release +``` + + ### Usage of MiniCPM-o 2.6 Convert PyTorch model to gguf files (You can also download the converted [gguf](https://huggingface.co/openbmb/MiniCPM-o-2_6-gguf) by us) @@ -22,25 +34,15 @@ python ./examples/llava/minicpmv-convert-image-encoder-to-gguf.py -m ../MiniCPM- python ./convert_hf_to_gguf.py ../MiniCPM-o-2_6/model # quantize int4 version -./llama-quantize ../MiniCPM-o-2_6/model/ggml-model-f16.gguf ../MiniCPM-o-2_6/model/ggml-model-Q4_K_M.gguf Q4_K_M +./build/bin/llama-quantize ../MiniCPM-o-2_6/model/ggml-model-f16.gguf ../MiniCPM-o-2_6/model/ggml-model-Q4_K_M.gguf Q4_K_M ``` -Build llama.cpp using `CMake`: -https://github.com/ggml-org/llama.cpp/blob/master/docs/build.md - -```bash -cmake -B build -cmake --build build --config Release -``` Inference on Linux or Mac -``` +```bash # run f16 version -./llama-minicpmv-cli -m ../MiniCPM-o-2_6/model/ggml-model-f16.gguf --mmproj ../MiniCPM-o-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" +./build/bin/llama-minicpmv-cli -m ../MiniCPM-o-2_6/model/ggml-model-f16.gguf --mmproj ../MiniCPM-o-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" # run quantized int4 version -./llama-minicpmv-cli -m ../MiniCPM-o-2_6/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-o-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" - -# or run in interactive mode -./llama-minicpmv-cli -m ../MiniCPM-o-2_6/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-o-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -i +./build/bin/llama-minicpmv-cli -m ../MiniCPM-o-2_6/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-o-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" ``` diff --git a/examples/llava/README-minicpmv2.5.md b/examples/llava/README-minicpmv2.5.md index b0e72a0fa..6bfe7abd1 100644 --- a/examples/llava/README-minicpmv2.5.md +++ b/examples/llava/README-minicpmv2.5.md @@ -4,13 +4,26 @@ Download [MiniCPM-Llama3-V-2_5](https://huggingface.co/openbmb/MiniCPM-Llama3-V-2_5) PyTorch model from huggingface to "MiniCPM-Llama3-V-2_5" folder. + +### Build llama.cpp +Readme modification time: 20250206 + +If there are differences in usage, please refer to the official build [documentation](https://github.com/ggerganov/llama.cpp/blob/master/docs/build.md) + Clone llama.cpp: ```bash git clone https://github.com/ggml-org/llama.cpp cd llama.cpp ``` -### Usage +Build llama.cpp using `CMake`: +```bash +cmake -B build +cmake --build build --config Release +``` + + +### Usage of MiniCPM-Llama3-V 2.5 Convert PyTorch model to gguf files (You can also download the converted [gguf](https://huggingface.co/openbmb/MiniCPM-Llama3-V-2_5-gguf) by us) @@ -20,80 +33,15 @@ python ./examples/llava/minicpmv-convert-image-encoder-to-gguf.py -m ../MiniCPM- python ./convert_hf_to_gguf.py ../MiniCPM-Llama3-V-2_5/model # quantize int4 version -./llama-quantize ../MiniCPM-Llama3-V-2_5/model/model-8B-F16.gguf ../MiniCPM-Llama3-V-2_5/model/ggml-model-Q4_K_M.gguf Q4_K_M +./build/bin/llama-quantize ../MiniCPM-Llama3-V-2_5/model/model-8B-F16.gguf ../MiniCPM-Llama3-V-2_5/model/ggml-model-Q4_K_M.gguf Q4_K_M ``` -Build for Linux or Mac - -```bash -make -make llama-minicpmv-cli -``` Inference on Linux or Mac -``` +```bash # run f16 version -./llama-minicpmv-cli -m ../MiniCPM-Llama3-V-2_5/model/model-8B-F16.gguf --mmproj ../MiniCPM-Llama3-V-2_5/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" +./build/bin/llama-minicpmv-cli -m ../MiniCPM-Llama3-V-2_5/model/model-8B-F16.gguf --mmproj ../MiniCPM-Llama3-V-2_5/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" # run quantized int4 version -./llama-minicpmv-cli -m ../MiniCPM-Llama3-V-2_5/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-Llama3-V-2_5/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" - -# or run in interactive mode -./llama-minicpmv-cli -m ../MiniCPM-Llama3-V-2_5/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-Llama3-V-2_5/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -i -``` - -### Android - -#### Build on Android device using Termux -We found that build on Android device would bring better runtime performance, so we recommend to build on device. - -[Termux](https://github.com/termux/termux-app#installation) is a terminal app on Android device (no root required). - -Install tools in Termux: -``` -apt update && apt upgrade -y -apt install git make cmake -``` - -It's recommended to move your model inside the `~/` directory for best performance: -``` -cd storage/downloads -mv model.gguf ~/ -``` - -#### Building the Project using Android NDK -Obtain the [Android NDK](https://developer.android.com/ndk) and then build with CMake. - -Execute the following commands on your computer to avoid downloading the NDK to your mobile. Alternatively, you can also do this in Termux: - -```bash -mkdir build-android -cd build-android -export NDK=/your_ndk_path -cmake -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-23 -DCMAKE_C_FLAGS=-march=armv8.4a+dotprod .. -make -``` - -Install [termux](https://github.com/termux/termux-app#installation) on your device and run `termux-setup-storage` to get access to your SD card (if Android 11+ then run the command twice). - -Finally, copy these built `llama` binaries and the model file to your device storage. Because the file permissions in the Android sdcard cannot be changed, you can copy the executable files to the `/data/data/com.termux/files/home/bin` path, and then execute the following commands in Termux to add executable permission: - -(Assumed that you have pushed the built executable files to the /sdcard/llama.cpp/bin path using `adb push`) -``` -$cp -r /sdcard/llama.cpp/bin /data/data/com.termux/files/home/ -$cd /data/data/com.termux/files/home/bin -$chmod +x ./* -``` - -Download models and push them to `/sdcard/llama.cpp/`, then move it to `/data/data/com.termux/files/home/model/` - -``` -$mv /sdcard/llama.cpp/ggml-model-Q4_K_M.gguf /data/data/com.termux/files/home/model/ -$mv /sdcard/llama.cpp/mmproj-model-f16.gguf /data/data/com.termux/files/home/model/ -``` - -Now, you can start chatting: -``` -$cd /data/data/com.termux/files/home/bin -$./llama-minicpmv-cli -m ../model/ggml-model-Q4_K_M.gguf --mmproj ../model/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" +./build/bin/llama-minicpmv-cli -m ../MiniCPM-Llama3-V-2_5/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-Llama3-V-2_5/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" ``` diff --git a/examples/llava/README-minicpmv2.6.md b/examples/llava/README-minicpmv2.6.md index c4be5e5dd..2df39cdba 100644 --- a/examples/llava/README-minicpmv2.6.md +++ b/examples/llava/README-minicpmv2.6.md @@ -4,13 +4,25 @@ Download [MiniCPM-V-2_6](https://huggingface.co/openbmb/MiniCPM-V-2_6) PyTorch model from huggingface to "MiniCPM-V-2_6" folder. + +### Build llama.cpp +Readme modification time: 20250206 + +If there are differences in usage, please refer to the official build [documentation](https://github.com/ggerganov/llama.cpp/blob/master/docs/build.md) + Clone llama.cpp: ```bash -git clone git@github.com:OpenBMB/llama.cpp.git +git clone https://github.com/ggerganov/llama.cpp cd llama.cpp -git checkout minicpmv-main ``` +Build llama.cpp using `CMake`: +```bash +cmake -B build +cmake --build build --config Release +``` + + ### Usage of MiniCPM-V 2.6 Convert PyTorch model to gguf files (You can also download the converted [gguf](https://huggingface.co/openbmb/MiniCPM-V-2_6-gguf) by us) @@ -21,87 +33,15 @@ python ./examples/llava/minicpmv-convert-image-encoder-to-gguf.py -m ../MiniCPM- python ./convert_hf_to_gguf.py ../MiniCPM-V-2_6/model # quantize int4 version -./llama-quantize ../MiniCPM-V-2_6/model/ggml-model-f16.gguf ../MiniCPM-V-2_6/model/ggml-model-Q4_K_M.gguf Q4_K_M +./build/bin/llama-quantize ../MiniCPM-V-2_6/model/ggml-model-f16.gguf ../MiniCPM-V-2_6/model/ggml-model-Q4_K_M.gguf Q4_K_M ``` -Build for Linux or Mac - -```bash -make -make llama-minicpmv-cli -``` Inference on Linux or Mac -``` +```bash # run f16 version -./llama-minicpmv-cli -m ../MiniCPM-V-2_6/model/ggml-model-f16.gguf --mmproj ../MiniCPM-V-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" +./build/bin/llama-minicpmv-cli -m ../MiniCPM-V-2_6/model/ggml-model-f16.gguf --mmproj ../MiniCPM-V-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" # run quantized int4 version -./llama-minicpmv-cli -m ../MiniCPM-V-2_6/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-V-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" - -# or run in interactive mode -./llama-minicpmv-cli -m ../MiniCPM-V-2_6/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-V-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -i -``` - -### Video -Install FFmpeg -``` -brew install ffmpeg -brew install pkg-config -``` - -### Android - -#### Build on Android device using Termux -We found that build on Android device would bring better runtime performance, so we recommend to build on device. - -[Termux](https://github.com/termux/termux-app#installation) is a terminal app on Android device (no root required). - -Install tools in Termux: -``` -apt update && apt upgrade -y -apt install git make cmake -``` - -It's recommended to move your model inside the `~/` directory for best performance: -``` -cd storage/downloads -mv model.gguf ~/ -``` - -#### Building the Project using Android NDK -Obtain the [Android NDK](https://developer.android.com/ndk) and then build with CMake. - -Execute the following commands on your computer to avoid downloading the NDK to your mobile. Alternatively, you can also do this in Termux: - -```bash -mkdir build-android -cd build-android -export NDK=/your_ndk_path -cmake -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-23 -DCMAKE_C_FLAGS=-march=armv8.4a+dotprod .. -make -``` - -Install [termux](https://github.com/termux/termux-app#installation) on your device and run `termux-setup-storage` to get access to your SD card (if Android 11+ then run the command twice). - -Finally, copy these built `llama` binaries and the model file to your device storage. Because the file permissions in the Android sdcard cannot be changed, you can copy the executable files to the `/data/data/com.termux/files/home/bin` path, and then execute the following commands in Termux to add executable permission: - -(Assumed that you have pushed the built executable files to the /sdcard/llama.cpp/bin path using `adb push`) -``` -$cp -r /sdcard/llama.cpp/bin /data/data/com.termux/files/home/ -$cd /data/data/com.termux/files/home/bin -$chmod +x ./* -``` - -Download models and push them to `/sdcard/llama.cpp/`, then move it to `/data/data/com.termux/files/home/model/` - -``` -$mv /sdcard/llama.cpp/ggml-model-Q4_K_M.gguf /data/data/com.termux/files/home/model/ -$mv /sdcard/llama.cpp/mmproj-model-f16.gguf /data/data/com.termux/files/home/model/ -``` - -Now, you can start chatting: -``` -$cd /data/data/com.termux/files/home/bin -$./llama-minicpmv-cli -m ../model/ggml-model-Q4_K_M.gguf --mmproj ../model/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" +./build/bin/llama-minicpmv-cli -m ../MiniCPM-V-2_6/model/ggml-model-Q4_K_M.gguf --mmproj ../MiniCPM-V-2_6/mmproj-model-f16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -p "What is in the image?" ``` diff --git a/examples/llava/clip.cpp b/examples/llava/clip.cpp index 76d4a7852..3f558b7bd 100644 --- a/examples/llava/clip.cpp +++ b/examples/llava/clip.cpp @@ -1378,6 +1378,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { LOG_INF("%s: vision_encoder: %d\n", __func__, new_clip->has_vision_encoder); LOG_INF("%s: llava_projector: %d\n", __func__, new_clip->has_llava_projector); LOG_INF("%s: minicpmv_projector: %d\n", __func__, new_clip->has_minicpmv_projector); + LOG_INF("%s: minicpmv_version: %d\n", __func__, new_clip->minicpmv_version); LOG_INF("%s: glm_projector: %d\n", __func__, new_clip->has_glm_projector); LOG_INF("%s: model size: %.2f MB\n", __func__, model_size / 1024.0 / 1024.0); LOG_INF("%s: metadata size: %.2f MB\n", __func__, ggml_get_mem_size(meta) / 1024.0 / 1024.0); diff --git a/examples/llava/minicpmv-cli.cpp b/examples/llava/minicpmv-cli.cpp index 53d902d61..23b3de4db 100644 --- a/examples/llava/minicpmv-cli.cpp +++ b/examples/llava/minicpmv-cli.cpp @@ -148,19 +148,34 @@ static void process_image(struct llava_context * ctx_llava, struct llava_image_e process_eval_image_embed(ctx_llava, embeds, params->n_batch, &n_past, idx++); eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); if (num_image_embeds > 1) { - size_t num_image_embeds_col = clip_uhd_num_image_embeds_col(ctx_llava->ctx_clip); - eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); - for (size_t i = 0; i < (num_image_embeds-1)/num_image_embeds_col; ++i) { - for (size_t j = 0; j < num_image_embeds_col; ++j) { - eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); - process_eval_image_embed(ctx_llava, embeds, params->n_batch, &n_past, idx++); - eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); - if (j == num_image_embeds_col - 1) { - eval_string(ctx_llava->ctx_llama, std::string("\n").c_str(), params->n_batch, &n_past, false); + if (has_minicpmv_projector == 2) { + size_t num_image_embeds_col = clip_uhd_num_image_embeds_col(ctx_llava->ctx_clip); + eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); + for (size_t i = 0; i < (num_image_embeds-1)/num_image_embeds_col; ++i) { + for (size_t j = 0; j < num_image_embeds_col; ++j) { + eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); + process_eval_image_embed(ctx_llava, embeds, params->n_batch, &n_past, idx++); + eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); + if (j == num_image_embeds_col - 1) { + eval_string(ctx_llava->ctx_llama, std::string("\n").c_str(), params->n_batch, &n_past, false); + } + } + } + eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); + } + else if (has_minicpmv_projector == 3 || has_minicpmv_projector == 4) { + size_t num_image_embeds_col = clip_uhd_num_image_embeds_col(ctx_llava->ctx_clip); + for (size_t i = 0; i < (num_image_embeds-1)/num_image_embeds_col; ++i) { + for (size_t j = 0; j < num_image_embeds_col; ++j) { + eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); + process_eval_image_embed(ctx_llava, embeds, params->n_batch, &n_past, idx++); + eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); + if (j == num_image_embeds_col - 1) { + eval_string(ctx_llava->ctx_llama, std::string("\n").c_str(), params->n_batch, &n_past, false); + } } } } - eval_string(ctx_llava->ctx_llama, std::string("").c_str(), params->n_batch, &n_past, false); } LOG_INF("%s: image token past: %d\n", __func__, n_past); } diff --git a/examples/llava/minicpmv-convert-image-encoder-to-gguf.py b/examples/llava/minicpmv-convert-image-encoder-to-gguf.py index 9b196757f..cfe0961f9 100644 --- a/examples/llava/minicpmv-convert-image-encoder-to-gguf.py +++ b/examples/llava/minicpmv-convert-image-encoder-to-gguf.py @@ -597,7 +597,6 @@ elif args.minicpmv_projector is not None: fname_middle = "mmproj-" has_text_encoder = False has_minicpmv_projector = True - minicpmv_version = 4 elif args.vision_only: fname_middle = "vision-" has_text_encoder = False From 2b3a25c212f8c4d8a49cec23e03343a7719d51c9 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 10 Mar 2025 09:44:42 +0000 Subject: [PATCH 65/87] `sampler`: fixes trigger tokens + lazy grammars (fix typo cast from token to string) (#12291) * Fix typo in lazy grammar handling (fixes trigger tokens) Co-authored-by: Georgi Gerganov --------- Co-authored-by: Georgi Gerganov --- examples/server/server.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/server/server.cpp b/examples/server/server.cpp index 8386f4eeb..aec8b9eed 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -384,8 +384,9 @@ struct server_task { SRV_DBG("Grammar trigger token: %d (`%s`)\n", token, word.c_str()); common_grammar_trigger trigger; trigger.type = COMMON_GRAMMAR_TRIGGER_TYPE_TOKEN; - trigger.value = (llama_token) token; - params.sampling.grammar_triggers.push_back(trigger); + trigger.value = word; + trigger.token = token; + params.sampling.grammar_triggers.push_back(std::move(trigger)); } else { SRV_DBG("Grammar trigger word: `%s`\n", word.c_str()); params.sampling.grammar_triggers.push_back({COMMON_GRAMMAR_TRIGGER_TYPE_WORD, word}); From 87c2630546cd8ccc836ae4c7d87d03fa597d2267 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 10 Mar 2025 09:45:07 +0000 Subject: [PATCH 66/87] allow missing content in message if tool_calls provided (#12293) --- common/chat.cpp | 29 ++++++++++++++++------------- tests/test-chat.cpp | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/common/chat.cpp b/common/chat.cpp index 1b10219cc..1b3f286af 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -60,7 +60,9 @@ std::vector common_chat_msgs_parse_oaicompat(const json & messa } msg.role = message.at("role"); - if (message.contains("content")) { + auto has_content = message.contains("content"); + auto has_tool_calls = message.contains("tool_calls"); + if (has_content) { const auto & content = message.at("content"); if (content.is_string()) { msg.content = content; @@ -81,19 +83,8 @@ std::vector common_chat_msgs_parse_oaicompat(const json & messa } else if (!content.is_null()) { throw std::runtime_error("Invalid 'content' type: expected string or array, got " + content.dump() + " (ref: https://github.com/ggml-org/llama.cpp/issues/8367)"); } - } else { - throw std::runtime_error("Expected 'content' (ref: https://github.com/ggml-org/llama.cpp/issues/8367)"); } - if (message.contains("reasoning_content")) { - msg.reasoning_content = message.at("reasoning_content"); - } - if (message.contains("name")) { - msg.tool_name = message.at("name"); - } - if (message.contains("tool_call_id")) { - msg.tool_call_id = message.at("tool_call_id"); - } - if (message.contains("tool_calls")) { + if (has_tool_calls) { for (const auto & tool_call : message.at("tool_calls")) { common_chat_tool_call tc; if (!tool_call.contains("type")) { @@ -118,6 +109,18 @@ std::vector common_chat_msgs_parse_oaicompat(const json & messa msg.tool_calls.push_back(tc); } } + if (!has_content && !has_tool_calls) { + throw std::runtime_error("Expected 'content' or 'tool_calls' (ref: https://github.com/ggml-org/llama.cpp/issues/8367 & https://github.com/ggml-org/llama.cpp/issues/12279)"); + } + if (message.contains("reasoning_content")) { + msg.reasoning_content = message.at("reasoning_content"); + } + if (message.contains("name")) { + msg.tool_name = message.at("name"); + } + if (message.contains("tool_call_id")) { + msg.tool_call_id = message.at("tool_call_id"); + } msgs.push_back(msg); } diff --git a/tests/test-chat.cpp b/tests/test-chat.cpp index 35a307c63..35c7ee34e 100644 --- a/tests/test-chat.cpp +++ b/tests/test-chat.cpp @@ -480,6 +480,21 @@ static void test_msgs_oaicompat_json_conversion() { "]" ), common_chat_msgs_to_json_oaicompat({message_assist_call_python}).dump(2)); + + auto res = common_chat_msgs_parse_oaicompat(json::parse("[{\"role\": \"assistant\", \"tool_calls\": []}]")); + assert_equals(1, res.size()); + assert_equals(res[0].role, "assistant"); + assert_equals(true, res[0].content.empty()); + assert_equals(true, res[0].tool_calls.empty()); + + try { + common_chat_msgs_parse_oaicompat(json::parse("[{\"role\": \"assistant\"}]")); + throw std::runtime_error("Expected exception"); + } catch (const std::exception & e) { + if (std::string(e.what()).find("'content'") == std::string::npos) { + throw std::runtime_error("Expected exception about missing 'content'"); + } + } } static void test_tools_oaicompat_json_conversion() { From be421fc429795d135786f5a0e489709220a9c43a Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 10 Mar 2025 09:45:29 +0000 Subject: [PATCH 67/87] `tool-call`: ensure there's always a non-empty tool call id (#12292) --- examples/server/server.cpp | 5 ++++- examples/server/tests/unit/test_tool_call.py | 3 +++ examples/server/utils.hpp | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/server/server.cpp b/examples/server/server.cpp index aec8b9eed..8cb8d0033 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -751,7 +751,10 @@ struct server_task_result_cmpl_final : server_task_result { {"name", tc.name}, {"arguments", tc.arguments}, }}, - {"id", tc.id}, + // Some templates generate and require an id (sometimes in a very specific format, e.g. Mistral Nemo). + // We only generate a random id for the ones that don't generate one by themselves + // (they also won't get to see it as their template likely doesn't use it, so it's all for the client) + {"id", tc.id.empty() ? gen_tool_call_id() : tc.id}, }); } message["tool_calls"] = tool_calls; diff --git a/examples/server/tests/unit/test_tool_call.py b/examples/server/tests/unit/test_tool_call.py index 25bddbaee..569c2a1f8 100755 --- a/examples/server/tests/unit/test_tool_call.py +++ b/examples/server/tests/unit/test_tool_call.py @@ -92,6 +92,7 @@ def do_test_completion_with_required_tool_tiny(server: ServerProcess, tool: dict assert tool_calls and len(tool_calls) == 1, f'Expected 1 tool call in {choice["message"]}' tool_call = tool_calls[0] assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' + assert len(tool_call.get("id", "")) > 0, f'Expected non empty tool call id in {tool_call}' expected_function_name = "python" if tool["type"] == "code_interpreter" else tool["function"]["name"] assert expected_function_name == tool_call["function"]["name"] actual_arguments = tool_call["function"]["arguments"] @@ -373,6 +374,7 @@ def do_test_weather(server: ServerProcess, **kwargs): tool_call = tool_calls[0] # assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' assert tool_call["function"]["name"] == WEATHER_TOOL["function"]["name"], f'Expected weather tool call, got {tool_call["function"]["name"]}' + assert len(tool_call.get("id", "")) > 0, f'Expected non empty tool call id in {tool_call}' actual_arguments = json.loads(tool_call["function"]["arguments"]) assert 'location' in actual_arguments, f"location not found in {json.dumps(actual_arguments)}" location = actual_arguments["location"] @@ -596,6 +598,7 @@ def do_test_hello_world(server: ServerProcess, **kwargs): tool_call = tool_calls[0] # assert choice["message"].get("content") in (None, ""), f'Expected no content in {choice["message"]}' assert tool_call["function"]["name"] == PYTHON_TOOL["function"]["name"] + assert len(tool_call.get("id", "")) > 0, f'Expected non empty tool call id in {tool_call}' actual_arguments = json.loads(tool_call["function"]["arguments"]) assert 'code' in actual_arguments, f"code not found in {json.dumps(actual_arguments)}" code = actual_arguments["code"] diff --git a/examples/server/utils.hpp b/examples/server/utils.hpp index 393e3927c..36ad276fd 100644 --- a/examples/server/utils.hpp +++ b/examples/server/utils.hpp @@ -435,6 +435,10 @@ static std::string gen_chatcmplid() { return "chatcmpl-" + random_string(); } +static std::string gen_tool_call_id() { + return random_string(); +} + // // other common utils // From 4e39a3c332f84b890e91353ec448502cb8373a6f Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 10 Mar 2025 10:59:03 +0000 Subject: [PATCH 68/87] `server`: extract tags from qwq outputs (#12297) * extract tags from qwq outputs * const for all static regexes in chat.cpp --- common/chat.cpp | 282 +++++++++++++++++++++++--------------------- common/chat.h | 1 + tests/test-chat.cpp | 13 ++ 3 files changed, 162 insertions(+), 134 deletions(-) diff --git a/common/chat.cpp b/common/chat.cpp index 1b3f286af..62ca26ad7 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -445,6 +445,7 @@ std::string common_chat_format_name(common_chat_format format) { case COMMON_CHAT_FORMAT_FUNCTIONARY_V3_2: return "Functionary v3.2"; case COMMON_CHAT_FORMAT_FUNCTIONARY_V3_1_LLAMA_3_1: return "Functionary v3.1 Llama 3.1"; case COMMON_CHAT_FORMAT_HERMES_2_PRO: return "Hermes 2 Pro"; + case COMMON_CHAT_FORMAT_HERMES_2_PRO_EXTRACT_REASONING: return "Hermes 2 Pro (extract reasoning)"; case COMMON_CHAT_FORMAT_COMMAND_R7B: return "Command R7B"; case COMMON_CHAT_FORMAT_COMMAND_R7B_EXTRACT_REASONING: return "Command R7B (extract reasoning)"; default: @@ -878,9 +879,9 @@ static common_chat_params common_chat_params_init_command_r7b(const common_chat_ return data; } static common_chat_msg common_chat_parse_command_r7b(const std::string & input, bool extract_reasoning) { - static std::regex thought_regex("(<\\|START_THINKING\\|>([\\s\\S]*?)<\\|END_THINKING\\|>)([\\s\\S]*)"); - static std::regex action_regex("<\\|START_ACTION\\|>([\\s\\S]*?)<\\|END_ACTION\\|>"); - static std::regex response_regex("(?:<\\|START_RESPONSE\\|>)?([\\s\\S]*?)<\\|END_RESPONSE\\|>"); + static const std::regex thought_regex("(<\\|START_THINKING\\|>([\\s\\S]*?)<\\|END_THINKING\\|>)([\\s\\S]*)"); + static const std::regex action_regex("<\\|START_ACTION\\|>([\\s\\S]*?)<\\|END_ACTION\\|>"); + static const std::regex response_regex("(?:<\\|START_RESPONSE\\|>)?([\\s\\S]*?)<\\|END_RESPONSE\\|>"); std::smatch match; @@ -1012,10 +1013,10 @@ static common_chat_params common_chat_params_init_llama_3_1_tool_calls(const com } static common_chat_msg common_chat_parse_llama_3_1(const std::string & input, bool with_builtin_tools = false) { // TODO: tighten & simplify the parser, don't accept leading text context. - static std::regex function_regex( + static const std::regex function_regex( "\\s*\\{\\s*(?:\"type\"\\s*:\\s*\"function\"\\s*,\\s*)?\"name\"\\s*:\\s*\"([^\"]+)\"\\s*,\\s*\"parameters\"\\s*: "); - static std::regex close_regex("\\}\\s*"); - static std::regex builtin_call_regex("<\\|python_tag\\|>\\s*([^.(]+)\\s*\\.\\s*call\\s*\\(\\s*([\\w]+)\\s*=\\s*([\\s\\S]*?)\\)"); + static const std::regex close_regex("\\}\\s*"); + static const std::regex builtin_call_regex("<\\|python_tag\\|>\\s*([^.(]+)\\s*\\.\\s*call\\s*\\(\\s*([\\w]+)\\s*=\\s*([\\s\\S]*?)\\)"); if (with_builtin_tools) { std::smatch match; @@ -1105,34 +1106,42 @@ static common_chat_params common_chat_params_init_deepseek_r1(const common_chat_ data.format = inputs.extract_reasoning ? COMMON_CHAT_FORMAT_DEEPSEEK_R1_EXTRACT_REASONING : COMMON_CHAT_FORMAT_DEEPSEEK_R1; return data; } -static common_chat_msg common_chat_parse_deepseek_r1(const std::string & input, bool extract_reasoning) { - static std::regex function_regex("<|tool▁call▁begin|>function<|tool▁sep|>([^\n]+)\n```json\n"); - static std::regex close_regex("```[\\s\\r\\n]*<|tool▁call▁end|>"); - static std::regex reasoning_content_regex("((?:)?([\\s\\S\\r\\n]*?))?([\\s\\S\\r\\n]*)"); - static std::regex tool_calls_regex("[\\s\\r\\n]*(?:<|tool▁calls▁begin|>|<|tool_calls_begin|>|<|tool calls begin|>|<|tool\\\\_calls\\\\_begin|>)([\\s\\S\\r\\n]*?)<|tool▁calls▁end|>"); - common_chat_msg msg; - msg.role = "assistant"; +static common_chat_msg handle_think_tag_prelude(const std::string & input, bool extract_reasoning, const std::function & rest_parser) { std::smatch match; + static const std::regex reasoning_content_regex("((?:)?([\\s\\S\\r\\n]*?))?([\\s\\S\\r\\n]*)"); if (std::regex_match(input, match, reasoning_content_regex)) { - std::string rest; + auto rest = match[3].str(); + auto msg = rest_parser(rest); + auto reasoning_content = string_strip(match[2].str()); if (extract_reasoning) { - msg.reasoning_content = string_strip(match[2].str()); - } else { - msg.content = match[1].str(); + msg.reasoning_content = reasoning_content; + } else if (!reasoning_content.empty()) { + std::ostringstream content; + content << "" << reasoning_content << "" << msg.content; + msg.content = content.str(); } - rest = match[3].str(); + return msg; + } + return rest_parser(input); +} +static common_chat_msg common_chat_parse_deepseek_r1(const std::string & input, bool extract_reasoning) { + return handle_think_tag_prelude(input, extract_reasoning, [](const std::string & input) { + static const std::regex function_regex("<|tool▁call▁begin|>function<|tool▁sep|>([^\n]+)\n```json\n"); + static const std::regex close_regex("```[\\s\\r\\n]*<|tool▁call▁end|>"); + static const std::regex tool_calls_regex("[\\s\\r\\n]*(?:<|tool▁calls▁begin|>|<|tool_calls_begin|>|<|tool calls begin|>|<|tool\\\\_calls\\\\_begin|>)([\\s\\S\\r\\n]*?)<|tool▁calls▁end|>"); - if (std::regex_search(rest, match, tool_calls_regex)) { + common_chat_msg msg; + msg.role = "assistant"; + std::smatch match; + if (std::regex_search(input, match, tool_calls_regex)) { auto tool_calls = match[1].str(); auto msg2 = parse_json_tool_calls(tool_calls, std::nullopt, function_regex, close_regex); msg.tool_calls = std::move(msg2.tool_calls); } else { - msg.content += std::string(rest.begin() + rest.find_first_not_of(" \r\n"), rest.end()); + msg.content = input; } - } else { - msg.content = input; - } - return msg; + return msg; + }); } static common_chat_params common_chat_params_init_firefunction_v2(const common_chat_template & tmpl, const struct templates_params & inputs) { @@ -1237,8 +1246,8 @@ static common_chat_params common_chat_params_init_functionary_v3_2(const common_ } static common_chat_msg common_chat_parse_functionary_v3_2(const std::string & input) { - static std::regex function_regex(R"((?:>>>)?(?:assistant<|end_header_id|>\n)?(\w+)\n)"); - static std::regex close_regex(R"($|(?=>>>))"); + static const std::regex function_regex(R"((?:>>>)?(?:assistant<|end_header_id|>\n)?(\w+)\n)"); + static const std::regex close_regex(R"($|(?=>>>))"); std::string content; auto it = input.begin(); @@ -1327,7 +1336,7 @@ static common_chat_params common_chat_params_init_functionary_v3_1_llama_3_1(con } static common_chat_msg common_chat_parse_functionary_v3_1_llama_3_1(const std::string & input) { // This version of Functionary still supports the llama 3.1 tool call format for the python tool. - static std::regex python_tag_regex(R"(<\|python_tag\|>([\s\S\n]*)$)"); + static const std::regex python_tag_regex(R"(<\|python_tag\|>([\s\S\n]*)$)"); std::smatch match; if (std::regex_search(input, match, python_tag_regex)) { auto code = match[1].str(); @@ -1341,8 +1350,8 @@ static common_chat_msg common_chat_parse_functionary_v3_1_llama_3_1(const std::s }); return msg; } - static std::regex function_regex(R"()"); - static std::regex close_regex(R"()"); + static const std::regex function_regex(R"()"); + static const std::regex close_regex(R"()"); // TODO: tighten & simplify. return parse_json_tool_calls(input, std::nullopt, function_regex, close_regex); } @@ -1409,6 +1418,8 @@ static common_chat_params common_chat_params_init_hermes_2_pro(const common_chat "(?:```(?:json|xml)?\n\\s*)?(?:|||)?\\s*\\{\\s*\"", //name\"\\s*:\\s*\"" + escaped_name + "\"", }); data.preserved_tokens = { + "", + "", "", "", "" // match 2 (open_tag) - "|" - "|" - "|" - "|" - "|" - "|" - "|" - ")?" - "(\\s*\\{\\s*\"name\"\\s*:[\\s\\S]*)" // match 3 (named tool call + rest) - ")" - "|" - "(?:]+)>" // match 4 (function name) - "|)" // match 5 (function name again) - "([\\s\\S]*)" // match 6 (function arguments + rest)})" - ); +static common_chat_msg common_chat_parse_hermes_2_pro(const std::string& input, bool extract_reasoning) { + return handle_think_tag_prelude(input, extract_reasoning, [](const std::string & input) { + static const std::regex open_regex( + "(?:" + "(```(?:xml|json)?\\n\\s*)?" // match 1 (block_start) + "(" // match 2 (open_tag) + "|" + "|" + "|" + "|" + "|" + "|" + "|" + ")?" + "(\\s*\\{\\s*\"name\"\\s*:[\\s\\S]*)" // match 3 (named tool call + rest) + ")" + "|" + "(?:]+)>" // match 4 (function name) + "|)" // match 5 (function name again) + "([\\s\\S]*)" // match 6 (function arguments + rest)})" + ); - try { + try { + common_chat_msg msg; + msg.role = "assistant"; - common_chat_msg msg; - msg.role = "assistant"; + std::string::const_iterator it = input.begin(); + const std::string::const_iterator end = input.end(); + std::smatch match; - std::string::const_iterator it = input.begin(); - const std::string::const_iterator end = input.end(); - std::smatch match; + while (it != end) { + if (std::regex_search(it, end, match, open_regex)) { + // Add content before the match + msg.content += std::string(it, match[0].first); - while (it != end) { - if (std::regex_search(it, end, match, open_regex)) { - // Add content before the match - msg.content += std::string(it, match[0].first); + auto block_start = match[1].str(); + std::string block_end = block_start.empty() ? "" : "```"; - auto block_start = match[1].str(); - std::string block_end = block_start.empty() ? "" : "```"; + auto open_tag = match[2].str(); + std::string close_tag; - auto open_tag = match[2].str(); - std::string close_tag; + if (match[3].matched) { + close_tag = open_tag.empty() ? "" : ""; + // Start parsing from after the opening tags + auto json_it = match[6].first; + json arguments; + if (parse_json(json_it, end, arguments)) { + msg.tool_calls.emplace_back(process_tool_call({ + {"name", function_name}, + {"arguments", arguments}, + })); + it = json_it; // Move iterator past parsed JSON + + // Handle close tags + consume_spaces(it, end); + if (!close_tag.empty() && !parse_literal(it, end, close_tag)) { + throw std::runtime_error("Failed to parse closing tag"); + } + consume_spaces(it, end); + if (!block_end.empty() && !parse_literal(it, end, block_end)) { + throw std::runtime_error("Failed to parse block end"); + } + consume_spaces(it, end); + } else { + // Not a valid tool call, treat as content + msg.content += std::string(match[0].first, match[0].second); + it = match[0].second; + } } } else { - auto function_name = match[4].str(); - if (function_name.empty()) { - function_name = match[5].str(); - } - GGML_ASSERT(!function_name.empty()); - - close_tag = ""; - // Start parsing from after the opening tags - auto json_it = match[6].first; - json arguments; - if (parse_json(json_it, end, arguments)) { - msg.tool_calls.emplace_back(process_tool_call({ - {"name", function_name}, - {"arguments", arguments}, - })); - it = json_it; // Move iterator past parsed JSON - - // Handle close tags - consume_spaces(it, end); - if (!close_tag.empty() && !parse_literal(it, end, close_tag)) { - throw std::runtime_error("Failed to parse closing tag"); - } - consume_spaces(it, end); - if (!block_end.empty() && !parse_literal(it, end, block_end)) { - throw std::runtime_error("Failed to parse block end"); - } - consume_spaces(it, end); - } else { - // Not a valid tool call, treat as content - msg.content += std::string(match[0].first, match[0].second); - it = match[0].second; - } + // Add remaining content + msg.content += std::string(it, end); + break; } - } else { - // Add remaining content - msg.content += std::string(it, end); - break; } + return msg; + } catch (const std::exception & e) { + LOG_ERR("Failed to parse hermes 2 pro input: %s\n", e.what()); + common_chat_msg msg; + msg.role = "assistant"; + msg.content = input; + return msg; } - return msg; - } catch (const std::exception & e) { - LOG_ERR("Failed to parse hermes 2 pro input: %s\n", e.what()); - common_chat_msg msg; - msg.role = "assistant"; - msg.content = input; - return msg; - } + }); } static common_chat_params common_chat_params_init_without_tools(const common_chat_template & tmpl, const struct templates_params & inputs) { @@ -1609,6 +1621,11 @@ static common_chat_params common_chat_templates_apply_jinja( return common_chat_params_init_command_r7b(tmpl, params); } + // Hermes 2/3 Pro, Qwen 2.5 Instruct (w/ tools) + if (src.find("") != std::string::npos && params.json_schema.is_null()) { + return common_chat_params_init_hermes_2_pro(tmpl, params); + } + // Use generic handler when mixing tools + JSON schema. // TODO: support that mix in handlers below. if ((params.tools.is_array() && params.json_schema.is_object())) { @@ -1630,11 +1647,6 @@ static common_chat_params common_chat_templates_apply_jinja( return common_chat_params_init_without_tools(tmpl, params); } - // Hermes 2/3 Pro, Qwen 2.5 Instruct (w/ tools) - if (src.find("") != std::string::npos) { - return common_chat_params_init_hermes_2_pro(tmpl, params); - } - // Functionary v3.1 (w/ tools) if (src.find("<|start_header_id|>") != std::string::npos && src.find("I'm thinkingHello, world!\nWhat's up?", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_thoughts_unparsed_think, + common_chat_parse("I'm thinkingHello, world!\nWhat's up?", + COMMON_CHAT_FORMAT_HERMES_2_PRO)); + assert_msg_equals(message_assist_thoughts, + common_chat_parse("I'm thinkingHello, world!\nWhat's up?", + COMMON_CHAT_FORMAT_HERMES_2_PRO_EXTRACT_REASONING)); + assert_msg_equals(message_assist_thoughts, + common_chat_parse("I'm thinkingHello, world!\nWhat's up?", + COMMON_CHAT_FORMAT_HERMES_2_PRO_EXTRACT_REASONING)); + test_templates(tmpls.get(), end_tokens, message_assist, tools, "Hello, world!\nWhat's up?", /* expect_grammar_triggered= */ false); test_templates(tmpls.get(), end_tokens, message_assist_call, tools, "\n" From 6ef79a67caf1159b0150b44ee80888c7ec98b83f Mon Sep 17 00:00:00 2001 From: marcoStocchi Date: Mon, 10 Mar 2025 12:34:13 +0100 Subject: [PATCH 69/87] common : refactor '-o' option (#12278) As discussed in PR 'llama-tts : add -o option' (#12042): * common_params : 'out_file' string is the only output file name parameter left in common_params. It's intended to be used in all example programs implementing an '-o' option. * cvector-generator, export-lora, imatrix : default output filenames moved from 'common_params' to the 'main()' of each example program. --- common/arg.cpp | 9 +-------- common/common.h | 8 +++----- examples/cvector-generator/cvector-generator.cpp | 4 +++- examples/export-lora/export-lora.cpp | 6 ++++-- examples/imatrix/imatrix.cpp | 5 ++--- 5 files changed, 13 insertions(+), 19 deletions(-) diff --git a/common/arg.cpp b/common/arg.cpp index b96a5678f..8531f0871 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -1867,16 +1867,9 @@ common_params_context common_params_parser_init(common_params & params, llama_ex ).set_examples({LLAMA_EXAMPLE_PASSKEY})); add_opt(common_arg( {"-o", "--output", "--output-file"}, "FNAME", - string_format("output file (default: '%s')", - ex == LLAMA_EXAMPLE_EXPORT_LORA - ? params.lora_outfile.c_str() - : ex == LLAMA_EXAMPLE_CVECTOR_GENERATOR - ? params.cvector_outfile.c_str() - : params.out_file.c_str()), + string_format("output file (default: '%s')", params.out_file.c_str()), [](common_params & params, const std::string & value) { params.out_file = value; - params.cvector_outfile = value; - params.lora_outfile = value; } ).set_examples({LLAMA_EXAMPLE_IMATRIX, LLAMA_EXAMPLE_CVECTOR_GENERATOR, LLAMA_EXAMPLE_EXPORT_LORA})); add_opt(common_arg( diff --git a/common/common.h b/common/common.h index 733f7f1c8..1c0f19977 100644 --- a/common/common.h +++ b/common/common.h @@ -407,8 +407,6 @@ struct common_params { int32_t i_pos = -1; // position of the passkey in the junk text // imatrix params - std::string out_file = "imatrix.dat"; // save the resulting imatrix to this file - int32_t n_out_freq = 10; // output the imatrix every n_out_freq iterations int32_t n_save_freq = 0; // save the imatrix every n_save_freq iterations int32_t i_chunk = 0; // start processing from this chunk @@ -420,16 +418,16 @@ struct common_params { int n_pca_batch = 100; int n_pca_iterations = 1000; dimre_method cvector_dimre_method = DIMRE_METHOD_PCA; - std::string cvector_outfile = "control_vector.gguf"; std::string cvector_positive_file = "examples/cvector-generator/positive.txt"; std::string cvector_negative_file = "examples/cvector-generator/negative.txt"; bool spm_infill = false; // suffix/prefix/middle pattern for infill - std::string lora_outfile = "ggml-lora-merged-f16.gguf"; - // batched-bench params bool batched_bench_output_jsonl = false; + + // common params + std::string out_file; // output filename for all example programs }; // call once at the start of a program if it uses libcommon diff --git a/examples/cvector-generator/cvector-generator.cpp b/examples/cvector-generator/cvector-generator.cpp index 413b71d34..c72528dac 100644 --- a/examples/cvector-generator/cvector-generator.cpp +++ b/examples/cvector-generator/cvector-generator.cpp @@ -394,6 +394,8 @@ static int prepare_entries(common_params & params, train_context & ctx_train) { int main(int argc, char ** argv) { common_params params; + params.out_file = "control_vector.gguf"; + if (!common_params_parse(argc, argv, params, LLAMA_EXAMPLE_CVECTOR_GENERATOR, print_usage)) { return 1; } @@ -498,7 +500,7 @@ int main(int argc, char ** argv) { } // write output vectors to gguf - export_gguf(ctx_train.v_final, params.cvector_outfile, model_hint); + export_gguf(ctx_train.v_final, params.out_file, model_hint); llama_backend_free(); diff --git a/examples/export-lora/export-lora.cpp b/examples/export-lora/export-lora.cpp index 91238e4be..e7d0fbfff 100644 --- a/examples/export-lora/export-lora.cpp +++ b/examples/export-lora/export-lora.cpp @@ -413,20 +413,22 @@ static void print_usage(int, char ** argv) { int main(int argc, char ** argv) { common_params params; + params.out_file = "ggml-lora-merged-f16.gguf"; + if (!common_params_parse(argc, argv, params, LLAMA_EXAMPLE_EXPORT_LORA, print_usage)) { return 1; } g_verbose = (params.verbosity > 1); try { - lora_merge_ctx ctx(params.model, params.lora_adapters, params.lora_outfile, params.cpuparams.n_threads); + lora_merge_ctx ctx(params.model, params.lora_adapters, params.out_file, params.cpuparams.n_threads); ctx.run_merge(); } catch (const std::exception & err) { fprintf(stderr, "%s\n", err.what()); exit(EXIT_FAILURE); } - printf("done, output file is %s\n", params.lora_outfile.c_str()); + printf("done, output file is %s\n", params.out_file.c_str()); return 0; } diff --git a/examples/imatrix/imatrix.cpp b/examples/imatrix/imatrix.cpp index 4edc0bfac..91649c450 100644 --- a/examples/imatrix/imatrix.cpp +++ b/examples/imatrix/imatrix.cpp @@ -206,9 +206,6 @@ bool IMatrixCollector::collect_imatrix(struct ggml_tensor * t, bool ask, void * void IMatrixCollector::save_imatrix(int ncall) const { auto fname = m_params.out_file; - if (fname.empty()) { - fname = "imatrix.dat"; - } if (ncall > 0) { fname += ".at_"; @@ -583,6 +580,8 @@ static bool compute_imatrix(llama_context * ctx, const common_params & params) { int main(int argc, char ** argv) { common_params params; + params.out_file = "imatrix.dat" ; + params.n_ctx = 512; params.logits_all = true; params.escape = false; From e128a1bf5b65741b485dd094a4201264d0580d68 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Mon, 10 Mar 2025 14:07:15 +0200 Subject: [PATCH 70/87] tests : fix test-quantize-fns to init the CPU backend (#12306) ggml-ci --- tests/test-quantize-fns.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/test-quantize-fns.cpp b/tests/test-quantize-fns.cpp index c77c8ed13..037c0582b 100644 --- a/tests/test-quantize-fns.cpp +++ b/tests/test-quantize-fns.cpp @@ -120,13 +120,7 @@ int main(int argc, char * argv[]) { generate_data(0.0, test_data.size(), test_data.data()); generate_data(1.0, test_data2.size(), test_data2.data()); - // Initialize GGML, ensures float conversion tables are initialized - struct ggml_init_params ggml_params = { - /* .mem_size = */ 1*1024, - /* .mem_buffer = */ NULL, - /* .no_alloc = */ true, - }; - struct ggml_context * ctx = ggml_init(ggml_params); + ggml_cpu_init(); int num_failed = 0; bool failed = false; @@ -188,7 +182,5 @@ int main(int argc, char * argv[]) { printf("%d tests failed\n", num_failed); } - ggml_free(ctx); - return num_failed > 0; } From 89b2b56e8658800375a8314200870b1ad4208a0b Mon Sep 17 00:00:00 2001 From: John Bean <113509988+johnbean393@users.noreply.github.com> Date: Mon, 10 Mar 2025 22:13:09 +0800 Subject: [PATCH 71/87] readme: added Sidekick to available UIs (#12311) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e371c44ed..1eec944f2 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,7 @@ Instructions for adding support for new models: [HOWTO-add-model.md](docs/develo - [eva](https://github.com/ylsdamxssjxxdd/eva) (MIT) - [iohub/collama](https://github.com/iohub/coLLaMA) (Apache-2.0) - [janhq/jan](https://github.com/janhq/jan) (AGPL) +- [johnbean393/Sidekick](https://github.com/johnbean393/Sidekick) (MIT) - [KanTV](https://github.com/zhouwg/kantv?tab=readme-ov-file) (Apache-2.0) - [KodiBot](https://github.com/firatkiral/kodibot) (GPL) - [llama.vim](https://github.com/ggml-org/llama.vim) (MIT) From 8acdacb3ea00697477eb019efbb6fc183371055c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henry=20Linjam=C3=A4ki?= Date: Mon, 10 Mar 2025 18:57:00 +0200 Subject: [PATCH 72/87] opencl: use OpenCL C standard supported by the device (#12221) This patch nudges the llama.cpp a bit to be supported on PoCL which doesn't support OpenCL C CL2.0. The issue is solved by querying the device for the supported OpenCL C versions and using the highest one available. --- ggml/CMakeLists.txt | 2 + ggml/src/ggml-opencl/CMakeLists.txt | 1 + ggml/src/ggml-opencl/ggml-opencl.cpp | 176 ++++++++++++++++++++------- 3 files changed, 136 insertions(+), 43 deletions(-) diff --git a/ggml/CMakeLists.txt b/ggml/CMakeLists.txt index 412d294dc..9a4ee4992 100644 --- a/ggml/CMakeLists.txt +++ b/ggml/CMakeLists.txt @@ -195,6 +195,8 @@ option(GGML_OPENCL "ggml: use OpenCL" option(GGML_OPENCL_PROFILING "ggml: use OpenCL profiling (increases overhead)" OFF) option(GGML_OPENCL_EMBED_KERNELS "ggml: embed kernels" ON) option(GGML_OPENCL_USE_ADRENO_KERNELS "ggml: use optimized kernels for Adreno" ON) +set (GGML_OPENCL_TARGET_VERSION "300" CACHE STRING + "gmml: OpenCL API version to target") # toolchain for vulkan-shaders-gen set (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN "" CACHE FILEPATH "ggml: toolchain file for vulkan-shaders-gen") diff --git a/ggml/src/ggml-opencl/CMakeLists.txt b/ggml/src/ggml-opencl/CMakeLists.txt index 45328a657..59a208fe9 100644 --- a/ggml/src/ggml-opencl/CMakeLists.txt +++ b/ggml/src/ggml-opencl/CMakeLists.txt @@ -15,6 +15,7 @@ if (GGML_OPENCL_PROFILING) endif () add_compile_definitions(GGML_OPENCL_SOA_Q) +add_compile_definitions(GGML_OPENCL_TARGET_VERSION=${GGML_OPENCL_TARGET_VERSION}) if (GGML_OPENCL_USE_ADRENO_KERNELS) message(STATUS "OpenCL will use matmul kernels optimized for Adreno") diff --git a/ggml/src/ggml-opencl/ggml-opencl.cpp b/ggml/src/ggml-opencl/ggml-opencl.cpp index b85a895c4..14d9934fb 100644 --- a/ggml/src/ggml-opencl/ggml-opencl.cpp +++ b/ggml/src/ggml-opencl/ggml-opencl.cpp @@ -1,4 +1,4 @@ -#define CL_TARGET_OPENCL_VERSION 220 +#define CL_TARGET_OPENCL_VERSION GGML_OPENCL_TARGET_VERSION #define CL_USE_DEPRECATED_OPENCL_1_2_APIS // suppress warnings in CL headers for GCC and Clang @@ -25,6 +25,8 @@ #include #include #include +#include +#include #undef MIN #undef MAX @@ -62,6 +64,97 @@ enum ADRENO_GPU_GEN { X1E, }; +struct ggml_cl_version { + cl_uint major = 0; + cl_uint minor = 0; +}; + +// Parses a version string of form "XX.YY ". On an error returns ggml_cl_version with all zeroes. +static ggml_cl_version parse_cl_version(std::string_view str) { + size_t major_str_begin = 0; + size_t major_str_end = str.find(".", major_str_begin); + if (major_str_end == std::string::npos) { + return {}; + } + + size_t minor_str_begin = major_str_end + 1; + size_t minor_str_end = str.find(" ", minor_str_begin); + if (minor_str_end == std::string::npos) { + return {}; + } + + cl_uint version_major; + if (std::from_chars(str.data() + major_str_begin, str.data() + major_str_end, version_major).ec != std::errc{}) { + return {}; + } + + cl_uint version_minor; + if (std::from_chars(str.data() + minor_str_begin, str.data() + minor_str_end, version_minor).ec != std::errc{}) { + return {}; + } + return { version_major, version_minor }; +} + +// Returns OpenCL platform's version. On an error returns ggml_cl_version with all zeroes. +static ggml_cl_version get_opencl_platform_version(cl_platform_id platform) { + size_t param_size; + CL_CHECK(clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, nullptr, ¶m_size)); + std::unique_ptr param_storage(new char[param_size]); + CL_CHECK(clGetPlatformInfo(platform, CL_PLATFORM_VERSION, param_size, param_storage.get(), nullptr)); + + auto param_value = std::string_view(param_storage.get(), param_size); + const std::string version_prefix = "OpenCL "; // Suffix: "XX.YY " + if (param_value.find(version_prefix) != 0) { + return {}; + } + param_value.remove_prefix(version_prefix.length()); + return parse_cl_version(param_value); +} + +// Return a version to use in OpenCL C compilation. On an error returns ggml_cl_version with all zeroes. +static ggml_cl_version get_opencl_c_version(ggml_cl_version platform_version, cl_device_id device) { + size_t param_size; + +#if CL_TARGET_OPENCL_VERSION >= 300 + if (platform_version.major >= 3) { + CL_CHECK(clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_ALL_VERSIONS, 0, nullptr, ¶m_size)); + if (!param_size) { + return {}; + } + + std::unique_ptr versions(new cl_name_version[param_size]); + CL_CHECK(clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_ALL_VERSIONS, param_size, versions.get(), nullptr)); + unsigned versions_count = param_size / sizeof(cl_name_version); + + cl_version version_max = 0; + for (unsigned i = 0; i < versions_count; i++) { + version_max = std::max(versions[i].version, version_max); + } + + return { CL_VERSION_MAJOR(version_max), CL_VERSION_MINOR(version_max) }; + } +#else + GGML_UNUSED(platform_version); +#endif // CL_TARGET_OPENCL_VERSION >= 300 + + CL_CHECK(clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_VERSION, 0, nullptr, ¶m_size)); + if (!param_size) { + return {}; + } + + std::unique_ptr param_storage(new char[param_size]); + CL_CHECK(clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_VERSION, param_size, param_storage.get(), nullptr)); + auto param_value = std::string_view(param_storage.get(), param_size); + + const std::string version_prefix = "OpenCL C "; // Suffix: "XX.YY " + if (param_value.find(version_prefix) != 0) { + return {}; + } + param_value.remove_prefix(version_prefix.length()); + + return parse_cl_version(param_value); +} + static ADRENO_GPU_GEN get_adreno_gpu_gen(const char *device_name) { if (strstr(device_name, "730") || strstr(device_name, "740") || @@ -470,16 +563,11 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { // A local ref of cl_device_id for convenience cl_device_id device = backend_ctx->device; - // Check device OpenCL version, OpenCL 2.0 or above is required - size_t device_ver_str_size; - clGetDeviceInfo(device, CL_DEVICE_VERSION, 0, NULL, &device_ver_str_size); - char *device_ver_buffer = (char *)alloca(device_ver_str_size + 1); - clGetDeviceInfo(device, CL_DEVICE_VERSION, device_ver_str_size, device_ver_buffer, NULL); - device_ver_buffer[device_ver_str_size] = '\0'; - GGML_LOG_INFO("ggml_opencl: device OpenCL version: %s\n", device_ver_buffer); + ggml_cl_version platform_version = get_opencl_platform_version(default_device->platform->id); - if (strstr(device_ver_buffer, "OpenCL 2") == NULL && - strstr(device_ver_buffer, "OpenCL 3") == NULL) { + // Check device OpenCL version, OpenCL 2.0 or above is required + ggml_cl_version opencl_c_version = get_opencl_c_version(platform_version, device); + if (opencl_c_version.major < 2) { GGML_LOG_ERROR("ggml_opencl: OpenCL 2.0 or above is required\n"); return backend_ctx; } @@ -516,8 +604,7 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { // If OpenCL 3.0 is supported, then check for cl_khr_subgroups, which becomes // optional in OpenCL 3.0 (cl_khr_subgroup is mandatory in OpenCL 2.x) - if (strstr(device_ver_buffer, "OpenCL 3") && - strstr(ext_buffer, "cl_khr_subgroups") == NULL && + if (opencl_c_version.major == 3 && strstr(ext_buffer, "cl_khr_subgroups") == NULL && strstr(ext_buffer, "cl_intel_subgroups") == NULL) { GGML_LOG_ERROR("ggml_opencl: device does not support subgroups (cl_khr_subgroups or cl_intel_subgroups) " "(note that subgroups is an optional feature in OpenCL 3.0)\n"); @@ -581,9 +668,12 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { const std::string kernel_src = read_file("ggml-opencl.cl"); #endif - std::string compile_opts = - "-cl-std=CL2.0 -cl-mad-enable -cl-unsafe-math-optimizations " - "-cl-finite-math-only -cl-fast-relaxed-math "; + auto opencl_c_std = + std::string("CL") + std::to_string(opencl_c_version.major) + "." + std::to_string(opencl_c_version.minor); + + std::string compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable -cl-unsafe-math-optimizations" + " -cl-finite-math-only -cl-fast-relaxed-math"; backend_ctx->program = build_program_from_source(context, device, kernel_src.c_str(), compile_opts); // Non matmul kernels. @@ -693,10 +783,10 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { CL_CHECK((backend_ctx->kernel_transpose_16 = clCreateKernel(backend_ctx->program_transpose_16, "kernel_transpose_16", &err), err)); // Gemv general - std::string CL_gemv_compile_opts = - " -cl-std=CL2.0 " - " -cl-mad-enable " - " -DSIMDGROUP_WIDTH=" + std::to_string(backend_ctx->adreno_wave_size); + std::string CL_gemv_compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable " + " -DSIMDGROUP_WIDTH=" + + std::to_string(backend_ctx->adreno_wave_size); if (has_vector_subgroup_broadcast) { CL_gemv_compile_opts += " -DVECTOR_SUB_GROUP_BROADCAT "; } @@ -713,12 +803,12 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { CL_CHECK((backend_ctx->CL_mul_mat_vec_q4_0_f32_1d_4x_flat_general = clCreateKernel(backend_ctx->program_CL_gemv_general, "kernel_gemv_noshuffle", &err), err)); // Gemv 2048, 16384 - CL_gemv_compile_opts = - " -cl-std=CL2.0 " - " -cl-mad-enable " - " -DLINE_STRIDE_A=2048 " - " -DBLOCK_STRIDE_A=16384 " - " -DSIMDGROUP_WIDTH=" + std::to_string(backend_ctx->adreno_wave_size); + CL_gemv_compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable " + " -DLINE_STRIDE_A=2048 " + " -DBLOCK_STRIDE_A=16384 " + " -DSIMDGROUP_WIDTH=" + + std::to_string(backend_ctx->adreno_wave_size); if (has_vector_subgroup_broadcast) { CL_gemv_compile_opts += " -DVECTOR_SUB_GROUP_BROADCAT "; } @@ -735,12 +825,12 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { CL_CHECK((backend_ctx->CL_mul_mat_vec_q4_0_f32_1d_4x_flat_4096_1_4096 = clCreateKernel(backend_ctx->program_CL_gemv_4096_1_4096, "kernel_gemv_noshuffle", &err), err)); // Gemv 2048, 16384 - CL_gemv_compile_opts = - " -cl-std=CL2.0 " - " -cl-mad-enable " - " -DLINE_STRIDE_A=2048 " - " -DBLOCK_STRIDE_A=16384 " - " -DSIMDGROUP_WIDTH=" + std::to_string(backend_ctx->adreno_wave_size); + CL_gemv_compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable " + " -DLINE_STRIDE_A=2048 " + " -DBLOCK_STRIDE_A=16384 " + " -DSIMDGROUP_WIDTH=" + + std::to_string(backend_ctx->adreno_wave_size); if (has_vector_subgroup_broadcast) { CL_gemv_compile_opts += " -DVECTOR_SUB_GROUP_BROADCAT "; } @@ -750,12 +840,12 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { CL_CHECK((backend_ctx->CL_mul_mat_vec_q4_0_f32_1d_4x_flat_4096_1_11008 = clCreateKernel(backend_ctx->program_CL_gemv_4096_1_11008, "kernel_gemv_noshuffle", &err), err)); // Gemv 5504, 44032 - CL_gemv_compile_opts = - " -cl-std=CL2.0 " - " -cl-mad-enable " - " -DLINE_STRIDE_A=5504 " - " -DBLOCK_STRIDE_A=44032 " - " -DSIMDGROUP_WIDTH=" + std::to_string(backend_ctx->adreno_wave_size); + CL_gemv_compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable " + " -DLINE_STRIDE_A=5504 " + " -DBLOCK_STRIDE_A=44032 " + " -DSIMDGROUP_WIDTH=" + + std::to_string(backend_ctx->adreno_wave_size); if (has_vector_subgroup_broadcast) { CL_gemv_compile_opts += " -DVECTOR_SUB_GROUP_BROADCAT "; } @@ -765,12 +855,12 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) { CL_CHECK((backend_ctx->CL_mul_mat_vec_q4_0_f32_1d_4x_flat_11008_1_4096 = clCreateKernel(backend_ctx->program_CL_gemv_11008_1_4096, "kernel_gemv_noshuffle", &err), err)); // Gemv 16000, 128000 - CL_gemv_compile_opts = - " -cl-std=CL2.0 " - " -cl-mad-enable " - " -DLINE_STRIDE_A=16000 " - " -DBLOCK_STRIDE_A=128000 " - " -DSIMDGROUP_WIDTH=" + std::to_string(backend_ctx->adreno_wave_size); + CL_gemv_compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable " + " -DLINE_STRIDE_A=16000 " + " -DBLOCK_STRIDE_A=128000 " + " -DSIMDGROUP_WIDTH=" + + std::to_string(backend_ctx->adreno_wave_size); if (has_vector_subgroup_broadcast) { CL_gemv_compile_opts += " -DVECTOR_SUB_GROUP_BROADCAT "; } From 251364549fe4a78d4e2e66f1adfaf2bd53041d2c Mon Sep 17 00:00:00 2001 From: R0CKSTAR Date: Tue, 11 Mar 2025 01:18:25 +0800 Subject: [PATCH 73/87] musa: support new arch mp_31 and update doc (#12296) Signed-off-by: Xiaodong Ye --- Makefile | 2 +- docs/build.md | 48 +++++++++++++++++++++++-------- ggml/src/ggml-musa/CMakeLists.txt | 2 +- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 5339d490b..1f9455eff 100644 --- a/Makefile +++ b/Makefile @@ -836,7 +836,7 @@ ifdef GGML_MUSA else MUSA_PATH ?= /opt/musa endif - MUSA_ARCHITECTURES ?= 21;22 + MUSA_ARCHITECTURES ?= 21;22;31 MK_CPPFLAGS += -DGGML_USE_MUSA -DGGML_USE_CUDA MK_LDFLAGS += -L$(MUSA_PATH)/lib -Wl,-rpath=$(MUSA_PATH)/lib diff --git a/docs/build.md b/docs/build.md index 3d8333328..2e3975c14 100644 --- a/docs/build.md +++ b/docs/build.md @@ -197,29 +197,53 @@ The following compilation options are also available to tweak performance: ## MUSA -This provides GPU acceleration using the MUSA cores of your Moore Threads MTT GPU. Make sure to have the MUSA SDK installed. You can download it from here: [MUSA SDK](https://developer.mthreads.com/sdk/download/musa). +This provides GPU acceleration using a Moore Threads GPU. Make sure to have the [MUSA SDK](https://developer.mthreads.com/musa/musa-sdk) installed. -- Using `CMake`: +#### Download directly from Moore Threads - ```bash - cmake -B build -DGGML_MUSA=ON - cmake --build build --config Release +You may find the official downloads here: [Moore Threads developer site](https://developer.mthreads.com/sdk/download/musa). + +### Compilation + +```bash +cmake -B build -DGGML_MUSA=ON +cmake --build build --config Release +``` + +#### Override Compute Capability Specifications + +By default, all supported compute capabilities are enabled. To customize this behavior, you can specify the `MUSA_ARCHITECTURES` option in the CMake command: + +```bash +cmake -B build -DGGML_MUSA=ON -DMUSA_ARCHITECTURES="21" +``` + +This configuration enables only compute capability `2.1` (MTT S80) during compilation, which can help reduce compilation time. + +#### Compilation options + +Most of the compilation options available for CUDA should also be available for MUSA, though they haven't been thoroughly tested yet. + +- For static builds, add `-DBUILD_SHARED_LIBS=OFF` and `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`: ``` - - For static build: - - ```bash cmake -B build -DGGML_MUSA=ON \ -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON cmake --build build --config Release ``` -The environment variable [`MUSA_VISIBLE_DEVICES`](https://docs.mthreads.com/musa-sdk/musa-sdk-doc-online/programming_guide/Z%E9%99%84%E5%BD%95/) can be used to specify which GPU(s) will be used. +### Runtime MUSA environmental variables + +You may set the [musa environmental variables](https://docs.mthreads.com/musa-sdk/musa-sdk-doc-online/programming_guide/Z%E9%99%84%E5%BD%95/) at runtime. + +```bash +# Use `MUSA_VISIBLE_DEVICES` to hide the first compute device. +MUSA_VISIBLE_DEVICES="-0" ./build/bin/llama-server --model /srv/models/llama.gguf +``` + +### Unified Memory The environment variable `GGML_CUDA_ENABLE_UNIFIED_MEMORY=1` can be used to enable unified memory in Linux. This allows swapping to system RAM instead of crashing when the GPU VRAM is exhausted. -Most of the compilation options available for CUDA should also be available for MUSA, though they haven't been thoroughly tested yet. - ## HIP This provides GPU acceleration on HIP-supported AMD GPUs. diff --git a/ggml/src/ggml-musa/CMakeLists.txt b/ggml/src/ggml-musa/CMakeLists.txt index 2c75abf61..166970ca6 100644 --- a/ggml/src/ggml-musa/CMakeLists.txt +++ b/ggml/src/ggml-musa/CMakeLists.txt @@ -21,7 +21,7 @@ if (MUSAToolkit_FOUND) message(STATUS "MUSA Toolkit found") if (NOT DEFINED MUSA_ARCHITECTURES) - set(MUSA_ARCHITECTURES "21;22") + set(MUSA_ARCHITECTURES "21;22;31") endif() message(STATUS "Using MUSA architectures: ${MUSA_ARCHITECTURES}") From 2c9f833d17bb5b8ea89dec663b072b5420fc5438 Mon Sep 17 00:00:00 2001 From: Eve <139727413+netrunnereve@users.noreply.github.com> Date: Mon, 10 Mar 2025 19:28:11 +0000 Subject: [PATCH 74/87] mat vec double buffer (#12188) --- .../vulkan-shaders/mul_mat_vec_q2_k.comp | 47 ++++++++++--------- .../vulkan-shaders/mul_mat_vec_q3_k.comp | 26 +++++----- .../vulkan-shaders/mul_mat_vec_q6_k.comp | 12 ++--- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp index 8cdc640e8..423ceb8a3 100644 --- a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp +++ b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp @@ -5,23 +5,24 @@ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE sccache1[BLOCK_SIZE/16][16]; -shared FLOAT_TYPE sccache2[BLOCK_SIZE/16][16]; +shared FLOAT_TYPE sccache1[2][BLOCK_SIZE/16][16]; +shared FLOAT_TYPE sccache2[2][BLOCK_SIZE/16][16]; FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; +uint csel = 0; void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, const uint v_im, const uint ix, const uint q_offset, const uint y_offset, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows, const bool all_threads) { const uint y_idx = i * QUANT_K + y_offset; [[unroll]] for (uint n = 0; n < num_rows; ++n) { const uint ib0 = a_offset / QUANT_K + (first_row+n)*num_blocks_per_row; + csel ^= 1; - barrier(); if (!all_threads) { // when we don't have enough blocks to use all threads if (i < num_blocks_per_row) { const uint32_t scale = uint32_t(data_a[ib0 + i].scales[itid]); - sccache1[ix][itid] = FLOAT_TYPE(scale & 0xF); - sccache2[ix][itid] = FLOAT_TYPE((scale >> 4) & 0xF); + sccache1[csel][ix][itid] = FLOAT_TYPE(scale & 0xF); + sccache2[csel][ix][itid] = FLOAT_TYPE((scale >> 4) & 0xF); } barrier(); @@ -29,8 +30,8 @@ void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, continue; } else { const uint32_t scale = uint32_t(data_a[ib0 + i].scales[itid]); - sccache1[ix][itid] = FLOAT_TYPE(scale & 0xF); - sccache2[ix][itid] = FLOAT_TYPE((scale >> 4) & 0xF); + sccache1[csel][ix][itid] = FLOAT_TYPE(scale & 0xF); + sccache2[csel][ix][itid] = FLOAT_TYPE((scale >> 4) & 0xF); barrier(); } @@ -57,22 +58,22 @@ void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, FLOAT_TYPE sum1 = FLOAT_TYPE(0.0); FLOAT_TYPE sum2 = FLOAT_TYPE(0.0); [[unroll]] for (int l = 0; l < 2; ++l) { - sum1 = fma(FLOAT_TYPE(b0[l]), sccache1[ix][ 8*v_im] * qs_u32_0[l ], - fma(FLOAT_TYPE(b16[l]), sccache1[ix][1 + 8*v_im] * qs_u32_0[l+2], - fma(FLOAT_TYPE(b32[l]), sccache1[ix][2 + 8*v_im] * qs_u32_2[l ], - fma(FLOAT_TYPE(b48[l]), sccache1[ix][3 + 8*v_im] * qs_u32_2[l+2], - fma(FLOAT_TYPE(b64[l]), sccache1[ix][4 + 8*v_im] * qs_u32_4[l ], - fma(FLOAT_TYPE(b80[l]), sccache1[ix][5 + 8*v_im] * qs_u32_4[l+2], - fma(FLOAT_TYPE(b96[l]), sccache1[ix][6 + 8*v_im] * qs_u32_6[l ], - fma(FLOAT_TYPE(b112[l]), sccache1[ix][7 + 8*v_im] * qs_u32_6[l+2], sum1)))))))); - sum2 = fma(FLOAT_TYPE(b0[l]), sccache2[ix][ 8*v_im], - fma(FLOAT_TYPE(b16[l]), sccache2[ix][1 + 8*v_im], - fma(FLOAT_TYPE(b32[l]), sccache2[ix][2 + 8*v_im], - fma(FLOAT_TYPE(b48[l]), sccache2[ix][3 + 8*v_im], - fma(FLOAT_TYPE(b64[l]), sccache2[ix][4 + 8*v_im], - fma(FLOAT_TYPE(b80[l]), sccache2[ix][5 + 8*v_im], - fma(FLOAT_TYPE(b96[l]), sccache2[ix][6 + 8*v_im], - fma(FLOAT_TYPE(b112[l]), sccache2[ix][7 + 8*v_im], sum2)))))))); + sum1 = fma(FLOAT_TYPE(b0[l]), sccache1[csel][ix][ 8*v_im] * qs_u32_0[l ], + fma(FLOAT_TYPE(b16[l]), sccache1[csel][ix][1 + 8*v_im] * qs_u32_0[l+2], + fma(FLOAT_TYPE(b32[l]), sccache1[csel][ix][2 + 8*v_im] * qs_u32_2[l ], + fma(FLOAT_TYPE(b48[l]), sccache1[csel][ix][3 + 8*v_im] * qs_u32_2[l+2], + fma(FLOAT_TYPE(b64[l]), sccache1[csel][ix][4 + 8*v_im] * qs_u32_4[l ], + fma(FLOAT_TYPE(b80[l]), sccache1[csel][ix][5 + 8*v_im] * qs_u32_4[l+2], + fma(FLOAT_TYPE(b96[l]), sccache1[csel][ix][6 + 8*v_im] * qs_u32_6[l ], + fma(FLOAT_TYPE(b112[l]), sccache1[csel][ix][7 + 8*v_im] * qs_u32_6[l+2], sum1)))))))); + sum2 = fma(FLOAT_TYPE(b0[l]), sccache2[csel][ix][ 8*v_im], + fma(FLOAT_TYPE(b16[l]), sccache2[csel][ix][1 + 8*v_im], + fma(FLOAT_TYPE(b32[l]), sccache2[csel][ix][2 + 8*v_im], + fma(FLOAT_TYPE(b48[l]), sccache2[csel][ix][3 + 8*v_im], + fma(FLOAT_TYPE(b64[l]), sccache2[csel][ix][4 + 8*v_im], + fma(FLOAT_TYPE(b80[l]), sccache2[csel][ix][5 + 8*v_im], + fma(FLOAT_TYPE(b96[l]), sccache2[csel][ix][6 + 8*v_im], + fma(FLOAT_TYPE(b112[l]), sccache2[csel][ix][7 + 8*v_im], sum2)))))))); } temp[j][n] = fma(dall, sum1, fma(-dmin, sum2, temp[j][n])); } diff --git a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q3_k.comp b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q3_k.comp index 3116fad16..e91724a28 100644 --- a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q3_k.comp +++ b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q3_k.comp @@ -5,20 +5,21 @@ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE sccache[BLOCK_SIZE/16][2][8]; +shared FLOAT_TYPE sccache[2][BLOCK_SIZE/16][2][8]; FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; +uint csel = 0; void calc_superblock(const uint a_offset, const uint b_offset, const uint ix, const uint itid8, const uint v_im, const uint v_im4, const uint v_in, const uint32_t hm_m[4], const uint q_offset, const uint y_offset, const uint s_shift, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows, const bool all_threads) { const uint y_idx = i * QUANT_K + y_offset; [[unroll]] for (uint n = 0; n < num_rows; ++n) { const uint ib0 = a_offset / QUANT_K + (first_row+n)*num_blocks_per_row; + csel ^= 1; if (!all_threads) { // when we don't have enough blocks to use all threads - barrier(); if (i < num_blocks_per_row) - sccache[ix][v_im][itid8] = FLOAT_TYPE(int8_t(((data_a[ib0+i].scales[itid8] >> v_im4) & 0xF) | (((data_a[ib0+i].scales[itid8%4+8] >> s_shift) & 3) << 4)) - 32); + sccache[csel][ix][v_im][itid8] = FLOAT_TYPE(int8_t(((data_a[ib0+i].scales[itid8] >> v_im4) & 0xF) | (((data_a[ib0+i].scales[itid8%4+8] >> s_shift) & 3) << 4)) - 32); barrier(); if (i >= num_blocks_per_row) @@ -40,8 +41,7 @@ void calc_superblock(const uint a_offset, const uint b_offset, const uint ix, co const vec4 qs_u32_6 = vec4(unpack8((qs_u32 >> 6) & 0x03030303)); if (all_threads) { - barrier(); - sccache[ix][v_im][itid8] = FLOAT_TYPE(int8_t(((data_a[ib0+i].scales[itid8] >> v_im4) & 0xF) | (((data_a[ib0+i].scales[itid8%4+8] >> s_shift) & 3) << 4)) - 32); + sccache[csel][ix][v_im][itid8] = FLOAT_TYPE(int8_t(((data_a[ib0+i].scales[itid8] >> v_im4) & 0xF) | (((data_a[ib0+i].scales[itid8%4+8] >> s_shift) & 3) << 4)) - 32); barrier(); } @@ -59,14 +59,14 @@ void calc_superblock(const uint a_offset, const uint b_offset, const uint ix, co FLOAT_TYPE sum = FLOAT_TYPE(0.0); [[unroll]] for (int l = 0; l < 2; ++l) { - sum = fma(FLOAT_TYPE( b0[l]) * sccache[ix][v_im][0], qs_u32_0[l ] - hmk_0[l ], - fma(FLOAT_TYPE( b16[l]) * sccache[ix][v_im][1], qs_u32_0[l+2] - hmk_0[l+2], - fma(FLOAT_TYPE( b32[l]) * sccache[ix][v_im][2], qs_u32_2[l ] - hmk_1[l ], - fma(FLOAT_TYPE( b48[l]) * sccache[ix][v_im][3], qs_u32_2[l+2] - hmk_1[l+2], - fma(FLOAT_TYPE( b64[l]) * sccache[ix][v_im][4], qs_u32_4[l ] - hmk_2[l ], - fma(FLOAT_TYPE( b80[l]) * sccache[ix][v_im][5], qs_u32_4[l+2] - hmk_2[l+2], - fma(FLOAT_TYPE( b96[l]) * sccache[ix][v_im][6], qs_u32_6[l ] - hmk_3[l ], - fma(FLOAT_TYPE(b112[l]) * sccache[ix][v_im][7], qs_u32_6[l+2] - hmk_3[l+2], sum)))))))); + sum = fma(FLOAT_TYPE( b0[l]) * sccache[csel][ix][v_im][0], qs_u32_0[l ] - hmk_0[l ], + fma(FLOAT_TYPE( b16[l]) * sccache[csel][ix][v_im][1], qs_u32_0[l+2] - hmk_0[l+2], + fma(FLOAT_TYPE( b32[l]) * sccache[csel][ix][v_im][2], qs_u32_2[l ] - hmk_1[l ], + fma(FLOAT_TYPE( b48[l]) * sccache[csel][ix][v_im][3], qs_u32_2[l+2] - hmk_1[l+2], + fma(FLOAT_TYPE( b64[l]) * sccache[csel][ix][v_im][4], qs_u32_4[l ] - hmk_2[l ], + fma(FLOAT_TYPE( b80[l]) * sccache[csel][ix][v_im][5], qs_u32_4[l+2] - hmk_2[l+2], + fma(FLOAT_TYPE( b96[l]) * sccache[csel][ix][v_im][6], qs_u32_6[l ] - hmk_3[l ], + fma(FLOAT_TYPE(b112[l]) * sccache[csel][ix][v_im][7], qs_u32_6[l+2] - hmk_3[l+2], sum)))))))); } temp[j][n] = fma(d, sum, temp[j][n]); } diff --git a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q6_k.comp b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q6_k.comp index f05f96b5e..d53d9ee0a 100644 --- a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q6_k.comp +++ b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q6_k.comp @@ -6,20 +6,21 @@ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE sccache[BLOCK_SIZE/16][16]; +shared FLOAT_TYPE sccache[2][BLOCK_SIZE/16][16]; FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; +uint csel = 0; void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, const uint ix, const uint ql_offset, const uint qh_offset, const uint s_offset, const uint y_offset, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows, const bool all_threads) { const uint y_idx = i * QUANT_K + y_offset; [[unroll]] for (uint n = 0; n < num_rows; ++n) { const uint ib0 = a_offset / QUANT_K + (first_row+n)*num_blocks_per_row; + csel ^= 1; if (!all_threads) { // when we don't have enough blocks to use all threads - barrier(); if (i < num_blocks_per_row) - sccache[ix][itid] = FLOAT_TYPE(data_a[ib0 + i].scales[itid]); + sccache[csel][ix][itid] = FLOAT_TYPE(data_a[ib0 + i].scales[itid]); barrier(); if (i >= num_blocks_per_row) @@ -51,8 +52,7 @@ void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, const vec4 q3 = vec4(unpack8(q3_u32)) - 32; if (all_threads) { - barrier(); - sccache[ix][itid] = FLOAT_TYPE(data_a[ib0 + i].scales[itid]); + sccache[csel][ix][itid] = FLOAT_TYPE(data_a[ib0 + i].scales[itid]); barrier(); } @@ -71,7 +71,7 @@ void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, sum[2] = fma(FLOAT_TYPE(by64[l]), q2[l], sum[2]); sum[3] = fma(FLOAT_TYPE(by96[l]), q3[l], sum[3]); } - temp[j][n] = fma(fma(sum[0], sccache[ix][s_offset], fma(sum[1], sccache[ix][s_offset + 2], fma(sum[2], sccache[ix][s_offset + 4], sum[3] * sccache[ix][s_offset + 6]))), d, temp[j][n]); + temp[j][n] = fma(fma(sum[0], sccache[csel][ix][s_offset], fma(sum[1], sccache[csel][ix][s_offset + 2], fma(sum[2], sccache[csel][ix][s_offset + 4], sum[3] * sccache[csel][ix][s_offset + 6]))), d, temp[j][n]); } } } From 96e1280839561aaabb73851f94972a2cd37b2d96 Mon Sep 17 00:00:00 2001 From: Xuan-Son Nguyen Date: Tue, 11 Mar 2025 09:20:16 +0100 Subject: [PATCH 75/87] clip : bring back GPU support (#12322) * clip : bring back GPU support * use n_gpu_layers param * fix double free * ggml_backend_init_by_type * clean up --- examples/llava/clip.cpp | 149 ++++++++++++++++---------------- examples/llava/clip.h | 11 ++- examples/llava/minicpmv-cli.cpp | 6 +- 3 files changed, 89 insertions(+), 77 deletions(-) diff --git a/examples/llava/clip.cpp b/examples/llava/clip.cpp index 3f558b7bd..7f892beb6 100644 --- a/examples/llava/clip.cpp +++ b/examples/llava/clip.cpp @@ -4,31 +4,12 @@ // Note: Even when using identical normalized image inputs (see normalize_image_u8_to_f32()) we have a significant difference in resulting embeddings compared to pytorch #include "clip.h" #include "ggml.h" +#include "ggml-cpp.h" #include "ggml-cpu.h" #include "ggml-alloc.h" #include "ggml-backend.h" #include "gguf.h" -//#ifdef GGML_USE_CUDA -//#include "ggml-cuda.h" -//#endif -// -//#ifdef GGML_USE_SYCL -//#include "ggml-sycl.h" -//#endif -// -//#ifdef GGML_USE_METAL -//#include "ggml-metal.h" -//#endif -// -//#ifdef GGML_USE_CANN -//#include "ggml-cann.h" -//#endif -// -//#ifdef GGML_USE_VULKAN -//#include "ggml-vulkan.h" -//#endif - #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" @@ -600,18 +581,54 @@ struct clip_ctx { bool has_post_norm = false; bool has_patch_bias = false; - struct gguf_context * ctx_gguf; - struct ggml_context * ctx_data; + struct gguf_context * ctx_gguf = nullptr; + struct ggml_context * ctx_data = nullptr; std::vector buf_compute_meta; - // memory buffers to evaluate the model - ggml_backend_buffer_t params_buffer = NULL; + std::vector backend_ptrs; + std::vector backend_buft; - ggml_backend_t backend = NULL; - ggml_gallocr_t compute_alloc = NULL; + ggml_backend_t backend = nullptr; + ggml_backend_t backend_cpu = nullptr; + ggml_backend_buffer_t buf = nullptr; + + ggml_backend_sched_ptr sched; struct clip_image_size * load_image_size; + + clip_ctx(clip_context_params & ctx_params) { + backend_cpu = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr); + backend = ctx_params.use_gpu + ? ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_GPU, nullptr) + : nullptr; + + if (backend) { + LOG_INF("%s: CLIP using %s backend\n", __func__, ggml_backend_name(backend)); + backend_ptrs.push_back(backend); + backend_buft.push_back(ggml_backend_get_default_buffer_type(backend)); + } else { + backend = backend_cpu; + LOG_INF("%s: CLIP using CPU backend\n", __func__); + } + + backend_ptrs.push_back(backend_cpu); + backend_buft.push_back(ggml_backend_get_default_buffer_type(backend_cpu)); + + sched.reset( + ggml_backend_sched_new(backend_ptrs.data(), backend_buft.data(), backend_ptrs.size(), 8192, false) + ); + } + + ~clip_ctx() { + ggml_free(ctx_data); + gguf_free(ctx_gguf); + ggml_backend_buffer_free(buf); + ggml_backend_free(backend); + if (backend_cpu != backend) { + ggml_backend_free(backend_cpu); + } + } }; static ggml_cgraph * clip_image_build_graph(clip_ctx * ctx, const clip_image_f32_batch * imgs, struct clip_image_size * load_image_size, bool is_inf = false) { @@ -1184,6 +1201,14 @@ static ggml_cgraph * clip_image_build_graph(clip_ctx * ctx, const clip_image_f32 // read and create ggml_context containing the tensors and their data struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { + return clip_init(fname, clip_context_params{ + /* use_gpu */ true, + /* verbosity */ verbosity, + }); +} + +struct clip_ctx * clip_init(const char * fname, struct clip_context_params ctx_params) { + int verbosity = ctx_params.verbosity; struct ggml_context * meta = NULL; struct gguf_init_params params = { @@ -1277,7 +1302,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { } } - clip_ctx * new_clip = new clip_ctx{}; + clip_ctx * new_clip = new clip_ctx(ctx_params); // update projector type { @@ -1296,36 +1321,6 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { } } -//#ifdef GGML_USE_CUDA -// new_clip->backend = ggml_backend_cuda_init(0); -// LOG_INF("%s: CLIP using CUDA backend\n", __func__); -//#endif -// -//#ifdef GGML_USE_METAL -// new_clip->backend = ggml_backend_metal_init(); -// LOG_INF("%s: CLIP using Metal backend\n", __func__); -//#endif -// -//#ifdef GGML_USE_CANN -// new_clip->backend = ggml_backend_cann_init(0); -// LOG_INF("%s: CLIP using CANN backend\n", __func__); -//#endif -// -//#ifdef GGML_USE_VULKAN -// new_clip->backend = ggml_backend_vk_init(0); -// LOG_INF("%s: CLIP using Vulkan backend\n", __func__); -//#endif -// -//#ifdef GGML_USE_SYCL -// new_clip->backend = ggml_backend_sycl_init(0); -// LOG_INF("%s: CLIP using SYCL backend\n", __func__); -//#endif - - if (!new_clip->backend) { - new_clip->backend = ggml_backend_cpu_init(); - LOG_INF("%s: CLIP using CPU backend\n", __func__); - } - // model size and capabilities { int idx = get_key_idx(ctx, KEY_HAS_TEXT_ENC); @@ -1421,7 +1416,9 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { } // alloc memory and offload data - new_clip->params_buffer = ggml_backend_alloc_ctx_tensors(new_clip->ctx_data, new_clip->backend); + ggml_backend_buffer_type_t buft = ggml_backend_get_default_buffer_type(new_clip->backend); + new_clip->buf = ggml_backend_alloc_ctx_tensors_from_buft(new_clip->ctx_data, buft); + ggml_backend_buffer_set_usage(new_clip->buf, GGML_BACKEND_BUFFER_USAGE_WEIGHTS); for (int i = 0; i < n_tensors; ++i) { const char * name = gguf_get_tensor_name(ctx, i); struct ggml_tensor * cur = ggml_get_tensor(new_clip->ctx_data, name); @@ -1434,7 +1431,7 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { return nullptr; } int num_bytes = ggml_nbytes(cur); - if (ggml_backend_buffer_is_host(new_clip->params_buffer)) { + if (ggml_backend_buft_is_host(buft)) { // for the CPU and Metal backend, we can read directly into the tensor fin.read(reinterpret_cast(cur->data), num_bytes); } else { @@ -1720,14 +1717,21 @@ struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { // measure mem requirement and allocate { new_clip->buf_compute_meta.resize(GGML_DEFAULT_GRAPH_SIZE * ggml_tensor_overhead() + ggml_graph_overhead()); - new_clip->compute_alloc = ggml_gallocr_new(ggml_backend_get_default_buffer_type(new_clip->backend)); clip_image_f32_batch batch; batch.size = 1; batch.data = nullptr; ggml_cgraph * gf = clip_image_build_graph(new_clip, &batch, nullptr, false); - ggml_gallocr_reserve(new_clip->compute_alloc, gf); - size_t compute_memory_buffer_size = ggml_gallocr_get_buffer_size(new_clip->compute_alloc, 0); - LOG_INF("%s: compute allocated memory: %.2f MB\n", __func__, compute_memory_buffer_size /1024.0/1024.0); + ggml_backend_sched_reserve(new_clip->sched.get(), gf); + for (size_t i = 0; i < new_clip->backend_ptrs.size(); ++i) { + ggml_backend_t backend = new_clip->backend_ptrs[i]; + ggml_backend_buffer_type_t buft = new_clip->backend_buft[i]; + size_t size = ggml_backend_sched_get_buffer_size(new_clip->sched.get(), backend); + if (size > 1) { + LOG_INF("%s: %10s compute buffer size = %8.2f MiB\n", __func__, + ggml_backend_buft_name(buft), + size / 1024.0 / 1024.0); + } + } } return new_clip; @@ -2408,12 +2412,6 @@ ggml_tensor * clip_get_newline_tensor(const struct clip_ctx * ctx) { } void clip_free(clip_ctx * ctx) { - ggml_free(ctx->ctx_data); - gguf_free(ctx->ctx_gguf); - - ggml_backend_buffer_free(ctx->params_buffer); - ggml_backend_free(ctx->backend); - ggml_gallocr_free(ctx->compute_alloc); delete ctx; } @@ -2609,8 +2607,9 @@ bool clip_image_batch_encode(clip_ctx * ctx, const int n_threads, const clip_ima } // build the inference graph + ggml_backend_sched_reset(ctx->sched.get()); ggml_cgraph * gf = clip_image_build_graph(ctx, imgs, ctx->load_image_size, true); - ggml_gallocr_alloc_graph(ctx->compute_alloc, gf); + ggml_backend_sched_alloc_graph(ctx->sched.get(), gf); // set inputs const auto & model = ctx->vision_model; @@ -2775,11 +2774,13 @@ bool clip_image_batch_encode(clip_ctx * ctx, const int n_threads, const clip_ima } } - if (ggml_backend_is_cpu(ctx->backend)) { - ggml_backend_cpu_set_n_threads(ctx->backend, n_threads); - } + ggml_backend_cpu_set_n_threads(ctx->backend_cpu, n_threads); - ggml_backend_graph_compute(ctx->backend, gf); + auto status = ggml_backend_sched_graph_compute(ctx->sched.get(), gf); + if (status != GGML_STATUS_SUCCESS) { + LOG_ERR("%s: ggml_backend_sched_graph_compute failed with error %d\n", __func__, status); + return false; + } // the last node is the embedding tensor struct ggml_tensor * embeddings = ggml_graph_node(gf, -1); diff --git a/examples/llava/clip.h b/examples/llava/clip.h index 002c41965..47059ca1b 100644 --- a/examples/llava/clip.h +++ b/examples/llava/clip.h @@ -39,8 +39,15 @@ struct clip_image_f32_batch { size_t size; }; -CLIP_API struct clip_ctx * clip_model_load (const char * fname, int verbosity); -CLIP_API struct clip_ctx * clip_model_load_cpu(const char * fname, int verbosity); +struct clip_context_params { + bool use_gpu; + int verbosity; +}; + +// deprecated, use clip_init +CLIP_API struct clip_ctx * clip_model_load(const char * fname, int verbosity); + +CLIP_API struct clip_ctx * clip_init(const char * fname, struct clip_context_params ctx_params); CLIP_API void clip_free(struct clip_ctx * ctx); diff --git a/examples/llava/minicpmv-cli.cpp b/examples/llava/minicpmv-cli.cpp index 23b3de4db..12f536cf5 100644 --- a/examples/llava/minicpmv-cli.cpp +++ b/examples/llava/minicpmv-cli.cpp @@ -86,7 +86,11 @@ static struct clip_ctx * clip_init_context(common_params * params) { if (prompt.empty()) { prompt = "describe the image in detail."; } - auto * ctx_clip = clip_model_load(clip_path, /*verbosity=*/ 1); + struct clip_context_params clip_params = { + /* use_gpu */ params->n_gpu_layers != 0, + /* verbosity */ params->verbosity, + }; + auto * ctx_clip = clip_init(clip_path, clip_params); return ctx_clip; } From 6ab2e4765a673abcd162258a2671560a76106d69 Mon Sep 17 00:00:00 2001 From: BB-fat <45072480+BB-fat@users.noreply.github.com> Date: Tue, 11 Mar 2025 19:45:02 +0800 Subject: [PATCH 76/87] metal : Cache the Metal library at the device context level (#12265) --- ggml/src/ggml-metal/ggml-metal.m | 279 ++++++++++++++++--------------- 1 file changed, 147 insertions(+), 132 deletions(-) diff --git a/ggml/src/ggml-metal/ggml-metal.m b/ggml/src/ggml-metal/ggml-metal.m index 1158b285c..e51a4169a 100644 --- a/ggml/src/ggml-metal/ggml-metal.m +++ b/ggml/src/ggml-metal/ggml-metal.m @@ -46,6 +46,7 @@ static struct ggml_backend_device g_ggml_backend_metal_device; static struct ggml_backend_metal_device_context { id mtl_device; int mtl_device_ref_count; + id mtl_library; bool has_simdgroup_reduction; bool has_simdgroup_mm; @@ -57,6 +58,7 @@ static struct ggml_backend_metal_device_context { } g_ggml_ctx_dev_main = { /*.mtl_device =*/ nil, /*.mtl_device_ref_count =*/ 0, + /*.mtl_library =*/ nil, /*.has_simdgroup_reduction =*/ false, /*.has_simdgroup_mm =*/ false, /*.has_residency_sets =*/ false, @@ -108,6 +110,11 @@ static void ggml_backend_metal_device_rel(struct ggml_backend_metal_device_conte ctx->mtl_device_ref_count--; if (ctx->mtl_device_ref_count == 0) { + if (ctx->mtl_library) { + [ctx->mtl_library release]; + ctx->mtl_library = nil; + } + if (ctx->mtl_device) { [ctx->mtl_device release]; ctx->mtl_device = nil; @@ -495,6 +502,139 @@ static void * ggml_metal_host_malloc(size_t n) { return data; } +// load library +// +// - first check if the library is embedded +// - then check if the library is in the bundle +// - if not found, load the source and compile it +// - if that fails, return NULL +static id ggml_metal_load_library(id device, bool use_bfloat) { + id metal_library = nil; + NSError * error = nil; + NSString * src = nil; + +#if GGML_METAL_EMBED_LIBRARY + GGML_LOG_INFO("%s: using embedded metal library\n", __func__); + + extern const char ggml_metallib_start[]; + extern const char ggml_metallib_end[]; + + src = [[NSString alloc] initWithBytes:ggml_metallib_start length:(ggml_metallib_end-ggml_metallib_start) encoding:NSUTF8StringEncoding]; + +#else + +#ifdef SWIFT_PACKAGE + NSBundle * bundle = SWIFTPM_MODULE_BUNDLE; +#else + NSBundle * bundle = [NSBundle bundleForClass:[GGMLMetalClass class]]; +#endif + + NSString * path_lib = [bundle pathForResource:@"default" ofType:@"metallib"]; + if (path_lib == nil) { + // Try to find the resource in the directory where the current binary located. + NSString * current_binary = [[NSProcessInfo processInfo] arguments][0]; + NSString * bin_dir = [current_binary stringByDeletingLastPathComponent]; + NSString * default_metallib_path = [NSString pathWithComponents:@[bin_dir, @"default.metallib"]]; + if ([[NSFileManager defaultManager] isReadableFileAtPath:default_metallib_path]) { + GGML_LOG_INFO("%s: found '%s'\n", __func__, [default_metallib_path UTF8String]); + NSDictionary * atts = [[NSFileManager defaultManager] attributesOfItemAtPath:default_metallib_path error:&error]; + if (atts && atts[NSFileType] == NSFileTypeSymbolicLink) { + // Optionally, if this is a symlink, try to resolve it. + default_metallib_path = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:default_metallib_path error:&error]; + if (default_metallib_path && [default_metallib_path length] > 0 && ![[default_metallib_path substringToIndex:1] isEqualToString:@"/"]) { + // It is a relative path, adding the binary directory as directory prefix. + default_metallib_path = [NSString pathWithComponents:@[bin_dir, default_metallib_path]]; + } + if (!default_metallib_path || ![[NSFileManager defaultManager] isReadableFileAtPath:default_metallib_path]) { + // Link to the resource could not be resolved. + default_metallib_path = nil; + } else { + GGML_LOG_INFO("%s: symlink resolved '%s'\n", __func__, [default_metallib_path UTF8String]); + } + } + } else { + // The resource couldn't be found in the binary's directory. + default_metallib_path = nil; + } + path_lib = default_metallib_path; + } + + if (path_lib != nil) { + // pre-compiled library found + NSURL * libURL = [NSURL fileURLWithPath:path_lib]; + GGML_LOG_INFO("%s: loading '%s'\n", __func__, [path_lib UTF8String]); + + metal_library = [device newLibraryWithURL:libURL error:&error]; + if (error) { + GGML_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]); + return NULL; + } + } else { + GGML_LOG_INFO("%s: default.metallib not found, loading from source\n", __func__); + + NSString * path_source; + NSString * path_resource = [[NSProcessInfo processInfo].environment objectForKey:@"GGML_METAL_PATH_RESOURCES"]; + + GGML_LOG_INFO("%s: GGML_METAL_PATH_RESOURCES = %s\n", __func__, path_resource ? [path_resource UTF8String] : "nil"); + + if (path_resource) { + path_source = [path_resource stringByAppendingPathComponent:@"ggml-metal.metal"]; + } else { + path_source = [bundle pathForResource:@"ggml-metal" ofType:@"metal"]; + } + + if (path_source == nil) { + GGML_LOG_WARN("%s: error: could not use bundle path to find ggml-metal.metal, falling back to trying cwd\n", __func__); + path_source = @"ggml-metal.metal"; + } + + GGML_LOG_INFO("%s: loading '%s'\n", __func__, [path_source UTF8String]); + + src = [NSString stringWithContentsOfFile:path_source encoding:NSUTF8StringEncoding error:&error]; + if (error) { + GGML_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]); + return NULL; + } + } +#endif + + if (!metal_library) { + @autoreleasepool { + // dictionary of preprocessor macros + NSMutableDictionary * prep = [NSMutableDictionary dictionary]; + + if (use_bfloat) { + [prep setObject:@"1" forKey:@"GGML_METAL_USE_BF16"]; + } + +#if GGML_METAL_EMBED_LIBRARY + [prep setObject:@"1" forKey:@"GGML_METAL_EMBED_LIBRARY"]; +#endif + + MTLCompileOptions * options = [MTLCompileOptions new]; + options.preprocessorMacros = prep; + + //[options setFastMathEnabled:false]; + + metal_library = [device newLibraryWithSource:src options:options error:&error]; + if (error) { + GGML_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]); + return NULL; + } + +#if !__has_feature(objc_arc) + [options release]; +#endif + } + } + +#if GGML_METAL_EMBED_LIBRARY + [src release]; +#endif // GGML_METAL_EMBED_LIBRARY + + return metal_library; +} + static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t dev) { GGML_LOG_INFO("%s: allocating\n", __func__); @@ -522,136 +662,14 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de ctx->d_queue = dispatch_queue_create("ggml-metal", DISPATCH_QUEUE_CONCURRENT); - id metal_library = nil; - // load library - // - // - first check if the library is embedded - // - then check if the library is in the bundle - // - if not found, load the source and compile it - // - if that fails, return NULL - { - NSError * error = nil; - NSString * src = nil; - -#if GGML_METAL_EMBED_LIBRARY - GGML_LOG_INFO("%s: using embedded metal library\n", __func__); - - extern const char ggml_metallib_start[]; - extern const char ggml_metallib_end[]; - - src = [[NSString alloc] initWithBytes:ggml_metallib_start length:(ggml_metallib_end-ggml_metallib_start) encoding:NSUTF8StringEncoding]; - -#else - -#ifdef SWIFT_PACKAGE - NSBundle * bundle = SWIFTPM_MODULE_BUNDLE; -#else - NSBundle * bundle = [NSBundle bundleForClass:[GGMLMetalClass class]]; -#endif - - NSString * path_lib = [bundle pathForResource:@"default" ofType:@"metallib"]; - if (path_lib == nil) { - // Try to find the resource in the directory where the current binary located. - NSString * current_binary = [[NSProcessInfo processInfo] arguments][0]; - NSString * bin_dir = [current_binary stringByDeletingLastPathComponent]; - NSString * default_metallib_path = [NSString pathWithComponents:@[bin_dir, @"default.metallib"]]; - if ([[NSFileManager defaultManager] isReadableFileAtPath:default_metallib_path]) { - GGML_LOG_INFO("%s: found '%s'\n", __func__, [default_metallib_path UTF8String]); - NSDictionary * atts = [[NSFileManager defaultManager] attributesOfItemAtPath:default_metallib_path error:&error]; - if (atts && atts[NSFileType] == NSFileTypeSymbolicLink) { - // Optionally, if this is a symlink, try to resolve it. - default_metallib_path = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:default_metallib_path error:&error]; - if (default_metallib_path && [default_metallib_path length] > 0 && ![[default_metallib_path substringToIndex:1] isEqualToString:@"/"]) { - // It is a relative path, adding the binary directory as directory prefix. - default_metallib_path = [NSString pathWithComponents:@[bin_dir, default_metallib_path]]; - } - if (!default_metallib_path || ![[NSFileManager defaultManager] isReadableFileAtPath:default_metallib_path]) { - // Link to the resource could not be resolved. - default_metallib_path = nil; - } else { - GGML_LOG_INFO("%s: symlink resolved '%s'\n", __func__, [default_metallib_path UTF8String]); - } - } - } else { - // The resource couldn't be found in the binary's directory. - default_metallib_path = nil; - } - path_lib = default_metallib_path; - } - - if (path_lib != nil) { - // pre-compiled library found - NSURL * libURL = [NSURL fileURLWithPath:path_lib]; - GGML_LOG_INFO("%s: loading '%s'\n", __func__, [path_lib UTF8String]); - - metal_library = [device newLibraryWithURL:libURL error:&error]; - if (error) { - GGML_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]); - return NULL; - } - } else { - GGML_LOG_INFO("%s: default.metallib not found, loading from source\n", __func__); - - NSString * path_source; - NSString * path_resource = [[NSProcessInfo processInfo].environment objectForKey:@"GGML_METAL_PATH_RESOURCES"]; - - GGML_LOG_INFO("%s: GGML_METAL_PATH_RESOURCES = %s\n", __func__, path_resource ? [path_resource UTF8String] : "nil"); - - if (path_resource) { - path_source = [path_resource stringByAppendingPathComponent:@"ggml-metal.metal"]; - } else { - path_source = [bundle pathForResource:@"ggml-metal" ofType:@"metal"]; - } - - if (path_source == nil) { - GGML_LOG_WARN("%s: error: could not use bundle path to find ggml-metal.metal, falling back to trying cwd\n", __func__); - path_source = @"ggml-metal.metal"; - } - - GGML_LOG_INFO("%s: loading '%s'\n", __func__, [path_source UTF8String]); - - src = [NSString stringWithContentsOfFile:path_source encoding:NSUTF8StringEncoding error:&error]; - if (error) { - GGML_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]); - return NULL; - } - } -#endif - - if (!metal_library) { - @autoreleasepool { - // dictionary of preprocessor macros - NSMutableDictionary * prep = [NSMutableDictionary dictionary]; - - if (ctx_dev->use_bfloat) { - [prep setObject:@"1" forKey:@"GGML_METAL_USE_BF16"]; - } - -#if GGML_METAL_EMBED_LIBRARY - [prep setObject:@"1" forKey:@"GGML_METAL_EMBED_LIBRARY"]; -#endif - - MTLCompileOptions * options = [MTLCompileOptions new]; - options.preprocessorMacros = prep; - - //[options setFastMathEnabled:false]; - - metal_library = [device newLibraryWithSource:src options:options error:&error]; - if (error) { - GGML_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]); - return NULL; - } - -#if !__has_feature(objc_arc) - [options release]; -#endif - } - } - -#if GGML_METAL_EMBED_LIBRARY - [src release]; -#endif // GGML_METAL_EMBED_LIBRARY + if (ctx_dev->mtl_library == nil) { + ctx_dev->mtl_library = ggml_metal_load_library(device, ctx_dev->use_bfloat); + } + id metal_library = ctx_dev->mtl_library; + if (metal_library == nil) { + GGML_LOG_ERROR("%s: error: metal library is nil\n", __func__); + return NULL; } // print MTL GPU family: @@ -725,7 +743,6 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de [metal_function release]; \ if (error) { \ GGML_LOG_ERROR("%s: error: load pipeline error: %s\n", __func__, [[error description] UTF8String]); \ - [metal_library release]; \ return NULL; \ } \ } else { \ @@ -1044,8 +1061,6 @@ static struct ggml_backend_metal_context * ggml_metal_init(ggml_backend_dev_t de GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_POOL_2D_MAX_F32, pool_2d_max_f32, true); } - [metal_library release]; - return ctx; } From ba7654380a3c7c1b5ae154bea19134a3a9417a1e Mon Sep 17 00:00:00 2001 From: jklincn <985765408@qq.com> Date: Tue, 11 Mar 2025 21:25:17 +0800 Subject: [PATCH 77/87] ggml-backend : fix backend search path (#12330) * Fix backend search path * replace .native() with '/' * reverted .native() --- ggml/src/ggml-backend-reg.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ggml/src/ggml-backend-reg.cpp b/ggml/src/ggml-backend-reg.cpp index 9bedeae78..405d8e315 100644 --- a/ggml/src/ggml-backend-reg.cpp +++ b/ggml/src/ggml-backend-reg.cpp @@ -497,7 +497,7 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, search_paths.push_back(get_executable_path()); search_paths.push_back(fs::current_path()); } else { - search_paths.push_back(user_search_path); + search_paths.push_back(fs::u8path(user_search_path)); } int best_score = 0; @@ -511,9 +511,9 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, fs::directory_iterator dir_it(search_path, fs::directory_options::skip_permission_denied); for (const auto & entry : dir_it) { if (entry.is_regular_file()) { - auto filename = entry.path().filename().native(); - auto ext = entry.path().extension().native(); - if (filename.find(file_prefix) == 0 && ext == file_extension) { + auto filename = entry.path().filename(); + auto ext = entry.path().extension(); + if (filename.native().find(file_prefix) == 0 && ext == file_extension) { dl_handle_ptr handle { dl_load_library(entry) }; if (!handle && !silent) { GGML_LOG_ERROR("%s: failed to load %s\n", __func__, path_str(entry.path()).c_str()); @@ -544,7 +544,7 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, // try to load the base backend for (const auto & search_path : search_paths) { fs::path filename = backend_filename_prefix().native() + name_path.native() + backend_filename_extension().native(); - fs::path path = search_path.native() + filename.native(); + fs::path path = search_path / filename; if (fs::exists(path)) { return get_reg().load_backend(path, silent); } From 10f2e81809bbb69ecfe64fc8b4686285f84b0c07 Mon Sep 17 00:00:00 2001 From: uvos Date: Tue, 11 Mar 2025 20:16:03 +0100 Subject: [PATCH 78/87] CUDA/HIP: refractor mmqv to unify the calculation of nwarps and rows per block between host and device code. (#12177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor mmqv to unify the calculation of nwarps and rows per block between host and device code. --------- Co-authored-by: Johannes Gäßler --- ggml/src/ggml-cuda/common.cuh | 4 +- ggml/src/ggml-cuda/mmvq.cu | 197 ++++++++++++++++++++++++---------- 2 files changed, 142 insertions(+), 59 deletions(-) diff --git a/ggml/src/ggml-cuda/common.cuh b/ggml/src/ggml-cuda/common.cuh index 1832314ec..4d4ac47c0 100644 --- a/ggml/src/ggml-cuda/common.cuh +++ b/ggml/src/ggml-cuda/common.cuh @@ -395,11 +395,11 @@ static __device__ __forceinline__ uint32_t __hgt2_mask(const half2 a, const half static __device__ __forceinline__ int ggml_cuda_dp4a(const int a, const int b, int c) { #if defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__) -#if defined(__gfx906__) || defined(__gfx908__) || defined(__gfx90a__) || defined(RDNA2) +#if defined(CDNA) || defined(RDNA2) || defined(__gfx906__) c = __builtin_amdgcn_sdot4(a, b, c, false); #elif defined(RDNA3) c = __builtin_amdgcn_sudot4( true, a, true, b, c, false); -#elif defined(__gfx1010__) || defined(__gfx900__) +#elif defined(RDNA1) || defined(__gfx900__) int tmp1; int tmp2; asm("\n \ diff --git a/ggml/src/ggml-cuda/mmvq.cu b/ggml/src/ggml-cuda/mmvq.cu index 4fb466ca0..a7d518a57 100644 --- a/ggml/src/ggml-cuda/mmvq.cu +++ b/ggml/src/ggml-cuda/mmvq.cu @@ -47,11 +47,89 @@ static constexpr __device__ int get_vdr_mmvq(ggml_type type) { 1; } +enum mmvq_parameter_table_id { + MMVQ_PARAMETERS_GENERIC = 0, + MMVQ_PARAMETERS_GCN, + MMVQ_PARAMETERS_RDNA2 +}; + +static constexpr __device__ mmvq_parameter_table_id get_device_table_id() { +#if defined(RDNA2) || defined(RDNA3) + return MMVQ_PARAMETERS_RDNA2; +#elif defined(GCN) || defined(CDNA) + return MMVQ_PARAMETERS_GCN; +#else + return MMVQ_PARAMETERS_GENERIC; +#endif +} + +static __host__ mmvq_parameter_table_id get_device_table_id(int cc) { + if (GGML_CUDA_CC_IS_RDNA2(cc) || GGML_CUDA_CC_IS_RDNA3(cc)) { + return MMVQ_PARAMETERS_RDNA2; + } + if (GGML_CUDA_CC_IS_GCN(cc) || GGML_CUDA_CC_IS_CDNA(cc)) { + return MMVQ_PARAMETERS_GCN; + } + return MMVQ_PARAMETERS_GENERIC; +} + +static constexpr __host__ __device__ int calc_nwarps(int ncols_y, mmvq_parameter_table_id table_id) { + if (table_id == MMVQ_PARAMETERS_GENERIC) { + switch (ncols_y) { + case 1: + case 2: + case 3: + case 4: + return 4; + case 5: + case 6: + case 7: + case 8: + return 2; + default: + return 1; + } + } else if (table_id == MMVQ_PARAMETERS_GCN) { + switch (ncols_y) { + case 1: + case 2: + case 3: + case 4: + return 2; + case 5: + case 6: + case 7: + case 8: + default: + return 1; + } + } + return 1; +} + +static constexpr __host__ __device__ int calc_rows_per_block(int ncols_y, int table_id) { + if (table_id == MMVQ_PARAMETERS_GENERIC || table_id == MMVQ_PARAMETERS_GCN) { + switch (ncols_y) { + case 1: + return 1; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return 2; + default: + return 1; + } + } + return 1; +} + template -#if !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) // tell the compiler to use as many registers as it wants, see nwarps definition below -__launch_bounds__((ncols_y <= 4 ? 4 : 2)*WARP_SIZE, 1) -#endif // !(defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__)) +__launch_bounds__(calc_nwarps(ncols_y, get_device_table_id())*ggml_cuda_get_physical_warp_size(), 1) static __global__ void mul_mat_vec_q( const void * __restrict__ vx, const void * __restrict__ vy, float * __restrict__ dst, const int ncols_x, const int nrows_x, const int nrows_y, const int nrows_dst) { @@ -59,24 +137,20 @@ static __global__ void mul_mat_vec_q( constexpr int qk = ggml_cuda_type_traits::qk; constexpr int qi = ggml_cuda_type_traits::qi; constexpr int vdr = get_vdr_mmvq(type); + constexpr mmvq_parameter_table_id table_id = get_device_table_id(); + constexpr int nwarps = calc_nwarps(ncols_y, table_id); + constexpr int rows_per_cuda_block = calc_rows_per_block(ncols_y, table_id); + constexpr int warp_size = ggml_cuda_get_physical_warp_size(); constexpr vec_dot_q_cuda_t vec_dot_q_cuda = get_vec_dot_q_cuda(type); -#if defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__) && (defined(RDNA2) || defined(RDNA3)) - constexpr int nwarps = 1; - constexpr int rows_per_cuda_block = 1; -#else - constexpr int nwarps = ncols_y <= 4 ? 4 : 2; - constexpr int rows_per_cuda_block = ncols_y == 1 ? 1 : 2; -#endif // defined(GGML_USE_HIP) && defined(__HIP_PLATFORM_AMD__) && !defined(RDNA2) && !defined(RDNA3) - - const int tid = WARP_SIZE*threadIdx.y + threadIdx.x; + const int tid = warp_size*threadIdx.y + threadIdx.x; const int row0 = rows_per_cuda_block*blockIdx.x; const int blocks_per_row_x = ncols_x / qk; const int blocks_per_col_y = nrows_y / QK8_1; - constexpr int blocks_per_iter = vdr * nwarps*WARP_SIZE / qi; + constexpr int blocks_per_iter = vdr * nwarps*warp_size / qi; -// partial sum for each thread + // partial sum for each thread float tmp[ncols_y][rows_per_cuda_block] = {0.0f}; const block_q8_1 * y = (const block_q8_1 *) vy; @@ -96,7 +170,7 @@ static __global__ void mul_mat_vec_q( } } - __shared__ float tmp_shared[nwarps-1 > 0 ? nwarps-1 : 1][ncols_y][rows_per_cuda_block][WARP_SIZE]; + __shared__ float tmp_shared[nwarps-1 > 0 ? nwarps-1 : 1][ncols_y][rows_per_cuda_block][warp_size]; if (threadIdx.y > 0) { #pragma unroll for (int j = 0; j < ncols_y; ++j) { @@ -120,7 +194,7 @@ static __global__ void mul_mat_vec_q( for (int l = 0; l < nwarps-1; ++l) { tmp[j][i] += tmp_shared[l][j][i][threadIdx.x]; } - tmp[j][i] = warp_reduce_sum(tmp[j][i]); + tmp[j][i] = warp_reduce_sum(tmp[j][i]); } if (threadIdx.x < rows_per_cuda_block && (rows_per_cuda_block == 1 || row0 + threadIdx.x < nrows_dst)) { @@ -129,6 +203,13 @@ static __global__ void mul_mat_vec_q( } } +static std::pair calc_launch_params(const int ncols_y, const int nrows_x, const int warp_size, const mmvq_parameter_table_id table_id) { + const int64_t nblocks = (nrows_x + calc_rows_per_block(ncols_y, table_id) - 1) / calc_rows_per_block(ncols_y, table_id); + const dim3 block_nums(nblocks, 1, 1); + const dim3 block_dims(warp_size, calc_nwarps(ncols_y, table_id), 1); + return {block_nums, block_dims}; +} + template static void mul_mat_vec_q_cuda( const void * vx, const void * vy, float * dst, @@ -137,65 +218,67 @@ static void mul_mat_vec_q_cuda( GGML_ASSERT(ncols_x % ggml_blck_size(type) == 0); GGML_ASSERT(ncols_y <= MMVQ_MAX_BATCH_SIZE); - int id = ggml_cuda_get_device(); - - int64_t nwarps = 1; - int64_t rows_per_cuda_block = 1; - - if (ggml_cuda_info().devices[id].cc < GGML_CUDA_CC_RDNA2) { // NVIDIA and AMD older than RDNA2 - switch(ncols_y) { - case 1: - nwarps = 4; - rows_per_cuda_block = 1; - break; - case 2: - case 3: - case 4: - nwarps = 4; - rows_per_cuda_block = 2; - break; - case 5: - case 6: - case 7: - case 8: - nwarps = 2; - rows_per_cuda_block = 2; - break; - default: - GGML_ABORT("fatal error"); - break; - } - } - - const int64_t nblocks = (nrows_x + rows_per_cuda_block - 1) / rows_per_cuda_block; - const dim3 block_nums(nblocks, 1, 1); - const dim3 block_dims(WARP_SIZE, nwarps, 1); + const int device = ggml_cuda_get_device(); + const int warp_size = ggml_cuda_info().devices[device].warp_size; + const mmvq_parameter_table_id table_id = get_device_table_id(ggml_cuda_info().devices[device].cc); switch (ncols_y) { case 1: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 1; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } case 2: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 2; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } case 3: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 3; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } case 4: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 4; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } case 5: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 5; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } case 6: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 6; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } case 7: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 7; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } case 8: - mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); + { + constexpr int c_ncols_y = 8; + std::pair dims = calc_launch_params(c_ncols_y, nrows_x, warp_size, table_id); + mul_mat_vec_q<<>>(vx, vy, dst, ncols_x, nrows_x, nrows_y, nrows_dst); break; + } default: GGML_ABORT("fatal error"); break; From bf69cfe62f9ccc01112c0232a55820b95a8c1fda Mon Sep 17 00:00:00 2001 From: Jeff Bolz Date: Wed, 12 Mar 2025 00:59:19 -0500 Subject: [PATCH 79/87] vulkan: fix bug in coopmat1 mul_mat_id (#12316) * tests: run mul_mat_id with a larger N * vulkan: fix bug in coopmat1 mul_mat_id --- ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp | 2 +- tests/test-backend-ops.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp index a8fd93fde..0d03411f2 100644 --- a/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp +++ b/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp @@ -777,7 +777,7 @@ void main() { [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) { coopMatStore(sums[cm_col * cms_per_row + cm_row], coopmat_stage, warp_i * TM * TN, TM, gl_CooperativeMatrixLayoutColumnMajor); - [[unroll]] for (uint col = 0; col < BN; col += storestride) { + [[unroll]] for (uint col = 0; col < TN; col += storestride) { const uint row_i = dc + cm_col * TN + col + store_c; if (row_i >= _ne1) break; diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index b4e3631ed..c86ffb64e 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -4113,7 +4113,7 @@ static std::vector> make_test_cases_eval() { for (int n_mats : {4, 8}) { for (int n_used : {1, 2, 4}) { for (bool b : {false, true}) { - for (int n : {1, 32}) { + for (int n : {1, 32, 129}) { int m = 512; int k = 256; test_cases.emplace_back(new test_mul_mat_id(type_a, type_b, n_mats, n_used, b, m, n, k)); From 7841fc723e059d1fd9640e5c0ef19050fcc7c698 Mon Sep 17 00:00:00 2001 From: Xuan-Son Nguyen Date: Wed, 12 Mar 2025 09:30:24 +0100 Subject: [PATCH 80/87] llama : Add Gemma 3 support (+ experimental vision capability) (#12343) * llama : Add Gemma 3 text-only support * fix python coding style * fix compile on ubuntu * python: fix style * fix ubuntu compile * fix build on ubuntu (again) * fix ubuntu build, finally * clip : Experimental support for Gemma 3 vision (#12344) * clip : Experimental support for Gemma 3 vision * fix build * PRId64 --- convert_hf_to_gguf.py | 80 ++++ examples/llava/CMakeLists.txt | 7 + examples/llava/README-gemma3.md | 30 ++ examples/llava/clip.cpp | 210 ++++++++++- examples/llava/gemma3-cli.cpp | 341 ++++++++++++++++++ .../llava/gemma3_convert_encoder_to_gguf.py | 307 ++++++++++++++++ gguf-py/gguf/constants.py | 19 + src/llama-arch.cpp | 21 ++ src/llama-arch.h | 1 + src/llama-model.cpp | 49 +++ src/llama.cpp | 147 ++++++++ 11 files changed, 1202 insertions(+), 10 deletions(-) create mode 100644 examples/llava/README-gemma3.md create mode 100644 examples/llava/gemma3-cli.cpp create mode 100644 examples/llava/gemma3_convert_encoder_to_gguf.py diff --git a/convert_hf_to_gguf.py b/convert_hf_to_gguf.py index 6358a94e9..b5d95bd56 100755 --- a/convert_hf_to_gguf.py +++ b/convert_hf_to_gguf.py @@ -861,6 +861,9 @@ class Model: for token_id, token_data in added_tokens_decoder.items(): token_id = int(token_id) token: str = token_data["content"] + if token_id >= vocab_size: + logger.warning(f'ignore token {token_id}: id is out of range, max={vocab_size - 1}') + continue if toktypes[token_id] != SentencePieceTokenTypes.UNUSED: if tokens[token_id] != token.encode("utf-8"): logger.warning(f'replacing token {token_id}: {tokens[token_id].decode("utf-8")!r} -> {token!r}') @@ -3322,6 +3325,83 @@ class Gemma2Model(Model): return [(self.map_tensor_name(name), data_torch)] +@Model.register("Gemma3ForCausalLM", "Gemma3ForConditionalGeneration") +class Gemma3Model(Model): + model_arch = gguf.MODEL_ARCH.GEMMA3 + has_vision: bool = False + + # we need to merge the text_config into the root level of hparams + def __init__(self, *args, **kwargs): + hparams = Model.load_hparams(kwargs["dir_model"]) + if "text_config" in hparams: + hparams = {**hparams, **hparams["text_config"]} + kwargs["hparams"] = hparams + super().__init__(*args, **kwargs) + if "vision_config" in hparams: + logger.info("Has vision encoder, but it will be ignored") + self.has_vision = True + + def write(self): + super().write() + if self.has_vision: + logger.info("NOTE: this script only convert the language model to GGUF") + logger.info(" for the vision model, please use gemma3_convert_encoder_to_gguf.py") + + def set_vocab(self): + self._set_vocab_sentencepiece() + + self.gguf_writer.add_add_space_prefix(False) + + def set_gguf_parameters(self): + hparams = self.hparams + block_count = hparams["num_hidden_layers"] + + # some default values are not specified in the hparams + self.gguf_writer.add_context_length(hparams.get("max_position_embeddings", 131072)) + self.gguf_writer.add_embedding_length(hparams["hidden_size"]) + self.gguf_writer.add_block_count(block_count) + self.gguf_writer.add_feed_forward_length(hparams["intermediate_size"]) + self.gguf_writer.add_head_count(hparams.get("num_attention_heads", 8)) + self.gguf_writer.add_layer_norm_rms_eps(self.hparams.get("rms_norm_eps", 1e-6)) + self.gguf_writer.add_key_length(hparams.get("head_dim", 256)) + self.gguf_writer.add_value_length(hparams.get("head_dim", 256)) + self.gguf_writer.add_file_type(self.ftype) + self.gguf_writer.add_rope_freq_base(hparams.get("rope_theta", 1_000_000.0)) # for global layers + # both attn_logit_softcapping and final_logit_softcapping are removed in Gemma3 + assert hparams.get("attn_logit_softcapping") is None + assert hparams.get("final_logit_softcapping") is None + self.gguf_writer.add_sliding_window(hparams["sliding_window"]) + self.gguf_writer.add_head_count_kv(hparams.get("num_key_value_heads", 4)) + if hparams.get("rope_scaling") is not None: + assert hparams["rope_scaling"]["rope_type"] == "linear" + # important: this rope_scaling is only applied for global layers, and not used by 1B model + self.gguf_writer.add_rope_scaling_type(gguf.RopeScalingType.LINEAR) + self.gguf_writer.add_rope_scaling_factor(hparams["rope_scaling"]["factor"]) + + def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]: + del bid # unused + + if name.startswith("language_model."): + name = name.replace("language_model.", "") + elif name.startswith("multi_modal_projector.") or name.startswith("vision_tower.") \ + or name.startswith("multimodal_projector.") or name.startswith("vision_model."): # this is for old HF model, should be removed later + # ignore vision tensors + return [] + + # remove OOV (out-of-vocabulary) rows in token_embd + if "embed_tokens.weight" in name: + vocab = self._create_vocab_sentencepiece() + tokens = vocab[0] + data_torch = data_torch[:len(tokens)] + + # ref code in Gemma3RMSNorm + # output = output * (1.0 + self.weight.float()) + if name.endswith("norm.weight"): + data_torch = data_torch + 1 + + return [(self.map_tensor_name(name), data_torch)] + + @Model.register("Starcoder2ForCausalLM") class StarCoder2Model(Model): model_arch = gguf.MODEL_ARCH.STARCODER2 diff --git a/examples/llava/CMakeLists.txt b/examples/llava/CMakeLists.txt index 319effd19..f275ce1cc 100644 --- a/examples/llava/CMakeLists.txt +++ b/examples/llava/CMakeLists.txt @@ -51,6 +51,13 @@ install(TARGETS ${TARGET} RUNTIME) target_link_libraries(${TARGET} PRIVATE common llava ${CMAKE_THREAD_LIBS_INIT}) target_compile_features(${TARGET} PRIVATE cxx_std_17) +set(TARGET llama-gemma3-cli) +add_executable(${TARGET} gemma3-cli.cpp) +set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME llama-gemma3-cli) +install(TARGETS ${TARGET} RUNTIME) +target_link_libraries(${TARGET} PRIVATE common llava ${CMAKE_THREAD_LIBS_INIT}) +target_compile_features(${TARGET} PRIVATE cxx_std_17) + set(TARGET llama-llava-clip-quantize-cli) add_executable(${TARGET} clip-quantize-cli.cpp) set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME llama-llava-clip-quantize-cli) diff --git a/examples/llava/README-gemma3.md b/examples/llava/README-gemma3.md new file mode 100644 index 000000000..20bf73fb5 --- /dev/null +++ b/examples/llava/README-gemma3.md @@ -0,0 +1,30 @@ +# Gemma 3 vision + +> [!IMPORTANT] +> +> This is very experimental, only used for demo purpose. + +## How to get mmproj.gguf? + +```bash +cd gemma-3-4b-it +python ../llama.cpp/examples/llava/gemma3_convert_encoder_to_gguf.py . + +# output file is mmproj.gguf +``` + +## How to run it? + +What you need: +- The text model GGUF, can be converted using `convert_hf_to_gguf.py` +- The mmproj file from step above +- An image file + +```bash +# build +cmake -B build +cmake --build build --target llama-gemma3-cli + +# run it +./build/bin/llama-gemma3-cli -m {text_model}.gguf --mmproj mmproj.gguf --image your_image.jpg +``` diff --git a/examples/llava/clip.cpp b/examples/llava/clip.cpp index 7f892beb6..a1f050e39 100644 --- a/examples/llava/clip.cpp +++ b/examples/llava/clip.cpp @@ -136,6 +136,8 @@ static std::string format(const char * fmt, ...) { #define TN_MVLM_PROJ_BLOCK "mm.model.mb_block.%d.block.%d.%s" #define TN_MVLM_PROJ_PEG "mm.model.peg.%d.%s" #define TN_IMAGE_NEWLINE "model.image_newline" +#define TN_MM_INP_PROJ "mm.input_projection.weight" // gemma3 +#define TN_MM_SOFT_EMB_N "mm.soft_emb_norm.weight" // gemma3 #define TN_MINICPMV_POS_EMBD_K "resampler.pos_embed_k" #define TN_MINICPMV_QUERY "resampler.query" @@ -162,6 +164,7 @@ enum projector_type { PROJECTOR_TYPE_RESAMPLER, PROJECTOR_TYPE_GLM_EDGE, PROJECTOR_TYPE_MERGER, + PROJECTOR_TYPE_GEMMA3, PROJECTOR_TYPE_UNKNOWN, }; @@ -172,6 +175,7 @@ static std::map PROJECTOR_TYPE_NAMES = { { PROJECTOR_TYPE_RESAMPLER, "resampler"}, { PROJECTOR_TYPE_GLM_EDGE, "adapter"}, { PROJECTOR_TYPE_MERGER, "qwen2vl_merger"}, + { PROJECTOR_TYPE_GEMMA3, "gemma3"}, }; @@ -298,7 +302,7 @@ static projector_type clip_projector_type_from_string(const std::string & name) return kv.first; } } - return PROJECTOR_TYPE_UNKNOWN; + throw std::runtime_error(format("Unknown projector type: %s", name.c_str())); } #ifdef CLIP_DEBUG_FUNCTIONS @@ -555,6 +559,10 @@ struct clip_vision_model { struct ggml_tensor * mm_model_ln_kv_b; struct ggml_tensor * mm_model_ln_post_w; struct ggml_tensor * mm_model_ln_post_b; + + // gemma3 + struct ggml_tensor * mm_input_proj_w; + struct ggml_tensor * mm_soft_emb_norm_w; }; struct clip_ctx { @@ -569,7 +577,7 @@ struct clip_ctx { struct clip_vision_model vision_model; projector_type proj_type = PROJECTOR_TYPE_MLP; - int32_t max_feature_layer; + int32_t max_feature_layer; // unused in newer models like gemma3 float image_mean[3]; float image_std[3]; bool use_gelu = false; @@ -595,7 +603,7 @@ struct clip_ctx { ggml_backend_sched_ptr sched; - struct clip_image_size * load_image_size; + struct clip_image_size * load_image_size = nullptr; clip_ctx(clip_context_params & ctx_params) { backend_cpu = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr); @@ -631,7 +639,159 @@ struct clip_ctx { } }; -static ggml_cgraph * clip_image_build_graph(clip_ctx * ctx, const clip_image_f32_batch * imgs, struct clip_image_size * load_image_size, bool is_inf = false) { +static ggml_cgraph * clip_image_build_graph_siglip(clip_ctx * ctx, const clip_image_f32_batch * imgs) { + const auto & model = ctx->vision_model; + const auto & hparams = model.hparams; + + const int image_size = hparams.image_size; + int image_size_width = image_size; + int image_size_height = image_size; + + const int patch_size = hparams.patch_size; + const int num_patches = ((image_size_width / patch_size) * (image_size_height / patch_size)); + const int hidden_size = hparams.hidden_size; + const int n_head = hparams.n_head; + const int d_head = hidden_size / n_head; + const int n_layer = hparams.n_layer; + const float eps = hparams.eps; + + GGML_ASSERT(imgs->size == 1); // batch_size == 1 + + struct ggml_init_params params = { + /*.mem_size =*/ ctx->buf_compute_meta.size(), + /*.mem_buffer =*/ ctx->buf_compute_meta.data(), + /*.no_alloc =*/ true, + }; + + struct ggml_context * ctx0 = ggml_init(params); + struct ggml_cgraph * gf = ggml_new_graph(ctx0); + + // input raw + struct ggml_tensor * inp_raw = ggml_new_tensor_3d(ctx0, GGML_TYPE_F32, image_size_width, image_size_height, 3); + ggml_set_name(inp_raw, "inp_raw"); + ggml_set_input(inp_raw); + + struct ggml_tensor * inp = ggml_conv_2d(ctx0, model.patch_embeddings_0, inp_raw, patch_size, patch_size, 0, 0, 1, 1); + inp = ggml_reshape_2d(ctx0, inp, num_patches, hidden_size); + inp = ggml_cont(ctx0, ggml_transpose(ctx0, inp)); + inp = ggml_add(ctx0, inp, model.patch_bias); + + // position embeddings + struct ggml_tensor * embeddings = ggml_add(ctx0, inp, model.position_embeddings); + + // loop over layers + for (int il = 0; il < n_layer; il++) { + struct ggml_tensor * cur = embeddings; // embeddings = residual, cur = hidden_states + + // layernorm1 + { + cur = ggml_norm(ctx0, cur, eps); + cur = ggml_add(ctx0, ggml_mul(ctx0, cur, model.layers[il].ln_1_w), model.layers[il].ln_1_b); + } + + // self-attention + { + + struct ggml_tensor * Q = + ggml_add(ctx0, ggml_mul_mat(ctx0, model.layers[il].q_w, cur), model.layers[il].q_b); + + Q = ggml_reshape_3d(ctx0, Q, d_head, n_head, num_patches); + Q = ggml_cont(ctx0, ggml_permute(ctx0, Q, 0, 2, 1, 3)); + + struct ggml_tensor * K = + ggml_add(ctx0, ggml_mul_mat(ctx0, model.layers[il].k_w, cur), model.layers[il].k_b); + + K = ggml_reshape_3d(ctx0, K, d_head, n_head, num_patches); + K = ggml_cont(ctx0, ggml_permute(ctx0, K, 0, 2, 1, 3)); + + struct ggml_tensor * V = + ggml_add(ctx0, ggml_mul_mat(ctx0, model.layers[il].v_w, cur), model.layers[il].v_b); + + V = ggml_reshape_3d(ctx0, V, d_head, n_head, num_patches); + V = ggml_cont(ctx0, ggml_permute(ctx0, V, 1, 2, 0, 3)); + + struct ggml_tensor * KQ = ggml_mul_mat(ctx0, K, Q); + KQ = ggml_scale_inplace(ctx0, KQ, 1.0f / sqrtf((float)d_head)); + KQ = ggml_soft_max_inplace(ctx0, KQ); + + struct ggml_tensor * KQV = ggml_mul_mat(ctx0, V, KQ); + KQV = ggml_reshape_3d(ctx0, KQV, d_head, num_patches, n_head); + KQV = ggml_permute(ctx0, KQV, 0, 2, 1, 3); + + cur = ggml_cont_2d(ctx0, KQV, hidden_size, num_patches); + } + + // attention output + cur = ggml_add(ctx0, ggml_mul_mat(ctx0, model.layers[il].o_w, cur), model.layers[il].o_b); + + // re-add the layer input, e.g., residual + cur = ggml_add(ctx0, cur, embeddings); + + embeddings = cur; // embeddings = residual, cur = hidden_states + + // layernorm2 + { + cur = ggml_norm(ctx0, cur, eps); + cur = ggml_add(ctx0, ggml_mul(ctx0, cur, model.layers[il].ln_2_w), model.layers[il].ln_2_b); + } + + cur = ggml_mul_mat(ctx0, model.layers[il].ff_i_w, cur); + cur = ggml_add(ctx0, cur, model.layers[il].ff_i_b); + + // siglip uses gelu + cur = ggml_gelu(ctx0, cur); + + cur = ggml_mul_mat(ctx0, model.layers[il].ff_o_w, cur); + cur = ggml_add(ctx0, cur, model.layers[il].ff_o_b); + + // residual 2 + cur = ggml_add(ctx0, embeddings, cur); + + embeddings = cur; + } + + // post-layernorm + if (ctx->has_post_norm) { + embeddings = ggml_norm(ctx0, embeddings, eps); + ggml_set_name(embeddings, "post_ln"); + + embeddings = ggml_add(ctx0, ggml_mul(ctx0, embeddings, model.post_ln_w), model.post_ln_b); + } + + if (ctx->proj_type == PROJECTOR_TYPE_GEMMA3) { + const int batch_size = 1; + const int mm_tokens_per_image = 256; // default value for gemma3 + const int tokens_per_side = sqrt(mm_tokens_per_image); + const int patches_per_image = sqrt(num_patches); + const int kernel_size = patches_per_image / tokens_per_side; + + embeddings = ggml_cont(ctx0, ggml_transpose(ctx0, embeddings)); + embeddings = ggml_reshape_4d(ctx0, embeddings, patches_per_image, patches_per_image, hidden_size, batch_size); + + // doing a pool2d to reduce the number of output tokens to 256 + embeddings = ggml_pool_2d(ctx0, embeddings, GGML_OP_POOL_AVG, kernel_size, kernel_size, kernel_size, kernel_size, 0, 0); + embeddings = ggml_reshape_3d(ctx0, embeddings, embeddings->ne[0] * embeddings->ne[0], hidden_size, batch_size); + embeddings = ggml_cont(ctx0, ggml_transpose(ctx0, embeddings)); + + // apply norm before projection + embeddings = ggml_rms_norm(ctx0, embeddings, eps); + embeddings = ggml_mul(ctx0, embeddings, model.mm_soft_emb_norm_w); + + // apply projection + embeddings = ggml_mul_mat(ctx0, + ggml_cont(ctx0, ggml_transpose(ctx0, model.mm_input_proj_w)), + embeddings); + } + + // build the graph + ggml_build_forward_expand(gf, embeddings); + + ggml_free(ctx0); + + return gf; +} + +static ggml_cgraph * clip_image_build_graph_legacy(clip_ctx * ctx, const clip_image_f32_batch * imgs, struct clip_image_size * load_image_size, bool is_inf = false) { if (!ctx->has_vision_encoder) { LOG_ERR("This gguf file seems to have no vision encoder\n"); return nullptr; @@ -1177,7 +1337,8 @@ static ggml_cgraph * clip_image_build_graph(clip_ctx * ctx, const clip_image_f32 } else { GGML_ABORT("fatel error"); } - } else if (ctx->proj_type == PROJECTOR_TYPE_MERGER) { + } + else if (ctx->proj_type == PROJECTOR_TYPE_MERGER) { embeddings = ggml_reshape_3d(ctx0, embeddings, hidden_size * 4, num_positions / 4, batch_size); embeddings = ggml_mul_mat(ctx0, model.mm_0_w, embeddings); @@ -1199,6 +1360,15 @@ static ggml_cgraph * clip_image_build_graph(clip_ctx * ctx, const clip_image_f32 return gf; } +static ggml_cgraph * clip_image_build_graph(clip_ctx * ctx, const clip_image_f32_batch * imgs, struct clip_image_size * load_image_size, bool is_inf = false) { + if (ctx->proj_type == PROJECTOR_TYPE_GEMMA3) { + return clip_image_build_graph_siglip(ctx, imgs); + } else { + // TODO: we should have one build_* function per model + return clip_image_build_graph_legacy(ctx, imgs, load_image_size, is_inf); + } +} + // read and create ggml_context containing the tensors and their data struct clip_ctx * clip_model_load(const char * fname, const int verbosity = 1) { return clip_init(fname, clip_context_params{ @@ -1358,8 +1528,12 @@ struct clip_ctx * clip_init(const char * fname, struct clip_context_params ctx_p GGML_ASSERT(new_clip->has_vision_encoder); GGML_ASSERT(!new_clip->has_text_encoder); - idx = get_key_idx(ctx, KEY_USE_GELU); - new_clip->use_gelu = gguf_get_val_bool(ctx, idx); + try { + idx = get_key_idx(ctx, KEY_USE_GELU); + new_clip->use_gelu = gguf_get_val_bool(ctx, idx); + } catch (std::runtime_error & /*e*/) { + new_clip->use_gelu = false; + } try { idx = get_key_idx(ctx, KEY_USE_SILU); @@ -1567,11 +1741,17 @@ struct clip_ctx * clip_init(const char * fname, struct clip_context_params ctx_p } try { - vision_model.patch_embeddings_0 = get_tensor(new_clip->ctx_data, TN_PATCH_EMBD); + vision_model.patch_embeddings_0 = get_tensor(new_clip->ctx_data, TN_PATCH_EMBD); + } catch(const std::exception& /*e*/) { + vision_model.patch_embeddings_0 = nullptr; + } + + try { vision_model.position_embeddings = get_tensor(new_clip->ctx_data, format(TN_POS_EMBD, "v")); } catch(const std::exception& /*e*/) { - LOG_ERR("%s: failed to load vision model tensors\n", __func__); + vision_model.position_embeddings = nullptr; } + try { vision_model.patch_embeddings_1 = get_tensor(new_clip->ctx_data, TN_PATCH_EMBD_1); } catch(const std::exception& /*e*/) { @@ -1682,6 +1862,10 @@ struct clip_ctx * clip_init(const char * fname, struct clip_context_params ctx_p vision_model.mm_1_w = get_tensor(new_clip->ctx_data, format(TN_LLAVA_PROJ, 2, "weight")); vision_model.mm_1_b = get_tensor(new_clip->ctx_data, format(TN_LLAVA_PROJ, 2, "bias")); } + else if (new_clip->proj_type == PROJECTOR_TYPE_GEMMA3) { + vision_model.mm_input_proj_w = get_tensor(new_clip->ctx_data, TN_MM_INP_PROJ); + vision_model.mm_soft_emb_norm_w = get_tensor(new_clip->ctx_data, TN_MM_SOFT_EMB_N); + } else { std::string proj_type = PROJECTOR_TYPE_NAMES[new_clip->proj_type]; throw std::runtime_error(format("%s: don't support projector with: %s currently\n", __func__, proj_type.c_str())); @@ -2223,7 +2407,7 @@ bool clip_image_preprocess(struct clip_ctx * ctx, const clip_image_u8 * img, cli return true; } - if (ctx->has_glm_projector) { + if (ctx->has_glm_projector || ctx->proj_type == PROJECTOR_TYPE_GEMMA3) { res_imgs->size = 1; res_imgs->data = new clip_image_f32[res_imgs->size]; clip_image_u8 resized_image; @@ -2748,6 +2932,9 @@ bool clip_image_batch_encode(clip_ctx * ctx, const int n_threads, const clip_ima ggml_backend_tensor_set(positions, positions_data, 0, ggml_nbytes(positions)); free(positions_data); } + else if (ctx->proj_type == PROJECTOR_TYPE_GEMMA3) { + // do nothing + } else { struct ggml_tensor * positions = ggml_graph_get_tensor(gf, "positions"); @@ -2960,6 +3147,9 @@ int clip_n_mmproj_embd(const struct clip_ctx * ctx) { if (ctx->proj_type == PROJECTOR_TYPE_MERGER) { return ctx->vision_model.mm_1_b->ne[0]; } + if (ctx->proj_type == PROJECTOR_TYPE_GEMMA3) { + return ctx->vision_model.mm_input_proj_w->ne[0]; + } std::string proj_type = PROJECTOR_TYPE_NAMES[ctx->proj_type]; throw std::runtime_error(format("%s: don't support projector with: %s currently\n", __func__, proj_type.c_str())); diff --git a/examples/llava/gemma3-cli.cpp b/examples/llava/gemma3-cli.cpp new file mode 100644 index 000000000..a07864d4e --- /dev/null +++ b/examples/llava/gemma3-cli.cpp @@ -0,0 +1,341 @@ +#include "arg.h" +#include "log.h" +#include "common.h" +#include "sampling.h" +#include "clip.h" +#include "stb_image.h" +#include "llama.h" +#include "ggml.h" +#include "console.h" + +#include +#include +#include + +#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) +#include +#include +#elif defined (_WIN32) +#define WIN32_LEAN_AND_MEAN +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#endif + +static bool g_is_generating = false; + +/** + * Please note that this is NOT a production-ready stuff. + * It is a playground for trying Gemma 3 vision capabilities. + * For contributors: please keep this code simple and easy to understand. + */ + +static void show_additional_info(int /*argc*/, char ** argv) { + LOG( + "Experimental CLI for using Gemma 3 vision model\n\n" + "Usage: %s [options] -m --mmproj --image -p \n\n" + " -m and --mmproj are required\n" + " --image and -p are optional, if NOT provided, the CLI will run in chat mode\n", + argv[0] + ); +} + +#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) || defined (_WIN32) +static void sigint_handler(int signo) { + if (signo == SIGINT) { + if (g_is_generating) { + g_is_generating = false; + } else { + console::cleanup(); + LOG("\nInterrupted by user\n"); + _exit(130); + } + } +} +#endif + +struct gemma3_context { + struct clip_ctx * ctx_clip = NULL; + common_init_result llama_init; + + llama_model * model; + llama_context * lctx; + const llama_vocab * vocab; + llama_batch batch; + + int n_threads = 1; + llama_pos n_past = 0; + + gemma3_context(common_params & params) : llama_init(common_init_from_params(params)) { + model = llama_init.model.get(); + lctx = llama_init.context.get(); + vocab = llama_model_get_vocab(model); + n_threads = params.cpuparams.n_threads; + batch = llama_batch_init(params.n_batch, 0, 1); + init_clip_model(params); + } + + void init_clip_model(common_params & params) { + const char * clip_path = params.mmproj.c_str(); + ctx_clip = clip_model_load(clip_path, params.verbosity > 1); + } + + ~gemma3_context() { + clip_free(ctx_clip); + } +}; + +struct decode_embd_batch { + std::vector pos; + std::vector n_seq_id; + std::vector seq_id_0; + std::vector seq_ids; + std::vector logits; + llama_batch batch; + decode_embd_batch(float * embd, int32_t n_tokens, llama_pos pos_0, llama_seq_id seq_id) { + pos .resize(n_tokens); + n_seq_id.resize(n_tokens); + seq_ids .resize(n_tokens + 1); + logits .resize(n_tokens); + seq_id_0.resize(1); + seq_id_0[0] = seq_id; + seq_ids [n_tokens] = nullptr; + batch = { + /*n_tokens =*/ n_tokens, + /*tokens =*/ nullptr, + /*embd =*/ embd, + /*pos =*/ pos.data(), + /*n_seq_id =*/ n_seq_id.data(), + /*seq_id =*/ seq_ids.data(), + /*logits =*/ logits.data(), + }; + for (int i = 0; i < n_tokens; i++) { + batch.pos [i] = pos_0 + i; + batch.n_seq_id[i] = 1; + batch.seq_id [i] = seq_id_0.data(); + batch.logits [i] = false; + } + } +}; + +static int eval_text(gemma3_context & ctx, std::string input, bool logits_last = false) { + llama_tokens tokens = common_tokenize(ctx.lctx, input, false, true); + common_batch_clear(ctx.batch); + for (llama_token & t : tokens) { + common_batch_add(ctx.batch, t, ctx.n_past++, {0}, false); + } + if (logits_last) { + ctx.batch.logits[ctx.batch.n_tokens - 1] = true; + } + // LOG("eval_text (n_tokens = %d): %s\n", (int)tokens.size(), input.c_str()); + if (llama_decode(ctx.lctx, ctx.batch)) { + LOG_ERR("Failed to decode text\n"); + return 1; + } + return 0; +} + +static int eval_image(gemma3_context & ctx, std::string & fname) { + std::vector image_embd_v; + int n_embd = llama_model_n_embd(ctx.model); + int n_tokens = 256; + image_embd_v.resize(n_tokens * n_embd); + + bool ok; + struct clip_image_u8 * img_u8 = clip_image_u8_init(); + ok = clip_image_load_from_file(fname.c_str(), img_u8); + if (!ok) { + LOG_ERR("Unable to load image %s\n", fname.c_str()); + clip_image_u8_free(img_u8); + return 2; // non-fatal error + } + + clip_image_f32_batch batch_f32; + ok = clip_image_preprocess(ctx.ctx_clip, img_u8, &batch_f32); + if (!ok) { + LOG_ERR("Unable to preprocess image\n"); + clip_image_f32_batch_free(&batch_f32); + clip_image_u8_free(img_u8); + return 1; + } + + int64_t t0 = ggml_time_ms(); + LOG("Encoding image %s\n", fname.c_str()); + ok = clip_image_batch_encode(ctx.ctx_clip, ctx.n_threads, &batch_f32, image_embd_v.data()); + if (!ok) { + LOG_ERR("Unable to encode image\n"); + clip_image_f32_batch_free(&batch_f32); + clip_image_u8_free(img_u8); + return 1; + } + LOG("Image encoded in %" PRId64 " ms\n", ggml_time_ms() - t0); + + clip_image_f32_batch_free(&batch_f32); + clip_image_u8_free(img_u8); + + // decode image embeddings + int64_t t1 = ggml_time_ms(); + eval_text(ctx, ""); + llama_set_causal_attn(ctx.lctx, false); + decode_embd_batch batch_img(image_embd_v.data(), n_tokens, ctx.n_past, 0); + if (llama_decode(ctx.lctx, batch_img.batch)) { + LOG_ERR("failed to decode image\n"); + return 1; + } + ctx.n_past += n_tokens; + llama_set_causal_attn(ctx.lctx, true); + eval_text(ctx, ""); + LOG("Image decoded in %" PRId64 " ms\n", ggml_time_ms() - t1); + return 0; +} + +static int generate_response(gemma3_context & ctx, common_sampler * smpl, int n_predict) { + for (int i = 0; i < n_predict; i++) { + if (i > n_predict || !g_is_generating) { + printf("\n"); + break; + } + + llama_token token_id = common_sampler_sample(smpl, ctx.lctx, -1); + common_sampler_accept(smpl, token_id, true); + + if (llama_vocab_is_eog(ctx.vocab, token_id)) { + printf("\n"); + break; // end of generation + } + + printf("%s", common_token_to_piece(ctx.lctx, token_id).c_str()); + fflush(stdout); + + // eval the token + common_batch_clear(ctx.batch); + common_batch_add(ctx.batch, token_id, ctx.n_past++, {0}, true); + if (llama_decode(ctx.lctx, ctx.batch)) { + LOG_ERR("failed to decode token\n"); + return 1; + } + } + return 0; +} + +int main(int argc, char ** argv) { + ggml_time_init(); + + common_params params; + params.sampling.temp = 0.2; // lower temp by default for better quality + + if (!common_params_parse(argc, argv, params, LLAMA_EXAMPLE_LLAVA, show_additional_info)) { + return 1; + } + + common_init(); + + if (params.mmproj.empty()) { + show_additional_info(argc, argv); + return 1; + } + + gemma3_context ctx(params); + printf("%s: %s\n", __func__, params.model.c_str()); + + bool is_single_turn = !params.prompt.empty() && !params.image.empty(); + + struct common_sampler * smpl = common_sampler_init(ctx.model, params.sampling); + int n_predict = params.n_predict < 0 ? INT_MAX : params.n_predict; + + // ctrl+C handling + { +#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) + struct sigaction sigint_action; + sigint_action.sa_handler = sigint_handler; + sigemptyset (&sigint_action.sa_mask); + sigint_action.sa_flags = 0; + sigaction(SIGINT, &sigint_action, NULL); +#elif defined (_WIN32) + auto console_ctrl_handler = +[](DWORD ctrl_type) -> BOOL { + return (ctrl_type == CTRL_C_EVENT) ? (sigint_handler(SIGINT), true) : false; + }; + SetConsoleCtrlHandler(reinterpret_cast(console_ctrl_handler), true); +#endif + } + + if (eval_text(ctx, "")) { + return 1; + } + + if (is_single_turn) { + g_is_generating = true; + if (eval_text(ctx, "user\n")) { + return 1; + } + for (auto & fname : params.image) { + if (eval_image(ctx, fname)) { + return 1; + } + } + if (eval_text(ctx, params.prompt + "model\n", true)) { + return 1; + } + if (generate_response(ctx, smpl, n_predict)) { + return 1; + } + + } else { + LOG("\n Running in chat mode, available commands:"); + LOG("\n /image load an image"); + LOG("\n /clear clear the chat history"); + LOG("\n /quit or /exit exit the program"); + LOG("\n"); + + if (eval_text(ctx, "user\n")) { + return 1; + } + + while (true) { + g_is_generating = false; + LOG("\n> "); + console::set_display(console::user_input); + std::string line; + console::readline(line, false); + console::set_display(console::reset); + line = string_strip(line); + if (line.empty()) { + continue; + } + if (line == "/quit" || line == "/exit") { + break; + } + if (line == "/clear") { + ctx.n_past = 0; + llama_kv_cache_seq_rm(ctx.lctx, 0, 1, -1); // keep BOS + LOG("Chat history cleared\n\n"); + continue; + } + g_is_generating = true; + if (line.find("/image") == 0) { + std::string image = line.substr(7); + int res = eval_image(ctx, image); + if (res == 2) { + continue; // image not found + } + if (res) { + return 1; + } + continue; + } + if (eval_text(ctx, line + "model\n", true)) { + return 1; + } + if (generate_response(ctx, smpl, n_predict)) { + return 1; + } + if (eval_text(ctx, "user\n")) { + return 1; + } + } + } + + return 0; +} diff --git a/examples/llava/gemma3_convert_encoder_to_gguf.py b/examples/llava/gemma3_convert_encoder_to_gguf.py new file mode 100644 index 000000000..241b526b9 --- /dev/null +++ b/examples/llava/gemma3_convert_encoder_to_gguf.py @@ -0,0 +1,307 @@ +import gguf +import argparse +import logging +import sys +import torch +import json +import os +import numpy as np +from typing import cast, ContextManager, Any, Iterator +from pathlib import Path +from torch import Tensor + +logger = logging.getLogger("gemma3-mmproj") + + +# (copied from convert_hf_to_gguf.py) +# tree of lazy tensors +class LazyTorchTensor(gguf.LazyBase): + _tensor_type = torch.Tensor + # to keep the type-checker happy + dtype: torch.dtype + shape: torch.Size + + # only used when converting a torch.Tensor to a np.ndarray + _dtype_map: dict[torch.dtype, type] = { + torch.float16: np.float16, + torch.float32: np.float32, + } + + # used for safetensors slices + # ref: https://github.com/huggingface/safetensors/blob/079781fd0dc455ba0fe851e2b4507c33d0c0d407/bindings/python/src/lib.rs#L1046 + # TODO: uncomment U64, U32, and U16, ref: https://github.com/pytorch/pytorch/issues/58734 + _dtype_str_map: dict[str, torch.dtype] = { + "F64": torch.float64, + "F32": torch.float32, + "BF16": torch.bfloat16, + "F16": torch.float16, + # "U64": torch.uint64, + "I64": torch.int64, + # "U32": torch.uint32, + "I32": torch.int32, + # "U16": torch.uint16, + "I16": torch.int16, + "U8": torch.uint8, + "I8": torch.int8, + "BOOL": torch.bool, + "F8_E4M3": torch.float8_e4m3fn, + "F8_E5M2": torch.float8_e5m2, + } + + def numpy(self) -> gguf.LazyNumpyTensor: + dtype = self._dtype_map[self.dtype] + return gguf.LazyNumpyTensor( + meta=gguf.LazyNumpyTensor.meta_with_dtype_and_shape(dtype, self.shape), + args=(self,), + func=(lambda s: s.numpy()) + ) + + @classmethod + def meta_with_dtype_and_shape(cls, dtype: torch.dtype, shape: tuple[int, ...]) -> Tensor: + return torch.empty(size=shape, dtype=dtype, device="meta") + + @classmethod + def from_safetensors_slice(cls, st_slice: Any) -> Tensor: + dtype = cls._dtype_str_map[st_slice.get_dtype()] + shape: tuple[int, ...] = tuple(st_slice.get_shape()) + lazy = cls(meta=cls.meta_with_dtype_and_shape(dtype, shape), args=(st_slice,), func=lambda s: s[:]) + return cast(torch.Tensor, lazy) + + @classmethod + def __torch_function__(cls, func, types, args=(), kwargs=None): + del types # unused + + if kwargs is None: + kwargs = {} + + if func is torch.Tensor.numpy: + return args[0].numpy() + + return cls._wrap_fn(func)(*args, **kwargs) + + +class Gemma3VisionTower: + hparams: dict + gguf_writer: gguf.GGUFWriter + fname_out: Path + ftype: gguf.LlamaFileType + + @staticmethod + def load_hparams(dir_model: Path): + with open(dir_model / "config.json", "r", encoding="utf-8") as f: + return json.load(f) + + @staticmethod + def get_model_part_names(dir_model: Path, prefix: str, suffix: str) -> list[str]: + part_names: list[str] = [] + for filename in os.listdir(dir_model): + if filename.startswith(prefix) and filename.endswith(suffix): + part_names.append(filename) + part_names.sort() + return part_names + + def __init__(self, + dir_model: Path, + fname_out: Path, + ftype: gguf.LlamaFileType, + is_big_endian: bool,): + hparams = Gemma3VisionTower.load_hparams(dir_model) + self.hparams = hparams + self.fname_out = fname_out + self.ftype = ftype + endianess = gguf.GGUFEndian.BIG if is_big_endian else gguf.GGUFEndian.LITTLE + self.gguf_writer = gguf.GGUFWriter(path=None, arch="clip", endianess=endianess) + + text_config = hparams["text_config"] + vision_config = hparams["vision_config"] + + assert hparams["architectures"][0] == "Gemma3ForConditionalGeneration" + assert text_config is not None + assert vision_config is not None + + self.gguf_writer.add_string ("clip.projector_type", "gemma3") + self.gguf_writer.add_bool ("clip.has_text_encoder", False) + self.gguf_writer.add_bool ("clip.has_vision_encoder", True) + self.gguf_writer.add_bool ("clip.has_llava_projector", False) # legacy + self.gguf_writer.add_uint32 ("clip.vision.image_size", vision_config["image_size"]) + self.gguf_writer.add_uint32 ("clip.vision.patch_size", vision_config["patch_size"]) + self.gguf_writer.add_uint32 ("clip.vision.embedding_length", vision_config["hidden_size"]) + self.gguf_writer.add_uint32 ("clip.vision.feed_forward_length", vision_config["intermediate_size"]) + self.gguf_writer.add_uint32 ("clip.vision.projection_dim", text_config["hidden_size"]) + self.gguf_writer.add_uint32 ("clip.vision.block_count", vision_config["num_hidden_layers"]) + self.gguf_writer.add_uint32 ("clip.vision.attention.head_count", vision_config["num_attention_heads"]) + self.gguf_writer.add_float32("clip.vision.attention.layer_norm_epsilon", vision_config.get("layer_norm_eps", 1e-6)) + # default values taken from HF tranformers code + self.gguf_writer.add_array ("clip.vision.image_mean", [0.5, 0.5, 0.5]) + self.gguf_writer.add_array ("clip.vision.image_std", [0.5, 0.5, 0.5]) + self.gguf_writer.add_bool ("clip.use_gelu", True) + + # load tensors + for name, data_torch in self.get_tensors(dir_model): + # convert any unsupported data types to float32 + if data_torch.dtype not in (torch.float16, torch.float32): + data_torch = data_torch.to(torch.float32) + self.add_tensor(name, data_torch) + + def get_tensors(self, dir_model: Path) -> Iterator[tuple[str, Tensor]]: + part_names = Gemma3VisionTower.get_model_part_names(dir_model, "model", ".safetensors") + tensor_names_from_parts: set[str] = set() + for part_name in part_names: + logger.info(f"gguf: loading model part '{part_name}'") + from safetensors import safe_open + ctx = cast(ContextManager[Any], safe_open(dir_model / part_name, framework="pt", device="cpu")) + with ctx as model_part: + tensor_names_from_parts.update(model_part.keys()) + + for name in model_part.keys(): + data = model_part.get_slice(name) + data = LazyTorchTensor.from_safetensors_slice(data) + yield name, data + + def add_tensor(self, name: str, data_torch: Tensor): + is_1d = len(data_torch.shape) == 1 + is_embd = ".embeddings." in name + old_dtype = data_torch.dtype + can_quantize = not is_1d and not is_embd + data_qtype = gguf.GGMLQuantizationType.F32 + + # this is to support old checkpoint + # TODO: remove this when we have the final model + name = name.replace("vision_model.vision_model.", "vision_tower.vision_model.") + name = name.replace("multimodal_projector.", "multi_modal_projector.") + + # filter only vision tensors + if not name.startswith("vision_tower.vision_model.") and not name.startswith("multi_modal_projector."): + return + # prefix + name = name.replace("vision_tower.vision_model.encoder.layers.", "v.blk.") + name = name.replace("vision_tower.vision_model.", "v.") + # projector and input embd + name = name.replace(".embeddings.patch_embedding.", ".patch_embd.") + name = name.replace(".embeddings.position_embedding.", ".position_embd.") + name = name.replace( + "multi_modal_projector.mm_input_projection_weight", + "mm.input_projection.weight" + ) + name = name.replace( + "multi_modal_projector.mm_soft_emb_norm.weight", + "mm.soft_emb_norm.weight" + ) + name = name.replace("post_layernorm.", "post_ln.") + # each block + name = name.replace(".self_attn.k_proj.", ".attn_k.") + name = name.replace(".self_attn.v_proj.", ".attn_v.") + name = name.replace(".self_attn.q_proj.", ".attn_q.") + name = name.replace(".self_attn.out_proj.", ".attn_out.") + name = name.replace(".layer_norm1.", ".ln1.") + name = name.replace(".layer_norm2.", ".ln2.") + name = name.replace(".mlp.fc1.", ".ffn_down.") + name = name.replace(".mlp.fc2.", ".ffn_up.") + + if can_quantize: + if self.ftype == gguf.LlamaFileType.ALL_F32: + data_qtype = gguf.GGMLQuantizationType.F32 + elif self.ftype == gguf.LlamaFileType.MOSTLY_F16: + data_qtype = gguf.GGMLQuantizationType.F16 + elif self.ftype == gguf.LlamaFileType.MOSTLY_BF16: + data_qtype = gguf.GGMLQuantizationType.BF16 + elif self.ftype == gguf.LlamaFileType.MOSTLY_Q8_0: + data_qtype = gguf.GGMLQuantizationType.Q8_0 + else: + raise ValueError(f"Unsupported file type: {self.ftype}") + + # corrent norm value ; only this "soft_emb_norm" need to be corrected as it's part of Gemma projector + # the other norm values are part of SigLIP model, and they are already correct + # ref code: Gemma3RMSNorm + if "soft_emb_norm.weight" in name: + logger.info(f"Correcting norm value for '{name}'") + data_torch = data_torch + 1 + + data = data_torch.numpy() + + try: + data = gguf.quants.quantize(data, data_qtype) + except Exception as e: + logger.error(f"Error quantizing tensor '{name}': {e}, fallback to F16") + data_qtype = gguf.GGMLQuantizationType.F16 + data = gguf.quants.quantize(data, data_qtype) + + # reverse shape to make it similar to the internal ggml dimension order + shape_str = f"{{{', '.join(str(n) for n in reversed(data_torch.shape))}}}" + logger.info(f"{f'%-32s' % f'{name},'} {old_dtype} --> {data_qtype.name}, shape = {shape_str}") + + self.gguf_writer.add_tensor(name, data, raw_dtype=data_qtype) + + def write(self): + self.gguf_writer.write_header_to_file(path=self.fname_out) + self.gguf_writer.write_kv_data_to_file() + self.gguf_writer.write_tensors_to_file(progress=True) + self.gguf_writer.close() + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Convert Gemma 3 vision tower safetensors to GGUF format",) + parser.add_argument( + "--outfile", type=Path, default="mmproj.gguf", + help="path to write to", + ) + parser.add_argument( + "--outtype", type=str, choices=["f32", "f16", "bf16", "q8_0"], default="f16", + help="output format", + ) + parser.add_argument( + "--bigendian", action="store_true", + help="model is executed on big endian machine", + ) + parser.add_argument( + "model", type=Path, + help="directory containing model file", + nargs="?", + ) + parser.add_argument( + "--verbose", action="store_true", + help="increase output verbosity", + ) + + args = parser.parse_args() + if args.model is None: + parser.error("the following arguments are required: model") + return args + + +def main() -> None: + args = parse_args() + + if args.verbose: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + + dir_model = args.model + + if not dir_model.is_dir(): + logger.error(f'Error: {args.model} is not a directory') + sys.exit(1) + + ftype_map: dict[str, gguf.LlamaFileType] = { + "f32": gguf.LlamaFileType.ALL_F32, + "f16": gguf.LlamaFileType.MOSTLY_F16, + "bf16": gguf.LlamaFileType.MOSTLY_BF16, + "q8_0": gguf.LlamaFileType.MOSTLY_Q8_0, + } + + logger.info(f"Loading model: {dir_model.name}") + + with torch.inference_mode(): + gemma3_vision_tower = Gemma3VisionTower( + dir_model=dir_model, + fname_out=args.outfile, + ftype=ftype_map[args.outtype], + is_big_endian=args.bigendian, + ) + gemma3_vision_tower.write() + + +if __name__ == '__main__': + main() + diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py index ecac5b4bb..19624eae0 100644 --- a/gguf-py/gguf/constants.py +++ b/gguf-py/gguf/constants.py @@ -253,6 +253,7 @@ class MODEL_ARCH(IntEnum): MINICPM3 = auto() GEMMA = auto() GEMMA2 = auto() + GEMMA3 = auto() STARCODER2 = auto() RWKV6 = auto() RWKV6QWEN2 = auto() @@ -440,6 +441,7 @@ MODEL_ARCH_NAMES: dict[MODEL_ARCH, str] = { MODEL_ARCH.MINICPM3: "minicpm3", MODEL_ARCH.GEMMA: "gemma", MODEL_ARCH.GEMMA2: "gemma2", + MODEL_ARCH.GEMMA3: "gemma3", MODEL_ARCH.STARCODER2: "starcoder2", MODEL_ARCH.RWKV6: "rwkv6", MODEL_ARCH.RWKV6QWEN2: "rwkv6qwen2", @@ -1077,6 +1079,23 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = { MODEL_TENSOR.FFN_PRE_NORM, MODEL_TENSOR.FFN_POST_NORM, ], + MODEL_ARCH.GEMMA3: [ + MODEL_TENSOR.TOKEN_EMBD, + MODEL_TENSOR.OUTPUT_NORM, + MODEL_TENSOR.ATTN_Q, + MODEL_TENSOR.ATTN_Q_NORM, + MODEL_TENSOR.ATTN_K, + MODEL_TENSOR.ATTN_K_NORM, + MODEL_TENSOR.ATTN_V, + MODEL_TENSOR.ATTN_OUT, + MODEL_TENSOR.FFN_GATE, + MODEL_TENSOR.FFN_DOWN, + MODEL_TENSOR.FFN_UP, + MODEL_TENSOR.ATTN_NORM, + MODEL_TENSOR.ATTN_POST_NORM, + MODEL_TENSOR.FFN_PRE_NORM, + MODEL_TENSOR.FFN_POST_NORM, + ], MODEL_ARCH.STARCODER2: [ MODEL_TENSOR.TOKEN_EMBD, MODEL_TENSOR.OUTPUT_NORM, diff --git a/src/llama-arch.cpp b/src/llama-arch.cpp index 97a1e7e5e..28f2bbc8f 100644 --- a/src/llama-arch.cpp +++ b/src/llama-arch.cpp @@ -36,6 +36,7 @@ static const std::map LLM_ARCH_NAMES = { { LLM_ARCH_MINICPM3, "minicpm3" }, { LLM_ARCH_GEMMA, "gemma" }, { LLM_ARCH_GEMMA2, "gemma2" }, + { LLM_ARCH_GEMMA3, "gemma3" }, { LLM_ARCH_STARCODER2, "starcoder2" }, { LLM_ARCH_MAMBA, "mamba" }, { LLM_ARCH_XVERSE, "xverse" }, @@ -766,6 +767,26 @@ static const std::map> LLM_TENSOR_N { LLM_TENSOR_FFN_POST_NORM, "blk.%d.post_ffw_norm" }, }, }, + { + LLM_ARCH_GEMMA3, + { + { LLM_TENSOR_TOKEN_EMBD, "token_embd" }, + { LLM_TENSOR_OUTPUT_NORM, "output_norm" }, + { LLM_TENSOR_ATTN_NORM, "blk.%d.attn_norm" }, + { LLM_TENSOR_ATTN_Q, "blk.%d.attn_q" }, + { LLM_TENSOR_ATTN_Q_NORM, "blk.%d.attn_q_norm" }, + { LLM_TENSOR_ATTN_K, "blk.%d.attn_k" }, + { LLM_TENSOR_ATTN_K_NORM, "blk.%d.attn_k_norm" }, + { LLM_TENSOR_ATTN_V, "blk.%d.attn_v" }, + { LLM_TENSOR_ATTN_OUT, "blk.%d.attn_output" }, + { LLM_TENSOR_ATTN_POST_NORM, "blk.%d.post_attention_norm" }, + { LLM_TENSOR_FFN_NORM, "blk.%d.ffn_norm" }, + { LLM_TENSOR_FFN_GATE, "blk.%d.ffn_gate" }, + { LLM_TENSOR_FFN_DOWN, "blk.%d.ffn_down" }, + { LLM_TENSOR_FFN_UP, "blk.%d.ffn_up" }, + { LLM_TENSOR_FFN_POST_NORM, "blk.%d.post_ffw_norm" }, + }, + }, { LLM_ARCH_STARCODER2, { diff --git a/src/llama-arch.h b/src/llama-arch.h index 122fdcebe..2ec2e2362 100644 --- a/src/llama-arch.h +++ b/src/llama-arch.h @@ -40,6 +40,7 @@ enum llm_arch { LLM_ARCH_MINICPM3, LLM_ARCH_GEMMA, LLM_ARCH_GEMMA2, + LLM_ARCH_GEMMA3, LLM_ARCH_STARCODER2, LLM_ARCH_MAMBA, LLM_ARCH_XVERSE, diff --git a/src/llama-model.cpp b/src/llama-model.cpp index 1da4eae7e..9f75589d8 100644 --- a/src/llama-model.cpp +++ b/src/llama-model.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -864,6 +865,23 @@ void llama_model::load_hparams(llama_model_loader & ml) { default: type = LLM_TYPE_UNKNOWN; } } break; + case LLM_ARCH_GEMMA3: + { + ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa); + ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps); + + switch (hparams.n_layer) { + case 26: type = LLM_TYPE_1B; break; + case 34: type = LLM_TYPE_4B; break; + case 48: type = LLM_TYPE_12B; break; + case 62: type = LLM_TYPE_27B; break; + default: type = LLM_TYPE_UNKNOWN; + } + + hparams.f_attention_scale = type == LLM_TYPE_27B + ? 1.0f / std::sqrt(float(hparams.n_embd / hparams.n_head(0))) + : 1.0f / std::sqrt(float(hparams.n_embd_head_k)); + } break; case LLM_ARCH_STARCODER2: { ml.get_key(LLM_KV_ATTENTION_LAYERNORM_EPS, hparams.f_norm_eps); @@ -2454,6 +2472,35 @@ bool llama_model::load_tensors(llama_model_loader & ml) { layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head_k * n_head, n_embd}, 0); layer.attn_post_norm = create_tensor(tn(LLM_TENSOR_ATTN_POST_NORM, "weight", i), {n_embd}, 0); + layer.ffn_norm = create_tensor(tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0); + layer.ffn_gate = create_tensor(tn(LLM_TENSOR_FFN_GATE, "weight", i), {n_embd, n_ff}, 0); + layer.ffn_up = create_tensor(tn(LLM_TENSOR_FFN_UP, "weight", i), {n_embd, n_ff}, 0); + layer.ffn_down = create_tensor(tn(LLM_TENSOR_FFN_DOWN, "weight", i), { n_ff, n_embd}, 0); + layer.ffn_post_norm = create_tensor(tn(LLM_TENSOR_FFN_POST_NORM, "weight", i), {n_embd}, 0); + } + } break; + case LLM_ARCH_GEMMA3: + { + tok_embd = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0); + + // output + output_norm = create_tensor(tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0); + output = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, TENSOR_DUPLICATED); // same as tok_embd, duplicated to allow offloading + + for (int i = 0; i < n_layer; ++i) { + auto & layer = layers[i]; + + layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0); + + layer.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); + layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head_k * n_head, n_embd}, 0); + + layer.attn_post_norm = create_tensor(tn(LLM_TENSOR_ATTN_POST_NORM, "weight", i), {n_embd}, 0); + layer.attn_k_norm = create_tensor(tn(LLM_TENSOR_ATTN_K_NORM, "weight", i), {n_embd_head_k}, 0); + layer.attn_q_norm = create_tensor(tn(LLM_TENSOR_ATTN_Q_NORM, "weight", i), {n_embd_head_k}, 0); + layer.ffn_norm = create_tensor(tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0); layer.ffn_gate = create_tensor(tn(LLM_TENSOR_FFN_GATE, "weight", i), {n_embd, n_ff}, 0); layer.ffn_up = create_tensor(tn(LLM_TENSOR_FFN_UP, "weight", i), {n_embd, n_ff}, 0); @@ -3650,6 +3697,7 @@ void llama_model::print_info() const { LLAMA_LOG_INFO("%s: f_clamp_kqv = %.1e\n", __func__, hparams.f_clamp_kqv); LLAMA_LOG_INFO("%s: f_max_alibi_bias = %.1e\n", __func__, hparams.f_max_alibi_bias); LLAMA_LOG_INFO("%s: f_logit_scale = %.1e\n", __func__, hparams.f_logit_scale); + LLAMA_LOG_INFO("%s: f_attn_scale = %.1e\n", __func__, hparams.f_attention_scale); LLAMA_LOG_INFO("%s: n_ff = %s\n", __func__, print_f([&](uint32_t il) { return hparams.n_ff(il); }, hparams.n_layer).c_str()); LLAMA_LOG_INFO("%s: n_expert = %u\n", __func__, hparams.n_expert); LLAMA_LOG_INFO("%s: n_expert_used = %u\n", __func__, hparams.n_expert_used); @@ -3923,6 +3971,7 @@ enum llama_rope_type llama_model_rope_type(const struct llama_model * model) { case LLM_ARCH_PHIMOE: case LLM_ARCH_GEMMA: case LLM_ARCH_GEMMA2: + case LLM_ARCH_GEMMA3: case LLM_ARCH_STARCODER2: case LLM_ARCH_OPENELM: case LLM_ARCH_GPTNEOX: diff --git a/src/llama.cpp b/src/llama.cpp index 607f27861..4a4e91490 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -4978,6 +4978,149 @@ struct llm_build_context { return gf; } + struct ggml_cgraph * build_gemma3() { + struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); + + const int64_t n_embd_head_k = hparams.n_embd_head_k; + + struct ggml_tensor * cur; + struct ggml_tensor * inpL; + + inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); + + // important: do not normalize weights for raw embeddings input (i.e. encoded image emdeddings) + if (ubatch.token) { + inpL = ggml_scale(ctx0, inpL, sqrtf(n_embd)); + cb(inpL, "inp_scaled", -1); + } + + // inp_pos - contains the positions + struct ggml_tensor * inp_pos = build_inp_pos(); + + // KQ_mask (mask for 1 head, it will be broadcasted to all heads) + // gemma3 requires different mask for layers using sliding window (SWA) + struct ggml_tensor * KQ_mask = build_inp_KQ_mask(true); + struct ggml_tensor * KQ_mask_swa = build_inp_KQ_mask_swa(true); + + // "5-to-1 interleaved attention" + // 5 layers of local attention followed by 1 layer of global attention + static const int sliding_window_pattern = 6; + + for (int il = 0; il < n_layer; ++il) { + const bool is_sliding = (il + 1) % sliding_window_pattern; + const float freq_base_l = is_sliding ? 10000.0f : freq_base; + const float freq_scale_l = is_sliding ? 1.0f : freq_scale; + struct ggml_tensor * KQ_mask_l = is_sliding ? KQ_mask_swa : KQ_mask; + + // norm + cur = llm_build_norm(ctx0, inpL, hparams, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, cb, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head_k, n_head, n_tokens); + Qcur = llm_build_norm(ctx0, Qcur, hparams, + model.layers[il].attn_q_norm, + NULL, + LLM_NORM_RMS, cb, il); + cb(Qcur, "Qcur_normed", il); + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Qcur, "Qcur", il); + + Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_kv, n_tokens); + Kcur = llm_build_norm(ctx0, Kcur, hparams, + model.layers[il].attn_k_norm, + NULL, + LLM_NORM_RMS, cb, il); + cb(Kcur, "Kcur_normed", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Kcur, "Kcur", il); + + cur = llm_build_kv(ctx0, lctx, kv_self, gf, + model.layers[il].wo, NULL, + Kcur, Vcur, Qcur, KQ_mask_l, n_tokens, kv_head, n_kv, hparams.f_attention_scale, cb, il); + } + + cur = llm_build_norm(ctx0, cur, hparams, + model.layers[il].attn_post_norm, NULL, + LLM_NORM_RMS, cb, il); + cb(cur, "attn_post_norm", il); + + if (il == n_layer - 1) { + // skip computing output for unused tokens + struct ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + struct ggml_tensor * sa_out = ggml_add(ctx0, cur, inpL); + cb(sa_out, "sa_out", il); + + cur = llm_build_norm(ctx0, sa_out, hparams, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, cb, il); + cb(cur, "ffn_norm", il); + + // feed-forward network + { + cur = llm_build_ffn(ctx0, lctx, cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_PAR, cb, il); + cb(cur, "ffn_out", il); + } + + cur = llm_build_norm(ctx0, cur, hparams, + model.layers[il].ffn_post_norm, NULL, + LLM_NORM_RMS, cb, -1); + cb(cur, "ffn_post_norm", -1); + + cur = ggml_add(ctx0, cur, sa_out); + cur = lctx.cvec.apply_to(ctx0, cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = llm_build_norm(ctx0, cur, hparams, + model.output_norm, NULL, + LLM_NORM_RMS, cb, -1); + cb(cur, "result_norm", -1); + + // lm_head + cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); + + cb(cur, "result_output", -1); + + ggml_build_forward_expand(gf, cur); + + return gf; + } struct ggml_cgraph * build_starcoder2() { struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); @@ -8298,6 +8441,10 @@ static struct ggml_cgraph * llama_build_graph( { result = llm.build_gemma2(); } break; + case LLM_ARCH_GEMMA3: + { + result = llm.build_gemma3(); + } break; case LLM_ARCH_STARCODER2: { result = llm.build_starcoder2(); From 34c961b181836a4f06ab4c56d5ce61ce03fc478b Mon Sep 17 00:00:00 2001 From: uvos Date: Wed, 12 Mar 2025 10:14:11 +0100 Subject: [PATCH 81/87] CUDA/HIP: Fix fattn-vec-* when device warp size is not 32 (#12315) When fattn-wmma was ported over to warp64 various bits that also touch fattn-vec where converted to selectable warp size, however the fattn-vec kernels dont work with 64 wide warps for now, so we need to avoid launching them with parameters for warp64 --- ggml/src/ggml-cuda/fattn-common.cuh | 52 ++++++++++++---------------- ggml/src/ggml-cuda/fattn-wmma-f16.cu | 7 ++-- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/ggml/src/ggml-cuda/fattn-common.cuh b/ggml/src/ggml-cuda/fattn-common.cuh index 46de14093..4067fd41b 100644 --- a/ggml/src/ggml-cuda/fattn-common.cuh +++ b/ggml/src/ggml-cuda/fattn-common.cuh @@ -52,12 +52,11 @@ typedef half (*vec_dot_KQ_f16_t)( typedef float (*vec_dot_KQ_f32_t)( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8 , const void * __restrict__ Q_ds); -template +template static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_0( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q4_0 * K_q4_0 = (const block_q4_0 *) K_c; - constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; @@ -93,12 +92,11 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_0( return sum; } -template +template static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_1( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q4_1 * K_q4_1 = (const block_q4_1 *) K_c; - constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; @@ -138,12 +136,11 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q4_1( return sum; } -template +template static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_0( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q5_0 * K_q5_0 = (const block_q5_0 *) K_c; - constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; @@ -186,12 +183,11 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_0( return sum; } -template +template static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_1( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q5_1 * K_q5_1 = (const block_q5_1 *) K_c; - constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; @@ -238,12 +234,11 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q5_1( return sum; } -template +template static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q8_0( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) { const block_q8_0 * K_q8_0 = (const block_q8_0 *) K_c; - constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_v); T sum = 0.0f; @@ -272,12 +267,11 @@ static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_q8_0( return sum; } -template +template static __device__ __forceinline__ T vec_dot_fattn_vec_KQ_f16( const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8 , const void * __restrict__ Q_ds_v) { const half2 * K_h2 = (const half2 *) K_c; - constexpr int warp_size = ggml_cuda_get_physical_warp_size(); GGML_UNUSED(Q_q8); GGML_UNUSED(Q_ds_v); @@ -480,25 +474,25 @@ static __device__ __forceinline__ T dequantize_1_f16(const void * __restrict__ v return x[i]; } -template +template constexpr __device__ vec_dot_KQ_f16_t get_vec_dot_KQ_f16(ggml_type type_K) { - return type_K == GGML_TYPE_Q4_0 ? vec_dot_fattn_vec_KQ_q4_0 : - type_K == GGML_TYPE_Q4_1 ? vec_dot_fattn_vec_KQ_q4_1 : - type_K == GGML_TYPE_Q5_0 ? vec_dot_fattn_vec_KQ_q5_0 : - type_K == GGML_TYPE_Q5_1 ? vec_dot_fattn_vec_KQ_q5_1 : - type_K == GGML_TYPE_Q8_0 ? vec_dot_fattn_vec_KQ_q8_0 : - type_K == GGML_TYPE_F16 ? vec_dot_fattn_vec_KQ_f16 : + return type_K == GGML_TYPE_Q4_0 ? vec_dot_fattn_vec_KQ_q4_0 : + type_K == GGML_TYPE_Q4_1 ? vec_dot_fattn_vec_KQ_q4_1 : + type_K == GGML_TYPE_Q5_0 ? vec_dot_fattn_vec_KQ_q5_0 : + type_K == GGML_TYPE_Q5_1 ? vec_dot_fattn_vec_KQ_q5_1 : + type_K == GGML_TYPE_Q8_0 ? vec_dot_fattn_vec_KQ_q8_0 : + type_K == GGML_TYPE_F16 ? vec_dot_fattn_vec_KQ_f16 : nullptr; } -template +template constexpr __device__ vec_dot_KQ_f32_t get_vec_dot_KQ_f32(ggml_type type_K) { - return type_K == GGML_TYPE_Q4_0 ? vec_dot_fattn_vec_KQ_q4_0 : - type_K == GGML_TYPE_Q4_1 ? vec_dot_fattn_vec_KQ_q4_1 : - type_K == GGML_TYPE_Q5_0 ? vec_dot_fattn_vec_KQ_q5_0 : - type_K == GGML_TYPE_Q5_1 ? vec_dot_fattn_vec_KQ_q5_1 : - type_K == GGML_TYPE_Q8_0 ? vec_dot_fattn_vec_KQ_q8_0 : - type_K == GGML_TYPE_F16 ? vec_dot_fattn_vec_KQ_f16 : + return type_K == GGML_TYPE_Q4_0 ? vec_dot_fattn_vec_KQ_q4_0 : + type_K == GGML_TYPE_Q4_1 ? vec_dot_fattn_vec_KQ_q4_1 : + type_K == GGML_TYPE_Q5_0 ? vec_dot_fattn_vec_KQ_q5_0 : + type_K == GGML_TYPE_Q5_1 ? vec_dot_fattn_vec_KQ_q5_1 : + type_K == GGML_TYPE_Q8_0 ? vec_dot_fattn_vec_KQ_q8_0 : + type_K == GGML_TYPE_F16 ? vec_dot_fattn_vec_KQ_f16 : nullptr; } @@ -681,7 +675,8 @@ static void on_no_fattn_vec_case(const int D) { template void launch_fattn( ggml_backend_cuda_context & ctx, ggml_tensor * dst, fattn_kernel_t fattn_kernel, - const int nwarps, const size_t nbytes_shared, const bool need_f16_K, const bool need_f16_V + const int nwarps, const size_t nbytes_shared, const bool need_f16_K, const bool need_f16_V, + const int warp_size = WARP_SIZE ) { constexpr int ncols = ncols1 * ncols2; @@ -704,8 +699,6 @@ void launch_fattn( GGML_ASSERT(Q->ne[3] == 1); - const int warp_size = ggml_cuda_info().devices[ctx.device].warp_size; - ggml_cuda_pool & pool = ctx.pool(); cudaStream_t main_stream = ctx.stream(); const int id = ggml_cuda_get_device(); @@ -805,7 +798,6 @@ void launch_fattn( const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2); GGML_ASSERT(block_dim.x % warp_size == 0); - GGML_ASSERT(!GGML_CUDA_CC_IS_AMD(cc) || block_dim.x * block_dim.y <= 4 * (unsigned int)warp_size); fattn_kernel<<>>( (const char *) Q->data, K_data, diff --git a/ggml/src/ggml-cuda/fattn-wmma-f16.cu b/ggml/src/ggml-cuda/fattn-wmma-f16.cu index 622cf2857..dab1d5cbc 100644 --- a/ggml/src/ggml-cuda/fattn-wmma-f16.cu +++ b/ggml/src/ggml-cuda/fattn-wmma-f16.cu @@ -469,6 +469,7 @@ void ggml_cuda_flash_attn_ext_wmma_f16_case(ggml_backend_cuda_context & ctx, ggm constexpr int frag_m = cols_per_block == 8 && D % 32 == 0 ? 32 : 16; const int blocks_num_pb1 = ((Q->ne[1] + cols_per_block - 1) / cols_per_block)*Q->ne[2]*Q->ne[3]; const int nsm = ggml_cuda_info().devices[ggml_cuda_get_device()].nsm; + const int warp_size = ggml_cuda_info().devices[ggml_cuda_get_device()].warp_size; float logit_softcap; memcpy(&logit_softcap, (const float *) KQV->op_params + 2, sizeof(float)); @@ -485,7 +486,7 @@ void ggml_cuda_flash_attn_ext_wmma_f16_case(ggml_backend_cuda_context & ctx, ggm fattn_kernel = flash_attn_ext_f16< D, cols_per_block, nwarps, get_VKQ_stride(D, nwarps, frag_m), parallel_blocks, KQ_acc_t, use_logit_softcap>; } - launch_fattn(ctx, dst, fattn_kernel, nwarps, 0, true, true); + launch_fattn(ctx, dst, fattn_kernel, nwarps, 0, true, true, warp_size); return; } if (2*blocks_num_pb1 < 2*nsm) { @@ -500,7 +501,7 @@ void ggml_cuda_flash_attn_ext_wmma_f16_case(ggml_backend_cuda_context & ctx, ggm fattn_kernel = flash_attn_ext_f16< D, cols_per_block, nwarps, get_VKQ_stride(D, nwarps, frag_m), parallel_blocks, KQ_acc_t, use_logit_softcap>; } - launch_fattn(ctx, dst, fattn_kernel, nwarps, 0, true, true); + launch_fattn(ctx, dst, fattn_kernel, nwarps, 0, true, true, warp_size); return; } constexpr int parallel_blocks = 1; @@ -514,7 +515,7 @@ void ggml_cuda_flash_attn_ext_wmma_f16_case(ggml_backend_cuda_context & ctx, ggm fattn_kernel = flash_attn_ext_f16< D, cols_per_block, nwarps, get_VKQ_stride(D, nwarps, frag_m), parallel_blocks, KQ_acc_t, use_logit_softcap>; } - launch_fattn(ctx, dst, fattn_kernel, nwarps, 0, true, true); + launch_fattn(ctx, dst, fattn_kernel, nwarps, 0, true, true, warp_size); } void ggml_cuda_flash_attn_ext_wmma_f16(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { From 363f8c5d67dcf80e00c39580dfa86dc2774d74c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Cabrera=20P=C3=A9rez?= Date: Wed, 12 Mar 2025 09:57:32 +0000 Subject: [PATCH 82/87] sycl : variable sg_size support for mmvq kernels (#12336) --- ggml/src/ggml-sycl/mmvq.cpp | 152 ++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 77 deletions(-) diff --git a/ggml/src/ggml-sycl/mmvq.cpp b/ggml/src/ggml-sycl/mmvq.cpp index 221f65c21..a96286d71 100644 --- a/ggml/src/ggml-sycl/mmvq.cpp +++ b/ggml/src/ggml-sycl/mmvq.cpp @@ -3,44 +3,42 @@ #include template -static void mul_mat_vec_q(const void * __restrict__ vx, const void * __restrict__ vy, float * __restrict__ dst, const int ncols, const int nrows, - const sycl::nd_item<3> &item_ct1) { - const int row = item_ct1.get_group(2) * item_ct1.get_local_range(1) + - item_ct1.get_local_id(1); +static void mul_mat_vec_q(const void * __restrict__ vx, const void * __restrict__ vy, float * __restrict__ dst, + const int ncols, const int nrows, const sycl::nd_item<3> & item_ct1) { + const int row = item_ct1.get_group(2) * item_ct1.get_local_range(1) + item_ct1.get_local_id(1); if (row >= nrows) { return; } - const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; - assert(blocks_per_warp>0); + const int blocks_per_row = ncols / qk; + constexpr int blocks_per_warp = (vdr * WARP_SIZE + qi - 1) / qi; // Ensuring blocks_per_warp > 0 -// partial sum for each thread + assert(blocks_per_warp > 0); + + // partial sum for each thread float tmp = 0.0f; - const block_q_t * x = (const block_q_t *) vx; + const block_q_t * x = (const block_q_t *) vx; const block_q8_1 * y = (const block_q8_1 *) vy; - for (int i = item_ct1.get_local_id(2) / (qi / vdr); i < blocks_per_row; - i += blocks_per_warp) { - const int ibx = row*blocks_per_row + i; // x block index + for (int i = item_ct1.get_local_id(2) / (qi / vdr); i < blocks_per_row; i += blocks_per_warp) { + const int ibx = row * blocks_per_row + i; // x block index - const int iby = i * (qk/QK8_1); // y block index that aligns with ibx + const int iby = i * (qk / QK8_1); // y block index that aligns with ibx - const int iqs = - vdr * - (item_ct1.get_local_id(2) % - (qi / vdr)); // x block quant index when casting the quants to int + for (size_t elem = 0; elem < qi / vdr; elem += WARP_SIZE) { + const int iqs = elem + vdr * (item_ct1.get_local_id(2) % + (qi / vdr)); // x block quant index when casting the quants to int - tmp += vec_dot_q_sycl(&x[ibx], &y[iby], iqs); + tmp += vec_dot_q_sycl(&x[ibx], &y[iby], iqs); + } } // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { - tmp += - dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { + tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } if (item_ct1.get_local_id(2) == 0) { @@ -62,7 +60,7 @@ static void mul_mat_vec_q_iq2_xxs_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread @@ -87,7 +85,7 @@ static void mul_mat_vec_q_iq2_xxs_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -111,7 +109,7 @@ static void mul_mat_vec_q_iq2_xs_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -135,7 +133,7 @@ static void mul_mat_vec_q_iq2_xs_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -159,7 +157,7 @@ static void mul_mat_vec_q_iq2_s_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -183,7 +181,7 @@ static void mul_mat_vec_q_iq2_s_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -207,7 +205,7 @@ static void mul_mat_vec_q_iq3_xxs_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -231,7 +229,7 @@ static void mul_mat_vec_q_iq3_xxs_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -255,7 +253,7 @@ static void mul_mat_vec_q_iq3_s_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -279,7 +277,7 @@ static void mul_mat_vec_q_iq3_s_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -303,7 +301,7 @@ static void mul_mat_vec_q_iq1_s_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -327,7 +325,7 @@ static void mul_mat_vec_q_iq1_s_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -351,7 +349,7 @@ static void mul_mat_vec_q_iq1_m_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -375,7 +373,7 @@ static void mul_mat_vec_q_iq1_m_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -399,7 +397,7 @@ static void mul_mat_vec_q_iq4_nl_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -423,7 +421,7 @@ static void mul_mat_vec_q_iq4_nl_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -448,7 +446,7 @@ static void mul_mat_vec_q_iq4_xs_q8_1(const void *__restrict__ vx, } const int blocks_per_row = ncols / qk; - const int blocks_per_warp = vdr * QK_WARP_SIZE / qi; + const int blocks_per_warp = vdr * WARP_SIZE / qi; assert(blocks_per_warp>0); // partial sum for each thread float tmp = 0.0f; @@ -472,7 +470,7 @@ static void mul_mat_vec_q_iq4_xs_q8_1(const void *__restrict__ vx, // sum up partial sums and write back result #pragma unroll - for (int mask = QK_WARP_SIZE / 2; mask > 0; mask >>= 1) { + for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) { tmp += dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask); } @@ -489,7 +487,7 @@ static void mul_mat_vec_q4_0_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK4_0 == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -497,7 +495,7 @@ static void mul_mat_vec_q4_0_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -513,7 +511,7 @@ static void mul_mat_vec_q4_1_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK4_1 == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -521,7 +519,7 @@ static void mul_mat_vec_q4_1_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -537,7 +535,7 @@ static void mul_mat_vec_q5_0_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK5_0 == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -545,7 +543,7 @@ static void mul_mat_vec_q5_0_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -561,7 +559,7 @@ static void mul_mat_vec_q5_1_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK5_1 == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -569,7 +567,7 @@ static void mul_mat_vec_q5_1_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -585,7 +583,7 @@ static void mul_mat_vec_q8_0_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK8_0 == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -593,7 +591,7 @@ static void mul_mat_vec_q8_0_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -609,7 +607,7 @@ static void mul_mat_vec_q2_K_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -617,7 +615,7 @@ static void mul_mat_vec_q2_K_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -633,7 +631,7 @@ static void mul_mat_vec_q3_K_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -641,7 +639,7 @@ static void mul_mat_vec_q3_K_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -657,7 +655,7 @@ static void mul_mat_vec_q4_K_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -665,7 +663,7 @@ static void mul_mat_vec_q4_K_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -681,7 +679,7 @@ static void mul_mat_vec_q5_K_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -689,7 +687,7 @@ static void mul_mat_vec_q5_K_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -705,7 +703,7 @@ static void mul_mat_vec_q6_K_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { @@ -713,7 +711,7 @@ static void mul_mat_vec_q6_K_q8_1_sycl(const void *vx, const void *vy, cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q( vx, vy, dst, ncols, nrows, item_ct1); @@ -730,13 +728,13 @@ static void mul_mat_vec_iq2_xxs_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq2_xxs_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -751,13 +749,13 @@ static void mul_mat_vec_iq2_xs_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler & cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq2_xs_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -772,14 +770,14 @@ static void mul_mat_vec_iq2_s_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq2_s_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -794,14 +792,14 @@ static void mul_mat_vec_iq3_xxs_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq3_xxs_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -816,14 +814,14 @@ static void mul_mat_vec_iq3_s_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq3_s_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -838,14 +836,14 @@ static void mul_mat_vec_iq1_s_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq1_s_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -860,13 +858,13 @@ static void mul_mat_vec_iq1_m_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq1_m_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -881,14 +879,14 @@ static void mul_mat_vec_iq4_nl_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK4_NL == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq4_nl_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); @@ -903,14 +901,14 @@ static void mul_mat_vec_iq4_xs_q8_1_sycl(const void *vx, const void *vy, GGML_ASSERT(ncols % QK_K == 0); const int block_num_y = (nrows + GGML_SYCL_MMV_Y - 1) / GGML_SYCL_MMV_Y; const sycl::range<3> block_nums(1, 1, block_num_y); - const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, QK_WARP_SIZE); + const sycl::range<3> block_dims(1, GGML_SYCL_MMV_Y, WARP_SIZE); { stream->submit([&](sycl::handler &cgh) { cgh.parallel_for( sycl::nd_range<3>(block_nums * block_dims, block_dims), [=](sycl::nd_item<3> item_ct1) - [[intel::reqd_sub_group_size(QK_WARP_SIZE)]] { + [[intel::reqd_sub_group_size(WARP_SIZE)]] { mul_mat_vec_q_iq4_xs_q8_1( vx, vy, dst, ncols, nrows, item_ct1); }); From 80a02aa8588ef167d616f76f1781b104c245ace0 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Wed, 12 Mar 2025 13:45:32 +0100 Subject: [PATCH 83/87] llama.swiftui : fix xcframework dir in README [no ci] (#12353) This commit fixes the path to the xcframework in the README file which I had forgotten to change after renaming the build directory. --- examples/llama.swiftui/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/llama.swiftui/README.md b/examples/llama.swiftui/README.md index 5b0ee9472..bd7ce3774 100644 --- a/examples/llama.swiftui/README.md +++ b/examples/llama.swiftui/README.md @@ -16,7 +16,7 @@ Open `llama.swiftui.xcodeproj` project in Xcode and you should be able to build a simulator or a real device. To use the framework with a different project, the XCFramework can be added to the project by -adding `build-ios/llama.xcframework` by dragging and dropping it into the project navigator, or +adding `build-apple/llama.xcframework` by dragging and dropping it into the project navigator, or by manually selecting the framework in the "Frameworks, Libraries, and Embedded Content" section of the project settings. From f08f4b3187b691bb08a8884ed39ebaa94e956707 Mon Sep 17 00:00:00 2001 From: Oscar Barenys Date: Wed, 12 Mar 2025 20:06:58 +0100 Subject: [PATCH 84/87] Update build.yml for Windows Vulkan builder to use Vulkan 1.4.304 SDK for VK_NV_cooperative_matrix2 support (#12301) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f2c81c0c2..1e2429364 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -774,7 +774,7 @@ jobs: env: OPENBLAS_VERSION: 0.3.23 SDE_VERSION: 9.33.0-2024-01-07 - VULKAN_VERSION: 1.3.261.1 + VULKAN_VERSION: 1.4.304.1 strategy: matrix: From 2048b5913d51beab82dfe29955f9008130b936c0 Mon Sep 17 00:00:00 2001 From: Ishaan Gandhi Date: Thu, 13 Mar 2025 06:10:05 -0400 Subject: [PATCH 85/87] server : fix crash when using verbose output with input tokens that are not in printable range (#12178) (#12338) * Fix DOS index bug * Remove new APIs * remove extra line * Remove from API * Add extra newline * Update examples/server/server.cpp --------- Co-authored-by: Xuan-Son Nguyen --- examples/server/server.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/examples/server/server.cpp b/examples/server/server.cpp index 8cb8d0033..ce0195475 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -2040,6 +2040,18 @@ struct server_context { return ret; } + bool can_be_detokenized(const struct llama_context * ctx, const std::vector & tokens) { + const llama_model * model = llama_get_model(ctx); + const llama_vocab * vocab = llama_model_get_vocab(model); + const int32_t n_vocab = llama_vocab_n_tokens(vocab); + for (const auto & token : tokens) { + if (token < 0 || token >= n_vocab) { + return false; + } + } + return true; + } + bool launch_slot_with_task(server_slot & slot, const server_task & task) { slot.reset(); slot.id_task = task.id; @@ -2054,6 +2066,11 @@ struct server_context { slot.lora = task.params.lora; } + bool can_detokenize = can_be_detokenized(ctx, slot.prompt_tokens); + if (!can_detokenize) { + send_error(task, "Prompt contains invalid tokens", ERROR_TYPE_INVALID_REQUEST); + return false; + } SLT_DBG(slot, "launching slot : %s\n", safe_json_to_str(slot.to_json()).c_str()); if (slot.n_predict > 0 && slot.params.n_predict > slot.n_predict) { From e0dbec0bc6cd4b6230cda7a6ed1e9dac08d1600b Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Thu, 13 Mar 2025 12:35:44 +0200 Subject: [PATCH 86/87] llama : refactor llama_context, llama_kv_cache, llm_build_context (#12181) * llama : refactor llama_context, llama_kv_cache, llm_build_context ggml-ci * graph : don't mutate the KV cache during defrag ggml-ci * context : reduce virtuals + remove test function ggml-ci * context : move interface implementation to source file + factory ggml-ci * graph : move KV cache build functions to llama_context impl ggml-ci * graph : remove model reference from build_pooling ggml-ci * graph : remove llama_model reference ggml-ci * kv_cache : provide rope factors ggml-ci * graph : rework inputs to use only unique_ptr, remove attn input abstraction ggml-ci * context : remove llama_context_i abstraction ggml-ci * context : clean-up ggml-ci * graph : clean-up ggml-ci * llama : remove redundant keywords (struct, enum) ggml-ci * model : adapt gemma3 ggml-ci * graph : restore same attention ops as on master ggml-ci * llama : remove TODO + fix indent ggml-ci --- common/common.cpp | 6 +- common/speculative.cpp | 8 +- examples/batched-bench/batched-bench.cpp | 4 +- examples/batched.swift/Sources/main.swift | 2 +- .../cvector-generator/cvector-generator.cpp | 2 +- examples/embedding/embedding.cpp | 2 +- examples/gritlm/gritlm.cpp | 4 +- examples/imatrix/imatrix.cpp | 2 +- examples/infill/infill.cpp | 4 +- examples/llama-bench/llama-bench.cpp | 4 +- .../llama/src/main/cpp/llama-android.cpp | 8 +- .../llama.cpp.swift/LibLlama.swift | 8 +- examples/llava/gemma3-cli.cpp | 2 +- examples/lookahead/lookahead.cpp | 12 +- examples/lookup/lookup.cpp | 2 +- examples/main/main.cpp | 12 +- examples/parallel/parallel.cpp | 10 +- examples/passkey/passkey.cpp | 28 +- examples/perplexity/perplexity.cpp | 12 +- examples/quantize-stats/quantize-stats.cpp | 4 +- examples/retrieval/retrieval.cpp | 2 +- examples/run/run.cpp | 4 +- examples/save-load-state/save-load-state.cpp | 4 +- examples/server/server.cpp | 22 +- examples/server/tests/utils.py | 2 +- examples/simple-chat/simple-chat.cpp | 4 +- .../speculative-simple/speculative-simple.cpp | 2 +- examples/speculative/speculative.cpp | 24 +- include/llama.h | 106 +- src/CMakeLists.txt | 7 +- src/llama-adapter.cpp | 39 +- src/llama-adapter.h | 20 +- src/llama-batch.h | 4 +- src/llama-context.cpp | 3809 +++--- src/llama-context.h | 298 +- src/llama-graph.cpp | 1695 +++ src/llama-graph.h | 576 + src/llama-io.cpp | 15 + src/llama-io.h | 35 + src/llama-kv-cache.cpp | 1519 ++- src/llama-kv-cache.h | 302 +- src/llama-memory.cpp | 1 + src/llama-memory.h | 21 + src/llama-model.cpp | 7392 +++++++++++- src/llama-model.h | 19 +- src/llama.cpp | 10035 +--------------- 46 files changed, 13903 insertions(+), 12190 deletions(-) create mode 100644 src/llama-graph.cpp create mode 100644 src/llama-graph.h create mode 100644 src/llama-io.cpp create mode 100644 src/llama-io.h create mode 100644 src/llama-memory.cpp create mode 100644 src/llama-memory.h diff --git a/common/common.cpp b/common/common.cpp index 6448b7b03..8487e3834 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -955,8 +955,8 @@ struct common_init_result common_init_from_params(common_params & params) { return iparams; } - if (params.ctx_shift && !llama_kv_cache_can_shift(lctx)) { - LOG_WRN("%s: KV cache shifting is not supported for this model, disabling KV cache shifting\n", __func__); + if (params.ctx_shift && !llama_kv_self_can_shift(lctx)) { + LOG_WRN("%s: KV cache shifting is not supported for this context, disabling KV cache shifting\n", __func__); params.ctx_shift = false; } @@ -1060,7 +1060,7 @@ struct common_init_result common_init_from_params(common_params & params) { if (llama_model_has_decoder(model)) { llama_decode(lctx, llama_batch_get_one(tmp.data(), std::min(tmp.size(), (size_t) params.n_batch))); } - llama_kv_cache_clear(lctx); + llama_kv_self_clear(lctx); llama_synchronize(lctx); llama_perf_context_reset(lctx); } diff --git a/common/speculative.cpp b/common/speculative.cpp index 1bac3a1ce..ccad70fa9 100644 --- a/common/speculative.cpp +++ b/common/speculative.cpp @@ -173,7 +173,7 @@ llama_tokens common_speculative_gen_draft( result.reserve(params.n_draft); if (reuse_n == 0) { - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); prompt.clear(); } else { @@ -192,14 +192,14 @@ llama_tokens common_speculative_gen_draft( } if (reuse_i > 0) { - llama_kv_cache_seq_rm (ctx, 0, 0, reuse_i); - llama_kv_cache_seq_add(ctx, 0, reuse_i, -1, -reuse_i); + llama_kv_self_seq_rm (ctx, 0, 0, reuse_i); + llama_kv_self_seq_add(ctx, 0, reuse_i, -1, -reuse_i); prompt.erase(prompt.begin(), prompt.begin() + reuse_i); } if (reuse_n < (int) prompt.size()) { - llama_kv_cache_seq_rm (ctx, 0, reuse_n, -1); + llama_kv_self_seq_rm (ctx, 0, reuse_n, -1); prompt.erase(prompt.begin() + reuse_n, prompt.end()); } diff --git a/examples/batched-bench/batched-bench.cpp b/examples/batched-bench/batched-bench.cpp index 0659ab6f1..430e8be51 100644 --- a/examples/batched-bench/batched-bench.cpp +++ b/examples/batched-bench/batched-bench.cpp @@ -132,7 +132,7 @@ int main(int argc, char ** argv) { const auto t_pp_start = ggml_time_us(); - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); if (!decode_helper(ctx, batch, ctx_params.n_batch)) { LOG_ERR("%s: llama_decode() failed\n", __func__); @@ -141,7 +141,7 @@ int main(int argc, char ** argv) { if (is_pp_shared) { for (int32_t i = 1; i < pl; ++i) { - llama_kv_cache_seq_cp(ctx, 0, i, -1, -1); + llama_kv_self_seq_cp(ctx, 0, i, -1, -1); } } diff --git a/examples/batched.swift/Sources/main.swift b/examples/batched.swift/Sources/main.swift index 55c31166c..514989e34 100644 --- a/examples/batched.swift/Sources/main.swift +++ b/examples/batched.swift/Sources/main.swift @@ -116,7 +116,7 @@ if llama_decode(context, batch) != 0 { } for i in 1 ..< n_parallel { - llama_kv_cache_seq_cp(context, 0, Int32(i), 0, batch.n_tokens) + llama_kv_self_seq_cp(context, 0, Int32(i), 0, batch.n_tokens) } if n_parallel > 1 { diff --git a/examples/cvector-generator/cvector-generator.cpp b/examples/cvector-generator/cvector-generator.cpp index c72528dac..2a9071550 100644 --- a/examples/cvector-generator/cvector-generator.cpp +++ b/examples/cvector-generator/cvector-generator.cpp @@ -342,7 +342,7 @@ static bool cb_eval(struct ggml_tensor * t, bool ask, void * user_data) { } static bool get_hidden_layers(llama_context * ctx, std::vector & tokens) { - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); if (llama_decode(ctx, llama_batch_get_one(tokens.data(), tokens.size()))) { fprintf(stderr, "%s : failed to eval\n", __func__); return false; diff --git a/examples/embedding/embedding.cpp b/examples/embedding/embedding.cpp index 3dd9f2b07..6f0890415 100644 --- a/examples/embedding/embedding.cpp +++ b/examples/embedding/embedding.cpp @@ -38,7 +38,7 @@ static void batch_decode(llama_context * ctx, llama_batch & batch, float * outpu const struct llama_model * model = llama_get_model(ctx); // clear previous kv_cache values (irrelevant for embeddings) - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); // run model LOG_INF("%s: n_tokens = %d, n_seq = %d\n", __func__, batch.n_tokens, n_seq); diff --git a/examples/gritlm/gritlm.cpp b/examples/gritlm/gritlm.cpp index 72eb46257..f7db7861c 100644 --- a/examples/gritlm/gritlm.cpp +++ b/examples/gritlm/gritlm.cpp @@ -45,7 +45,7 @@ static std::vector> encode(llama_context * ctx, const std::ve } // clear previous kv_cache values (irrelevant for embeddings) - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); llama_set_embeddings(ctx, true); llama_set_causal_attn(ctx, false); @@ -102,7 +102,7 @@ static std::string generate(llama_context * ctx, llama_sampler * smpl, const std llama_token eos_token = llama_vocab_eos(vocab); - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); llama_set_embeddings(ctx, false); llama_set_causal_attn(ctx, true); diff --git a/examples/imatrix/imatrix.cpp b/examples/imatrix/imatrix.cpp index 91649c450..31b675e8f 100644 --- a/examples/imatrix/imatrix.cpp +++ b/examples/imatrix/imatrix.cpp @@ -495,7 +495,7 @@ static bool compute_imatrix(llama_context * ctx, const common_params & params) { const auto t_start = std::chrono::high_resolution_clock::now(); // clear the KV cache - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); llama_batch batch = llama_batch_init(n_batch, 0, 1); diff --git a/examples/infill/infill.cpp b/examples/infill/infill.cpp index 489a208b6..4e2f7b727 100644 --- a/examples/infill/infill.cpp +++ b/examples/infill/infill.cpp @@ -332,8 +332,8 @@ int main(int argc, char ** argv) { LOG_DBG("context full, swapping: n_past = %d, n_left = %d, n_ctx = %d, n_keep = %d, n_discard = %d\n", n_past, n_left, n_ctx, params.n_keep, n_discard); - llama_kv_cache_seq_rm (ctx, 0, params.n_keep + 1 , params.n_keep + n_discard + 1); - llama_kv_cache_seq_add(ctx, 0, params.n_keep + 1 + n_discard, n_past, -n_discard); + llama_kv_self_seq_rm (ctx, 0, params.n_keep + 1 , params.n_keep + n_discard + 1); + llama_kv_self_seq_add(ctx, 0, params.n_keep + 1 + n_discard, n_past, -n_discard); n_past -= n_discard; diff --git a/examples/llama-bench/llama-bench.cpp b/examples/llama-bench/llama-bench.cpp index f518d02d3..cbcbfcee8 100644 --- a/examples/llama-bench/llama-bench.cpp +++ b/examples/llama-bench/llama-bench.cpp @@ -1578,7 +1578,7 @@ int main(int argc, char ** argv) { test t(inst, lmodel, ctx); - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); // cool off before the test if (params.delay) { @@ -1618,7 +1618,7 @@ int main(int argc, char ** argv) { } for (int i = 0; i < params.reps; i++) { - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); uint64_t t_start = get_time_ns(); diff --git a/examples/llama.android/llama/src/main/cpp/llama-android.cpp b/examples/llama.android/llama/src/main/cpp/llama-android.cpp index 0de61ce77..9654cd53c 100644 --- a/examples/llama.android/llama/src/main/cpp/llama-android.cpp +++ b/examples/llama.android/llama/src/main/cpp/llama-android.cpp @@ -194,7 +194,7 @@ Java_android_llama_cpp_LLamaAndroid_bench_1model( } batch->logits[batch->n_tokens - 1] = true; - llama_kv_cache_clear(context); + llama_kv_self_clear(context); const auto t_pp_start = ggml_time_us(); if (llama_decode(context, *batch) != 0) { @@ -206,7 +206,7 @@ Java_android_llama_cpp_LLamaAndroid_bench_1model( LOGi("Benchmark text generation (tg)"); - llama_kv_cache_clear(context); + llama_kv_self_clear(context); const auto t_tg_start = ggml_time_us(); for (i = 0; i < tg; i++) { @@ -223,7 +223,7 @@ Java_android_llama_cpp_LLamaAndroid_bench_1model( const auto t_tg_end = ggml_time_us(); - llama_kv_cache_clear(context); + llama_kv_self_clear(context); const auto t_pp = double(t_pp_end - t_pp_start) / 1000000.0; const auto t_tg = double(t_tg_end - t_tg_start) / 1000000.0; @@ -448,5 +448,5 @@ Java_android_llama_cpp_LLamaAndroid_completion_1loop( extern "C" JNIEXPORT void JNICALL Java_android_llama_cpp_LLamaAndroid_kv_1cache_1clear(JNIEnv *, jobject, jlong context) { - llama_kv_cache_clear(reinterpret_cast(context)); + llama_kv_self_clear(reinterpret_cast(context)); } diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index ee7141a66..f6e31abc9 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -210,7 +210,7 @@ actor LlamaContext { } batch.logits[Int(batch.n_tokens) - 1] = 1 // true - llama_kv_cache_clear(context) + llama_kv_self_clear(context) let t_pp_start = DispatchTime.now().uptimeNanoseconds / 1000; @@ -223,7 +223,7 @@ actor LlamaContext { // bench text generation - llama_kv_cache_clear(context) + llama_kv_self_clear(context) let t_tg_start = DispatchTime.now().uptimeNanoseconds / 1000; @@ -242,7 +242,7 @@ actor LlamaContext { let t_tg_end = DispatchTime.now().uptimeNanoseconds / 1000; - llama_kv_cache_clear(context) + llama_kv_self_clear(context) let t_pp = Double(t_pp_end - t_pp_start) / 1000000.0 let t_tg = Double(t_tg_end - t_tg_start) / 1000000.0 @@ -292,7 +292,7 @@ actor LlamaContext { func clear() { tokens_list.removeAll() temporary_invalid_cchars.removeAll() - llama_kv_cache_clear(context) + llama_kv_self_clear(context) } private func tokenize(text: String, add_bos: Bool) -> [llama_token] { diff --git a/examples/llava/gemma3-cli.cpp b/examples/llava/gemma3-cli.cpp index a07864d4e..c36bb2eda 100644 --- a/examples/llava/gemma3-cli.cpp +++ b/examples/llava/gemma3-cli.cpp @@ -309,7 +309,7 @@ int main(int argc, char ** argv) { } if (line == "/clear") { ctx.n_past = 0; - llama_kv_cache_seq_rm(ctx.lctx, 0, 1, -1); // keep BOS + llama_kv_self_seq_rm(ctx.lctx, 0, 1, -1); // keep BOS LOG("Chat history cleared\n\n"); continue; } diff --git a/examples/lookahead/lookahead.cpp b/examples/lookahead/lookahead.cpp index b9e8de694..7df20aee1 100644 --- a/examples/lookahead/lookahead.cpp +++ b/examples/lookahead/lookahead.cpp @@ -96,7 +96,7 @@ int main(int argc, char ** argv) { llama_decode(ctx, llama_batch_get_one(&inp.back(), 1)); for (int s = 1; s < W + G + 1; ++s) { - llama_kv_cache_seq_cp(ctx, 0, s, -1, -1); + llama_kv_self_seq_cp(ctx, 0, s, -1, -1); } const auto t_enc_end = ggml_time_us(); @@ -438,17 +438,17 @@ int main(int argc, char ** argv) { // KV cache management // if no verification token matched, we simply remove all cells from this batch -> no fragmentation - llama_kv_cache_seq_rm(ctx, -1, n_past, -1); + llama_kv_self_seq_rm(ctx, -1, n_past, -1); if (seq_id_best != 0) { // if a verification token matched, we keep the best sequence and remove the rest // this leads to some KV cache fragmentation - llama_kv_cache_seq_keep(ctx, seq_id_best); - llama_kv_cache_seq_cp (ctx, seq_id_best, 0, -1, -1); - llama_kv_cache_seq_rm (ctx, seq_id_best, -1, -1); + llama_kv_self_seq_keep(ctx, seq_id_best); + llama_kv_self_seq_cp (ctx, seq_id_best, 0, -1, -1); + llama_kv_self_seq_rm (ctx, seq_id_best, -1, -1); for (int s = 1; s < W + G + 1; ++s) { - llama_kv_cache_seq_cp(ctx, 0, s, -1, -1); + llama_kv_self_seq_cp(ctx, 0, s, -1, -1); } } } diff --git a/examples/lookup/lookup.cpp b/examples/lookup/lookup.cpp index dbd0444ec..4ae93b2a5 100644 --- a/examples/lookup/lookup.cpp +++ b/examples/lookup/lookup.cpp @@ -192,7 +192,7 @@ int main(int argc, char ** argv){ // KV cache management // clean the cache of draft tokens that weren't accepted - llama_kv_cache_seq_rm(ctx, 0, n_past, -1); + llama_kv_self_seq_rm(ctx, 0, n_past, -1); common_batch_clear(batch_tgt); common_batch_add(batch_tgt, draft[0], n_past, { 0 }, true); diff --git a/examples/main/main.cpp b/examples/main/main.cpp index 4e0c69473..fd7410a64 100644 --- a/examples/main/main.cpp +++ b/examples/main/main.cpp @@ -354,7 +354,7 @@ int main(int argc, char ** argv) { } // remove any "future" tokens that we might have inherited from the previous session - llama_kv_cache_seq_rm(ctx, -1, n_matching_session_tokens, -1); + llama_kv_self_seq_rm(ctx, -1, n_matching_session_tokens, -1); } LOG_DBG("recalculate the cached logits (check): embd_inp.size() %zu, n_matching_session_tokens %zu, embd_inp.size() %zu, session_tokens.size() %zu\n", @@ -602,8 +602,8 @@ int main(int argc, char ** argv) { LOG_DBG("context full, swapping: n_past = %d, n_left = %d, n_ctx = %d, n_keep = %d, n_discard = %d\n", n_past, n_left, n_ctx, params.n_keep, n_discard); - llama_kv_cache_seq_rm (ctx, 0, params.n_keep , params.n_keep + n_discard); - llama_kv_cache_seq_add(ctx, 0, params.n_keep + n_discard, n_past, -n_discard); + llama_kv_self_seq_rm (ctx, 0, params.n_keep , params.n_keep + n_discard); + llama_kv_self_seq_add(ctx, 0, params.n_keep + n_discard, n_past, -n_discard); n_past -= n_discard; @@ -626,9 +626,9 @@ int main(int argc, char ** argv) { LOG_DBG("div: [%6d, %6d] / %6d -> [%6d, %6d]\n", ga_i + ib*bd, ga_i + ib*bd + ga_w, ga_n, (ga_i + ib*bd)/ga_n, (ga_i + ib*bd + ga_w)/ga_n); LOG_DBG("shift: [%6d, %6d] + %6d -> [%6d, %6d]\n", ga_i + ib*bd + ga_w, n_past + ib*bd, dd, ga_i + ib*bd + ga_w + dd, n_past + ib*bd + dd); - llama_kv_cache_seq_add(ctx, 0, ga_i, n_past, ib*bd); - llama_kv_cache_seq_div(ctx, 0, ga_i + ib*bd, ga_i + ib*bd + ga_w, ga_n); - llama_kv_cache_seq_add(ctx, 0, ga_i + ib*bd + ga_w, n_past + ib*bd, dd); + llama_kv_self_seq_add(ctx, 0, ga_i, n_past, ib*bd); + llama_kv_self_seq_div(ctx, 0, ga_i + ib*bd, ga_i + ib*bd + ga_w, ga_n); + llama_kv_self_seq_add(ctx, 0, ga_i + ib*bd + ga_w, n_past + ib*bd, dd); n_past -= bd; diff --git a/examples/parallel/parallel.cpp b/examples/parallel/parallel.cpp index be18909ed..588632f04 100644 --- a/examples/parallel/parallel.cpp +++ b/examples/parallel/parallel.cpp @@ -202,7 +202,7 @@ int main(int argc, char ** argv) { // assign the system KV cache to all parallel sequences for (int32_t i = 1; i <= n_clients; ++i) { - llama_kv_cache_seq_cp(ctx, 0, i, -1, -1); + llama_kv_self_seq_cp(ctx, 0, i, -1, -1); } LOG_INF("\n"); @@ -234,9 +234,9 @@ int main(int argc, char ** argv) { if (batch.n_tokens == 0) { // all sequences have ended - clear the entire KV cache for (int i = 1; i <= n_clients; ++i) { - llama_kv_cache_seq_rm(ctx, i, -1, -1); + llama_kv_self_seq_rm(ctx, i, -1, -1); // but keep the system prompt - llama_kv_cache_seq_cp(ctx, 0, i, -1, -1); + llama_kv_self_seq_cp(ctx, 0, i, -1, -1); } LOG_INF("%s: clearing the KV cache\n", __func__); @@ -372,8 +372,8 @@ int main(int argc, char ** argv) { } // delete only the generated part of the sequence, i.e. keep the system prompt in the cache - llama_kv_cache_seq_rm(ctx, client.id + 1, -1, -1); - llama_kv_cache_seq_cp(ctx, 0, client.id + 1, -1, -1); + llama_kv_self_seq_rm(ctx, client.id + 1, -1, -1); + llama_kv_self_seq_cp(ctx, 0, client.id + 1, -1, -1); const auto t_main_end = ggml_time_us(); diff --git a/examples/passkey/passkey.cpp b/examples/passkey/passkey.cpp index fa8519051..ea3a6c1fc 100644 --- a/examples/passkey/passkey.cpp +++ b/examples/passkey/passkey.cpp @@ -133,11 +133,11 @@ int main(int argc, char ** argv) { const int ib = i/n_batch - 1; const int bd = n_batch_grp*(n_grp - 1); - llama_kv_cache_seq_add (ctx, 0, n_past - n_batch, n_past, ib*bd); - llama_kv_cache_seq_div (ctx, 0, n_past - n_batch + ib*bd, n_past + ib*bd, n_grp); - llama_kv_cache_update (ctx); + llama_kv_self_seq_add (ctx, 0, n_past - n_batch, n_past, ib*bd); + llama_kv_self_seq_div (ctx, 0, n_past - n_batch + ib*bd, n_past + ib*bd, n_grp); + llama_kv_self_update (ctx); - n_past = llama_kv_cache_seq_pos_max(ctx, 0) + 1; + n_past = llama_kv_self_seq_pos_max(ctx, 0) + 1; } common_batch_clear(batch); @@ -167,12 +167,12 @@ int main(int argc, char ** argv) { LOG_INF("%s: shifting KV cache with %d\n", __func__, n_discard); - llama_kv_cache_seq_rm (ctx, 0, n_keep , n_keep + n_discard); - llama_kv_cache_seq_add(ctx, 0, n_keep + n_discard, n_ctx, -n_discard); - //llama_kv_cache_defrag (ctx); - llama_kv_cache_update (ctx); + llama_kv_self_seq_rm (ctx, 0, n_keep , n_keep + n_discard); + llama_kv_self_seq_add(ctx, 0, n_keep + n_discard, n_ctx, -n_discard); + //llama_kv_self_defrag (ctx); + llama_kv_self_update (ctx); - n_past = llama_kv_cache_seq_pos_max(ctx, 0) + 1; + n_past = llama_kv_self_seq_pos_max(ctx, 0) + 1; common_batch_clear(batch); @@ -198,12 +198,12 @@ int main(int argc, char ** argv) { if (n_discard > 0) { LOG_INF("%s: shifting KV cache with %d to free space for the answer\n", __func__, n_discard); - llama_kv_cache_seq_rm (ctx, 0, n_keep , n_keep + n_discard); - llama_kv_cache_seq_add(ctx, 0, n_keep + n_discard, n_ctx, -n_discard); - //llama_kv_cache_defrag (ctx); - llama_kv_cache_update (ctx); + llama_kv_self_seq_rm (ctx, 0, n_keep , n_keep + n_discard); + llama_kv_self_seq_add(ctx, 0, n_keep + n_discard, n_ctx, -n_discard); + //llama_kv_self_defrag (ctx); + llama_kv_self_update (ctx); - n_past = llama_kv_cache_seq_pos_max(ctx, 0) + 1; + n_past = llama_kv_self_seq_pos_max(ctx, 0) + 1; } } diff --git a/examples/perplexity/perplexity.cpp b/examples/perplexity/perplexity.cpp index 5d07421e8..8c413f7d6 100644 --- a/examples/perplexity/perplexity.cpp +++ b/examples/perplexity/perplexity.cpp @@ -361,7 +361,7 @@ static results_perplexity perplexity_v2(llama_context * ctx, const common_params const auto t_start = std::chrono::high_resolution_clock::now(); // clear the KV cache - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); llama_batch batch = llama_batch_init(n_batch, 0, 1); @@ -547,7 +547,7 @@ static results_perplexity perplexity(llama_context * ctx, const common_params & const auto t_start = std::chrono::high_resolution_clock::now(); // clear the KV cache - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); for (int j = 0; j < num_batches; ++j) { const int batch_start = start + j * n_batch; @@ -924,7 +924,7 @@ static void hellaswag_score(llama_context * ctx, const common_params & params) { return; } - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); // decode all tasks [i0, i1) if (!decode_helper(ctx, batch, batch_logits, n_batch, n_vocab)) { @@ -1203,7 +1203,7 @@ static void winogrande_score(llama_context * ctx, const common_params & params) return; } - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); // decode all tasks [i0, i1) if (!decode_helper(ctx, batch, batch_logits, n_batch, n_vocab)) { @@ -1575,7 +1575,7 @@ static void multiple_choice_score(llama_context * ctx, const common_params & par return; } - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); // decode all tasks [i0, i1) if (!decode_helper(ctx, batch, batch_logits, n_batch, n_vocab)) { @@ -1765,7 +1765,7 @@ static void kl_divergence(llama_context * ctx, const common_params & params) { } // clear the KV cache - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); llama_batch batch = llama_batch_init(n_batch, 0, 1); diff --git a/examples/quantize-stats/quantize-stats.cpp b/examples/quantize-stats/quantize-stats.cpp index bd2f73467..dd07ab9b3 100644 --- a/examples/quantize-stats/quantize-stats.cpp +++ b/examples/quantize-stats/quantize-stats.cpp @@ -1,6 +1,6 @@ #include "ggml.h" #include "llama.h" -#include "llama-context.h" +#include "llama-model.h" #include "common.h" #include @@ -328,7 +328,7 @@ int main(int argc, char ** argv) { } } - const auto & tensors = llama_internal_get_tensor_map(ctx); + const auto & tensors = llama_internal_get_tensor_map(model); // check layer tensors int included_layers = 0; diff --git a/examples/retrieval/retrieval.cpp b/examples/retrieval/retrieval.cpp index 2439022a2..0efe20d4b 100644 --- a/examples/retrieval/retrieval.cpp +++ b/examples/retrieval/retrieval.cpp @@ -83,7 +83,7 @@ static void batch_add_seq(llama_batch & batch, const std::vector & toke static void batch_decode(llama_context * ctx, llama_batch & batch, float * output, int n_seq, int n_embd) { // clear previous kv_cache values (irrelevant for embeddings) - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); // run model LOG_INF("%s: n_tokens = %d, n_seq = %d\n", __func__, batch.n_tokens, n_seq); diff --git a/examples/run/run.cpp b/examples/run/run.cpp index 38407d519..437f2533e 100644 --- a/examples/run/run.cpp +++ b/examples/run/run.cpp @@ -891,7 +891,7 @@ static int apply_chat_template(const struct common_chat_templates * tmpls, Llama // Function to tokenize the prompt static int tokenize_prompt(const llama_vocab * vocab, const std::string & prompt, std::vector & prompt_tokens, const LlamaData & llama_data) { - const bool is_first = llama_get_kv_cache_used_cells(llama_data.context.get()) == 0; + const bool is_first = llama_kv_self_used_cells(llama_data.context.get()) == 0; const int n_prompt_tokens = -llama_tokenize(vocab, prompt.c_str(), prompt.size(), NULL, 0, is_first, true); prompt_tokens.resize(n_prompt_tokens); @@ -907,7 +907,7 @@ static int tokenize_prompt(const llama_vocab * vocab, const std::string & prompt // Check if we have enough space in the context to evaluate this batch static int check_context_size(const llama_context_ptr & ctx, const llama_batch & batch) { const int n_ctx = llama_n_ctx(ctx.get()); - const int n_ctx_used = llama_get_kv_cache_used_cells(ctx.get()); + const int n_ctx_used = llama_kv_self_used_cells(ctx.get()); if (n_ctx_used + batch.n_tokens > n_ctx) { printf(LOG_COL_DEFAULT "\n"); printe("context size exceeded\n"); diff --git a/examples/save-load-state/save-load-state.cpp b/examples/save-load-state/save-load-state.cpp index cf7cbd815..760ebbbf0 100644 --- a/examples/save-load-state/save-load-state.cpp +++ b/examples/save-load-state/save-load-state.cpp @@ -15,7 +15,7 @@ int main(int argc, char ** argv) { return 1; } - print_build_info(); + common_init(); if (params.n_predict < 0) { params.n_predict = 16; @@ -196,7 +196,7 @@ int main(int argc, char ** argv) { fprintf(stderr, "%s : seq 0 copied, %zd bytes\n", __func__, ncopy); // erase whole kv - llama_kv_cache_clear(ctx3); + llama_kv_self_clear(ctx3); fprintf(stderr, "%s : kv cache cleared\n", __func__); // restore kv into seq 1 diff --git a/examples/server/server.cpp b/examples/server/server.cpp index ce0195475..71e053b20 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -2113,7 +2113,7 @@ struct server_context { SRV_DBG("%s", "clearing KV cache\n"); // clear the entire KV cache - llama_kv_cache_clear(ctx); + llama_kv_self_clear(ctx); clean_kv_cache = false; } @@ -2655,8 +2655,8 @@ struct server_context { res->n_tasks_deferred = queue_tasks.queue_tasks_deferred.size(); res->t_start = metrics.t_start; - res->kv_cache_tokens_count = llama_get_kv_cache_token_count(ctx); - res->kv_cache_used_cells = llama_get_kv_cache_used_cells(ctx); + res->kv_cache_tokens_count = llama_kv_self_n_tokens(ctx); + res->kv_cache_used_cells = llama_kv_self_used_cells(ctx); res->n_prompt_tokens_processed_total = metrics.n_prompt_tokens_processed_total; res->t_prompt_processing_total = metrics.t_prompt_processing_total; @@ -2772,7 +2772,7 @@ struct server_context { // Erase token cache const size_t n_erased = slot->cache_tokens.size(); - llama_kv_cache_seq_rm(ctx, slot->id, -1, -1); + llama_kv_self_seq_rm(ctx, slot->id, -1, -1); slot->cache_tokens.clear(); auto res = std::make_unique(); @@ -2840,8 +2840,8 @@ struct server_context { SLT_WRN(slot, "slot context shift, n_keep = %d, n_left = %d, n_discard = %d\n", n_keep, n_left, n_discard); - llama_kv_cache_seq_rm (ctx, slot.id, n_keep , n_keep + n_discard); - llama_kv_cache_seq_add(ctx, slot.id, n_keep + n_discard, slot.n_past, -n_discard); + llama_kv_self_seq_rm (ctx, slot.id, n_keep , n_keep + n_discard); + llama_kv_self_seq_add(ctx, slot.id, n_keep + n_discard, slot.n_past, -n_discard); if (slot.params.cache_prompt) { for (size_t i = n_keep + n_discard; i < slot.cache_tokens.size(); i++) { @@ -3032,8 +3032,8 @@ struct server_context { const int64_t kv_shift = (int64_t) head_p - (int64_t) head_c; - llama_kv_cache_seq_rm (ctx, slot.id, head_p, head_c); - llama_kv_cache_seq_add(ctx, slot.id, head_c, head_c + n_match, kv_shift); + llama_kv_self_seq_rm (ctx, slot.id, head_p, head_c); + llama_kv_self_seq_add(ctx, slot.id, head_c, head_c + n_match, kv_shift); for (size_t i = 0; i < n_match; i++) { slot.cache_tokens[head_p + i] = slot.cache_tokens[head_c + i]; @@ -3071,9 +3071,9 @@ struct server_context { } // keep only the common part - if (!llama_kv_cache_seq_rm(ctx, slot.id, slot.n_past, -1)) { + if (!llama_kv_self_seq_rm(ctx, slot.id, slot.n_past, -1)) { // could not partially delete (likely using a non-Transformer model) - llama_kv_cache_seq_rm(ctx, slot.id, -1, -1); + llama_kv_self_seq_rm(ctx, slot.id, -1, -1); // there is no common part left slot.n_past = 0; @@ -3313,7 +3313,7 @@ struct server_context { slot.cache_tokens.push_back(id); slot.cache_tokens.insert(slot.cache_tokens.end(), ids.begin(), ids.end() - 1); - llama_kv_cache_seq_rm(ctx, slot.id, slot.n_past, -1); + llama_kv_self_seq_rm(ctx, slot.id, slot.n_past, -1); for (size_t i = 0; i < ids.size(); ++i) { completion_token_output result; diff --git a/examples/server/tests/utils.py b/examples/server/tests/utils.py index ec2d8ec55..30aa86609 100644 --- a/examples/server/tests/utils.py +++ b/examples/server/tests/utils.py @@ -302,7 +302,7 @@ class ServerPreset: server.model_hf_repo = "ggml-org/models" server.model_hf_file = "tinyllamas/stories260K.gguf" server.model_alias = "tinyllama-2" - server.n_ctx = 256 + server.n_ctx = 512 server.n_batch = 32 server.n_slots = 2 server.n_predict = 64 diff --git a/examples/simple-chat/simple-chat.cpp b/examples/simple-chat/simple-chat.cpp index c5534cc13..84f415973 100644 --- a/examples/simple-chat/simple-chat.cpp +++ b/examples/simple-chat/simple-chat.cpp @@ -98,7 +98,7 @@ int main(int argc, char ** argv) { auto generate = [&](const std::string & prompt) { std::string response; - const bool is_first = llama_get_kv_cache_used_cells(ctx) == 0; + const bool is_first = llama_kv_self_used_cells(ctx) == 0; // tokenize the prompt const int n_prompt_tokens = -llama_tokenize(vocab, prompt.c_str(), prompt.size(), NULL, 0, is_first, true); @@ -113,7 +113,7 @@ int main(int argc, char ** argv) { while (true) { // check if we have enough space in the context to evaluate this batch int n_ctx = llama_n_ctx(ctx); - int n_ctx_used = llama_get_kv_cache_used_cells(ctx); + int n_ctx_used = llama_kv_self_used_cells(ctx); if (n_ctx_used + batch.n_tokens > n_ctx) { printf("\033[0m\n"); fprintf(stderr, "context size exceeded\n"); diff --git a/examples/speculative-simple/speculative-simple.cpp b/examples/speculative-simple/speculative-simple.cpp index 403ba2dd2..a5d2bc9d0 100644 --- a/examples/speculative-simple/speculative-simple.cpp +++ b/examples/speculative-simple/speculative-simple.cpp @@ -217,7 +217,7 @@ int main(int argc, char ** argv) { { LOG_DBG("clear kv cache from any extra tokens, n_past = %d\n", n_past); - llama_kv_cache_seq_rm(ctx_tgt, 0, n_past, -1); + llama_kv_self_seq_rm(ctx_tgt, 0, n_past, -1); } if ((params.n_predict >= 0 && n_predict > params.n_predict) || has_eos) { diff --git a/examples/speculative/speculative.cpp b/examples/speculative/speculative.cpp index c7ccea50d..bfddc67e0 100644 --- a/examples/speculative/speculative.cpp +++ b/examples/speculative/speculative.cpp @@ -420,14 +420,14 @@ int main(int argc, char ** argv) { { LOG_DBG("keeping sequence %d, n_past_tgt = %d, n_past_dft = %d\n", s_keep, n_past_tgt, n_past_dft); - llama_kv_cache_seq_keep(ctx_dft, s_keep); - llama_kv_cache_seq_cp (ctx_dft, s_keep, 0, -1, -1); - llama_kv_cache_seq_keep(ctx_dft, 0); + llama_kv_self_seq_keep(ctx_dft, s_keep); + llama_kv_self_seq_cp (ctx_dft, s_keep, 0, -1, -1); + llama_kv_self_seq_keep(ctx_dft, 0); - llama_kv_cache_seq_rm (ctx_tgt, s_keep, n_past_tgt, -1); - llama_kv_cache_seq_keep(ctx_tgt, s_keep); - llama_kv_cache_seq_cp (ctx_tgt, s_keep, 0, -1, -1); - llama_kv_cache_seq_keep(ctx_tgt, 0); + llama_kv_self_seq_rm (ctx_tgt, s_keep, n_past_tgt, -1); + llama_kv_self_seq_keep(ctx_tgt, s_keep); + llama_kv_self_seq_cp (ctx_tgt, s_keep, 0, -1, -1); + llama_kv_self_seq_keep(ctx_tgt, 0); } for (int s = 0; s < n_seq_dft; ++s) { @@ -444,7 +444,7 @@ int main(int argc, char ** argv) { common_batch_clear(batch_dft); common_batch_add (batch_dft, token_id, n_past_dft, { 0 }, true); - llama_kv_cache_seq_rm(ctx_dft, 0, n_past_dft, -1); + llama_kv_self_seq_rm(ctx_dft, 0, n_past_dft, -1); // LOG_DBG("dft batch: %s\n", LOG_BATCH_TOSTR_PRETTY(ctx_dft, batch_dft).c_str()); llama_decode(ctx_dft, batch_dft); @@ -503,8 +503,8 @@ int main(int argc, char ** argv) { if (n_seq_cur < n_seq_dft && cur_p->data[f].p > p_draft_split) { LOG_DBG("splitting seq %3d into %3d\n", s, n_seq_cur); - llama_kv_cache_seq_rm(ctx_dft, n_seq_cur, -1, -1); - llama_kv_cache_seq_cp(ctx_dft, s, n_seq_cur, -1, -1); + llama_kv_self_seq_rm(ctx_dft, n_seq_cur, -1, -1); + llama_kv_self_seq_cp(ctx_dft, s, n_seq_cur, -1, -1); // all previous tokens from this branch are now also part of the new branch for (int t = 0; t < batch_tgt.n_tokens; ++t) { @@ -585,9 +585,9 @@ int main(int argc, char ** argv) { // evaluate the target model on the drafted tokens { - llama_kv_cache_seq_keep(ctx_tgt, 0); + llama_kv_self_seq_keep(ctx_tgt, 0); for (int s = 1; s < n_seq_dft; ++s) { - llama_kv_cache_seq_cp(ctx_tgt, 0, s, -1, -1); + llama_kv_self_seq_cp(ctx_tgt, 0, s, -1, -1); } // LOG_DBG("target batch: %s\n", LOG_BATCH_TOSTR_PRETTY(ctx_tgt, batch_tgt).c_str()); diff --git a/include/llama.h b/include/llama.h index d62792c0a..e5286f061 100644 --- a/include/llama.h +++ b/include/llama.h @@ -60,6 +60,7 @@ extern "C" { struct llama_model; struct llama_context; struct llama_sampler; + struct llama_kv_cache; typedef int32_t llama_pos; typedef int32_t llama_token; @@ -469,7 +470,8 @@ extern "C" { DEPRECATED(LLAMA_API int32_t llama_n_vocab (const struct llama_vocab * vocab), "use llama_vocab_n_tokens instead"); LLAMA_API const struct llama_model * llama_get_model (const struct llama_context * ctx); - LLAMA_API enum llama_pooling_type llama_pooling_type(const struct llama_context * ctx); + LLAMA_API struct llama_kv_cache * llama_get_kv_self ( struct llama_context * ctx); + LLAMA_API enum llama_pooling_type llama_pooling_type(const struct llama_context * ctx); // TODO: rename to llama_get_pooling_type LLAMA_API const struct llama_vocab * llama_model_get_vocab(const struct llama_model * model); LLAMA_API enum llama_rope_type llama_model_rope_type(const struct llama_model * model); @@ -586,7 +588,7 @@ extern "C" { // KV cache // - // TODO: remove llama_kv_cache_view_* API + // TODO: start using struct llama_kv_cache // Information associated with an individual cell in the KV cache view. struct llama_kv_cache_view_cell { @@ -641,13 +643,19 @@ extern "C" { // Returns the number of tokens in the KV cache (slow, use only for debug) // If a KV cell has multiple sequences assigned to it, it will be counted multiple times - LLAMA_API int32_t llama_get_kv_cache_token_count(const struct llama_context * ctx); + LLAMA_API int32_t llama_kv_self_n_tokens(const struct llama_context * ctx); + + DEPRECATED(LLAMA_API int32_t llama_get_kv_cache_token_count(const struct llama_context * ctx), + "use llama_kv_self_n_tokens instead"); // Returns the number of used KV cells (i.e. have at least one sequence assigned to them) - LLAMA_API int32_t llama_get_kv_cache_used_cells(const struct llama_context * ctx); + LLAMA_API int32_t llama_kv_self_used_cells(const struct llama_context * ctx); + + DEPRECATED(LLAMA_API int32_t llama_get_kv_cache_used_cells(const struct llama_context * ctx), + "use llama_kv_self_used_cells instead"); // Clear the KV cache - both cell info is erased and KV data is zeroed - LLAMA_API void llama_kv_cache_clear( + LLAMA_API void llama_kv_self_clear( struct llama_context * ctx); // Removes all tokens that belong to the specified sequence and have positions in [p0, p1) @@ -655,7 +663,7 @@ extern "C" { // seq_id < 0 : match any sequence // p0 < 0 : [0, p1] // p1 < 0 : [p0, inf) - LLAMA_API bool llama_kv_cache_seq_rm( + LLAMA_API bool llama_kv_self_seq_rm( struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, @@ -665,7 +673,7 @@ extern "C" { // Note that this does not allocate extra KV cache memory - it simply assigns the tokens to the new sequence // p0 < 0 : [0, p1] // p1 < 0 : [p0, inf) - LLAMA_API void llama_kv_cache_seq_cp( + LLAMA_API void llama_kv_self_seq_cp( struct llama_context * ctx, llama_seq_id seq_id_src, llama_seq_id seq_id_dst, @@ -673,17 +681,17 @@ extern "C" { llama_pos p1); // Removes all tokens that do not belong to the specified sequence - LLAMA_API void llama_kv_cache_seq_keep( + LLAMA_API void llama_kv_self_seq_keep( struct llama_context * ctx, llama_seq_id seq_id); // Adds relative position "delta" to all tokens that belong to the specified sequence and have positions in [p0, p1) // If the KV cache is RoPEd, the KV data is updated accordingly: // - lazily on next llama_decode() - // - explicitly with llama_kv_cache_update() + // - explicitly with llama_kv_self_update() // p0 < 0 : [0, p1] // p1 < 0 : [p0, inf) - LLAMA_API void llama_kv_cache_seq_add( + LLAMA_API void llama_kv_self_seq_add( struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, @@ -693,10 +701,10 @@ extern "C" { // Integer division of the positions by factor of `d > 1` // If the KV cache is RoPEd, the KV data is updated accordingly: // - lazily on next llama_decode() - // - explicitly with llama_kv_cache_update() + // - explicitly with llama_kv_self_update() // p0 < 0 : [0, p1] // p1 < 0 : [p0, inf) - LLAMA_API void llama_kv_cache_seq_div( + LLAMA_API void llama_kv_self_seq_div( struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, @@ -704,24 +712,76 @@ extern "C" { int d); // Returns the largest position present in the KV cache for the specified sequence - LLAMA_API llama_pos llama_kv_cache_seq_pos_max( + LLAMA_API llama_pos llama_kv_self_seq_pos_max( struct llama_context * ctx, - llama_seq_id seq_id); - - // TODO: the llama_kv_cache_defrag and llama_kv_cache_update API tightly couples llama_context with llama_kv_cache - // how to avoid this? + llama_seq_id seq_id); // Defragment the KV cache // This will be applied: // - lazily on next llama_decode() - // - explicitly with llama_kv_cache_update() - LLAMA_API void llama_kv_cache_defrag(struct llama_context * ctx); - - // Apply the KV cache updates (such as K-shifts, defragmentation, etc.) - LLAMA_API void llama_kv_cache_update(struct llama_context * ctx); + // - explicitly with llama_kv_self_update() + LLAMA_API void llama_kv_self_defrag(struct llama_context * ctx); // Check if the context supports KV cache shifting - LLAMA_API bool llama_kv_cache_can_shift(struct llama_context * ctx); + LLAMA_API bool llama_kv_self_can_shift(const struct llama_context * ctx); + + // Apply the KV cache updates (such as K-shifts, defragmentation, etc.) + LLAMA_API void llama_kv_self_update(struct llama_context * ctx); + + DEPRECATED(LLAMA_API void llama_kv_cache_clear( + struct llama_context * ctx), + "use llama_kv_self_clear instead"); + + DEPRECATED(LLAMA_API bool llama_kv_cache_seq_rm( + struct llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1), + "use llama_kv_self_seq_rm instead"); + + DEPRECATED(LLAMA_API void llama_kv_cache_seq_cp( + struct llama_context * ctx, + llama_seq_id seq_id_src, + llama_seq_id seq_id_dst, + llama_pos p0, + llama_pos p1), + "use llama_kv_self_seq_cp instead"); + + DEPRECATED(LLAMA_API void llama_kv_cache_seq_keep( + struct llama_context * ctx, + llama_seq_id seq_id), + "use llama_kv_self_seq_keep instead"); + + DEPRECATED(LLAMA_API void llama_kv_cache_seq_add( + struct llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + llama_pos delta), + "use llama_kv_self_seq_add instead"); + + DEPRECATED(LLAMA_API void llama_kv_cache_seq_div( + struct llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + int d), + "use llama_kv_self_seq_div instead"); + + DEPRECATED(LLAMA_API llama_pos llama_kv_cache_seq_pos_max( + struct llama_context * ctx, + llama_seq_id seq_id), + "use llama_kv_self_seq_pos_max instead"); + + DEPRECATED(LLAMA_API void llama_kv_cache_defrag(struct llama_context * ctx), + "use llama_kv_self_defrag instead"); + + DEPRECATED(LLAMA_API bool llama_kv_cache_can_shift(const struct llama_context * ctx), + "use llama_kv_self_can_shift instead"); + + DEPRECATED(LLAMA_API void llama_kv_cache_update(struct llama_context * ctx), + "use llama_kv_self_update instead"); + // // State / sessions diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e1b02e4c0..b340dae5b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,18 +15,21 @@ add_library(llama llama-chat.cpp llama-context.cpp llama-grammar.cpp + llama-graph.cpp llama-hparams.cpp llama-impl.cpp + llama-io.cpp llama-kv-cache.cpp + llama-memory.cpp llama-mmap.cpp llama-model-loader.cpp llama-model.cpp llama-quant.cpp llama-sampling.cpp llama-vocab.cpp - unicode.h - unicode.cpp unicode-data.cpp + unicode.cpp + unicode.h ) target_include_directories(llama PUBLIC . ../include ../common) diff --git a/src/llama-adapter.cpp b/src/llama-adapter.cpp index 8a0800463..b448614e4 100644 --- a/src/llama-adapter.cpp +++ b/src/llama-adapter.cpp @@ -4,14 +4,13 @@ #include "llama-mmap.h" #include "llama-model.h" -#include #include #include #include // vec -struct ggml_tensor * llama_adapter_cvec::tensor_for(int il) const { +ggml_tensor * llama_adapter_cvec::tensor_for(int il) const { if (il < 0 || il < layer_start || il > layer_end || (size_t) il >= tensors.size()) { return nullptr; } @@ -19,7 +18,7 @@ struct ggml_tensor * llama_adapter_cvec::tensor_for(int il) const { return tensors[il]; } -struct ggml_tensor * llama_adapter_cvec::apply_to(struct ggml_context * ctx, struct ggml_tensor * cur, int il) const { +ggml_tensor * llama_adapter_cvec::apply_to(ggml_context * ctx, ggml_tensor * cur, int il) const { ggml_tensor * layer_dir = tensor_for(il); if (layer_dir != nullptr) { cur = ggml_add(ctx, cur, layer_dir); @@ -40,7 +39,7 @@ bool llama_adapter_cvec::init(const llama_model & model) { auto ctx_for_buft = [&](ggml_backend_buffer_type_t buft) -> ggml_context * { auto it = ctx_map.find(buft); if (it == ctx_map.end()) { - struct ggml_init_params params = { + ggml_init_params params = { /*.mem_size =*/ hparams.n_layer*ggml_tensor_overhead(), /*.mem_buffer =*/ NULL, /*.no_alloc =*/ true, @@ -91,7 +90,7 @@ bool llama_adapter_cvec::init(const llama_model & model) { return true; } -int32_t llama_adapter_cvec::apply( +bool llama_adapter_cvec::apply( const llama_model & model, const float * data, size_t len, @@ -104,17 +103,17 @@ int32_t llama_adapter_cvec::apply( // disable the current control vector (but leave allocated for later) layer_start = -1; layer_end = -1; - return 0; + return true; } if (n_embd != (int) hparams.n_embd) { LLAMA_LOG_ERROR("%s: control vector n_embd does not match model\n", __func__); - return 1; + return false; } if (tensors.empty()) { if (!init(model)) { - return 1; + return false; } } @@ -130,12 +129,12 @@ int32_t llama_adapter_cvec::apply( } } - return 0; + return true; } // lora -llama_adapter_lora_weight * llama_adapter_lora::get_weight(struct ggml_tensor * w) { +llama_adapter_lora_weight * llama_adapter_lora::get_weight(ggml_tensor * w) { const std::string name(w->name); const auto pos = ab_map.find(name); @@ -146,11 +145,11 @@ llama_adapter_lora_weight * llama_adapter_lora::get_weight(struct ggml_tensor * return nullptr; } -static void llama_adapter_lora_init_impl(struct llama_model & model, const char * path_lora, struct llama_adapter_lora & adapter) { +static void llama_adapter_lora_init_impl(llama_model & model, const char * path_lora, llama_adapter_lora & adapter) { LLAMA_LOG_INFO("%s: loading lora adapter from '%s' ...\n", __func__, path_lora); ggml_context * ctx_init; - struct gguf_init_params meta_gguf_params = { + gguf_init_params meta_gguf_params = { /* .no_alloc = */ true, /* .ctx = */ &ctx_init, }; @@ -201,7 +200,7 @@ static void llama_adapter_lora_init_impl(struct llama_model & model, const char auto it = ctx_map.find(buft); if (it == ctx_map.end()) { // add a new context - struct ggml_init_params params = { + ggml_init_params params = { /*.mem_size =*/ n_tensors*ggml_tensor_overhead(), /*.mem_buffer =*/ NULL, /*.no_alloc =*/ true, @@ -264,7 +263,7 @@ static void llama_adapter_lora_init_impl(struct llama_model & model, const char throw std::runtime_error("LoRA tensor '" + name + "' does not exist in base model (hint: maybe wrong base model?)"); } - struct ggml_context * dev_ctx = ctx_for_buft(ggml_backend_buffer_get_type(model_tensor->buffer)); + ggml_context * dev_ctx = ctx_for_buft(ggml_backend_buffer_get_type(model_tensor->buffer)); // validate tensor shape if (is_token_embd) { // expect B to be non-transposed, A and B are flipped; see llm_build_inp_embd() @@ -281,8 +280,8 @@ static void llama_adapter_lora_init_impl(struct llama_model & model, const char } // save tensor to adapter - struct ggml_tensor * tensor_a = ggml_dup_tensor(dev_ctx, w.a); - struct ggml_tensor * tensor_b = ggml_dup_tensor(dev_ctx, w.b); + ggml_tensor * tensor_a = ggml_dup_tensor(dev_ctx, w.a); + ggml_tensor * tensor_b = ggml_dup_tensor(dev_ctx, w.b); ggml_set_name(tensor_a, w.a->name); ggml_set_name(tensor_b, w.b->name); adapter.ab_map[name] = llama_adapter_lora_weight(tensor_a, tensor_b); @@ -308,7 +307,7 @@ static void llama_adapter_lora_init_impl(struct llama_model & model, const char { llama_file gguf_file(path_lora, "rb"); std::vector read_buf; - auto set_tensor = [&](struct ggml_tensor * orig, struct ggml_tensor * dev) { + auto set_tensor = [&](ggml_tensor * orig, ggml_tensor * dev) { size_t offs = gguf_get_data_offset(ctx_gguf.get()) + gguf_get_tensor_offset(ctx_gguf.get(), gguf_find_tensor(ctx_gguf.get(), orig->name)); size_t size = ggml_nbytes(orig); read_buf.resize(size); @@ -327,8 +326,8 @@ static void llama_adapter_lora_init_impl(struct llama_model & model, const char LLAMA_LOG_INFO("%s: loaded %zu tensors from lora file\n", __func__, adapter.ab_map.size()*2); } -struct llama_adapter_lora * llama_adapter_lora_init(struct llama_model * model, const char * path_lora) { - struct llama_adapter_lora * adapter = new llama_adapter_lora(); +llama_adapter_lora * llama_adapter_lora_init(llama_model * model, const char * path_lora) { + llama_adapter_lora * adapter = new llama_adapter_lora(); try { llama_adapter_lora_init_impl(*model, path_lora, *adapter); @@ -342,6 +341,6 @@ struct llama_adapter_lora * llama_adapter_lora_init(struct llama_model * model, return nullptr; } -void llama_adapter_lora_free(struct llama_adapter_lora * adapter) { +void llama_adapter_lora_free(llama_adapter_lora * adapter) { delete adapter; } diff --git a/src/llama-adapter.h b/src/llama-adapter.h index 603fa08f6..65824e972 100644 --- a/src/llama-adapter.h +++ b/src/llama-adapter.h @@ -15,11 +15,11 @@ // struct llama_adapter_cvec { - struct ggml_tensor * tensor_for(int il) const; + ggml_tensor * tensor_for(int il) const; - struct ggml_tensor * apply_to(struct ggml_context * ctx, struct ggml_tensor * cur, int il) const; + ggml_tensor * apply_to(ggml_context * ctx, ggml_tensor * cur, int il) const; - int32_t apply( + bool apply( const llama_model & model, const float * data, size_t len, @@ -36,7 +36,7 @@ private: std::vector ctxs; std::vector bufs; - std::vector tensors; // per layer + std::vector tensors; // per layer }; // @@ -44,8 +44,8 @@ private: // struct llama_adapter_lora_weight { - struct ggml_tensor * a = nullptr; - struct ggml_tensor * b = nullptr; + ggml_tensor * a = nullptr; + ggml_tensor * b = nullptr; // get actual scale based on rank and alpha float get_scale(float alpha, float adapter_scale) const { @@ -55,12 +55,12 @@ struct llama_adapter_lora_weight { } llama_adapter_lora_weight() = default; - llama_adapter_lora_weight(struct ggml_tensor * a, struct ggml_tensor * b) : a(a), b(b) {} + llama_adapter_lora_weight(ggml_tensor * a, ggml_tensor * b) : a(a), b(b) {} }; struct llama_adapter_lora { // map tensor name to lora_a_b - std::unordered_map ab_map; + std::unordered_map ab_map; std::vector ctxs; std::vector bufs; @@ -70,5 +70,7 @@ struct llama_adapter_lora { llama_adapter_lora() = default; ~llama_adapter_lora() = default; - llama_adapter_lora_weight * get_weight(struct ggml_tensor * w); + llama_adapter_lora_weight * get_weight(ggml_tensor * w); }; + +using llama_adapter_loras = std::unordered_map; diff --git a/src/llama-batch.h b/src/llama-batch.h index 773c3808b..f1df40d27 100644 --- a/src/llama-batch.h +++ b/src/llama-batch.h @@ -42,9 +42,9 @@ struct llama_sbatch { bool logits_all; // TODO: remove once lctx.logits_all is removed too // sorted indices into the batch - std::vector ids; + std::vector ids; // batch indices of the output - std::vector out_ids; + std::vector out_ids; std::vector seq; const llama_batch * batch = nullptr; diff --git a/src/llama-context.cpp b/src/llama-context.cpp index 671d2a81a..0a43a3af8 100644 --- a/src/llama-context.cpp +++ b/src/llama-context.cpp @@ -1,551 +1,1555 @@ #include "llama-context.h" #include "llama-impl.h" +#include "llama-io.h" #include "llama-mmap.h" +#include "llama-model.h" +#include "llama-kv-cache.h" #include -#include #include #include +#include -void llama_set_k_shift(struct llama_context & lctx) { - const int64_t kv_size = lctx.kv_self.size; +// +// llama_context +// - assert(ggml_backend_buffer_is_host(lctx.inp_K_shift->buffer)); +llama_context::llama_context( + const llama_model & model, + llama_context_params params) : + model(model) { + LLAMA_LOG_INFO("%s: constructing llama_context\n", __func__); - int32_t * data = (int32_t *) lctx.inp_K_shift->data; + t_start_us = model.t_start_us; + t_load_us = model.t_load_us; - for (int i = 0; i < kv_size; ++i) { - data[i] = lctx.kv_self.cells[i].delta; - } -} + const auto & hparams = model.hparams; -void llama_set_s_copy(struct llama_context & lctx) { - const int64_t kv_size = lctx.kv_self.size; + cparams.n_seq_max = std::max(1u, params.n_seq_max); + cparams.n_threads = params.n_threads; + cparams.n_threads_batch = params.n_threads_batch; + cparams.yarn_ext_factor = params.yarn_ext_factor; + cparams.yarn_attn_factor = params.yarn_attn_factor; + cparams.yarn_beta_fast = params.yarn_beta_fast; + cparams.yarn_beta_slow = params.yarn_beta_slow; + cparams.defrag_thold = params.defrag_thold; + cparams.embeddings = params.embeddings; + cparams.offload_kqv = params.offload_kqv; + cparams.flash_attn = params.flash_attn; + cparams.no_perf = params.no_perf; + cparams.pooling_type = params.pooling_type; - assert(ggml_backend_buffer_is_host(lctx.inp_s_copy->buffer)); + cparams.n_ctx = params.n_ctx == 0 ? hparams.n_ctx_train : params.n_ctx; + cparams.rope_freq_base = params.rope_freq_base == 0.0f ? hparams.rope_freq_base_train : params.rope_freq_base; + cparams.rope_freq_scale = params.rope_freq_scale == 0.0f ? hparams.rope_freq_scale_train : params.rope_freq_scale; - int32_t * data = (int32_t *) lctx.inp_s_copy->data; + cparams.n_ctx_orig_yarn = params.yarn_orig_ctx != 0 ? params.yarn_orig_ctx : + hparams.n_ctx_orig_yarn != 0 ? hparams.n_ctx_orig_yarn : + hparams.n_ctx_train; - for (int i = 0; i < kv_size; ++i) { - data[i] = lctx.kv_self.cells[i].src; - } -} + cparams.cb_eval = params.cb_eval; + cparams.cb_eval_user_data = params.cb_eval_user_data; -// llama input - -static int32_t llama_relative_position_bucket(llama_pos x, llama_pos y, uint64_t n_buckets, bool bidirectional) { - // TODO move to hparams if a T5 variant appears that uses a different value - const int64_t max_distance = 128; - - if (bidirectional) { - n_buckets >>= 1; + auto rope_scaling_type = params.rope_scaling_type; + if (rope_scaling_type == LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED) { + rope_scaling_type = hparams.rope_scaling_type_train; } - const int64_t max_exact = n_buckets >> 1; + if (rope_scaling_type == LLAMA_ROPE_SCALING_TYPE_NONE) { + cparams.rope_freq_scale = 1.0f; // never scale if scaling type is none + } - int32_t relative_position = x - y; - int32_t relative_bucket = 0; - if (bidirectional) { - relative_bucket += (relative_position > 0) * n_buckets; - relative_position = abs(relative_position); + if (cparams.yarn_ext_factor < 0.0f) { // negative indicates 'not set' + cparams.yarn_ext_factor = rope_scaling_type == LLAMA_ROPE_SCALING_TYPE_YARN ? 1.0f : 0.0f; + } + + cparams.yarn_attn_factor *= hparams.rope_attn_factor; + + if (cparams.pooling_type == LLAMA_POOLING_TYPE_UNSPECIFIED) { + if (hparams.pooling_type == LLAMA_POOLING_TYPE_UNSPECIFIED) { + cparams.pooling_type = LLAMA_POOLING_TYPE_NONE; + } else { + cparams.pooling_type = hparams.pooling_type; + } + } + + if (params.attention_type == LLAMA_ATTENTION_TYPE_UNSPECIFIED) { + cparams.causal_attn = hparams.causal_attn; } else { - relative_position = -std::min(relative_position, 0); + cparams.causal_attn = params.attention_type == LLAMA_ATTENTION_TYPE_CAUSAL; + } + + // with causal attention, the batch size is limited by the context size + cparams.n_batch = cparams.causal_attn ? std::min(cparams.n_ctx, params.n_batch) : params.n_batch; + + // the batch has to be at least GGML_KQ_MASK_PAD because we will be padding the KQ_mask + // this is required by GPU kernels in order to avoid out-of-bounds accesses (e.g. ggml_flash_attn_ext) + // ref: https://github.com/ggerganov/llama.cpp/pull/5021 + // TODO: this padding is not needed for the cache-less context so we should probably move it to llama_context_kv_self + if (cparams.n_batch < GGML_KQ_MASK_PAD) { + LLAMA_LOG_WARN("%s: n_batch is less than GGML_KQ_MASK_PAD - increasing to %d\n", __func__, GGML_KQ_MASK_PAD); + cparams.n_batch = GGML_KQ_MASK_PAD; + } + + cparams.n_ubatch = std::min(cparams.n_batch, params.n_ubatch == 0 ? params.n_batch : params.n_ubatch); + + const uint32_t n_ctx_per_seq = cparams.n_ctx / cparams.n_seq_max; + + LLAMA_LOG_INFO("%s: n_seq_max = %u\n", __func__, cparams.n_seq_max); + LLAMA_LOG_INFO("%s: n_ctx = %u\n", __func__, cparams.n_ctx); + LLAMA_LOG_INFO("%s: n_ctx_per_seq = %u\n", __func__, n_ctx_per_seq); + LLAMA_LOG_INFO("%s: n_batch = %u\n", __func__, cparams.n_batch); + LLAMA_LOG_INFO("%s: n_ubatch = %u\n", __func__, cparams.n_ubatch); + LLAMA_LOG_INFO("%s: causal_attn = %d\n", __func__, cparams.causal_attn); + LLAMA_LOG_INFO("%s: flash_attn = %d\n", __func__, cparams.flash_attn); + LLAMA_LOG_INFO("%s: freq_base = %.1f\n", __func__, cparams.rope_freq_base); + LLAMA_LOG_INFO("%s: freq_scale = %g\n", __func__, cparams.rope_freq_scale); + + if (n_ctx_per_seq < hparams.n_ctx_train) { + LLAMA_LOG_WARN("%s: n_ctx_per_seq (%u) < n_ctx_train (%u) -- the full capacity of the model will not be utilized\n", + __func__, n_ctx_per_seq, hparams.n_ctx_train); + } + + if (n_ctx_per_seq > hparams.n_ctx_train) { + LLAMA_LOG_WARN("%s: n_ctx_pre_seq (%u) > n_ctx_train (%u) -- possible training context overflow\n", + __func__, n_ctx_per_seq, hparams.n_ctx_train); + } + + logits_all = params.logits_all; + + if (!hparams.vocab_only) { + // GPU backends + for (auto * dev : model.devices) { + ggml_backend_t backend = ggml_backend_dev_init(dev, nullptr); + if (backend == nullptr) { + throw std::runtime_error(format("failed to initialize %s backend", ggml_backend_dev_name(dev))); + } + backends.emplace_back(backend); + } + + // add ACCEL backends (such as BLAS) + for (size_t i = 0; i < ggml_backend_dev_count(); ++i) { + ggml_backend_dev_t dev = ggml_backend_dev_get(i); + if (ggml_backend_dev_type(dev) == GGML_BACKEND_DEVICE_TYPE_ACCEL) { + ggml_backend_t backend = ggml_backend_dev_init(dev, nullptr); + if (backend == nullptr) { + throw std::runtime_error(format("failed to initialize %s backend", ggml_backend_dev_name(dev))); + } + backends.emplace_back(backend); + } + } + + // add CPU backend + backend_cpu = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr); + if (backend_cpu == nullptr) { + throw std::runtime_error("failed to initialize CPU backend"); + } + backends.emplace_back(backend_cpu); + + // create a list of the set_n_threads functions in the backends + for (auto & backend : backends) { + ggml_backend_dev_t dev = ggml_backend_get_device(backend.get()); + ggml_backend_reg_t reg = dev ? ggml_backend_dev_backend_reg(dev) : nullptr; + if (reg) { + auto ggml_backend_set_n_threads_fn = (ggml_backend_set_n_threads_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_set_n_threads"); + if (ggml_backend_set_n_threads_fn) { + set_n_threads_fns.emplace_back(backend.get(), ggml_backend_set_n_threads_fn); + } + } + } + + llama_set_abort_callback(this, params.abort_callback, params.abort_callback_data); + + // graph outputs buffer + { + // resized during inference when a batch uses more outputs + if ((uint32_t) output_reserve(params.n_seq_max) < params.n_seq_max) { + throw std::runtime_error("failed to reserve initial output buffer"); + } + + LLAMA_LOG_INFO("%s: %10s output buffer size = %8.2f MiB\n", __func__, + ggml_backend_buffer_name (buf_output.get()), + ggml_backend_buffer_get_size(buf_output.get()) / 1024.0 / 1024.0); + } + } + + // init the memory module + // TODO: for now, always create a unified KV cache + if (!hparams.vocab_only) { + kv_self.reset(static_cast(model.create_memory())); + + LLAMA_LOG_DEBUG("%s: n_ctx = %u\n", __func__, cparams.n_ctx); + + cparams.n_ctx = GGML_PAD(cparams.n_ctx, kv_self->get_padding(cparams)); + + LLAMA_LOG_DEBUG("%s: n_ctx = %u (padded)\n", __func__, cparams.n_ctx); + + uint32_t kv_size = cparams.n_ctx; + ggml_type type_k = params.type_k; + ggml_type type_v = params.type_v; + + if (llama_model_is_recurrent(&model)) { + // Mamba needs at least as many KV cells as there are sequences kept at any time + kv_size = std::max((uint32_t) 1, params.n_seq_max); + // it's probably best to keep as much precision as possible for the states + type_k = GGML_TYPE_F32; // required by ggml_ssm_conv for Mamba's conv_states + type_v = GGML_TYPE_F32; // required by ggml_ssm_scan for Mamba's ssm_states + } + + GGML_ASSERT(hparams.n_embd_head_k % ggml_blck_size(type_k) == 0); + GGML_ASSERT(hparams.n_embd_head_v % ggml_blck_size(type_v) == 0); + + if (!kv_self->init(model, cparams, type_k, type_v, kv_size, cparams.offload_kqv)) { + throw std::runtime_error("failed to initialize self-attention cache"); + } + + { + const size_t memory_size_k = kv_self->size_k_bytes(); + const size_t memory_size_v = kv_self->size_v_bytes(); + + LLAMA_LOG_INFO("%s: KV self size = %7.2f MiB, K (%s): %7.2f MiB, V (%s): %7.2f MiB\n", __func__, + (float)(memory_size_k + memory_size_v) / (1024.0f * 1024.0f), + ggml_type_name(type_k), (float)memory_size_k / (1024.0f * 1024.0f), + ggml_type_name(type_v), (float)memory_size_v / (1024.0f * 1024.0f)); + } + } + + // init backends + if (!hparams.vocab_only) { + LLAMA_LOG_DEBUG("%s: enumerating backends\n", __func__); + + backend_buft.clear(); + backend_ptrs.clear(); + + for (auto & backend : backends) { + auto * buft = ggml_backend_get_default_buffer_type(backend.get()); + auto backend_type = ggml_backend_dev_type(ggml_backend_get_device(backend.get())); + + if (backend_type == GGML_BACKEND_DEVICE_TYPE_CPU && !model.devices.empty()) { + // use the host buffer of the first device CPU for faster transfer of the intermediate state + auto * dev = model.devices[0]; + auto * host_buft = ggml_backend_dev_host_buffer_type(dev); + if (host_buft) { + buft = host_buft; + } + } + + backend_buft.push_back(buft); + backend_ptrs.push_back(backend.get()); + } + + LLAMA_LOG_DEBUG("%s: backend_ptrs.size() = %zu\n", __func__, backend_ptrs.size()); + + const size_t max_nodes = this->graph_max_nodes(); + + LLAMA_LOG_DEBUG("%s: max_nodes = %zu\n", __func__, max_nodes); + + // buffer used to store the computation graph and the tensor meta data + buf_compute_meta.resize(ggml_tensor_overhead()*max_nodes + ggml_graph_overhead_custom(max_nodes, false)); + + // TODO: move these checks to ggml_backend_sched + // enabling pipeline parallelism in the scheduler increases memory usage, so it is only done when necessary + bool pipeline_parallel = + model.n_devices() > 1 && + model.params.n_gpu_layers > (int) model.hparams.n_layer && + model.params.split_mode == LLAMA_SPLIT_MODE_LAYER && + cparams.offload_kqv; + + // pipeline parallelism requires support for async compute and events in all devices + if (pipeline_parallel) { + for (auto & backend : backends) { + auto dev_type = ggml_backend_dev_type(ggml_backend_get_device(backend.get())); + if (dev_type == GGML_BACKEND_DEVICE_TYPE_CPU) { + // ignore CPU backend + continue; + } + auto * dev = ggml_backend_get_device(backend.get()); + ggml_backend_dev_props props; + ggml_backend_dev_get_props(dev, &props); + if (!props.caps.async || !props.caps.events) { + // device does not support async compute or events + pipeline_parallel = false; + break; + } + } + } + + sched.reset(ggml_backend_sched_new(backend_ptrs.data(), backend_buft.data(), backend_ptrs.size(), max_nodes, pipeline_parallel)); + + if (pipeline_parallel) { + LLAMA_LOG_INFO("%s: pipeline parallelism enabled (n_copies=%d)\n", __func__, ggml_backend_sched_get_n_copies(sched.get())); + } + } + + // reserve worst-case graph + if (!hparams.vocab_only) { + uint32_t n_seqs = 1; // TODO: worst-case number of sequences + uint32_t n_tokens = std::min(cparams.n_ctx, cparams.n_ubatch); + + llama_token token = model.vocab.token_bos(); // not actually used by llama_build_graph, but required to choose between token and embedding inputs graph + + // max number of outputs + n_outputs = n_tokens; + + LLAMA_LOG_DEBUG("%s: n_tokens = %d, n_seqs = %d, n_outputs = %d\n", __func__, n_tokens, n_seqs, n_outputs); + + int n_splits_pp = -1; + int n_nodes_pp = -1; + + int n_splits_tg = -1; + int n_nodes_tg = -1; + + // simulate full KV cache + kv_self->n = kv_self->size; + + cross.v_embd.clear(); + + // reserve pp graph first so that buffers are only allocated once + { + llama_ubatch ubatch_pp = { true, n_tokens, n_tokens / n_seqs, n_seqs, &token, nullptr, nullptr, nullptr, nullptr, nullptr}; + auto * gf = graph_init(); + graph_build(ctx_compute.get(), gf, ubatch_pp, LLM_GRAPH_TYPE_DEFAULT); + if (!ggml_backend_sched_reserve(sched.get(), gf)) { + throw std::runtime_error("failed to allocate compute pp buffers"); + } + + n_splits_pp = ggml_backend_sched_get_n_splits(sched.get()); + n_nodes_pp = ggml_graph_n_nodes(gf); + } + + // reserve with tg graph to get the number of splits and nodes + { + llama_ubatch ubatch_tg = { true, 1, 1, n_seqs, &token, nullptr, nullptr, nullptr, nullptr, nullptr}; + auto * gf = graph_init(); + graph_build(ctx_compute.get(), gf, ubatch_tg, LLM_GRAPH_TYPE_DEFAULT); + if (!ggml_backend_sched_reserve(sched.get(), gf)) { + throw std::runtime_error("failed to allocate compute tg buffers"); + } + n_splits_tg = ggml_backend_sched_get_n_splits(sched.get()); + n_nodes_tg = ggml_graph_n_nodes(gf); + } + + // reserve again with pp graph to avoid ggml-alloc reallocations during inference + { + llama_ubatch ubatch_pp = { true, n_tokens, n_tokens / n_seqs, n_seqs, &token, nullptr, nullptr, nullptr, nullptr, nullptr}; + auto * gf = graph_init(); + graph_build(ctx_compute.get(), gf, ubatch_pp, LLM_GRAPH_TYPE_DEFAULT); + if (!ggml_backend_sched_reserve(sched.get(), gf)) { + throw std::runtime_error("failed to allocate compute pp buffers"); + } + } + + for (size_t i = 0; i < backend_ptrs.size(); ++i) { + ggml_backend_t backend = backend_ptrs[i]; + ggml_backend_buffer_type_t buft = backend_buft[i]; + size_t size = ggml_backend_sched_get_buffer_size(sched.get(), backend); + if (size > 1) { + LLAMA_LOG_INFO("%s: %10s compute buffer size = %8.2f MiB\n", __func__, + ggml_backend_buft_name(buft), + size / 1024.0 / 1024.0); + } + } + + if (n_nodes_pp == n_nodes_tg) { + LLAMA_LOG_INFO("%s: graph nodes = %d\n", __func__, n_nodes_pp); + } else { + LLAMA_LOG_INFO("%s: graph nodes = %d (with bs=%d), %d (with bs=1)\n", __func__, n_nodes_pp, n_tokens, n_nodes_tg); + } + + if (n_splits_pp == n_splits_tg) { + LLAMA_LOG_INFO("%s: graph splits = %d\n", __func__, n_splits_pp); + } else { + LLAMA_LOG_INFO("%s: graph splits = %d (with bs=%d), %d (with bs=1)\n", __func__, n_splits_pp, n_tokens, n_splits_tg); + } } - int32_t relative_position_if_large = floorf(max_exact + logf(1.0 * relative_position / max_exact) * (n_buckets - max_exact) / log(1.0 * max_distance / max_exact)); - relative_position_if_large = std::min(relative_position_if_large, n_buckets - 1); - relative_bucket += (relative_position < max_exact ? relative_position : relative_position_if_large); - return relative_bucket; } -void llama_set_inputs(llama_context & lctx, const llama_ubatch & ubatch) { +llama_context::~llama_context() = default; + +void llama_context::synchronize() { + ggml_backend_sched_synchronize(sched.get()); + + // FIXME: if multiple single tokens are evaluated without a synchronization, + // the stats will be added to the prompt evaluation stats + // this should only happen when using batch size 1 to evaluate a batch + + // add the evaluation to the stats + if (n_queued_tokens == 1) { + if (!cparams.no_perf) { + t_eval_us += ggml_time_us() - t_compute_start_us; + } + n_eval++; + } else if (n_queued_tokens > 1) { + if (!cparams.no_perf) { + t_p_eval_us += ggml_time_us() - t_compute_start_us; + } + n_p_eval += n_queued_tokens; + } + + // get a more accurate load time, upon first eval + if (n_queued_tokens > 0 && !has_evaluated_once) { + t_load_us = ggml_time_us() - t_start_us; + has_evaluated_once = true; + } + + n_queued_tokens = 0; + t_compute_start_us = 0; +} + +const llama_model & llama_context::get_model() const { + return model; +} + +uint32_t llama_context::n_ctx() const { + return cparams.n_ctx; +} + +uint32_t llama_context::n_ctx_per_seq() const { + return cparams.n_ctx / cparams.n_seq_max; +} + +uint32_t llama_context::n_batch() const { + return cparams.n_batch; +} + +uint32_t llama_context::n_ubatch() const { + return cparams.n_ubatch; +} + +uint32_t llama_context::n_seq_max() const { + return cparams.n_seq_max; +} + +uint32_t llama_context::n_threads() const { + return cparams.n_threads; +} + +uint32_t llama_context::n_threads_batch() const { + return cparams.n_threads_batch; +} + +llama_kv_cache * llama_context::get_kv_self() { + return kv_self.get(); +} + +const llama_kv_cache * llama_context::get_kv_self() const { + return kv_self.get(); +} + +ggml_tensor * llama_context::build_rope_shift( + ggml_context * ctx0, + ggml_tensor * cur, + ggml_tensor * shift, + ggml_tensor * factors, + ggml_backend_buffer * bbuf) const { + const auto & n_ctx_orig = cparams.n_ctx_orig_yarn; + const auto & freq_base = cparams.rope_freq_base; + const auto & freq_scale = cparams.rope_freq_scale; + + const auto & yarn_ext_factor = cparams.yarn_ext_factor; + const auto & yarn_attn_factor = cparams.yarn_attn_factor; + const auto & yarn_beta_fast = cparams.yarn_beta_fast; + const auto & yarn_beta_slow = cparams.yarn_beta_slow; + + const auto & hparams = model.hparams; + + const auto & n_rot = hparams.n_rot; + const auto & rope_type = hparams.rope_type; + + ggml_tensor * tmp; + + if (ggml_is_quantized(cur->type)) { + // dequantize to f32 -> RoPE -> quantize back + tmp = ggml_cast(ctx0, cur, GGML_TYPE_F32); + + if (bbuf) { + for (const auto & backend : backends) { + // Figure out which backend KV cache belongs to + if (ggml_backend_supports_buft(backend.get(), ggml_backend_buffer_get_type(bbuf))) { + ggml_backend_sched_set_tensor_backend(sched.get(), tmp, backend.get()); + break; + } + } + } + + tmp = ggml_rope_ext_inplace(ctx0, tmp, + shift, factors, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + yarn_ext_factor, yarn_attn_factor, yarn_beta_fast, yarn_beta_slow); + + tmp = ggml_cpy(ctx0, tmp, cur); + } else { + // we rotate only the first n_rot dimensions + tmp = ggml_rope_ext_inplace(ctx0, cur, + shift, factors, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + yarn_ext_factor, yarn_attn_factor, yarn_beta_fast, yarn_beta_slow); + } + + return tmp; +} + +class llm_graph_input_k_shift : public llm_graph_input_i { +public: + llm_graph_input_k_shift(const llama_kv_cache_unified * kv_self) : kv_self(kv_self) {} + virtual ~llm_graph_input_k_shift() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * k_shift; // I32 [kv_size] + + const llama_kv_cache_unified * kv_self; +}; + +void llm_graph_input_k_shift::set_input(const llama_ubatch * ubatch) { + GGML_UNUSED(ubatch); + + if (k_shift) { + assert(ggml_backend_buffer_is_host(k_shift->buffer)); + + int32_t * data = (int32_t *) k_shift->data; + + for (uint32_t i = 0; i < kv_self->size; ++i) { + data[i] = kv_self->cells[i].delta; + } + } +} + +llm_graph_result_ptr llama_context::build_kv_self_shift( + ggml_context * ctx0, + ggml_cgraph * gf) const { + auto res = std::make_unique(); + + const auto & hparams = model.hparams; + + const auto & n_layer = hparams.n_layer; + + const auto & n_embd_head_k = hparams.n_embd_head_k; + //const auto & n_embd_head_v = hparams.n_embd_head_v; + + //GGML_ASSERT(kv_self->size == n_ctx); + + auto inp = std::make_unique(kv_self.get()); + + inp->k_shift = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, cparams.n_ctx); + ggml_set_input(inp->k_shift); + + for (uint32_t il = 0; il < n_layer; ++il) { + const int64_t n_head_kv = hparams.n_head_kv(il); + const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); + + ggml_tensor * rope_factors = kv_self->cbs.get_rope_factors(n_ctx_per_seq(), il); + + ggml_tensor * k = + ggml_view_3d(ctx0, kv_self->k_l[il], + n_embd_head_k, n_head_kv, kv_self->size, + ggml_row_size(kv_self->k_l[il]->type, n_embd_head_k), + ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa), + 0); + + ggml_tensor * cur = build_rope_shift(ctx0, k, inp->k_shift, rope_factors, kv_self->k_l[il]->buffer); + + ggml_build_forward_expand(gf, cur); + } + + res->add_input(std::move(inp)); + + return res; +} + +llm_graph_result_ptr llama_context::build_kv_self_defrag( + ggml_context * ctx0, + ggml_cgraph * gf) const { + auto res = std::make_unique(); + + const auto & hparams = model.hparams; + + const auto & ids = kv_self->defrag_info.ids; + +#if 0 + // CPU defrag // - // set input data + // TODO: optimizations are possible: + // - multiple threads + // - avoid copying to the host memory when already there + // + // likely not worth the effort, as we have ggml_graph based defrag // - const auto & hparams = lctx.model.hparams; - const auto & cparams = lctx.cparams; - const auto & kv_self = lctx.kv_self; + const uint32_t n_embd_k_gqa = hparams.n_embd_k_gqa(); + const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(); - if (ubatch.token) { - const int64_t n_tokens = ubatch.n_tokens; + const uint32_t kv_size = size; - ggml_backend_tensor_set(lctx.inp_tokens, ubatch.token, 0, n_tokens*ggml_element_size(lctx.inp_tokens)); - } + std::vector buf_k; + std::vector buf_v; - if (ubatch.embd) { - const int64_t n_embd = hparams.n_embd; - const int64_t n_tokens = ubatch.n_tokens; + for (uint32_t il = 0; il < n_layer; ++il) { + const size_t k_size_row = ggml_row_size(k_l[il]->type, n_embd_k_gqa); + const size_t k_size = ggml_row_size(k_l[il]->type, n_embd_k_gqa*kv_size); - ggml_backend_tensor_set(lctx.inp_embd, ubatch.embd, 0, n_tokens*n_embd*ggml_element_size(lctx.inp_embd)); - } + const size_t v_size_el = ggml_type_size(v_l[il]->type); + const size_t v_size = ggml_row_size (v_l[il]->type, n_embd_v_gqa*kv_size); - if (ubatch.pos && lctx.inp_pos) { - const int64_t n_tokens = ubatch.n_tokens; - auto n_pos = lctx.n_pos_per_token; - ggml_backend_tensor_set(lctx.inp_pos, ubatch.pos, 0, n_tokens*n_pos*ggml_element_size(lctx.inp_pos)); - } + buf_k.resize(k_size); + buf_v.resize(v_size); - if (hparams.causal_attn || cparams.pooling_type == LLAMA_POOLING_TYPE_NONE) { - //GGML_ASSERT(lctx.inp_out_ids && "every model that can must skip unused outputs"); + ggml_backend_tensor_get(k_l[il], buf_k.data(), 0, buf_k.size()); + ggml_backend_tensor_get(v_l[il], buf_v.data(), 0, buf_v.size()); - if (!lctx.inp_out_ids) { - LLAMA_LOG_WARN("%s: 'lctx.inp_out_ids' is not created\n", __func__); - } else { - const int64_t n_tokens = ubatch.n_tokens; + // batch move [i, i+nm) to [id, id+nm) + // note: cells can move only to a lower index + for (uint32_t i = 0; i < n_kv; ++i) { + const uint32_t id = ids[i]; - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_out_ids->buffer)); - int32_t * data = (int32_t *) lctx.inp_out_ids->data; + if (i == id || id == n_kv) { + continue; + } - if (lctx.n_outputs == n_tokens) { - for (int i = 0; i < n_tokens; ++i) { - data[i] = i; + uint32_t nm = 1; + + while (i + nm < n_kv && ids[i + nm] == id + nm) { + nm++; + } + + // move keys + { + const int64_t os = i*k_size_row; + const int64_t od = id*k_size_row; + + memcpy(buf_k.data() + od, buf_k.data() + os, nm*k_size_row); + } + + // move values (note: they are transposed) + { + const int64_t os = i; + const int64_t od = id; + + for (uint32_t j = 0; j < n_embd_v_gqa; ++j) { + memcpy(buf_v.data() + (od + j*kv_size)*v_size_el, buf_v.data() + (os + j*kv_size)*v_size_el, nm*v_size_el); } - } else if (ubatch.output) { - int32_t n_outputs = 0; - for (int i = 0; i < n_tokens; ++i) { - if (ubatch.output[i]) { - data[n_outputs++] = i; - } - } - // the graph needs to have been passed the correct number of outputs - GGML_ASSERT(lctx.n_outputs == n_outputs); - } else if (lctx.n_outputs == 1) { - // only keep last output - data[0] = n_tokens - 1; + } + + i += nm - 1; + } + + ggml_backend_tensor_set(k_l[il], buf_k.data(), 0, buf_k.size()); + ggml_backend_tensor_set(v_l[il], buf_v.data(), 0, buf_v.size()); + } +#else + for (uint32_t i = 0; i < ids.size(); ++i) { + const uint32_t id = ids[i]; + + if (i == id || id == ids.size()) { + continue; + } + + uint32_t nm = 1; + + while (i + nm < ids.size() && ids[i + nm] == id + nm) { + nm++; + } + + for (uint32_t il = 0; il < hparams.n_layer; ++il) { // NOLINT + const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); + const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il); + + ggml_tensor * view_k_src = ggml_view_2d(ctx0, kv_self->k_l[il], + n_embd_k_gqa, nm, + ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa), + ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa*i)); + + ggml_tensor * view_k_dst = ggml_view_2d(ctx0, kv_self->k_l[il], + n_embd_k_gqa, nm, + ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa), + ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa*id)); + + ggml_tensor * view_v_src; + ggml_tensor * view_v_dst; + + if (cparams.flash_attn) { + // NOTE: the V cache is not transposed when using flash attention + view_v_src = ggml_view_2d(ctx0, kv_self->v_l[il], + n_embd_v_gqa, nm, + ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa), + ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa*i)); + + view_v_dst = ggml_view_2d(ctx0, kv_self->v_l[il], + n_embd_v_gqa, nm, + ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa), + ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa*id)); } else { - GGML_ASSERT(lctx.n_outputs == 0); + view_v_src = ggml_view_2d(ctx0, kv_self->v_l[il], + nm, n_embd_v_gqa, + ggml_row_size(kv_self->v_l[il]->type, kv_self->size), + ggml_row_size(kv_self->v_l[il]->type, i)); + + view_v_dst = ggml_view_2d(ctx0, kv_self->v_l[il], + nm, n_embd_v_gqa, + ggml_row_size(kv_self->v_l[il]->type, kv_self->size), + ggml_row_size(kv_self->v_l[il]->type, id)); + } + + ggml_build_forward_expand(gf, ggml_cpy(ctx0, view_k_src, view_k_dst)); + ggml_build_forward_expand(gf, ggml_cpy(ctx0, view_v_src, view_v_dst)); + } + + i += nm - 1; + } + + //LLAMA_LOG_INFO("gf->n_nodes = %d\n", gf->n_nodes); +#endif + + return res; +} + +void llama_context::kv_self_update() { + auto & kv = kv_self; + + bool need_reserve = false; + + if (kv->has_shift) { + if (!kv->get_can_shift()) { + GGML_ABORT("The current context does not support K-shift"); + } + + LLAMA_LOG_DEBUG("%s: applying K-shift\n", __func__); + + // apply K-shift if needed + if (model.hparams.rope_type != LLAMA_ROPE_TYPE_NONE) { + ggml_backend_sched_reset(sched.get()); + + auto * gf = graph_init(); + + auto res = build_kv_self_shift(ctx_compute.get(), gf); + + ggml_backend_sched_alloc_graph(sched.get(), gf); + + res->set_inputs(nullptr); + + graph_compute(gf, false); + + need_reserve = true; + } + + { + kv->has_shift = false; + + for (uint32_t i = 0; i < kv->size; ++i) { + kv->cells[i].delta = 0; } } } - GGML_ASSERT( - // (!a || b) is a logical implication (a -> b) - // !hparams.causal_attn -> !cparams.causal_attn - (hparams.causal_attn || !cparams.causal_attn) && - "causal attention is not supported by this model" - ); + // defragment the KV cache if needed + if (kv->do_defrag) { + LLAMA_LOG_DEBUG("%s: defragmenting KV cache\n", __func__); - if (lctx.inp_KQ_mask || lctx.inp_KQ_mask_swa) { - // NOTE: hparams.causal_attn indicates the model is capable of generation and uses the kv cache. - if (cparams.causal_attn && !lctx.is_encoding) { - const int64_t n_kv = kv_self.n; - const int64_t n_tokens = ubatch.n_tokens; - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - const int64_t n_seqs = ubatch.n_seqs; + if (kv->defrag_prepare(graph_max_nodes())) { + ggml_backend_sched_reset(sched.get()); + auto * gf = graph_init(); - float * data = nullptr; - float * data_swa = nullptr; + auto res = build_kv_self_defrag(ctx_compute.get(), gf); - if (lctx.inp_KQ_mask) { - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_KQ_mask->buffer)); - data = (float *) lctx.inp_KQ_mask->data; - } + ggml_backend_sched_alloc_graph(sched.get(), gf); - if (lctx.inp_KQ_mask_swa) { - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_KQ_mask_swa->buffer)); - data_swa = (float *) lctx.inp_KQ_mask_swa->data; - } + res->set_inputs(nullptr); - // For causal attention, use only the previous KV cells - // of the correct sequence for each token of the ubatch. - // It's assumed that if a token in the batch has multiple sequences, they are equivalent. - for (int h = 0; h < 1; ++h) { - for (int s = 0; s < n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; + graph_compute(gf, false); - for (int j = 0; j < n_seq_tokens; ++j) { - const llama_pos pos = ubatch.pos[s*n_seq_tokens + j]; - - for (int i = 0; i < n_kv; ++i) { - float f; - if (!kv_self.cells[i].has_seq_id(seq_id) || kv_self.cells[i].pos > pos) { - f = -INFINITY; - } else { - if (hparams.use_alibi) { - f = -std::abs(kv_self.cells[i].pos - pos); - } else { - f = 0.0f; - } - } - - if (data) { - data[h*(n_kv*n_tokens) + s*(n_kv*n_seq_tokens) + j*n_kv + i] = f; - } - - // may need to cut off old tokens for sliding window - if (data_swa) { - if (pos - kv_self.cells[i].pos >= (int32_t)hparams.n_swa) { - f = -INFINITY; - } - data_swa[h*(n_kv*n_tokens) + s*(n_kv*n_seq_tokens) + j*n_kv + i] = f; - } - } - } - } - - if (data) { - for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) { - for (int j = 0; j < n_kv; ++j) { - data[h*(n_kv*n_tokens) + i*n_kv + j] = -INFINITY; - } - } - } - - if (data_swa) { - for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) { - for (int j = 0; j < n_kv; ++j) { - data_swa[h*(n_kv*n_tokens) + i*n_kv + j] = -INFINITY; - } - } - } - } - } else { - const int64_t n_tokens = ubatch.n_tokens; - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - const int64_t n_seqs = ubatch.n_seqs; - // when using kv cache, the mask needs to match the kv cache size - const int64_t n_stride = hparams.causal_attn && !lctx.is_encoding ? kv_self.n : n_tokens; - - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_KQ_mask->buffer)); - - float * data = (float *) lctx.inp_KQ_mask->data; - - for (int h = 0; h < 1; ++h) { - for (int s1 = 0; s1 < n_seqs; ++s1) { - const llama_seq_id seq_id = ubatch.seq_id[s1][0]; - - for (int j = 0; j < n_seq_tokens; ++j) { - const int32_t tj = s1*n_seq_tokens + j; - - for (int s0 = 0; s0 < n_seqs; ++s0) { - for (int i = 0; i < n_seq_tokens; ++i) { - const int32_t ti = s0*n_seq_tokens + i; - float f = -INFINITY; - - for (int s = 0; s < ubatch.n_seq_id[s0]; ++s) { - if (ubatch.seq_id[s0][s] == seq_id) { - if (hparams.use_alibi) { - f = -std::abs(ubatch.pos[ti] - ubatch.pos[tj]); - } else { - f = 0.0f; - } - break; - } - } - - data[h*(n_tokens*n_tokens) + tj*n_stride + ti] = f; - } - } - - for (int i = n_tokens; i < n_stride; ++i) { - data[h*(n_tokens*n_tokens) + tj*n_stride + i] = -INFINITY; - } - } - } - } + need_reserve = true; } + + kv->do_defrag = false; } - if (cparams.embeddings && cparams.pooling_type == LLAMA_POOLING_TYPE_MEAN) { - const int64_t n_tokens = ubatch.n_tokens; - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - const int64_t n_seqs = ubatch.n_seqs; + // reserve a worst case graph if needed + if (need_reserve) { + LLAMA_LOG_DEBUG("%s: reserving a worst case graph\n", __func__); - GGML_ASSERT(lctx.inp_mean); - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_mean->buffer)); + // build worst-case graph + uint32_t n_seqs = 1; // TODO: worst-case number of sequences + uint32_t n_tokens = std::min(cparams.n_ctx, cparams.n_ubatch); - float * data = (float *) lctx.inp_mean->data; - memset(lctx.inp_mean->data, 0, n_tokens * n_tokens * ggml_element_size(lctx.inp_mean)); + // simulate full KV cache + kv_self->n = kv_self->size; - std::vector sum(n_tokens, 0); + llama_token token = model.vocab.token_bos(); // not actually used by llama_build_graph, but required to choose between token and embedding inputs graph + llama_ubatch ubatch = { true, n_tokens, n_tokens / n_seqs, n_seqs, &token, nullptr, nullptr, nullptr, nullptr, nullptr}; - for (int s = 0; s < n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; + auto * gf = graph_init(); + graph_build(ctx_compute.get(), gf, ubatch, LLM_GRAPH_TYPE_DEFAULT); - // TODO: adapt limits to n_seqs when ubatch.equal_seqs is true - GGML_ASSERT(seq_id < n_tokens && "seq_id cannot be larger than n_tokens with pooling_type == MEAN"); - - sum[seq_id] += ubatch.n_seq_tokens; - } - - std::vector div(n_tokens, 0.0f); - for (int i = 0; i < n_tokens; ++i) { - const uint64_t s = sum[i]; - if (s > 0) { - div[i] = 1.0f/float(s); - } - } - - for (int s = 0; s < n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; - - for (int i = 0; i < n_seq_tokens; ++i) { - data[seq_id*n_tokens + s*n_seq_tokens + i] = div[seq_id]; - } - } - } - - if (cparams.embeddings && ( - cparams.pooling_type == LLAMA_POOLING_TYPE_CLS || - cparams.pooling_type == LLAMA_POOLING_TYPE_RANK)) { - const int64_t n_tokens = ubatch.n_tokens; - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - const int64_t n_seqs = ubatch.n_seqs; - - GGML_ASSERT(lctx.inp_cls); - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_cls->buffer)); - - uint32_t * data = (uint32_t *) lctx.inp_cls->data; - memset(lctx.inp_cls->data, 0, n_tokens * ggml_element_size(lctx.inp_cls)); - - for (int s = 0; s < n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; - - // TODO: adapt limits to n_seqs when ubatch.equal_seqs is true - GGML_ASSERT(seq_id < n_tokens && "seq_id cannot be larger than n_tokens with pooling_type == CLS or RANK"); - - for (int i = 0; i < n_seq_tokens; ++i) { - const llama_pos pos = ubatch.pos[s*n_seq_tokens + i]; - - if (pos == 0) { - data[seq_id] = s*n_seq_tokens + i; - } - } - } - } - - if (cparams.embeddings && cparams.pooling_type == LLAMA_POOLING_TYPE_LAST) { - const int64_t n_tokens = ubatch.n_tokens; - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - const int64_t n_seqs = ubatch.n_seqs; - - GGML_ASSERT(lctx.inp_cls); - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_cls->buffer)); - - uint32_t * data = (uint32_t *) lctx.inp_cls->data; - memset(lctx.inp_cls->data, 0, n_tokens * ggml_element_size(lctx.inp_cls)); - - std::vector last_pos(n_tokens, -1); - std::vector last_row(n_tokens, -1); - - for (int s = 0; s < n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; - - // TODO: adapt limits to n_seqs when ubatch.equal_seqs is true - GGML_ASSERT(seq_id < n_tokens && "seq_id cannot be larger than n_tokens with pooling_type == LAST"); - - for (int i = 0; i < n_seq_tokens; ++i) { - const llama_pos pos = ubatch.pos[s*n_seq_tokens + i]; - - if (pos >= last_pos[seq_id]) { - last_pos[seq_id] = pos; - last_row[seq_id] = s*n_seq_tokens + i; - } - } - } - - for (int i = 0; i < n_tokens; ++i) { - if (last_row[i] >= 0) { - data[i] = last_row[i]; - } - } - } - - if (kv_self.recurrent) { - const int64_t n_kv = kv_self.n; - - if (lctx.inp_s_mask) { - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_s_mask->buffer)); - float * data = (float *) lctx.inp_s_mask->data; - - // clear unused states - for (int i = 0; i < n_kv; ++i) { - const uint32_t cell_id = i + kv_self.head; - llama_kv_cell & kv_cell = lctx.kv_self.cells[cell_id]; - - data[i] = (float) (kv_cell.src >= 0); - - // only clear once - if (kv_cell.src < 0) { - kv_cell.src = cell_id; - } - } - } - - if (lctx.inp_s_copy) { - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_s_copy->buffer)); - int32_t * data = (int32_t *) lctx.inp_s_copy->data; - - // assuming copy destinations ALWAYS happen ONLY on the cells between head and head+n - for (uint32_t i = 0; i < n_kv; ++i) { - const uint32_t cell_id = i + kv_self.head; - llama_kv_cell & kv_cell = lctx.kv_self.cells[cell_id]; - - // prevent out-of-bound sources - if (kv_cell.src < 0 || (uint32_t) kv_cell.src >= kv_self.size) { - kv_cell.src = cell_id; - } - - data[i] = kv_cell.src; - - // ensure copy only happens once - if (kv_cell.src != (int32_t) cell_id) { - kv_cell.src = cell_id; - } - } - } - } - - if (lctx.inp_pos_bucket) { - const int64_t n_tokens = ubatch.n_tokens; - - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_pos_bucket->buffer)); - GGML_ASSERT(!ubatch.equal_seqs); // TODO: use ubatch.n_seqs instead of failing - - int32_t * data = (int32_t *) lctx.inp_pos_bucket->data; - - if (!lctx.is_encoding) { - const int64_t n_kv = kv_self.n; - for (int h = 0; h < 1; ++h) { - for (int j = 0; j < n_tokens; ++j) { - for (int i = 0; i < n_kv; ++i) { - data[h*(n_kv*n_tokens) + j*n_kv + i] = llama_relative_position_bucket(lctx.kv_self.cells[i].pos, ubatch.pos[j], hparams.n_rel_attn_bkts, lctx.is_encoding); - } - } - } - } else { - for (int h = 0; h < 1; ++h) { - for (int j = 0; j < n_tokens; ++j) { - for (int i = 0; i < n_tokens; ++i) { - data[h*(n_tokens*n_tokens) + j*n_tokens + i] = llama_relative_position_bucket(ubatch.pos[i], ubatch.pos[j], hparams.n_rel_attn_bkts, lctx.is_encoding); - } - } - } - } - } - - if (!lctx.is_encoding && lctx.inp_embd_enc) { - assert(lctx.inp_embd_enc->type == GGML_TYPE_F32); - assert((size_t) ggml_nelements(lctx.inp_embd_enc) == lctx.embd_enc.size()); - - ggml_backend_tensor_set(lctx.inp_embd_enc, lctx.embd_enc.data(), 0, ggml_nbytes(lctx.inp_embd_enc)); - } - - if (!lctx.is_encoding && lctx.inp_KQ_mask_cross) { - const int64_t n_output_enc = lctx.embd_enc.size() / hparams.n_embd; - const int64_t n_tokens = ubatch.n_tokens; - - GGML_ASSERT(ggml_backend_buffer_is_host(lctx.inp_KQ_mask_cross->buffer)); - GGML_ASSERT(!ubatch.equal_seqs); // TODO: use ubatch.n_seqs instead of failing - - float * data = (float *) lctx.inp_KQ_mask_cross->data; - - for (int h = 0; h < 1; ++h) { - for (int j = 0; j < n_tokens; ++j) { - for (int i = 0; i < n_output_enc; ++i) { - float f = -INFINITY; - for (int s = 0; s < ubatch.n_seq_id[j]; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[j][s]; - if (lctx.seq_ids_enc[i].find(seq_id) != lctx.seq_ids_enc[i].end()) { - f = 0.0f; - } - } - data[h*(n_output_enc*n_tokens) + j*n_output_enc + i] = f; - } - } - - for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) { - for (int j = 0; j < n_output_enc; ++j) { - data[h*(n_output_enc*n_tokens) + i*n_output_enc + j] = -INFINITY; - } - } + // initialize scheduler with the worst-case graph + ggml_backend_sched_reset(sched.get()); + if (!ggml_backend_sched_reserve(sched.get(), gf)) { + LLAMA_LOG_ERROR("%s: failed to allocate compute buffers\n", __func__); } } } -// llama output +enum llama_pooling_type llama_context::pooling_type() const { + return cparams.pooling_type; +} -size_t llama_output_reserve(struct llama_context & lctx, size_t n_outputs) { - const auto & cparams = lctx.cparams; - const auto & hparams = lctx.model.hparams; - const auto & vocab = lctx.model.vocab; +float * llama_context::get_logits() { + // reorder logits for backward compatibility + output_reorder(); - const size_t n_outputs_max = std::max(n_outputs, (size_t) cparams.n_seq_max); + return logits; +} + +float * llama_context::get_logits_ith(int32_t i) { + int32_t j = -1; + + try { + if (logits == nullptr) { + throw std::runtime_error("no logits"); + } + + if (i < 0) { + j = n_outputs + i; + if (j < 0) { + throw std::runtime_error(format("negative index out of range [0, %d)", n_outputs)); + } + } else if ((size_t) i >= output_ids.size()) { + throw std::runtime_error(format("out of range [0, %zu)", output_ids.size())); + } else { + j = output_ids[i]; + } + + if (j < 0) { + throw std::runtime_error(format("batch.logits[%d] != true", i)); + } + if (j >= n_outputs) { + // This should not happen + throw std::runtime_error(format("corrupt output buffer (j=%d, n_outputs=%d)", j, n_outputs)); + } + + return logits + j*model.vocab.n_tokens(); + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: invalid logits id %d, reason: %s\n", __func__, i, err.what()); +#ifndef NDEBUG + GGML_ABORT("fatal error"); +#else + return nullptr; +#endif + } +} + +float * llama_context::get_embeddings() { + // reorder embeddings for backward compatibility + output_reorder(); + + return embd; +} + +float * llama_context::get_embeddings_ith(int32_t i) { + int32_t j = -1; + + try { + if (embd == nullptr) { + throw std::runtime_error("no embeddings"); + } + + if (i < 0) { + j = n_outputs + i; + if (j < 0) { + throw std::runtime_error(format("negative index out of range [0, %d)", n_outputs)); + } + } else if ((size_t) i >= output_ids.size()) { + throw std::runtime_error(format("out of range [0, %zu)", output_ids.size())); + } else { + j = output_ids[i]; + } + + if (j < 0) { + throw std::runtime_error(format("batch.logits[%d] != true", i)); + } + if (j >= n_outputs) { + // This should not happen + throw std::runtime_error(format("corrupt output buffer (j=%d, n_outputs=%d)", j, n_outputs)); + } + + return embd + j*model.hparams.n_embd; + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: invalid embeddings id %d, reason: %s\n", __func__, i, err.what()); +#ifndef NDEBUG + GGML_ABORT("fatal error"); +#else + return nullptr; +#endif + } +} + +float * llama_context::get_embeddings_seq(llama_seq_id seq_id) { + auto it = embd_seq.find(seq_id); + if (it == embd_seq.end()) { + return nullptr; + } + + return it->second.data(); +} + +void llama_context::attach_threadpool( + ggml_threadpool_t threadpool, + ggml_threadpool_t threadpool_batch) { + LLAMA_LOG_DEBUG("%s: call\n", __func__); + + this->threadpool = threadpool; + this->threadpool_batch = threadpool_batch ? threadpool_batch : threadpool; +} + +void llama_context::detach_threadpool() { + LLAMA_LOG_DEBUG("%s: call\n", __func__); + + this->threadpool = nullptr; + this->threadpool_batch = nullptr; +} + +void llama_context::set_n_threads(int32_t n_threads, int32_t n_threads_batch) { + LLAMA_LOG_DEBUG("%s: n_threads = %d, n_threads_batch = %d\n", __func__, n_threads, n_threads_batch); + + cparams.n_threads = n_threads; + cparams.n_threads_batch = n_threads_batch; +} + +void llama_context::set_abort_callback(bool (*abort_callback)(void * data), void * abort_callback_data) { + LLAMA_LOG_DEBUG("%s: call\n", __func__); + + this->abort_callback = abort_callback; + this->abort_callback_data = abort_callback_data; + + for (auto & backend : backends) { + auto * reg = ggml_backend_dev_backend_reg(ggml_backend_get_device(backend.get())); + auto * set_abort_callback_fn = (ggml_backend_set_abort_callback_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_set_abort_callback"); + if (set_abort_callback_fn) { + set_abort_callback_fn(backend.get(), this->abort_callback, this->abort_callback_data); + } + } +} + +void llama_context::set_embeddings(bool value) { + LLAMA_LOG_DEBUG("%s: value = %d\n", __func__, value); + + cparams.embeddings = value; +} + +void llama_context::set_causal_attn(bool value) { + LLAMA_LOG_DEBUG("%s: value = %d\n", __func__, value); + + cparams.causal_attn = value; +} + +void llama_context::set_adapter_lora( + llama_adapter_lora * adapter, + float scale) { + LLAMA_LOG_DEBUG("%s: adapter = %p, scale = %f\n", __func__, (void *) adapter, scale); + + loras[adapter] = scale; +} + +bool llama_context::rm_adapter_lora( + llama_adapter_lora * adapter) { + LLAMA_LOG_DEBUG("%s: adapter = %p\n", __func__, (void *) adapter); + + auto pos = loras.find(adapter); + if (pos != loras.end()) { + loras.erase(pos); + return true; + } + + return false; +} + +void llama_context::clear_adapter_lora() { + LLAMA_LOG_DEBUG("%s: call\n", __func__); + + loras.clear(); +} + +bool llama_context::apply_adapter_cvec( + const float * data, + size_t len, + int32_t n_embd, + int32_t il_start, + int32_t il_end) { + LLAMA_LOG_DEBUG("%s: il_start = %d, il_end = %d\n", __func__, il_start, il_end); + + return cvec.apply(model, data, len, n_embd, il_start, il_end); +} + +int llama_context::encode(llama_batch & inp_batch) { + if (inp_batch.n_tokens == 0) { + LLAMA_LOG_ERROR("%s: n_tokens == 0\n", __func__); + return -1; + } + + // temporary allocate memory for the input batch if needed + // TODO: this is incorrect for multiple sequences because pos_max() is the maximum across all sequences + llama_batch_allocr batch_allocr(inp_batch, inp_batch.pos ? -1 : kv_self->pos_max() + 1); + + const llama_batch & batch = batch_allocr.batch; + const int32_t n_tokens = batch.n_tokens; + + const auto & hparams = model.hparams; + + GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT + + if (batch.token) { + for (int32_t i = 0; i < n_tokens; ++i) { + if (batch.token[i] < 0 || (uint32_t) batch.token[i] >= model.vocab.n_tokens()) { + LLAMA_LOG_ERROR("%s: invalid token[%d] = %d\n", __func__, i, batch.token[i]); + return -1; + } + } + } + + // micro-batching is not possible for non-causal encoding, so we process the batch in a single shot + GGML_ASSERT(cparams.n_ubatch >= (uint32_t) n_tokens && "encoder requires n_ubatch >= n_tokens"); + + if (t_compute_start_us == 0) { + t_compute_start_us = ggml_time_us(); + } + + n_queued_tokens += n_tokens; + + const int64_t n_embd = hparams.n_embd; + + sbatch.from_batch(batch, n_embd, /* simple_split */ true, /* logits_all */ true); + + const llama_ubatch ubatch = sbatch.split_simple(n_tokens); + + // reserve output buffer + if (output_reserve(n_tokens) < n_tokens) { + LLAMA_LOG_ERROR("%s: could not reserve space for batch with %u outputs\n", __func__, n_tokens); + return -2; + }; + + for (int32_t i = 0; i < n_tokens; ++i) { + output_ids[i] = i; + } + + n_outputs = n_tokens; + + //batch_manager->prepare(ubatch); + + ggml_backend_sched_reset(sched.get()); + ggml_backend_sched_set_eval_callback(sched.get(), cparams.cb_eval, cparams.cb_eval_user_data); + + auto * gf = graph_init(); + auto res = graph_build(ctx_compute.get(), gf, ubatch, LLM_GRAPH_TYPE_ENCODER); + + ggml_backend_sched_alloc_graph(sched.get(), gf); + + res->set_inputs(&ubatch); + + const auto compute_status = graph_compute(gf, n_tokens > 1); + switch (compute_status) { + case GGML_STATUS_SUCCESS: + break; + case GGML_STATUS_ABORTED: + return 2; + case GGML_STATUS_ALLOC_FAILED: + return -2; + case GGML_STATUS_FAILED: + default: + return -3; + } + + auto * t_embd = res->get_embd_pooled() ? res->get_embd_pooled() : res->get_embd(); + + // extract embeddings + if (t_embd) { + ggml_backend_t backend_embd = ggml_backend_sched_get_tensor_backend(sched.get(), t_embd); + GGML_ASSERT(backend_embd != nullptr); + + GGML_ASSERT(embd != nullptr); + + switch (cparams.pooling_type) { + case LLAMA_POOLING_TYPE_NONE: + { + // extract token embeddings + GGML_ASSERT(n_tokens*n_embd <= (int64_t) embd_size); + ggml_backend_tensor_get_async(backend_embd, t_embd, embd, 0, n_tokens*n_embd*sizeof(float)); + } break; + case LLAMA_POOLING_TYPE_MEAN: + case LLAMA_POOLING_TYPE_CLS: + case LLAMA_POOLING_TYPE_LAST: + { + // extract sequence embeddings + auto & embd_seq_out = embd_seq; + embd_seq_out.clear(); + + GGML_ASSERT(!ubatch.equal_seqs); // TODO: handle equal splits + + for (int32_t i = 0; i < n_tokens; i++) { + const llama_seq_id seq_id = ubatch.seq_id[i][0]; + if (embd_seq_out.find(seq_id) != embd_seq_out.end()) { + continue; + } + embd_seq_out[seq_id].resize(n_embd); + ggml_backend_tensor_get_async(backend_embd, t_embd, embd_seq_out[seq_id].data(), (n_embd*seq_id)*sizeof(float), n_embd*sizeof(float)); + } + } break; + case LLAMA_POOLING_TYPE_RANK: + { + // TODO: this likely should be the same logic as in llama_decoder_internal, but better to + // wait for an encoder model that requires this pooling type in order to test it + // https://github.com/ggerganov/llama.cpp/pull/9510 + GGML_ABORT("RANK pooling not implemented yet"); + } + case LLAMA_POOLING_TYPE_UNSPECIFIED: + { + GGML_ABORT("unknown pooling type"); + } + } + } + + // Reset state for the next token before backend sync, to allow the CPU activities in the reset to + // overlap with device computation. + ggml_backend_sched_reset(sched.get()); + + // TODO: hacky solution + if (model.arch == LLM_ARCH_T5 && t_embd) { + //cross.t_embd = t_embd; + + cross.n_embd = t_embd->ne[0]; + cross.n_enc = t_embd->ne[1]; + cross.v_embd.resize(cross.n_embd*cross.n_enc); + memcpy(cross.v_embd.data(), embd, ggml_nbytes(t_embd)); + + // remember the sequence ids used during the encoding - needed for cross attention later + cross.seq_ids_enc.resize(n_tokens); + for (int32_t i = 0; i < n_tokens; i++) { + for (int s = 0; s < ubatch.n_seq_id[i]; s++) { + llama_seq_id seq_id = ubatch.seq_id[i][s]; + cross.seq_ids_enc[i].insert(seq_id); + } + } + } + + return 0; +} + +int llama_context::decode(llama_batch & inp_batch) { + if (inp_batch.n_tokens == 0) { + LLAMA_LOG_ERROR("%s: n_tokens == 0\n", __func__); + return -1; + } + + // temporary allocate memory for the input batch if needed + // TODO: this is incorrect for multiple sequences because pos_max() is the maximum across all sequences + llama_batch_allocr batch_allocr(inp_batch, inp_batch.pos ? -1 : kv_self->pos_max() + 1); + + const llama_batch & batch = batch_allocr.batch; + + const auto & vocab = model.vocab; + const auto & hparams = model.hparams; + + const int32_t n_vocab = vocab.n_tokens(); + + const int64_t n_tokens_all = batch.n_tokens; + const int64_t n_embd = hparams.n_embd; + + // TODO: remove this stuff + class batch_guard { + public: + batch_guard(llama_kv_cache_unified & kv_self) : kv_slot_restorer(kv_self) { + } + + ~batch_guard() { + if (!is_done) { + kv_slot_restorer.restore(); + } + } + + void done() { + is_done = true; + } + + void save(const llama_kv_cache_slot_info & slot_info) { + kv_slot_restorer.save(slot_info); + } + + private: + bool is_done = false; + + llama_kv_slot_restorer kv_slot_restorer; + }; + + batch_guard bg(*kv_self); + + GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT + + if (batch.token) { + for (int64_t i = 0; i < n_tokens_all; ++i) { + if (batch.token[i] < 0 || (uint32_t) batch.token[i] >= model.vocab.n_tokens()) { + LLAMA_LOG_ERROR("%s: invalid token[%" PRId64 "] = %d\n", __func__, i, batch.token[i]); + throw std::runtime_error("invalid token"); + } + } + } + + GGML_ASSERT(n_tokens_all <= cparams.n_batch); + + GGML_ASSERT((cparams.causal_attn || cparams.n_ubatch >= n_tokens_all) && "non-causal attention requires n_ubatch >= n_tokens"); + + if (t_compute_start_us == 0) { + t_compute_start_us = ggml_time_us(); + } + n_queued_tokens += n_tokens_all; + + // this indicates we are doing pooled embedding, so we ignore batch.logits and output all tokens + const bool embd_pooled = cparams.embeddings && cparams.pooling_type != LLAMA_POOLING_TYPE_NONE; + + embd_seq.clear(); + + int64_t n_outputs_all = 0; + + // count outputs + if (batch.logits && !embd_pooled) { + for (uint32_t i = 0; i < n_tokens_all; ++i) { + n_outputs_all += batch.logits[i] != 0; + } + } else if (logits_all || embd_pooled) { + n_outputs_all = n_tokens_all; + } else { + // keep last output only + n_outputs_all = 1; + } + + const bool logits_all = n_outputs_all == n_tokens_all; + + sbatch.from_batch(batch, n_embd, + /* simple_split */ !kv_self->recurrent, + /* logits_all */ logits_all); + + // reserve output buffer + if (output_reserve(n_outputs_all) < n_outputs_all) { + LLAMA_LOG_ERROR("%s: could not reserve space for batch with %" PRId64 " outputs\n", __func__, n_outputs_all); + return -2; + }; + + int64_t n_outputs_prev = 0; + + while (sbatch.n_tokens > 0) { + llama_ubatch ubatch = llama_ubatch(); + + const auto & n_ubatch = cparams.n_ubatch; + + if (kv_self->recurrent) { + if (embd_pooled) { + // Pooled embeddings cannot be split across ubatches (yet) + ubatch = sbatch.split_seq(cparams.n_ubatch); + } else { + // recurrent model architectures are easier to implement + // with equal-length sequences + ubatch = sbatch.split_equal(cparams.n_ubatch); + } + } else { + ubatch = sbatch.split_simple(n_ubatch); + } + + // count the outputs in this u_batch + { + int32_t n_outputs_new = 0; + + if (n_outputs_all == n_tokens_all) { + n_outputs_new = ubatch.n_tokens; + } else { + GGML_ASSERT(ubatch.output); + for (uint32_t i = 0; i < ubatch.n_tokens; i++) { + n_outputs_new += (int32_t) (ubatch.output[i] != 0); + } + } + + // needs to happen before the graph is built + n_outputs = n_outputs_new; + } + + // non-causal masks do not use the KV cache + if (hparams.causal_attn) { + kv_self_update(); + + // if we have enough unused cells before the current head -> + // better to start searching from the beginning of the cache, hoping to fill it + if (kv_self->head > kv_self->used + 2*ubatch.n_tokens) { + kv_self->head = 0; + } + + const auto slot_info = kv_self->find_slot(ubatch); + if (!slot_info) { + LLAMA_LOG_ERROR("%s: failed to prepare ubatch\n", __func__); + return -3; + } + + bg.save(slot_info); + + if (!kv_self->recurrent) { + // a heuristic, to avoid attending the full cache if it is not yet utilized + // after enough generations, the benefit from this heuristic disappears + // if we start defragmenting the cache, the benefit from this will be more important + const uint32_t pad = kv_self->get_padding(cparams); + kv_self->n = std::min(kv_self->size, std::max(pad, GGML_PAD(kv_self->cell_max(), pad))); + } + } + + //printf("kv_self.n = %5d, kv_self.used = %5d, kv_self.head = %5d\n", kv_self->n, kv_self->used, kv_self->head); + + ggml_backend_sched_reset(sched.get()); + ggml_backend_sched_set_eval_callback(sched.get(), cparams.cb_eval, cparams.cb_eval_user_data); + + auto * gf = graph_init(); + auto res = graph_build(ctx_compute.get(), gf, ubatch, LLM_GRAPH_TYPE_DECODER); + + // LLAMA_LOG_INFO("graph build time: %.3f ms (%d nodes, %d leafs)\n", (ggml_time_us() - t_start_us)/1000.0, gf->n_nodes, gf->n_leafs); + + ggml_backend_sched_alloc_graph(sched.get(), gf); + + res->set_inputs(&ubatch); + + const auto compute_status = graph_compute(gf, ubatch.n_tokens > 1); + if (compute_status != GGML_STATUS_SUCCESS) { + switch (compute_status) { + case GGML_STATUS_ABORTED: + return 2; + case GGML_STATUS_ALLOC_FAILED: + return -2; + case GGML_STATUS_FAILED: + default: + return -3; + } + } + + // update the kv ring buffer + { + kv_self->head += ubatch.n_tokens; + + // Ensure kv cache head points to a valid index. + if (kv_self->head >= kv_self->size) { + kv_self->head = 0; + } + } + + // plot the computation graph in dot format (for debugging purposes) + //if (n_past%100 == 0) { + // ggml_graph_dump_dot(gf, NULL, "llama.dot"); + //} + + auto * t_logits = cparams.embeddings ? nullptr : res->get_logits(); + auto * t_embd = cparams.embeddings ? res->get_embd() : nullptr; + + if (t_embd && res->get_embd_pooled()) { + t_embd = res->get_embd_pooled(); + } + + // extract logits + if (t_logits && n_outputs > 0) { + ggml_backend_t backend_res = ggml_backend_sched_get_tensor_backend(sched.get(), t_logits); + GGML_ASSERT(backend_res != nullptr); + GGML_ASSERT(logits != nullptr); + + float * logits_out = logits + n_outputs_prev*n_vocab; + + if (n_outputs) { + GGML_ASSERT( n_outputs_prev + n_outputs <= n_outputs_all); + GGML_ASSERT((n_outputs_prev + n_outputs)*n_vocab <= (int64_t) logits_size); + ggml_backend_tensor_get_async(backend_res, t_logits, logits_out, 0, n_outputs*n_vocab*sizeof(float)); + } + } + + // extract embeddings + if (t_embd && n_outputs > 0) { + ggml_backend_t backend_embd = ggml_backend_sched_get_tensor_backend(sched.get(), t_embd); + GGML_ASSERT(backend_embd != nullptr); + + switch (cparams.pooling_type) { + case LLAMA_POOLING_TYPE_NONE: + { + // extract token embeddings + GGML_ASSERT(embd != nullptr); + float * embd_out = embd + n_outputs_prev*n_embd; + + if (n_outputs) { + GGML_ASSERT( n_outputs_prev + n_outputs <= n_outputs_all); + GGML_ASSERT((n_outputs_prev + n_outputs)*n_embd <= (int64_t) embd_size); + ggml_backend_tensor_get_async(backend_embd, t_embd, embd_out, 0, n_outputs*n_embd*sizeof(float)); + } + } break; + case LLAMA_POOLING_TYPE_MEAN: + case LLAMA_POOLING_TYPE_CLS: + case LLAMA_POOLING_TYPE_LAST: + { + // extract sequence embeddings (cleared before processing each batch) + auto & embd_seq_out = embd_seq; + + for (uint32_t s = 0; s < ubatch.n_seqs; ++s) { + const llama_seq_id seq_id = ubatch.seq_id[s][0]; + if (embd_seq_out.find(seq_id) != embd_seq_out.end()) { + continue; + } + embd_seq_out[seq_id].resize(n_embd); + ggml_backend_tensor_get_async(backend_embd, t_embd, embd_seq_out[seq_id].data(), (n_embd*seq_id)*sizeof(float), n_embd*sizeof(float)); + } + } break; + case LLAMA_POOLING_TYPE_RANK: + { + // extract the rerank score - a single float per sequence + auto & embd_seq_out = embd_seq; + + for (uint32_t s = 0; s < ubatch.n_seqs; ++s) { + const llama_seq_id seq_id = ubatch.seq_id[s][0]; + if (embd_seq_out.find(seq_id) != embd_seq_out.end()) { + continue; + } + embd_seq_out[seq_id].resize(1); + ggml_backend_tensor_get_async(backend_embd, t_embd, embd_seq_out[seq_id].data(), (seq_id)*sizeof(float), sizeof(float)); + } + } break; + case LLAMA_POOLING_TYPE_UNSPECIFIED: + { + GGML_ABORT("unknown pooling type"); + } + } + } + + n_outputs_prev += n_outputs; + } + + // finalize the batch processing + bg.done(); + + // set output mappings + { + bool sorted_output = true; + + GGML_ASSERT(sbatch.out_ids.size() == (size_t) n_outputs_all); + + for (int64_t i = 0; i < n_outputs_all; ++i) { + int64_t out_id = sbatch.out_ids[i]; + output_ids[out_id] = i; + if (out_id != i) { + sorted_output = false; + } + } + + if (sorted_output) { + sbatch.out_ids.clear(); + } + } + + // set to total number of outputs in the batch, for use in llama_get_logits_ith + n_outputs = n_outputs_all; + + // wait for the computation to finish (automatically done when obtaining the model output) + //synchronize(); + + // decide if we need to defrag the kv cache + if (cparams.causal_attn && cparams.defrag_thold > 0.0f) { + // - do not defrag small contexts (i.e. < 2048 tokens) + // - count the padding towards the number of used tokens + const float fragmentation = kv_self->n >= 2048 ? std::max(0.0f, 1.0f - float(kv_self->used + kv_self->get_padding(cparams))/float(kv_self->n)) : 0.0f; + + // queue defragmentation for next llama_kv_cache_update + if (fragmentation > cparams.defrag_thold) { + LLAMA_LOG_DEBUG("%s: fragmentation: %.2f - requesting defrag\n", __func__, fragmentation); + + kv_self->defrag(); + } + } + + // Reset state for the next token before backend sync, to allow the CPU activities in the reset to + // overlap with device computation. + ggml_backend_sched_reset(sched.get()); + + return 0; +} + +// +// output +// + +int32_t llama_context::output_reserve(int32_t n_outputs) { + const auto & hparams = model.hparams; + const auto & vocab = model.vocab; + + const int64_t n_outputs_max = std::max(n_outputs, n_seq_max()); const auto n_batch = cparams.n_batch; const auto n_vocab = vocab.n_tokens(); const auto n_embd = hparams.n_embd; // TODO: use a per-batch flag for logits presence instead - const bool has_logits = !cparams.embeddings; - const bool has_embd = cparams.embeddings && (cparams.pooling_type == LLAMA_POOLING_TYPE_NONE); + bool has_logits = !cparams.embeddings; + bool has_embd = cparams.embeddings && (cparams.pooling_type == LLAMA_POOLING_TYPE_NONE); - const size_t logits_size = has_logits ? n_vocab*n_outputs_max : 0; - const size_t embd_size = has_embd ? n_embd*n_outputs_max : 0; - - if (lctx.output_ids.empty()) { - // init, never resized afterwards - lctx.output_ids.resize(n_batch); + // TODO: hacky enc-dec support + if (model.arch == LLM_ARCH_T5) { + has_logits = true; + has_embd = true; } - const size_t prev_size = lctx.buf_output ? ggml_backend_buffer_get_size(lctx.buf_output.get()) : 0; + logits_size = has_logits ? n_vocab*n_outputs_max : 0; + embd_size = has_embd ? n_embd*n_outputs_max : 0; + + if (output_ids.empty()) { + // init, never resized afterwards + output_ids.resize(n_batch); + } + + const size_t prev_size = buf_output ? ggml_backend_buffer_get_size(buf_output.get()) : 0; const size_t new_size = (logits_size + embd_size) * sizeof(float); // alloc only when more than the current capacity is required // TODO: also consider shrinking the buffer - if (!lctx.buf_output || prev_size < new_size) { - if (lctx.buf_output) { + if (!buf_output || prev_size < new_size) { + if (buf_output) { #ifndef NDEBUG // This doesn't happen often, but may be annoying in some cases (like the HellaSwag benchmark) LLAMA_LOG_INFO("%s: reallocating output buffer from size %.02f MiB to %.02f MiB\n", __func__, prev_size / 1024.0 / 1024.0, new_size / 1024.0 / 1024.0); #endif - lctx.buf_output = nullptr; - lctx.logits = nullptr; - lctx.embd = nullptr; + buf_output = nullptr; + logits = nullptr; + embd = nullptr; } auto * buft = ggml_backend_cpu_buffer_type(); // try to use the host buffer of the device where the output tensor is allocated for faster transfer to system memory - auto * output_dev = lctx.model.dev_output(); + auto * output_dev = model.dev_output(); auto * output_dev_host_buft = output_dev ? ggml_backend_dev_host_buffer_type(output_dev) : nullptr; if (output_dev_host_buft) { buft = output_dev_host_buft; } - lctx.buf_output.reset(ggml_backend_buft_alloc_buffer(buft, new_size)); - if (lctx.buf_output == nullptr) { + buf_output.reset(ggml_backend_buft_alloc_buffer(buft, new_size)); + if (buf_output == nullptr) { LLAMA_LOG_ERROR("%s: failed to allocate output buffer of size %.2f MiB\n", __func__, new_size / (1024.0 * 1024.0)); return 0; } } - float * output_base = (float *) ggml_backend_buffer_get_base(lctx.buf_output.get()); + float * output_base = (float *) ggml_backend_buffer_get_base(buf_output.get()); - lctx.logits = has_logits ? output_base : nullptr; - lctx.embd = has_embd ? output_base + logits_size : nullptr; - - lctx.output_size = n_outputs_max; - lctx.logits_size = logits_size; - lctx.embd_size = embd_size; + logits = has_logits ? output_base : nullptr; + embd = has_embd ? output_base + logits_size : nullptr; // set all ids as invalid (negative) - std::fill(lctx.output_ids.begin(), lctx.output_ids.end(), -1); + std::fill(output_ids.begin(), output_ids.end(), -1); - ggml_backend_buffer_clear(lctx.buf_output.get(), 0); + ggml_backend_buffer_clear(buf_output.get(), 0); - lctx.n_outputs = 0; + this->n_outputs = 0; + this->n_outputs_max = n_outputs_max; return n_outputs_max; } -void llama_output_reorder(struct llama_context & ctx) { - std::vector & out_ids = ctx.sbatch.out_ids; +void llama_context::output_reorder() { + auto & out_ids = sbatch.out_ids; if (!out_ids.empty()) { - const uint32_t n_vocab = ctx.model.vocab.n_tokens(); - const uint32_t n_embd = ctx.model.hparams.n_embd; + const uint32_t n_vocab = model.vocab.n_tokens(); + const uint32_t n_embd = model.hparams.n_embd; - const int32_t n_outputs = ctx.n_outputs; GGML_ASSERT((size_t) n_outputs == out_ids.size()); // TODO: is there something more efficient which also minimizes swaps? @@ -559,842 +1563,156 @@ void llama_output_reorder(struct llama_context & ctx) { } if (j_min == i) { continue; } std::swap(out_ids[i], out_ids[j_min]); - if (ctx.logits_size > 0) { + if (logits_size > 0) { for (uint32_t k = 0; k < n_vocab; k++) { - std::swap(ctx.logits[i*n_vocab + k], ctx.logits[j_min*n_vocab + k]); + std::swap(logits[i*n_vocab + k], logits[j_min*n_vocab + k]); } } - if (ctx.embd_size > 0) { + if (embd_size > 0) { for (uint32_t k = 0; k < n_embd; k++) { - std::swap(ctx.embd[i*n_embd + k], ctx.embd[j_min*n_embd + k]); + std::swap(embd[i*n_embd + k], embd[j_min*n_embd + k]); } } } - std::fill(ctx.output_ids.begin(), ctx.output_ids.end(), -1); + std::fill(output_ids.begin(), output_ids.end(), -1); for (int32_t i = 0; i < n_outputs; ++i) { - ctx.output_ids[out_ids[i]] = i; + output_ids[out_ids[i]] = i; } out_ids.clear(); } } // -// interface implementation +// graph // -void llama_free(struct llama_context * ctx) { - delete ctx; +int32_t llama_context::graph_max_nodes() const { + return std::max(8192, 5*model.n_tensors()); } -uint32_t llama_n_ctx(const struct llama_context * ctx) { - return ctx->cparams.n_ctx; +ggml_cgraph * llama_context::graph_init() { + ggml_init_params params = { + /*.mem_size =*/ buf_compute_meta.size(), + /*.mem_buffer =*/ buf_compute_meta.data(), + /*.no_alloc =*/ true, + }; + + ctx_compute.reset(ggml_init(params)); + + return ggml_new_graph_custom(ctx_compute.get(), graph_max_nodes(), false); } -uint32_t llama_n_batch(const struct llama_context * ctx) { - return ctx->cparams.n_batch; +llm_graph_result_ptr llama_context::graph_build( + ggml_context * ctx, + ggml_cgraph * gf, + const llama_ubatch & ubatch, + llm_graph_type gtype) { + return model.build_graph( + { + /*.ctx =*/ ctx, + /*.arch =*/ model.arch, + /*.hparams =*/ model.hparams, + /*.cparams =*/ cparams, + /*.ubatch =*/ ubatch, + /*.sched =*/ sched.get(), + /*.backend_cpu =*/ backend_cpu, + /*.cvec =*/ &cvec, + /*.loras =*/ &loras, + /*.memory =*/ kv_self.get(), + /*.cross =*/ &cross, + /*.n_outputs =*/ n_outputs, + /*.cb =*/ graph_get_cb(), + }, gf, gtype); } -uint32_t llama_n_ubatch(const struct llama_context * ctx) { - return ctx->cparams.n_ubatch; -} +ggml_status llama_context::graph_compute( + ggml_cgraph * gf, + bool batched) { + int n_threads = batched ? cparams.n_threads_batch : cparams.n_threads; + ggml_threadpool_t tp = batched ? threadpool_batch : threadpool; -uint32_t llama_n_seq_max(const struct llama_context * ctx) { - return ctx->kv_self.size; -} - -const struct llama_model * llama_get_model(const struct llama_context * ctx) { - return &ctx->model; -} - -enum llama_pooling_type llama_pooling_type(const struct llama_context * ctx) { - return ctx->cparams.pooling_type; -} - -void llama_attach_threadpool( - struct llama_context * ctx, - ggml_threadpool_t threadpool, - ggml_threadpool_t threadpool_batch) { - ctx->threadpool = threadpool; - ctx->threadpool_batch = threadpool_batch ? threadpool_batch : threadpool; -} - -void llama_detach_threadpool(struct llama_context * ctx) { - ctx->threadpool = nullptr; - ctx->threadpool_batch = nullptr; -} - -void llama_set_n_threads(struct llama_context * ctx, int32_t n_threads, int32_t n_threads_batch) { - ctx->cparams.n_threads = n_threads; - ctx->cparams.n_threads_batch = n_threads_batch; -} - -int32_t llama_n_threads(struct llama_context * ctx) { - return ctx->cparams.n_threads; -} - -int32_t llama_n_threads_batch(struct llama_context * ctx) { - return ctx->cparams.n_threads_batch; -} - -void llama_set_abort_callback(struct llama_context * ctx, bool (*abort_callback)(void * data), void * abort_callback_data) { - ctx->abort_callback = abort_callback; - ctx->abort_callback_data = abort_callback_data; - - for (auto & backend : ctx->backends) { - auto * reg = ggml_backend_dev_backend_reg(ggml_backend_get_device(backend.get())); - auto * set_abort_callback_fn = (ggml_backend_set_abort_callback_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_set_abort_callback"); - if (set_abort_callback_fn) { - set_abort_callback_fn(backend.get(), ctx->abort_callback, ctx->abort_callback_data); - } - } -} - -void llama_set_embeddings(struct llama_context * ctx, bool embeddings) { - ctx->cparams.embeddings = embeddings; -} - -void llama_set_causal_attn(struct llama_context * ctx, bool causal_attn) { - ctx->cparams.causal_attn = causal_attn; -} - -void llama_synchronize(struct llama_context * ctx) { - ggml_backend_sched_synchronize(ctx->sched.get()); - - // FIXME: if multiple single tokens are evaluated without a synchronization, - // the stats will be added to the prompt evaluation stats - // this should only happen when using batch size 1 to evaluate a batch - - // add the evaluation to the stats - if (ctx->n_queued_tokens == 1) { - if (!ctx->cparams.no_perf) { - ctx->t_eval_us += ggml_time_us() - ctx->t_compute_start_us; - } - ctx->n_eval++; - } else if (ctx->n_queued_tokens > 1) { - if (!ctx->cparams.no_perf) { - ctx->t_p_eval_us += ggml_time_us() - ctx->t_compute_start_us; - } - ctx->n_p_eval += ctx->n_queued_tokens; + if (backend_cpu != nullptr) { + auto * reg = ggml_backend_dev_backend_reg(ggml_backend_get_device(backend_cpu)); + auto * set_threadpool_fn = (decltype(ggml_backend_cpu_set_threadpool) *) ggml_backend_reg_get_proc_address(reg, "ggml_backend_cpu_set_threadpool"); + set_threadpool_fn(backend_cpu, tp); } - // get a more accurate load time, upon first eval - if (ctx->n_queued_tokens > 0 && !ctx->has_evaluated_once) { - ctx->t_load_us = ggml_time_us() - ctx->t_start_us; - ctx->has_evaluated_once = true; + // set the number of threads for all the backends + for (const auto & set_n_threads_fn : set_n_threads_fns) { + set_n_threads_fn.second(set_n_threads_fn.first, n_threads); } - ctx->n_queued_tokens = 0; - ctx->t_compute_start_us = 0; + auto status = ggml_backend_sched_graph_compute_async(sched.get(), gf); + if (status != GGML_STATUS_SUCCESS) { + LLAMA_LOG_ERROR("%s: ggml_backend_sched_graph_compute_async failed with error %d\n", __func__, status); + } + + // fprintf(stderr, "splits: %d\n", ggml_backend_sched_get_n_splits(sched)); + + return status; } -float * llama_get_logits(struct llama_context * ctx) { - llama_synchronize(ctx); - - // reorder logits for backward compatibility - // TODO: maybe deprecate this - llama_output_reorder(*ctx); - - return ctx->logits; -} - -float * llama_get_logits_ith(struct llama_context * ctx, int32_t i) { - int32_t j = -1; - - llama_synchronize(ctx); - - try { - if (ctx->logits == nullptr) { - throw std::runtime_error("no logits"); - } - - if (i < 0) { - j = ctx->n_outputs + i; - if (j < 0) { - throw std::runtime_error(format("negative index out of range [0, %d)", ctx->n_outputs)); - } - } else if ((size_t) i >= ctx->output_ids.size()) { - throw std::runtime_error(format("out of range [0, %zu)", ctx->output_ids.size())); +llm_graph_cb llama_context::graph_get_cb() const { + return [&](const llama_ubatch & ubatch, ggml_tensor * cur, const char * name, int il) { + if (il >= 0) { + ggml_format_name(cur, "%s-%d", name, il); } else { - j = ctx->output_ids[i]; + ggml_set_name(cur, name); } - if (j < 0) { - throw std::runtime_error(format("batch.logits[%d] != true", i)); - } - if (j >= ctx->n_outputs) { - // This should not happen - throw std::runtime_error(format("corrupt output buffer (j=%d, n_outputs=%d)", j, ctx->n_outputs)); - } - - return ctx->logits + j*ctx->model.vocab.n_tokens(); - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: invalid logits id %d, reason: %s\n", __func__, i, err.what()); -#ifndef NDEBUG - GGML_ABORT("fatal error"); -#else - return nullptr; -#endif - } -} - -float * llama_get_embeddings(struct llama_context * ctx) { - llama_synchronize(ctx); - - // reorder embeddings for backward compatibility - // TODO: maybe deprecate this - llama_output_reorder(*ctx); - - return ctx->embd; -} - -float * llama_get_embeddings_ith(struct llama_context * ctx, int32_t i) { - int32_t j = -1; - - llama_synchronize(ctx); - - try { - if (ctx->embd == nullptr) { - throw std::runtime_error("no embeddings"); - } - - if (i < 0) { - j = ctx->n_outputs + i; - if (j < 0) { - throw std::runtime_error(format("negative index out of range [0, %d)", ctx->n_outputs)); - } - } else if ((size_t) i >= ctx->output_ids.size()) { - throw std::runtime_error(format("out of range [0, %zu)", ctx->output_ids.size())); - } else { - j = ctx->output_ids[i]; - } - - if (j < 0) { - throw std::runtime_error(format("batch.logits[%d] != true", i)); - } - if (j >= ctx->n_outputs) { - // This should not happen - throw std::runtime_error(format("corrupt output buffer (j=%d, n_outputs=%d)", j, ctx->n_outputs)); - } - - return ctx->embd + j*ctx->model.hparams.n_embd; - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: invalid embeddings id %d, reason: %s\n", __func__, i, err.what()); -#ifndef NDEBUG - GGML_ABORT("fatal error"); -#else - return nullptr; -#endif - } -} - -float * llama_get_embeddings_seq(struct llama_context * ctx, llama_seq_id seq_id) { - llama_synchronize(ctx); - - auto it = ctx->embd_seq.find(seq_id); - if (it == ctx->embd_seq.end()) { - return nullptr; - } - - return it->second.data(); -} - -// llama state API - -// deprecated -size_t llama_get_state_size(struct llama_context * ctx) { - return llama_state_get_size(ctx); -} - -// deprecated -size_t llama_copy_state_data(struct llama_context * ctx, uint8_t * dst) { - return llama_state_get_data(ctx, dst, -1); -} - -// deprecated -size_t llama_set_state_data(struct llama_context * ctx, const uint8_t * src) { - return llama_state_set_data(ctx, src, -1); -} - -// deprecated -bool llama_load_session_file(struct llama_context * ctx, const char * path_session, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { - return llama_state_load_file(ctx, path_session, tokens_out, n_token_capacity, n_token_count_out); -} - -// deprecated -bool llama_save_session_file(struct llama_context * ctx, const char * path_session, const llama_token * tokens, size_t n_token_count) { - return llama_state_save_file(ctx, path_session, tokens, n_token_count); -} - -// TODO: replace all non-fatal assertions with returned errors or exceptions -struct llama_data_write { - virtual void write(const void * src, size_t size) = 0; - virtual void write_tensor_data(const struct ggml_tensor * tensor, size_t offset, size_t size) = 0; - virtual size_t get_size_written() = 0; - virtual ~llama_data_write() = default; - - void write_string(const std::string & str) { - uint32_t str_size = str.size(); - - write(&str_size, sizeof(str_size)); - write(str.data(), str_size); - } - - void write_model_info(const struct llama_context * ctx) { - const std::string arch_str = llm_arch_name(ctx->model.arch); - write_string(arch_str); - // TODO: add more model-specific info which should prevent loading the session file if not identical - } - - //void write_rng(const std::mt19937 & rng) { - // std::ostringstream rng_ss; - // rng_ss << rng; - - // const std::string & rng_str = rng_ss.str(); - - // write_string(rng_str); - //} - - void write_output_ids(struct llama_context * ctx) { - llama_output_reorder(*ctx); - - const uint32_t n_outputs = ctx->n_outputs; - - std::vector output_pos; - - const size_t n_batch = ctx->cparams.n_batch; - const auto & output_ids = ctx->output_ids; - - GGML_ASSERT(n_outputs <= ctx->output_size); - - output_pos.resize(n_outputs); - - // build a more compact representation of the output ids - for (size_t i = 0; i < n_batch; ++i) { - // map an output id to a position in the batch - int32_t pos = output_ids[i]; - if (pos >= 0) { - GGML_ASSERT((uint32_t) pos < n_outputs); - output_pos[pos] = i; + if (!cparams.offload_kqv) { + if (strcmp(name, "kqv_merged_cont") == 0) { + // all nodes between the KV store and the attention output are run on the CPU + ggml_backend_sched_set_tensor_backend(sched.get(), cur, backend_cpu); } } - write(&n_outputs, sizeof(n_outputs)); - - if (n_outputs) { - write(output_pos.data(), n_outputs * sizeof(int32_t)); - } - } - - void write_logits(const struct llama_context * ctx) { - const uint64_t logits_size = std::min((uint64_t) ctx->logits_size, (uint64_t) ctx->n_outputs * ctx->model.vocab.n_tokens()); - - write(&logits_size, sizeof(logits_size)); - - if (logits_size) { - write(ctx->logits, logits_size * sizeof(float)); - } - } - - void write_embeddings(const struct llama_context * ctx) { - const uint64_t embeddings_size = std::min((uint64_t) ctx->embd_size, (uint64_t) ctx->n_outputs * ctx->model.hparams.n_embd); - - write(&embeddings_size, sizeof(embeddings_size)); - - if (embeddings_size) { - write(ctx->embd, embeddings_size * sizeof(float)); - } - } - - void write_kv_cache_meta(const llama_kv_cache & kv_self, const std::vector> & cell_ranges, llama_seq_id seq_id = -1) { - for (const auto & range : cell_ranges) { - for (uint32_t i = range.first; i < range.second; ++i) { - const auto & cell = kv_self.cells[i]; - const llama_pos pos = cell.pos; - const uint32_t n_seq_id = seq_id == -1 ? cell.seq_id.size() : 0; - - write(&pos, sizeof(pos)); - write(&n_seq_id, sizeof(n_seq_id)); - - if (n_seq_id) { - for (auto seq_id : cell.seq_id) { - write(&seq_id, sizeof(seq_id)); - } - } - } - } - } - - void write_kv_cache_data(const struct llama_context * ctx, const std::vector> & cell_ranges) { - const struct llama_kv_cache & kv_self = ctx->kv_self; - const struct llama_hparams & hparams = ctx->model.hparams; - - const uint32_t v_trans = kv_self.v_trans ? 1 : 0; - const uint32_t n_layer = hparams.n_layer; - - write(&v_trans, sizeof(v_trans)); - write(&n_layer, sizeof(n_layer)); - - std::vector tmp_buf; - - // Iterate and write all the keys first, each row is a cell - // Get whole range at a time - for (uint32_t il = 0; il < n_layer; ++il) { - const uint32_t n_embd_k_gqa = hparams.n_embd_k_gqa(il) + hparams.n_embd_k_s(); - - // Write key type - const int32_t k_type_i = (int32_t)kv_self.k_l[il]->type; - write(&k_type_i, sizeof(k_type_i)); - - // Write row size of key - const uint64_t k_size_row = ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa); - write(&k_size_row, sizeof(k_size_row)); - - // Read each range of cells of k_size length each into tmp_buf and write out - for (const auto & range : cell_ranges) { - const size_t range_size = range.second - range.first; - const size_t buf_size = range_size * k_size_row; - write_tensor_data(kv_self.k_l[il], range.first * k_size_row, buf_size); - } - } - - if (!kv_self.v_trans) { - for (uint32_t il = 0; il < n_layer; ++il) { - const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); - - // Write value type - const int32_t v_type_i = (int32_t)kv_self.v_l[il]->type; - write(&v_type_i, sizeof(v_type_i)); - - // Write row size of value - const uint64_t v_size_row = ggml_row_size(kv_self.v_l[il]->type, n_embd_v_gqa); - write(&v_size_row, sizeof(v_size_row)); - - // Read each range of cells of v_size length each into tmp_buf and write out - for (const auto & range : cell_ranges) { - const size_t range_size = range.second - range.first; - const size_t buf_size = range_size * v_size_row; - write_tensor_data(kv_self.v_l[il], range.first * v_size_row, buf_size); - } - } - } else { - // When v is transposed, we also need the element size and get the element ranges from each row - const uint32_t kv_size = kv_self.size; - for (uint32_t il = 0; il < n_layer; ++il) { - const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); - - // Write value type - const int32_t v_type_i = (int32_t)kv_self.v_l[il]->type; - write(&v_type_i, sizeof(v_type_i)); - - // Write element size - const uint32_t v_size_el = ggml_type_size(kv_self.v_l[il]->type); - write(&v_size_el, sizeof(v_size_el)); - - // Write GQA embedding size - write(&n_embd_v_gqa, sizeof(n_embd_v_gqa)); - - // For each row, we get the element values of each cell - for (uint32_t j = 0; j < n_embd_v_gqa; ++j) { - // Read each range of cells of v_size_el length each into tmp_buf and write out - for (const auto & range : cell_ranges) { - const size_t range_size = range.second - range.first; - const size_t src_offset = (range.first + j * kv_size) * v_size_el; - const size_t buf_size = range_size * v_size_el; - write_tensor_data(kv_self.v_l[il], src_offset, buf_size); - } - } - } - } - } - - void write_kv_cache(const struct llama_context * ctx, llama_seq_id seq_id = -1) { - const struct llama_kv_cache & kv_self = ctx->kv_self; - std::vector> cell_ranges; // ranges, from inclusive, to exclusive - uint32_t cell_count = 0; - - // Count the number of cells with the specified seq_id - // Find all the ranges of cells with this seq id (or all, when -1) - uint32_t cell_range_begin = kv_self.size; - for (uint32_t i = 0; i < kv_self.size; ++i) { - const auto & cell = kv_self.cells[i]; - if ((seq_id == -1 && !cell.is_empty()) || cell.has_seq_id(seq_id)) { - ++cell_count; - if (cell_range_begin == kv_self.size) { - cell_range_begin = i; - } - } else { - if (cell_range_begin != kv_self.size) { - cell_ranges.emplace_back(cell_range_begin, i); - cell_range_begin = kv_self.size; - } - } - } - if (cell_range_begin != kv_self.size) { - cell_ranges.emplace_back(cell_range_begin, kv_self.size); - } - - // DEBUG CHECK: Sum of cell counts in ranges should equal the total cell count - uint32_t cell_count_check = 0; - for (const auto & range : cell_ranges) { - cell_count_check += range.second - range.first; - } - GGML_ASSERT(cell_count == cell_count_check); - - write(&cell_count, sizeof(cell_count)); - - write_kv_cache_meta(kv_self, cell_ranges, seq_id); - write_kv_cache_data(ctx, cell_ranges); - } -}; - -struct llama_data_read { - virtual const uint8_t * read(size_t size) = 0; - virtual void read_to(void * dst, size_t size) = 0; - virtual size_t get_size_read() = 0; - virtual ~llama_data_read() = default; - - void read_string(std::string & str) { - uint32_t str_size; - read_to(&str_size, sizeof(str_size)); - - str.assign((const char *) read(str_size), str_size); - } - - // validate model information - void read_model_info(const struct llama_context * ctx) { - const std::string cur_arch_str = llm_arch_name(ctx->model.arch); - - std::string arch_str; - read_string(arch_str); - if (cur_arch_str != arch_str) { - throw std::runtime_error(format("wrong model arch: '%s' instead of '%s'", arch_str.c_str(), cur_arch_str.c_str())); - } - // TODO: add more info which needs to be identical but which is not verified otherwise - } - - //void read_rng(std::mt19937 & rng) { - // std::string rng_str; - // read_string(rng_str); - - // std::istringstream rng_ss(rng_str); - // rng_ss >> rng; - - // if (rng_ss.fail()) { - // throw std::runtime_error("failed to load RNG state"); - // } - //} - - void read_output_ids(struct llama_context * ctx) { - std::vector output_pos; - - uint32_t n_outputs; - read_to(&n_outputs, sizeof(n_outputs)); - - if (n_outputs > llama_output_reserve(*ctx, n_outputs)) { - throw std::runtime_error("could not reserve outputs"); - } - - if (n_outputs) { - output_pos.resize(n_outputs); - read_to(output_pos.data(), n_outputs * sizeof(int32_t)); - - for (int32_t i = 0; i < (int32_t) output_pos.size(); ++i) { - int32_t id = output_pos[i]; - if ((uint32_t) id >= ctx->cparams.n_batch) { - throw std::runtime_error(format("invalid output id, %d does not fit in batch size of %u", id, ctx->cparams.n_batch)); - } - ctx->output_ids[id] = i; - } - - ctx->n_outputs = n_outputs; - } - } - - void read_logits(struct llama_context * ctx) { - uint64_t logits_size; - read_to(&logits_size, sizeof(logits_size)); - - if (ctx->logits_size < logits_size) { - throw std::runtime_error("logits buffer too small"); - } - - if (logits_size) { - read_to(ctx->logits, logits_size * sizeof(float)); - } - } - - void read_embeddings(struct llama_context * ctx) { - uint64_t embeddings_size; - read_to(&embeddings_size, sizeof(embeddings_size)); - - if (ctx->embd_size < embeddings_size) { - throw std::runtime_error("embeddings buffer too small"); - } - - if (embeddings_size) { - read_to(ctx->embd, embeddings_size * sizeof(float)); - } - } - - bool read_kv_cache_meta(struct llama_context * ctx, uint32_t cell_count, llama_seq_id dest_seq_id = -1) { - struct llama_kv_cache & kv_self = ctx->kv_self; - - if (dest_seq_id != -1) { - // single sequence - - llama_kv_cache_seq_rm(kv_self, dest_seq_id, -1, -1); - - llama_ubatch batch = ctx->sbatch.reserve_ubatch(cell_count, /* has_embd */ false); - batch.n_tokens = cell_count; - batch.n_seq_tokens = cell_count; - batch.n_seqs = 1; - - for (uint32_t i = 0; i < cell_count; ++i) { - llama_pos pos; - uint32_t n_seq_id; - - read_to(&pos, sizeof(pos)); - read_to(&n_seq_id, sizeof(n_seq_id)); - - if (n_seq_id != 0) { - LLAMA_LOG_ERROR("%s: invalid seq_id-agnostic kv cell\n", __func__); - return false; - } - - batch.pos[i] = pos; - } - batch.n_seq_id[0] = 1; - batch.seq_id[0] = &dest_seq_id; - if (!llama_kv_cache_find_slot(kv_self, batch)) { - LLAMA_LOG_ERROR("%s: failed to find available cells in kv cache\n", __func__); - return false; - } - - // DEBUG CHECK: kv_self.head should be our first cell, kv_self.head + cell_count - 1 should be our last cell (verify seq_id and pos values) - // Assume that this is one contiguous block of cells - GGML_ASSERT(kv_self.head + cell_count <= kv_self.size); - GGML_ASSERT(kv_self.cells[kv_self.head].pos == batch.pos[0]); - GGML_ASSERT(kv_self.cells[kv_self.head + cell_count - 1].pos == batch.pos[cell_count - 1]); - GGML_ASSERT(kv_self.cells[kv_self.head].has_seq_id(dest_seq_id)); - GGML_ASSERT(kv_self.cells[kv_self.head + cell_count - 1].has_seq_id(dest_seq_id)); - } else { - // whole KV cache restore - - if (cell_count > kv_self.size) { - LLAMA_LOG_ERROR("%s: not enough cells in kv cache\n", __func__); - return false; - } - - llama_kv_cache_clear(kv_self); - - for (uint32_t i = 0; i < cell_count; ++i) { - llama_kv_cell & cell = kv_self.cells[i]; - - llama_pos pos; - uint32_t n_seq_id; - - read_to(&pos, sizeof(pos)); - read_to(&n_seq_id, sizeof(n_seq_id)); - - cell.pos = pos; - - for (uint32_t j = 0; j < n_seq_id; ++j) { - llama_seq_id seq_id; - read_to(&seq_id, sizeof(seq_id)); - - if (seq_id < 0 || (uint32_t) seq_id >= llama_n_seq_max(ctx)) { - LLAMA_LOG_ERROR("%s: invalid seq_id, %d is out of range [0, %u)\n", __func__, seq_id, llama_n_seq_max(ctx)); - return false; - } - - cell.seq_id.insert(seq_id); - - if (kv_self.recurrent) { - int32_t & tail = kv_self.cells[seq_id].tail; - if (tail != -1) { - LLAMA_LOG_ERROR("%s: duplicate tail for seq_id %d in cell %d and %d\n", __func__, seq_id, i, tail); - return false; + // norm may be automatically assigned to the backend of the previous layer, increasing data transfer between backends + // FIXME: fix in ggml_backend_sched + const bool full_offload = model.params.n_gpu_layers > (int) model.hparams.n_layer; + if (ubatch.n_tokens < 32 || full_offload) { + if (il != -1 && strcmp(name, "norm") == 0) { + const auto & dev_layer = model.dev_layer(il); + for (const auto & backend : backends) { + if (ggml_backend_get_device(backend.get()) == dev_layer) { + if (ggml_backend_supports_op(backend.get(), cur)) { + ggml_backend_sched_set_tensor_backend(sched.get(), cur, backend.get()); } - tail = i; - } - } - } - - kv_self.head = 0; - kv_self.used = cell_count; - } - - if (kv_self.recurrent) { - for (uint32_t i = 0; i < cell_count; ++i) { - uint32_t cell_id = kv_self.head + i; - // make sure the recurrent states will keep their restored state - kv_self.cells[cell_id].src = cell_id; - } - } - - return true; - } - - bool read_kv_cache_data(struct llama_context * ctx, uint32_t cell_count) { - const struct llama_hparams & hparams = ctx->model.hparams; - struct llama_kv_cache & kv_self = ctx->kv_self; - uint32_t v_trans; - uint32_t n_layer; - read_to(&v_trans, sizeof(v_trans)); - read_to(&n_layer, sizeof(n_layer)); - - if (n_layer != hparams.n_layer) { - LLAMA_LOG_ERROR("%s: mismatched layer count (%u instead of %u)\n", __func__, n_layer, hparams.n_layer); - return false; - } - if (cell_count > kv_self.size) { - LLAMA_LOG_ERROR("%s: not enough cells in kv cache to restore state (%u > %u)\n", __func__, cell_count, kv_self.size); - return false; - } - if (kv_self.v_trans != (bool) v_trans) { - LLAMA_LOG_ERROR("%s: incompatible V transposition\n", __func__); - return false; - } - - // For each layer, read the keys for each cell, one row is one cell, read as one contiguous block - for (uint32_t il = 0; il < n_layer; ++il) { - const uint32_t n_embd_k_gqa = hparams.n_embd_k_gqa(il) + hparams.n_embd_k_s(); - - // Read type of key - int32_t k_type_i_ref; - read_to(&k_type_i_ref, sizeof(k_type_i_ref)); - const int32_t k_type_i = (int32_t)kv_self.k_l[il]->type; - if (k_type_i != k_type_i_ref) { - LLAMA_LOG_ERROR("%s: mismatched key type (%d != %d, layer %d)\n", __func__, k_type_i, k_type_i_ref, il); - return false; - } - - // Read row size of key - uint64_t k_size_row_ref; - read_to(&k_size_row_ref, sizeof(k_size_row_ref)); - const size_t k_size_row = ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa); - if (k_size_row != k_size_row_ref) { - LLAMA_LOG_ERROR("%s: mismatched key row size (%zu != %zu, layer %d)\n", __func__, k_size_row, (size_t) k_size_row_ref, il); - return false; - } - - if (cell_count) { - // Read and set the keys for the whole cell range - ggml_backend_tensor_set(kv_self.k_l[il], read(cell_count * k_size_row), kv_self.head * k_size_row, cell_count * k_size_row); - } - } - - if (!kv_self.v_trans) { - for (uint32_t il = 0; il < n_layer; ++il) { - const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); - - // Read type of value - int32_t v_type_i_ref; - read_to(&v_type_i_ref, sizeof(v_type_i_ref)); - const int32_t v_type_i = (int32_t)kv_self.v_l[il]->type; - if (v_type_i != v_type_i_ref) { - LLAMA_LOG_ERROR("%s: mismatched value type (%d != %d, layer %d)\n", __func__, v_type_i, v_type_i_ref, il); - return false; - } - - // Read row size of value - uint64_t v_size_row_ref; - read_to(&v_size_row_ref, sizeof(v_size_row_ref)); - const size_t v_size_row = ggml_row_size(kv_self.v_l[il]->type, n_embd_v_gqa); - if (v_size_row != v_size_row_ref) { - LLAMA_LOG_ERROR("%s: mismatched value row size (%zu != %zu, layer %d)\n", __func__, v_size_row, (size_t) v_size_row_ref, il); - return false; - } - - if (cell_count) { - // Read and set the values for the whole cell range - ggml_backend_tensor_set(kv_self.v_l[il], read(cell_count * v_size_row), kv_self.head * v_size_row, cell_count * v_size_row); - } - } - } else { - // For each layer, read the values for each cell (transposed) - for (uint32_t il = 0; il < n_layer; ++il) { - const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); - - // Read type of value - int32_t v_type_i_ref; - read_to(&v_type_i_ref, sizeof(v_type_i_ref)); - const int32_t v_type_i = (int32_t)kv_self.v_l[il]->type; - if (v_type_i != v_type_i_ref) { - LLAMA_LOG_ERROR("%s: mismatched value type (%d != %d, layer %d)\n", __func__, v_type_i, v_type_i_ref, il); - return false; - } - - // Read element size of value - uint32_t v_size_el_ref; - read_to(&v_size_el_ref, sizeof(v_size_el_ref)); - const size_t v_size_el = ggml_type_size(kv_self.v_l[il]->type); - if (v_size_el != v_size_el_ref) { - LLAMA_LOG_ERROR("%s: mismatched value element size (%zu != %zu, layer %d)\n", __func__, v_size_el, (size_t) v_size_el_ref, il); - return false; - } - - // Read GQA embedding size - uint32_t n_embd_v_gqa_ref; - read_to(&n_embd_v_gqa_ref, sizeof(n_embd_v_gqa_ref)); - if (n_embd_v_gqa != n_embd_v_gqa_ref) { - LLAMA_LOG_ERROR("%s: mismatched GQA embedding size (%u != %u, layer %d)\n", __func__, n_embd_v_gqa, n_embd_v_gqa_ref, il); - return false; - } - - if (cell_count) { - // For each row in the transposed matrix, read the values for the whole cell range - for (uint32_t j = 0; j < n_embd_v_gqa; ++j) { - const size_t dst_offset = (kv_self.head + j * kv_self.size) * v_size_el; - ggml_backend_tensor_set(kv_self.v_l[il], read(cell_count * v_size_el), dst_offset, cell_count * v_size_el); } } } } - return true; - } + }; +} - void read_kv_cache(struct llama_context * ctx, llama_seq_id seq_id = -1) { - uint32_t cell_count; - read_to(&cell_count, sizeof(cell_count)); +// +// state save/load +// - bool res = read_kv_cache_meta(ctx, cell_count, seq_id) && read_kv_cache_data(ctx, cell_count); - - if (!res) { - if (seq_id == -1) { - llama_kv_cache_clear(ctx); - } else { - llama_kv_cache_seq_rm(ctx, seq_id, -1, -1); - } - throw std::runtime_error("failed to restore kv cache"); - } - } -}; - -struct llama_data_write_dummy : llama_data_write { - size_t size_written = 0; - - llama_data_write_dummy() {} +class llama_io_write_dummy : public llama_io_write_i { +public: + llama_io_write_dummy() = default; void write(const void * /* src */, size_t size) override { size_written += size; } - void write_tensor_data(const struct ggml_tensor * /* tensor */, size_t /* offset */, size_t size) override { + void write_tensor(const ggml_tensor * /* tensor */, size_t /* offset */, size_t size) override { size_written += size; } - size_t get_size_written() override { + size_t n_bytes() override { return size_written; } + +private: + size_t size_written = 0; }; -struct llama_data_write_buffer : llama_data_write { - uint8_t * ptr; - size_t buf_size = 0; - size_t size_written = 0; - - llama_data_write_buffer(uint8_t * p, size_t len) : ptr(p), buf_size(len) {} +class llama_io_write_buffer : public llama_io_write_i { +public: + llama_io_write_buffer( + uint8_t * p, size_t len) : ptr(p), buf_size(len) {} void write(const void * src, size_t size) override { if (size > buf_size) { @@ -1406,7 +1724,7 @@ struct llama_data_write_buffer : llama_data_write { buf_size -= size; } - void write_tensor_data(const struct ggml_tensor * tensor, size_t offset, size_t size) override { + void write_tensor(const ggml_tensor * tensor, size_t offset, size_t size) override { if (size > buf_size) { throw std::runtime_error("unexpectedly reached end of buffer"); } @@ -1416,17 +1734,19 @@ struct llama_data_write_buffer : llama_data_write { buf_size -= size; } - size_t get_size_written() override { + size_t n_bytes() override { return size_written; } + +private: + uint8_t * ptr; + size_t buf_size = 0; + size_t size_written = 0; }; -struct llama_data_read_buffer : llama_data_read { - const uint8_t * ptr; - size_t buf_size = 0; - size_t size_read = 0; - - llama_data_read_buffer(const uint8_t * p, size_t len) : ptr(p), buf_size(len) {} +class llama_io_read_buffer : public llama_io_read_i { +public: + llama_io_read_buffer(const uint8_t * p, size_t len) : ptr(p), buf_size(len) {} const uint8_t * read(size_t size) override { const uint8_t * base_ptr = ptr; @@ -1443,40 +1763,44 @@ struct llama_data_read_buffer : llama_data_read { memcpy(dst, read(size), size); } - size_t get_size_read() override { + size_t n_bytes() override { return size_read; } + +private: + const uint8_t * ptr; + size_t buf_size = 0; + size_t size_read = 0; }; -struct llama_data_write_file : llama_data_write { - llama_file * file; - size_t size_written = 0; - std::vector temp_buffer; - - llama_data_write_file(llama_file * f) : file(f) {} +class llama_io_write_file : public llama_io_write_i { +public: + llama_io_write_file(llama_file * f) : file(f) {} void write(const void * src, size_t size) override { file->write_raw(src, size); size_written += size; } - void write_tensor_data(const struct ggml_tensor * tensor, size_t offset, size_t size) override { + void write_tensor(const ggml_tensor * tensor, size_t offset, size_t size) override { temp_buffer.resize(size); ggml_backend_tensor_get(tensor, temp_buffer.data(), offset, size); write(temp_buffer.data(), temp_buffer.size()); } - size_t get_size_written() override { + size_t n_bytes() override { return size_written; } + +private: + llama_file * file; + size_t size_written = 0; + std::vector temp_buffer; }; -struct llama_data_read_file : llama_data_read { - llama_file * file; - size_t size_read = 0; - std::vector temp_buffer; - - llama_data_read_file(llama_file * f) : file(f) {} +class llama_io_read_file : public llama_io_read_i { +public: + llama_io_read_file(llama_file * f) : file(f) {} void read_to(void * dst, size_t size) override { file->read_raw(dst, size); @@ -1489,89 +1813,78 @@ struct llama_data_read_file : llama_data_read { return temp_buffer.data(); } - size_t get_size_read() override { + size_t n_bytes() override { return size_read; } + +private: + llama_file * file; + size_t size_read = 0; + std::vector temp_buffer; }; -/** copy state data into either a buffer or file depending on the passed in context - * - * file context: - * llama_file file("/path", "wb"); - * llama_data_write_file data_ctx(&file); - * llama_state_get_data_internal(ctx, data_ctx); - * - * buffer context: - * std::vector buf(max_size, 0); - * llama_data_write_buffer data_ctx(buf.data(), max_size); - * llama_state_get_data_internal(ctx, data_ctx); - * -*/ -static size_t llama_state_get_data_internal(struct llama_context * ctx, llama_data_write & data_ctx) { - llama_synchronize(ctx); - - data_ctx.write_model_info(ctx); - - // copy outputs - data_ctx.write_output_ids(ctx); - data_ctx.write_logits(ctx); - data_ctx.write_embeddings(ctx); - - data_ctx.write_kv_cache(ctx); - - return data_ctx.get_size_written(); -} - -size_t llama_state_get_data(struct llama_context * ctx, uint8_t * dst, size_t size) { - llama_data_write_buffer data_ctx(dst, size); +size_t llama_context::state_get_size() { + llama_io_write_dummy io; try { - return llama_state_get_data_internal(ctx, data_ctx); - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: error saving state: %s\n", __func__, err.what()); - return 0; - } -} - -// Returns the *actual* size of the state. -// Intended to be used when saving to state to a buffer. -size_t llama_state_get_size(struct llama_context * ctx) { - llama_data_write_dummy data_ctx; - try { - return llama_state_get_data_internal(ctx, data_ctx); + return state_write_data(io); } catch (const std::exception & err) { LLAMA_LOG_ERROR("%s: error getting state size: %s\n", __func__, err.what()); return 0; } } -static size_t llama_state_set_data_internal(struct llama_context * ctx, llama_data_read & data_ctx) { - llama_synchronize(ctx); - - data_ctx.read_model_info(ctx); - - // set outputs - data_ctx.read_output_ids(ctx); - data_ctx.read_logits(ctx); - data_ctx.read_embeddings(ctx); - - data_ctx.read_kv_cache(ctx); - - return data_ctx.get_size_read(); +size_t llama_context::state_get_data(uint8_t * dst, size_t size) { + llama_io_write_buffer io(dst, size); + try { + return state_write_data(io); + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: error saving state: %s\n", __func__, err.what()); + return 0; + } } -// Sets the state reading from the specified source address -size_t llama_state_set_data(struct llama_context * ctx, const uint8_t * src, size_t size) { - llama_data_read_buffer data_ctx(src, size); +size_t llama_context::state_set_data(const uint8_t * src, size_t size) { + llama_io_read_buffer io(src, size); try { - return llama_state_set_data_internal(ctx, data_ctx); + return state_read_data(io); } catch (const std::exception & err) { LLAMA_LOG_ERROR("%s: error loading state: %s\n", __func__, err.what()); return 0; } } -static bool llama_state_load_file_internal(struct llama_context * ctx, const char * path_session, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { - llama_file file(path_session, "rb"); +size_t llama_context::state_seq_get_size(llama_seq_id seq_id) { + llama_io_write_dummy io; + try { + return state_seq_write_data(io, seq_id); + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: error getting state size: %s\n", __func__, err.what()); + return 0; + } +} + +size_t llama_context::state_seq_get_data(llama_seq_id seq_id, uint8_t * dst, size_t size) { + llama_io_write_buffer io(dst, size); + try { + return state_seq_write_data(io, seq_id); + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: error saving state: %s\n", __func__, err.what()); + return 0; + } +} + +size_t llama_context::state_seq_set_data(llama_seq_id seq_id, const uint8_t * src, size_t size) { + llama_io_read_buffer io(src, size); + try { + return state_seq_read_data(io, seq_id); + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: error loading state: %s\n", __func__, err.what()); + return 0; + } +} + +bool llama_context::state_load_file(const char * filepath, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { + llama_file file(filepath, "rb"); // sanity checks { @@ -1601,28 +1914,20 @@ static bool llama_state_load_file_internal(struct llama_context * ctx, const cha { const size_t n_state_size_cur = file.size() - file.tell(); - llama_data_read_file data_ctx(&file); - const size_t n_read = llama_state_set_data_internal(ctx, data_ctx); + llama_io_read_file io( &file); + const size_t n_read = state_read_data(io); if (n_read != n_state_size_cur) { LLAMA_LOG_ERROR("%s: did not read all of the session file data! size %zu, got %zu\n", __func__, n_state_size_cur, n_read); return false; } } + return true; } -bool llama_state_load_file(struct llama_context * ctx, const char * path_session, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { - try { - return llama_state_load_file_internal(ctx, path_session, tokens_out, n_token_capacity, n_token_count_out); - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: error loading session file: %s\n", __func__, err.what()); - return false; - } -} - -static bool llama_state_save_file_internal(struct llama_context * ctx, const char * path_session, const llama_token * tokens, size_t n_token_count) { - llama_file file(path_session, "wb"); +bool llama_context::state_save_file(const char * filepath, const llama_token * tokens, size_t n_token_count) { + llama_file file(filepath, "wb"); file.write_u32(LLAMA_SESSION_MAGIC); file.write_u32(LLAMA_SESSION_VERSION); @@ -1632,82 +1937,13 @@ static bool llama_state_save_file_internal(struct llama_context * ctx, const cha file.write_raw(tokens, sizeof(llama_token) * n_token_count); // save the context state using stream saving - llama_data_write_file data_ctx(&file); - llama_state_get_data_internal(ctx, data_ctx); + llama_io_write_file io(&file); + state_write_data(io); return true; } -bool llama_state_save_file(struct llama_context * ctx, const char * path_session, const llama_token * tokens, size_t n_token_count) { - try { - return llama_state_save_file_internal(ctx, path_session, tokens, n_token_count); - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: error saving session file: %s\n", __func__, err.what()); - return false; - } -} - -static size_t llama_state_seq_get_data_internal(struct llama_context * ctx, llama_data_write & data_ctx, llama_seq_id seq_id) { - llama_synchronize(ctx); - - data_ctx.write_kv_cache(ctx, seq_id); - - return data_ctx.get_size_written(); -} - -size_t llama_state_seq_get_size(struct llama_context * ctx, llama_seq_id seq_id) { - llama_data_write_dummy data_ctx; - return llama_state_seq_get_data_internal(ctx, data_ctx, seq_id); -} - -size_t llama_state_seq_get_data(struct llama_context * ctx, uint8_t * dst, size_t size, llama_seq_id seq_id) { - llama_data_write_buffer data_ctx(dst, size); - try { - return llama_state_seq_get_data_internal(ctx, data_ctx, seq_id); - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: error saving sequence state: %s\n", __func__, err.what()); - return 0; - } -} - -static size_t llama_state_seq_set_data_internal(struct llama_context * ctx, llama_data_read & data_ctx, llama_seq_id dest_seq_id) { - llama_synchronize(ctx); - - data_ctx.read_kv_cache(ctx, dest_seq_id); - - return data_ctx.get_size_read(); -} - -size_t llama_state_seq_set_data(struct llama_context * ctx, const uint8_t * src, size_t size, llama_seq_id dest_seq_id) { - llama_data_read_buffer data_ctx(src, size); - try { - return llama_state_seq_set_data_internal(ctx, data_ctx, dest_seq_id); - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: error loading sequence state: %s\n", __func__, err.what()); - return 0; - } -} - -static size_t llama_state_seq_save_file_internal(struct llama_context * ctx, const char * filepath, llama_seq_id seq_id, const llama_token * tokens, size_t n_token_count) { - llama_file file(filepath, "wb"); - - file.write_u32(LLAMA_STATE_SEQ_MAGIC); - file.write_u32(LLAMA_STATE_SEQ_VERSION); - - // save the prompt - file.write_u32((uint32_t) n_token_count); - file.write_raw(tokens, sizeof(llama_token) * n_token_count); - - // save the context state using stream saving - llama_data_write_file data_ctx(&file); - llama_state_seq_get_data_internal(ctx, data_ctx, seq_id); - - const size_t res = file.tell(); - GGML_ASSERT(res == sizeof(uint32_t) * 3 + sizeof(llama_token) * n_token_count + data_ctx.get_size_written()); - return res; -} - -static size_t llama_state_seq_load_file_internal(struct llama_context * ctx, const char * filepath, llama_seq_id dest_seq_id, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { +size_t llama_context::state_seq_load_file(llama_seq_id seq_id, const char * filepath, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { llama_file file(filepath, "rb"); // version checks @@ -1737,8 +1973,8 @@ static size_t llama_state_seq_load_file_internal(struct llama_context * ctx, con // restore the context state { const size_t state_size = file.size() - file.tell(); - llama_data_read_file data_ctx(&file); - const size_t nread = llama_state_seq_set_data_internal(ctx, data_ctx, dest_seq_id); + llama_io_read_file io(&file); + const size_t nread = state_seq_read_data(io, seq_id); if (!nread) { LLAMA_LOG_ERROR("%s: failed to restore sequence state\n", __func__); return 0; @@ -1750,26 +1986,785 @@ static size_t llama_state_seq_load_file_internal(struct llama_context * ctx, con return file.tell(); } -size_t llama_state_seq_save_file(struct llama_context * ctx, const char * filepath, llama_seq_id seq_id, const llama_token * tokens, size_t n_token_count) { +size_t llama_context::state_seq_save_file(llama_seq_id seq_id, const char * filepath, const llama_token * tokens, size_t n_token_count) { + llama_file file(filepath, "wb"); + + file.write_u32(LLAMA_STATE_SEQ_MAGIC); + file.write_u32(LLAMA_STATE_SEQ_VERSION); + + // save the prompt + file.write_u32((uint32_t) n_token_count); + file.write_raw(tokens, sizeof(llama_token) * n_token_count); + + // save the context state using stream saving + llama_io_write_file io(&file); + state_seq_write_data(io, seq_id); + + const size_t res = file.tell(); + GGML_ASSERT(res == sizeof(uint32_t) * 3 + sizeof(llama_token) * n_token_count + io.n_bytes()); + + return res; +} + +size_t llama_context::state_write_data(llama_io_write_i & io) { + LLAMA_LOG_DEBUG("%s: writing state\n", __func__); + + // write model info + { + LLAMA_LOG_DEBUG("%s: - writing model info\n", __func__); + + const std::string arch_str = llm_arch_name(model.arch); + io.write_string(arch_str); + // TODO: add more model-specific info which should prevent loading the session file if not identical + } + + // write output ids + { + LLAMA_LOG_DEBUG("%s: - writing output ids\n", __func__); + + output_reorder(); + + const auto n_outputs = this->n_outputs; + const auto & output_ids = this->output_ids; + + std::vector w_output_pos; + + GGML_ASSERT(n_outputs <= n_outputs_max); + + w_output_pos.resize(n_outputs); + + // build a more compact representation of the output ids + for (size_t i = 0; i < n_batch(); ++i) { + // map an output id to a position in the batch + int32_t pos = output_ids[i]; + if (pos >= 0) { + GGML_ASSERT(pos < n_outputs); + w_output_pos[pos] = i; + } + } + + io.write(&n_outputs, sizeof(n_outputs)); + + if (n_outputs) { + io.write(w_output_pos.data(), n_outputs * sizeof(int32_t)); + } + } + + // write logits + { + LLAMA_LOG_DEBUG("%s: - writing logits\n", __func__); + + const uint64_t logits_size = std::min((uint64_t) this->logits_size, (uint64_t) n_outputs * model.vocab.n_tokens()); + + io.write(&logits_size, sizeof(logits_size)); + + if (logits_size) { + io.write(logits, logits_size * sizeof(float)); + } + } + + // write embeddings + { + LLAMA_LOG_DEBUG("%s: - writing embeddings\n", __func__); + + const uint64_t embd_size = std::min((uint64_t) this->embd_size, (uint64_t) n_outputs * model.hparams.n_embd); + + io.write(&embd_size, sizeof(embd_size)); + + if (embd_size) { + io.write(embd, embd_size * sizeof(float)); + } + } + + LLAMA_LOG_DEBUG("%s: - writing KV self\n", __func__); + kv_self->state_write(io); + + return io.n_bytes(); +} + +size_t llama_context::state_read_data(llama_io_read_i & io) { + LLAMA_LOG_DEBUG("%s: reading state\n", __func__); + + // read model info + { + LLAMA_LOG_DEBUG("%s: - reading model info\n", __func__); + + const std::string cur_arch_str = llm_arch_name(model.arch); + + std::string arch_str; + io.read_string(arch_str); + if (cur_arch_str != arch_str) { + throw std::runtime_error(format("wrong model arch: '%s' instead of '%s'", arch_str.c_str(), cur_arch_str.c_str())); + } + // TODO: add more info which needs to be identical but which is not verified otherwise + } + + // read output ids + { + LLAMA_LOG_DEBUG("%s: - reading output ids\n", __func__); + + auto n_outputs = this->n_outputs; + io.read_to(&n_outputs, sizeof(n_outputs)); + + if (n_outputs > output_reserve(n_outputs)) { + throw std::runtime_error("could not reserve outputs"); + } + + std::vector output_pos; + + if (n_outputs) { + output_pos.resize(n_outputs); + io.read_to(output_pos.data(), n_outputs * sizeof(int32_t)); + + for (int32_t i = 0; i < (int32_t) output_pos.size(); ++i) { + int32_t id = output_pos[i]; + if ((uint32_t) id >= n_batch()) { + throw std::runtime_error(format("invalid output id, %d does not fit in batch size of %u", id, n_batch())); + } + this->output_ids[id] = i; + } + + this->n_outputs = n_outputs; + } + } + + // read logits + { + LLAMA_LOG_DEBUG("%s: - reading logits\n", __func__); + + uint64_t logits_size; + io.read_to(&logits_size, sizeof(logits_size)); + + if (this->logits_size < logits_size) { + throw std::runtime_error("logits buffer too small"); + } + + if (logits_size) { + io.read_to(this->logits, logits_size * sizeof(float)); + } + } + + // read embeddings + { + LLAMA_LOG_DEBUG("%s: - reading embeddings\n", __func__); + + uint64_t embd_size; + io.read_to(&embd_size, sizeof(embd_size)); + + if (this->embd_size < embd_size) { + throw std::runtime_error("embeddings buffer too small"); + } + + if (embd_size) { + io.read_to(this->embd, embd_size * sizeof(float)); + } + } + + LLAMA_LOG_DEBUG("%s: - reading KV self\n", __func__); + kv_self->state_read(io); + + return io.n_bytes(); +} + +size_t llama_context::state_seq_write_data(llama_io_write_i & io, llama_seq_id seq_id) { + GGML_UNUSED(seq_id); + + kv_self->state_write(io, seq_id); + + return io.n_bytes(); +} + +size_t llama_context::state_seq_read_data(llama_io_read_i & io, llama_seq_id seq_id) { + GGML_UNUSED(seq_id); + + kv_self->state_read(io, seq_id); + + return io.n_bytes(); +} + +// +// perf +// + +llama_perf_context_data llama_context::perf_get_data() const { + llama_perf_context_data data = {}; + + data.t_start_ms = 1e-3 * t_start_us; + data.t_load_ms = 1e-3 * t_load_us; + data.t_p_eval_ms = 1e-3 * t_p_eval_us; + data.t_eval_ms = 1e-3 * t_eval_us; + data.n_p_eval = std::max(1, n_p_eval); + data.n_eval = std::max(1, n_eval); + + return data; +} + +void llama_context::perf_reset() { + t_start_us = ggml_time_us(); + t_eval_us = n_eval = 0; + t_p_eval_us = n_p_eval = 0; +} + +// +// interface implementation +// + +llama_context_params llama_context_default_params() { + llama_context_params result = { + /*.n_ctx =*/ 512, + /*.n_batch =*/ 2048, + /*.n_ubatch =*/ 512, + /*.n_seq_max =*/ 1, + /*.n_threads =*/ GGML_DEFAULT_N_THREADS, // TODO: better default + /*.n_threads_batch =*/ GGML_DEFAULT_N_THREADS, + /*.rope_scaling_type =*/ LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED, + /*.pooling_type =*/ LLAMA_POOLING_TYPE_UNSPECIFIED, + /*.attention_type =*/ LLAMA_ATTENTION_TYPE_UNSPECIFIED, + /*.rope_freq_base =*/ 0.0f, + /*.rope_freq_scale =*/ 0.0f, + /*.yarn_ext_factor =*/ -1.0f, + /*.yarn_attn_factor =*/ 1.0f, + /*.yarn_beta_fast =*/ 32.0f, + /*.yarn_beta_slow =*/ 1.0f, + /*.yarn_orig_ctx =*/ 0, + /*.defrag_thold =*/ -1.0f, + /*.cb_eval =*/ nullptr, + /*.cb_eval_user_data =*/ nullptr, + /*.type_k =*/ GGML_TYPE_F16, + /*.type_v =*/ GGML_TYPE_F16, + /*.logits_all =*/ false, + /*.embeddings =*/ false, + /*.offload_kqv =*/ true, + /*.flash_attn =*/ false, + /*.no_perf =*/ true, + /*.abort_callback =*/ nullptr, + /*.abort_callback_data =*/ nullptr, + }; + + return result; +} + +llama_context * llama_init_from_model( + llama_model * model, + llama_context_params params) { + if (!model) { + LLAMA_LOG_ERROR("%s: model cannot be NULL\n", __func__); + return nullptr; + } + + if (params.n_batch == 0 && params.n_ubatch == 0) { + LLAMA_LOG_ERROR("%s: n_batch and n_ubatch cannot both be zero\n", __func__); + return nullptr; + } + + if (params.n_ctx == 0 && model->hparams.n_ctx_train == 0) { + LLAMA_LOG_ERROR("%s: n_ctx and model->hparams.n_ctx_train cannot both be zero\n", __func__); + return nullptr; + } + + if (params.flash_attn && model->arch == LLM_ARCH_GROK) { + LLAMA_LOG_WARN("%s: flash_attn is not compatible with Grok - forcing off\n", __func__); + params.flash_attn = false; + } + + if (params.flash_attn && model->hparams.n_embd_head_k != model->hparams.n_embd_head_v) { + LLAMA_LOG_WARN("%s: flash_attn requires n_embd_head_k == n_embd_head_v - forcing off\n", __func__); + params.flash_attn = false; + } + + if (ggml_is_quantized(params.type_v) && !params.flash_attn) { + LLAMA_LOG_ERROR("%s: V cache quantization requires flash_attn\n", __func__); + return nullptr; + } + try { - return llama_state_seq_save_file_internal(ctx, filepath, seq_id, tokens, n_token_count); + auto * ctx = new llama_context(*model, params); + return ctx; + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: failed to initialize the context: %s\n", __func__, err.what()); + } + + return nullptr; +} + +// deprecated +llama_context * llama_new_context_with_model( + llama_model * model, + llama_context_params params) { + return llama_init_from_model(model, params); +} + +void llama_free(llama_context * ctx) { + delete ctx; +} + +uint32_t llama_n_ctx(const llama_context * ctx) { + return ctx->n_ctx(); +} + +uint32_t llama_n_batch(const llama_context * ctx) { + return ctx->n_batch(); +} + +uint32_t llama_n_ubatch(const llama_context * ctx) { + return ctx->n_ubatch(); +} + +uint32_t llama_n_seq_max(const llama_context * ctx) { + return ctx->n_seq_max(); +} + +const llama_model * llama_get_model(const llama_context * ctx) { + return &ctx->get_model(); +} + +llama_kv_cache * llama_get_kv_self(llama_context * ctx) { + return ctx->get_kv_self(); +} + +void llama_kv_self_update(llama_context * ctx) { + ctx->kv_self_update(); +} + +enum llama_pooling_type llama_pooling_type(const llama_context * ctx) { + return ctx->pooling_type(); +} + +void llama_attach_threadpool( + llama_context * ctx, + ggml_threadpool_t threadpool, + ggml_threadpool_t threadpool_batch) { + ctx->attach_threadpool(threadpool, threadpool_batch); +} + +void llama_detach_threadpool(llama_context * ctx) { + ctx->detach_threadpool(); +} + +void llama_set_n_threads(llama_context * ctx, int32_t n_threads, int32_t n_threads_batch) { + ctx->set_n_threads(n_threads, n_threads_batch); +} + +int32_t llama_n_threads(llama_context * ctx) { + return ctx->n_threads(); +} + +int32_t llama_n_threads_batch(llama_context * ctx) { + return ctx->n_threads_batch(); +} + +void llama_set_abort_callback(llama_context * ctx, bool (*abort_callback)(void * data), void * abort_callback_data) { + ctx->set_abort_callback(abort_callback, abort_callback_data); +} + +void llama_set_embeddings(llama_context * ctx, bool embeddings) { + ctx->set_embeddings(embeddings); +} + +void llama_set_causal_attn(llama_context * ctx, bool causal_attn) { + ctx->set_causal_attn(causal_attn); +} + +void llama_synchronize(llama_context * ctx) { + ctx->synchronize(); +} + +float * llama_get_logits(llama_context * ctx) { + ctx->synchronize(); + + return ctx->get_logits(); +} + +float * llama_get_logits_ith(llama_context * ctx, int32_t i) { + ctx->synchronize(); + + return ctx->get_logits_ith(i); +} + +float * llama_get_embeddings(llama_context * ctx) { + ctx->synchronize(); + + return ctx->get_embeddings(); +} + +float * llama_get_embeddings_ith(llama_context * ctx, int32_t i) { + ctx->synchronize(); + + return ctx->get_embeddings_ith(i); +} + +float * llama_get_embeddings_seq(llama_context * ctx, llama_seq_id seq_id) { + ctx->synchronize(); + + return ctx->get_embeddings_seq(seq_id); +} + +// llama adapter API + +int32_t llama_set_adapter_lora( + llama_context * ctx, + llama_adapter_lora * adapter, + float scale) { + ctx->set_adapter_lora(adapter, scale); + + return 0; +} + +int32_t llama_rm_adapter_lora( + llama_context * ctx, + llama_adapter_lora * adapter) { + bool res = ctx->rm_adapter_lora(adapter); + + return res ? 0 : -1; +} + +void llama_clear_adapter_lora(llama_context * ctx) { + ctx->clear_adapter_lora(); +} + +int32_t llama_apply_adapter_cvec( + llama_context * ctx, + const float * data, + size_t len, + int32_t n_embd, + int32_t il_start, + int32_t il_end) { + bool res = ctx->apply_adapter_cvec(data, len, n_embd, il_start, il_end); + + return res ? 0 : -1; +} + +// +// kv cache view +// + +llama_kv_cache_view llama_kv_cache_view_init(const llama_context * ctx, int32_t n_seq_max) { + const auto * kv = ctx->get_kv_self(); + if (kv == nullptr) { + LLAMA_LOG_WARN("%s: the context does not have a KV cache\n", __func__); + return {}; + } + + return llama_kv_cache_view_init(*kv, n_seq_max); +} + +void llama_kv_cache_view_update(const llama_context * ctx, llama_kv_cache_view * view) { + const auto * kv = ctx->get_kv_self(); + if (kv == nullptr) { + LLAMA_LOG_WARN("%s: the context does not have a KV cache\n", __func__); + return; + } + + llama_kv_cache_view_update(view, kv); +} + +// +// kv cache +// + +// deprecated +int32_t llama_get_kv_cache_token_count(const llama_context * ctx) { + return llama_kv_self_n_tokens(ctx); +} + +int32_t llama_kv_self_n_tokens(const llama_context * ctx) { + return llama_kv_cache_n_tokens(ctx->get_kv_self()); +} + +// deprecated +int32_t llama_get_kv_cache_used_cells(const llama_context * ctx) { + return llama_kv_self_used_cells(ctx); +} + +int32_t llama_kv_self_used_cells(const llama_context * ctx) { + return llama_kv_cache_used_cells(ctx->get_kv_self()); +} + +// deprecated +void llama_kv_cache_clear(llama_context * ctx) { + llama_kv_self_clear(ctx); +} + +void llama_kv_self_clear(llama_context * ctx) { + llama_kv_cache_clear(ctx->get_kv_self()); +} + +// deprecated +bool llama_kv_cache_seq_rm( + llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1) { + return llama_kv_self_seq_rm(ctx, seq_id, p0, p1); +} + +bool llama_kv_self_seq_rm( + llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1) { + return llama_kv_cache_seq_rm(ctx->get_kv_self(), seq_id, p0, p1); +} + +// deprecated +void llama_kv_cache_seq_cp( + llama_context * ctx, + llama_seq_id seq_id_src, + llama_seq_id seq_id_dst, + llama_pos p0, + llama_pos p1) { + return llama_kv_self_seq_cp(ctx, seq_id_src, seq_id_dst, p0, p1); +} + +void llama_kv_self_seq_cp( + llama_context * ctx, + llama_seq_id seq_id_src, + llama_seq_id seq_id_dst, + llama_pos p0, + llama_pos p1) { + return llama_kv_cache_seq_cp(ctx->get_kv_self(), seq_id_src, seq_id_dst, p0, p1); +} + +// deprecated +void llama_kv_cache_seq_keep( + llama_context * ctx, + llama_seq_id seq_id) { + return llama_kv_self_seq_keep(ctx, seq_id); +} + +void llama_kv_self_seq_keep(llama_context * ctx, llama_seq_id seq_id) { + return llama_kv_cache_seq_keep(ctx->get_kv_self(), seq_id); +} + +// deprecated +void llama_kv_cache_seq_add( + llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + llama_pos delta) { + return llama_kv_self_seq_add(ctx, seq_id, p0, p1, delta); +} + +void llama_kv_self_seq_add( + llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + llama_pos delta) { + return llama_kv_cache_seq_add(ctx->get_kv_self(), seq_id, p0, p1, delta); +} + +// deprecated +void llama_kv_cache_seq_div( + llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + int d) { + return llama_kv_self_seq_div(ctx, seq_id, p0, p1, d); +} + +void llama_kv_self_seq_div( + llama_context * ctx, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + int d) { + return llama_kv_cache_seq_div(ctx->get_kv_self(), seq_id, p0, p1, d); +} + +// deprecated +llama_pos llama_kv_cache_seq_pos_max(llama_context * ctx, llama_seq_id seq_id) { + return llama_kv_self_seq_pos_max(ctx, seq_id); +} + +llama_pos llama_kv_self_seq_pos_max(llama_context * ctx, llama_seq_id seq_id) { + return llama_kv_cache_seq_pos_max(ctx->get_kv_self(), seq_id); +} + +// deprecated +void llama_kv_cache_defrag(llama_context * ctx) { + return llama_kv_self_defrag(ctx); +} + +void llama_kv_self_defrag(llama_context * ctx) { + llama_kv_cache_defrag(ctx->get_kv_self()); +} + +// deprecated +bool llama_kv_cache_can_shift(const llama_context * ctx) { + return llama_kv_self_can_shift(ctx); +} + +bool llama_kv_self_can_shift(const llama_context * ctx) { + return llama_kv_cache_can_shift(ctx->get_kv_self()); +} + +// deprecated +void llama_kv_cache_update(llama_context * ctx) { + llama_kv_self_update(ctx); +} + +// llama state API + +// deprecated +size_t llama_get_state_size(llama_context * ctx) { + return llama_state_get_size(ctx); +} + +// deprecated +size_t llama_copy_state_data(llama_context * ctx, uint8_t * dst) { + return llama_state_get_data(ctx, dst, -1); +} + +// deprecated +size_t llama_set_state_data(llama_context * ctx, const uint8_t * src) { + return llama_state_set_data(ctx, src, -1); +} + +// deprecated +bool llama_load_session_file(llama_context * ctx, const char * path_session, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { + return llama_state_load_file(ctx, path_session, tokens_out, n_token_capacity, n_token_count_out); +} + +// deprecated +bool llama_save_session_file(llama_context * ctx, const char * path_session, const llama_token * tokens, size_t n_token_count) { + return llama_state_save_file(ctx, path_session, tokens, n_token_count); +} + +// Returns the *actual* size of the state. +// Intended to be used when saving to state to a buffer. +size_t llama_state_get_size(llama_context * ctx) { + return ctx->state_get_size(); +} + +size_t llama_state_get_data(llama_context * ctx, uint8_t * dst, size_t size) { + ctx->synchronize(); + + return ctx->state_get_data(dst, size); +} + +// Sets the state reading from the specified source address +size_t llama_state_set_data(llama_context * ctx, const uint8_t * src, size_t size) { + ctx->synchronize(); + + return ctx->state_set_data(src, size); +} + +bool llama_state_load_file(llama_context * ctx, const char * path_session, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { + ctx->synchronize(); + + try { + return ctx->state_load_file(path_session, tokens_out, n_token_capacity, n_token_count_out); + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: error loading session file: %s\n", __func__, err.what()); + return false; + } +} + +bool llama_state_save_file(llama_context * ctx, const char * path_session, const llama_token * tokens, size_t n_token_count) { + ctx->synchronize(); + + try { + return ctx->state_save_file(path_session, tokens, n_token_count); + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: error saving session file: %s\n", __func__, err.what()); + return false; + } +} + +size_t llama_state_seq_get_size(llama_context * ctx, llama_seq_id seq_id) { + return ctx->state_seq_get_size(seq_id); +} + +size_t llama_state_seq_get_data(llama_context * ctx, uint8_t * dst, size_t size, llama_seq_id seq_id) { + ctx->synchronize(); + + return ctx->state_seq_get_data(seq_id, dst, size); +} + +size_t llama_state_seq_set_data(llama_context * ctx, const uint8_t * src, size_t size, llama_seq_id seq_id) { + ctx->synchronize(); + + return ctx->state_seq_set_data(seq_id, src, size); +} + +size_t llama_state_seq_save_file(llama_context * ctx, const char * filepath, llama_seq_id seq_id, const llama_token * tokens, size_t n_token_count) { + ctx->synchronize(); + + try { + return ctx->state_seq_save_file(seq_id, filepath, tokens, n_token_count); } catch (const std::exception & err) { LLAMA_LOG_ERROR("%s: error saving sequence state file: %s\n", __func__, err.what()); return 0; } } -size_t llama_state_seq_load_file(struct llama_context * ctx, const char * filepath, llama_seq_id dest_seq_id, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { +size_t llama_state_seq_load_file(llama_context * ctx, const char * filepath, llama_seq_id dest_seq_id, llama_token * tokens_out, size_t n_token_capacity, size_t * n_token_count_out) { + ctx->synchronize(); + try { - return llama_state_seq_load_file_internal(ctx, filepath, dest_seq_id, tokens_out, n_token_capacity, n_token_count_out); + return ctx->state_seq_load_file(dest_seq_id, filepath, tokens_out, n_token_capacity, n_token_count_out); } catch (const std::exception & err) { LLAMA_LOG_ERROR("%s: error loading sequence state file: %s\n", __func__, err.what()); return 0; } } -const std::vector> & llama_internal_get_tensor_map( - struct llama_context * ctx -) { - return ctx->model.tensors_by_name; +/// + +int32_t llama_encode( + llama_context * ctx, + llama_batch batch) { + const int ret = ctx->encode(batch); + if (ret != 0) { + LLAMA_LOG_ERROR("%s: failed to encode, ret = %d\n", __func__, ret); + } + + return ret; +} + +int32_t llama_decode( + llama_context * ctx, + llama_batch batch) { + const int ret = ctx->decode(batch); + if (ret != 0) { + LLAMA_LOG_ERROR("%s: failed to decode, ret = %d\n", __func__, ret); + } + + return ret; +} + +// +// perf +// + +llama_perf_context_data llama_perf_context(const llama_context * ctx) { + llama_perf_context_data data = {}; + + if (ctx == nullptr) { + return data; + } + + data = ctx->perf_get_data(); + + return data; +} + +void llama_perf_context_print(const llama_context * ctx) { + const auto data = llama_perf_context(ctx); + + const double t_end_ms = 1e-3 * ggml_time_us(); + + LLAMA_LOG_INFO("%s: load time = %10.2f ms\n", __func__, data.t_load_ms); + LLAMA_LOG_INFO("%s: prompt eval time = %10.2f ms / %5d tokens (%8.2f ms per token, %8.2f tokens per second)\n", + __func__, data.t_p_eval_ms, data.n_p_eval, data.t_p_eval_ms / data.n_p_eval, 1e3 / data.t_p_eval_ms * data.n_p_eval); + LLAMA_LOG_INFO("%s: eval time = %10.2f ms / %5d runs (%8.2f ms per token, %8.2f tokens per second)\n", + __func__, data.t_eval_ms, data.n_eval, data.t_eval_ms / data.n_eval, 1e3 / data.t_eval_ms * data.n_eval); + LLAMA_LOG_INFO("%s: total time = %10.2f ms / %5d tokens\n", __func__, (t_end_ms - data.t_start_ms), (data.n_p_eval + data.n_eval)); +} + +void llama_perf_context_reset(llama_context * ctx) { + ctx->perf_reset(); } diff --git a/src/llama-context.h b/src/llama-context.h index a9268b292..71d702e8b 100644 --- a/src/llama-context.h +++ b/src/llama-context.h @@ -3,66 +3,210 @@ #include "llama.h" #include "llama-batch.h" #include "llama-cparams.h" -#include "llama-model.h" -#include "llama-kv-cache.h" +#include "llama-graph.h" #include "llama-adapter.h" #include "ggml-cpp.h" #include -#include #include -#include + +struct llama_model; +struct llama_kv_cache; + +class llama_io_read_i; +class llama_io_write_i; struct llama_context { - llama_context(const llama_model & model) - : model(model) - , t_start_us(model.t_start_us) - , t_load_us(model.t_load_us) {} + // init scheduler and compute buffers, reserve worst-case graphs + llama_context( + const llama_model & model, + llama_context_params params); - const struct llama_model & model; + ~llama_context(); - struct llama_cparams cparams; - struct llama_sbatch sbatch; // TODO: revisit if needed - struct llama_kv_cache kv_self; - struct llama_adapter_cvec cvec; + void synchronize(); - std::unordered_map lora; + const llama_model & get_model() const; - std::vector backends; - std::vector> set_n_threads_fns; + uint32_t n_ctx() const; + uint32_t n_ctx_per_seq() const; + uint32_t n_batch() const; + uint32_t n_ubatch() const; + uint32_t n_seq_max() const; - ggml_backend_t backend_cpu = nullptr; + uint32_t n_threads() const; + uint32_t n_threads_batch() const; - ggml_threadpool_t threadpool = nullptr; - ggml_threadpool_t threadpool_batch = nullptr; + llama_kv_cache * get_kv_self(); + const llama_kv_cache * get_kv_self() const; - bool has_evaluated_once = false; + void kv_self_update(); - mutable int64_t t_start_us; - mutable int64_t t_load_us; - mutable int64_t t_p_eval_us = 0; - mutable int64_t t_eval_us = 0; + enum llama_pooling_type pooling_type() const; - mutable int64_t t_compute_start_us = 0; - mutable int64_t n_queued_tokens = 0; + float * get_logits(); + float * get_logits_ith(int32_t i); - mutable int32_t n_p_eval = 0; // number of tokens in eval calls for the prompt (with batch size > 1) - mutable int32_t n_eval = 0; // number of eval calls + float * get_embeddings(); + float * get_embeddings_ith(int32_t i); + float * get_embeddings_seq(llama_seq_id seq_id); - // host buffer for the model output (logits and embeddings) - ggml_backend_buffer_ptr buf_output; + void attach_threadpool( + ggml_threadpool_t threadpool, + ggml_threadpool_t threadpool_batch); + + void detach_threadpool(); + + void set_n_threads(int32_t n_threads, int32_t n_threads_batch); + + void set_abort_callback(bool (*abort_callback)(void * data), void * abort_callback_data); + + void set_embeddings (bool value); + void set_causal_attn(bool value); + + void set_adapter_lora( + llama_adapter_lora * adapter, + float scale); + + bool rm_adapter_lora( + llama_adapter_lora * adapter); + + void clear_adapter_lora(); + + bool apply_adapter_cvec( + const float * data, + size_t len, + int32_t n_embd, + int32_t il_start, + int32_t il_end); + + int encode(llama_batch & inp_batch); + int decode(llama_batch & inp_batch); + + // + // state save/load + // + + size_t state_get_size(); + size_t state_get_data( uint8_t * dst, size_t size); + size_t state_set_data(const uint8_t * src, size_t size); + + size_t state_seq_get_size(llama_seq_id seq_id); + size_t state_seq_get_data(llama_seq_id seq_id, uint8_t * dst, size_t size); + size_t state_seq_set_data(llama_seq_id seq_id, const uint8_t * src, size_t size); + + bool state_load_file( + const char * filepath, + llama_token * tokens_out, + size_t n_token_capacity, + size_t * n_token_count_out); + + bool state_save_file( + const char * filepath, + const llama_token * tokens, + size_t n_token_count); + + size_t state_seq_load_file( + llama_seq_id seq_id, + const char * filepath, + llama_token * tokens_out, + size_t n_token_capacity, + size_t * n_token_count_out); + + size_t state_seq_save_file( + llama_seq_id seq_id, + const char * filepath, + const llama_token * tokens, + size_t n_token_count); + + // + // perf + // + + llama_perf_context_data perf_get_data() const; + void perf_reset(); + +private: + // + // output + // + + // Make sure enough space is available for outputs. + // Returns max number of outputs for which space was reserved. + int32_t output_reserve(int32_t n_outputs); + + // make the outputs have the same order they had in the user-provided batch + // TODO: maybe remove this + void output_reorder(); + + // + // graph + // + + int32_t graph_max_nodes() const; + + // zero-out inputs and create the ctx_compute for the compute graph + ggml_cgraph * graph_init(); + + llm_graph_result_ptr graph_build( + ggml_context * ctx, + ggml_cgraph * gf, + const llama_ubatch & ubatch, + llm_graph_type gtype); + + // returns the result of ggml_backend_sched_graph_compute_async execution + ggml_status graph_compute( + ggml_cgraph * gf, + bool batched); + + llm_graph_cb graph_get_cb() const; + + // used by kv_self_update() + ggml_tensor * build_rope_shift( + ggml_context * ctx0, + ggml_tensor * cur, + ggml_tensor * shift, + ggml_tensor * factors, + ggml_backend_buffer * bbuf) const; + + llm_graph_result_ptr build_kv_self_shift( + ggml_context * ctx0, + ggml_cgraph * gf) const; + + llm_graph_result_ptr build_kv_self_defrag( + ggml_context * ctx0, + ggml_cgraph * gf) const; + + // TODO: read/write lora adapters and cvec + size_t state_write_data(llama_io_write_i & io); + size_t state_read_data (llama_io_read_i & io); + + size_t state_seq_write_data(llama_io_write_i & io, llama_seq_id seq_id); + size_t state_seq_read_data (llama_io_read_i & io, llama_seq_id seq_id); + + // + // members + // + + const llama_model & model; + + llama_cparams cparams; + llama_adapter_cvec cvec; + llama_adapter_loras loras; + llama_sbatch sbatch; + + llama_cross cross; // TODO: tmp for handling cross-attention - need something better probably + + std::unique_ptr kv_self; + + // TODO: remove + bool logits_all = false; // decode output (2-dimensional array: [n_outputs][n_vocab]) size_t logits_size = 0; // capacity (of floats) for logits float * logits = nullptr; - std::vector output_ids; // map batch token positions to ids of the logits and embd buffers - size_t output_size = 0; // capacity (of tokens positions) for the output buffers - int32_t n_outputs = 0; // number of actually-used outputs in the current ubatch or last logical batch - - bool logits_all = false; - // embeddings output (2-dimensional array: [n_outputs][n_embd]) // populated only when pooling_type == LLAMA_POOLING_TYPE_NONE size_t embd_size = 0; // capacity (of floats) for embeddings @@ -72,57 +216,47 @@ struct llama_context { // populated only when pooling_type != LLAMA_POOLING_TYPE_NONE std::map> embd_seq; - // whether we are computing encoder output or decoder output - bool is_encoding = false; + int32_t n_outputs = 0; // number of actually-used outputs in the current ubatch or last logical batch + int32_t n_outputs_max = 0; // capacity (of tokens positions) for the output buffers - // TODO: find a better way to accommodate mutli-dimension position encoding methods - // number of position id each token get, 1 for each token in most cases. - // when using m-rope, it will be 3 position ids per token to representing 3 dimension coordinate. - int n_pos_per_token = 1; + std::vector output_ids; // map batch token positions to ids of the logits and embd buffers - // output of the encoder part of the encoder-decoder models - std::vector embd_enc; - std::vector> seq_ids_enc; - - // memory buffers used to evaluate the model - std::vector buf_compute_meta; ggml_backend_sched_ptr sched; + ggml_backend_t backend_cpu = nullptr; + std::vector backends; + + ggml_context_ptr ctx_compute; + + ggml_threadpool_t threadpool = nullptr; + ggml_threadpool_t threadpool_batch = nullptr; + ggml_abort_callback abort_callback = nullptr; void * abort_callback_data = nullptr; - // input tensors - struct ggml_tensor * inp_tokens; // I32 [n_batch] - struct ggml_tensor * inp_embd; // F32 [n_embd, n_batch] - struct ggml_tensor * inp_pos; // I32 [n_batch] - struct ggml_tensor * inp_out_ids; // I32 [n_outputs] - struct ggml_tensor * inp_KQ_mask; // F32 [kv_size, n_batch] - struct ggml_tensor * inp_KQ_mask_swa; // F32 [kv_size, n_batch] - struct ggml_tensor * inp_K_shift; // I32 [kv_size] - struct ggml_tensor * inp_mean; // F32 [n_batch, n_batch] - struct ggml_tensor * inp_cls; // I32 [n_batch] - struct ggml_tensor * inp_s_copy; // I32 [kv_size] - struct ggml_tensor * inp_s_mask; // F32 [1, n_kv] - struct ggml_tensor * inp_s_seq; // I32 [n_kv, n_batch] - struct ggml_tensor * inp_pos_bucket; // I32 [n_batch|n_kv, n_batch] - struct ggml_tensor * inp_embd_enc; // F32 [n_embd, n_outputs_enc] - struct ggml_tensor * inp_KQ_mask_cross; // F32 [n_outputs_enc, n_batch] + std::vector> set_n_threads_fns; + + // buffer types used for the compute buffer of each backend + std::vector backend_ptrs; + std::vector backend_buft; + + // memory buffers used to evaluate the model + std::vector buf_compute_meta; + + // host buffer for the model output (logits and embeddings) + ggml_backend_buffer_ptr buf_output; + + bool has_evaluated_once = false; + + // perf + mutable int64_t t_start_us = 0; + mutable int64_t t_load_us = 0; + mutable int64_t t_p_eval_us = 0; + mutable int64_t t_eval_us = 0; + + mutable int64_t t_compute_start_us = 0; + mutable int64_t n_queued_tokens = 0; + + mutable int32_t n_p_eval = 0; // number of tokens in eval calls for the prompt (with batch size > 1) + mutable int32_t n_eval = 0; // number of eval calls }; - -// TODO: make these methods of llama_context -void llama_set_k_shift(struct llama_context & lctx); - -void llama_set_s_copy(struct llama_context & lctx); - -void llama_set_inputs(llama_context & lctx, const llama_ubatch & ubatch); - -// Make sure enough space is available for outputs. -// Returns max number of outputs for which space was reserved. -size_t llama_output_reserve(struct llama_context & lctx, size_t n_outputs); - -// make the outputs have the same order they had in the user-provided batch -void llama_output_reorder(struct llama_context & ctx); - -// For internal test use -// TODO: remove -const std::vector> & llama_internal_get_tensor_map(struct llama_context * ctx); diff --git a/src/llama-graph.cpp b/src/llama-graph.cpp new file mode 100644 index 000000000..1e3f2efc8 --- /dev/null +++ b/src/llama-graph.cpp @@ -0,0 +1,1695 @@ +#include "llama-graph.h" + +#include "llama-impl.h" +#include "llama-batch.h" +#include "llama-cparams.h" +#include "llama-kv-cache.h" + +#include +#include +#include + +static int32_t llama_relative_position_bucket(llama_pos x, llama_pos y, uint64_t n_buckets, bool bidirectional) { + // TODO move to hparams if a T5 variant appears that uses a different value + const int64_t max_distance = 128; + + if (bidirectional) { + n_buckets >>= 1; + } + + const int64_t max_exact = n_buckets >> 1; + + int32_t relative_position = x - y; + int32_t relative_bucket = 0; + + if (bidirectional) { + relative_bucket += (relative_position > 0) * n_buckets; + relative_position = abs(relative_position); + } else { + relative_position = -std::min(relative_position, 0); + } + + int32_t relative_position_if_large = floorf(max_exact + logf(1.0 * relative_position / max_exact) * (n_buckets - max_exact) / log(1.0 * max_distance / max_exact)); + relative_position_if_large = std::min(relative_position_if_large, n_buckets - 1); + relative_bucket += (relative_position < max_exact ? relative_position : relative_position_if_large); + + return relative_bucket; +} + +void llm_graph_input_embd::set_input(const llama_ubatch * ubatch) { + if (ubatch->token) { + const int64_t n_tokens = ubatch->n_tokens; + + ggml_backend_tensor_set(tokens, ubatch->token, 0, n_tokens*ggml_element_size(tokens)); + } + + if (ubatch->embd) { + const int64_t n_embd = embd->ne[0]; + const int64_t n_tokens = ubatch->n_tokens; + + ggml_backend_tensor_set(embd, ubatch->embd, 0, n_tokens*n_embd*ggml_element_size(embd)); + } +} + +void llm_graph_input_pos::set_input(const llama_ubatch * ubatch) { + if (ubatch->pos && pos) { + const int64_t n_tokens = ubatch->n_tokens; + + ggml_backend_tensor_set(pos, ubatch->pos, 0, n_tokens*n_pos_per_token*ggml_element_size(pos)); + } +} + +void llm_graph_input_pos_bucket::set_input(const llama_ubatch * ubatch) { + if (pos_bucket) { + const int64_t n_tokens = ubatch->n_tokens; + + GGML_ASSERT(ggml_backend_buffer_is_host(pos_bucket->buffer)); + GGML_ASSERT(!ubatch->equal_seqs); // TODO: use ubatch->n_seqs instead of failing + + int32_t * data = (int32_t *) pos_bucket->data; + + for (int h = 0; h < 1; ++h) { + for (int j = 0; j < n_tokens; ++j) { + for (int i = 0; i < n_tokens; ++i) { + data[h*(n_tokens*n_tokens) + j*n_tokens + i] = llama_relative_position_bucket(ubatch->pos[i], ubatch->pos[j], hparams.n_rel_attn_bkts, true); + } + } + } + } +} + +void llm_graph_input_pos_bucket_kv::set_input(const llama_ubatch * ubatch) { + if (pos_bucket) { + const int64_t n_tokens = ubatch->n_tokens; + + GGML_ASSERT(ggml_backend_buffer_is_host(pos_bucket->buffer)); + GGML_ASSERT(!ubatch->equal_seqs); // TODO: use ubatch->n_seqs instead of failing + + int32_t * data = (int32_t *) pos_bucket->data; + + const int64_t n_kv = kv_self->n; + + for (int h = 0; h < 1; ++h) { + for (int j = 0; j < n_tokens; ++j) { + for (int i = 0; i < n_kv; ++i) { + data[h*(n_kv*n_tokens) + j*n_kv + i] = llama_relative_position_bucket(kv_self->cells[i].pos, ubatch->pos[j], hparams.n_rel_attn_bkts, false); + } + } + } + } +} + +void llm_graph_input_out_ids::set_input(const llama_ubatch * ubatch) { + if (hparams.causal_attn || cparams.pooling_type == LLAMA_POOLING_TYPE_NONE) { + //GGML_ASSERT(out_ids && "every model that can must skip unused outputs"); + + if (!out_ids) { + LLAMA_LOG_WARN("%s: 'out_ids' is not created\n", __func__); + } else { + const int64_t n_tokens = ubatch->n_tokens; + + GGML_ASSERT(ggml_backend_buffer_is_host(out_ids->buffer)); + int32_t * data = (int32_t *) out_ids->data; + + if (n_outputs == n_tokens) { + for (int i = 0; i < n_tokens; ++i) { + data[i] = i; + } + } else if (ubatch->output) { + int32_t n_outputs = 0; + for (int i = 0; i < n_tokens; ++i) { + if (ubatch->output[i]) { + data[n_outputs++] = i; + } + } + // the graph needs to have been passed the correct number of outputs + GGML_ASSERT(n_outputs == n_outputs); + } else if (n_outputs == 1) { + // only keep last output + data[0] = n_tokens - 1; + } else { + GGML_ASSERT(n_outputs == 0); + } + } + } +} + +void llm_graph_input_mean::set_input(const llama_ubatch * ubatch) { + if (cparams.embeddings && cparams.pooling_type == LLAMA_POOLING_TYPE_MEAN) { + const int64_t n_tokens = ubatch->n_tokens; + const int64_t n_seq_tokens = ubatch->n_seq_tokens; + const int64_t n_seqs = ubatch->n_seqs; + + GGML_ASSERT(mean); + GGML_ASSERT(ggml_backend_buffer_is_host(mean->buffer)); + + float * data = (float *) mean->data; + memset(mean->data, 0, n_tokens * n_tokens * ggml_element_size(mean)); + + std::vector sum(n_tokens, 0); + + for (int s = 0; s < n_seqs; ++s) { + const llama_seq_id seq_id = ubatch->seq_id[s][0]; + + // TODO: adapt limits to n_seqs when ubatch->equal_seqs is true + GGML_ASSERT(seq_id < n_tokens && "seq_id cannot be larger than n_tokens with pooling_type == MEAN"); + + sum[seq_id] += ubatch->n_seq_tokens; + } + + std::vector div(n_tokens, 0.0f); + for (int i = 0; i < n_tokens; ++i) { + const uint64_t s = sum[i]; + if (s > 0) { + div[i] = 1.0f/float(s); + } + } + + for (int s = 0; s < n_seqs; ++s) { + const llama_seq_id seq_id = ubatch->seq_id[s][0]; + + for (int i = 0; i < n_seq_tokens; ++i) { + data[seq_id*n_tokens + s*n_seq_tokens + i] = div[seq_id]; + } + } + } +} + +void llm_graph_input_cls::set_input(const llama_ubatch * ubatch) { + if (cparams.embeddings && ( + cparams.pooling_type == LLAMA_POOLING_TYPE_CLS || + cparams.pooling_type == LLAMA_POOLING_TYPE_RANK)) { + const int64_t n_tokens = ubatch->n_tokens; + const int64_t n_seq_tokens = ubatch->n_seq_tokens; + const int64_t n_seqs = ubatch->n_seqs; + + GGML_ASSERT(cls); + GGML_ASSERT(ggml_backend_buffer_is_host(cls->buffer)); + + uint32_t * data = (uint32_t *) cls->data; + memset(cls->data, 0, n_tokens * ggml_element_size(cls)); + + for (int s = 0; s < n_seqs; ++s) { + const llama_seq_id seq_id = ubatch->seq_id[s][0]; + + // TODO: adapt limits to n_seqs when ubatch->equal_seqs is true + GGML_ASSERT(seq_id < n_tokens && "seq_id cannot be larger than n_tokens with pooling_type == CLS or RANK"); + + for (int i = 0; i < n_seq_tokens; ++i) { + const llama_pos pos = ubatch->pos[s*n_seq_tokens + i]; + + if (pos == 0) { + data[seq_id] = s*n_seq_tokens + i; + } + } + } + } + + if (cparams.embeddings && cparams.pooling_type == LLAMA_POOLING_TYPE_LAST) { + const int64_t n_tokens = ubatch->n_tokens; + const int64_t n_seq_tokens = ubatch->n_seq_tokens; + const int64_t n_seqs = ubatch->n_seqs; + + GGML_ASSERT(cls); + GGML_ASSERT(ggml_backend_buffer_is_host(cls->buffer)); + + uint32_t * data = (uint32_t *) cls->data; + memset(cls->data, 0, n_tokens * ggml_element_size(cls)); + + std::vector last_pos(n_tokens, -1); + std::vector last_row(n_tokens, -1); + + for (int s = 0; s < n_seqs; ++s) { + const llama_seq_id seq_id = ubatch->seq_id[s][0]; + + // TODO: adapt limits to n_seqs when ubatch->equal_seqs is true + GGML_ASSERT(seq_id < n_tokens && "seq_id cannot be larger than n_tokens with pooling_type == LAST"); + + for (int i = 0; i < n_seq_tokens; ++i) { + const llama_pos pos = ubatch->pos[s*n_seq_tokens + i]; + + if (pos >= last_pos[seq_id]) { + last_pos[seq_id] = pos; + last_row[seq_id] = s*n_seq_tokens + i; + } + } + } + + for (int i = 0; i < n_tokens; ++i) { + if (last_row[i] >= 0) { + data[i] = last_row[i]; + } + } + } +} + +void llm_graph_input_s_copy::set_input(const llama_ubatch * ubatch) { + GGML_UNUSED(ubatch); + + const int64_t n_kv = kv_self->n; + + if (s_copy) { + GGML_ASSERT(ggml_backend_buffer_is_host(s_copy->buffer)); + int32_t * data = (int32_t *) s_copy->data; + + // assuming copy destinations ALWAYS happen ONLY on the cells between head and head+n + for (uint32_t i = 0; i < n_kv; ++i) { + const uint32_t cell_id = i + kv_self->head; + + ////////////////////////////////////////////// + // TODO: this should not mutate the KV cache ! + llama_kv_cell & kv_cell = const_cast(kv_self)->cells[i]; + + // prevent out-of-bound sources + if (kv_cell.src < 0 || (uint32_t) kv_cell.src >= kv_self->size) { + kv_cell.src = cell_id; + } + + data[i] = kv_cell.src; + + // TODO: do not mutate the KV cache + // ensure copy only happens once + if (kv_cell.src != (int32_t) cell_id) { + kv_cell.src = cell_id; + } + } + } +} + +void llm_graph_input_s_mask::set_input(const llama_ubatch * ubatch) { + GGML_UNUSED(ubatch); + + const int64_t n_kv = kv_self->n; + + if (s_mask) { + GGML_ASSERT(ggml_backend_buffer_is_host(s_mask->buffer)); + float * data = (float *) s_mask->data; + + // clear unused states + for (int i = 0; i < n_kv; ++i) { + const uint32_t cell_id = i + kv_self->head; + + ////////////////////////////////////////////// + // TODO: this should not mutate the KV cache ! + llama_kv_cell & kv_cell = const_cast(kv_self)->cells[i]; + + data[i] = (float) (kv_cell.src >= 0); + + // only clear once + if (kv_cell.src < 0) { + kv_cell.src = cell_id; + } + } + } +} + +void llm_graph_input_cross_embd::set_input(const llama_ubatch * ubatch) { + GGML_UNUSED(ubatch); + + if (cross_embd && !cross->v_embd.empty()) { + assert(cross_embd->type == GGML_TYPE_F32); + + ggml_backend_tensor_set(cross_embd, cross->v_embd.data(), 0, ggml_nbytes(cross_embd)); + } +} + +void llm_graph_input_attn_no_cache::set_input(const llama_ubatch * ubatch) { + if (kq_mask) { + if (cparams.causal_attn) { + const int64_t n_kv = ubatch->n_tokens; + const int64_t n_tokens = ubatch->n_tokens; + const int64_t n_seq_tokens = ubatch->n_seq_tokens; + const int64_t n_seqs = ubatch->n_seqs; + + GGML_ASSERT(ggml_backend_buffer_is_host(kq_mask->buffer)); + float * data = (float *) kq_mask->data; + + for (int h = 0; h < 1; ++h) { + for (int s1 = 0; s1 < n_seqs; ++s1) { + const llama_seq_id seq_id = ubatch->seq_id[s1][0]; + + for (int j = 0; j < n_seq_tokens; ++j) { + const int32_t tj = s1*n_seq_tokens + j; + + for (int s0 = 0; s0 < n_seqs; ++s0) { + for (int i = 0; i < n_seq_tokens; ++i) { + const int32_t ti = s0*n_seq_tokens + i; + float f = -INFINITY; + + for (int s = 0; s < ubatch->n_seq_id[s0]; ++s) { + if (ubatch->seq_id[s0][s] == seq_id && ubatch->pos[ti] <= ubatch->pos[tj]) { + if (hparams.use_alibi) { + f = -std::abs(ubatch->pos[ti] - ubatch->pos[tj]); + } else { + f = 0.0f; + } + break; + } + } + + data[h*(n_kv*n_tokens) + tj*n_kv + ti] = f; + } + } + } + } + } + } else { + const int64_t n_tokens = ubatch->n_tokens; + const int64_t n_seq_tokens = ubatch->n_seq_tokens; + const int64_t n_seqs = ubatch->n_seqs; + const int64_t n_stride = ubatch->n_tokens; + + GGML_ASSERT(ggml_backend_buffer_is_host(kq_mask->buffer)); + + float * data = (float *) kq_mask->data; + + for (int h = 0; h < 1; ++h) { + for (int s1 = 0; s1 < n_seqs; ++s1) { + const llama_seq_id seq_id = ubatch->seq_id[s1][0]; + + for (int j = 0; j < n_seq_tokens; ++j) { + const int32_t tj = s1*n_seq_tokens + j; + + for (int s0 = 0; s0 < n_seqs; ++s0) { + for (int i = 0; i < n_seq_tokens; ++i) { + const int32_t ti = s0*n_seq_tokens + i; + float f = -INFINITY; + + for (int s = 0; s < ubatch->n_seq_id[s0]; ++s) { + if (ubatch->seq_id[s0][s] == seq_id) { + if (hparams.use_alibi) { + f = -std::abs(ubatch->pos[ti] - ubatch->pos[tj]); + } else { + f = 0.0f; + } + break; + } + } + + data[h*(n_tokens*n_tokens) + tj*n_stride + ti] = f; + } + } + + for (int i = n_tokens; i < n_stride; ++i) { + data[h*(n_tokens*n_tokens) + tj*n_stride + i] = -INFINITY; + } + } + } + } + } + } +} + +void llm_graph_input_attn_kv_unified::set_input(const llama_ubatch * ubatch) { + if (self_kq_mask || self_kq_mask_swa) { + // NOTE: hparams.causal_attn indicates the model is capable of generation and uses the kv cache. + if (cparams.causal_attn) { + const int64_t n_kv = kv_self->n; + const int64_t n_tokens = ubatch->n_tokens; + const int64_t n_seq_tokens = ubatch->n_seq_tokens; + const int64_t n_seqs = ubatch->n_seqs; + + float * data = nullptr; + float * data_swa = nullptr; + + if (self_kq_mask) { + GGML_ASSERT(ggml_backend_buffer_is_host(self_kq_mask->buffer)); + data = (float *) self_kq_mask->data; + } + + if (self_kq_mask_swa) { + GGML_ASSERT(ggml_backend_buffer_is_host(self_kq_mask_swa->buffer)); + data_swa = (float *) self_kq_mask_swa->data; + } + + // For causal attention, use only the previous KV cells + // of the correct sequence for each token of the ubatch. + // It's assumed that if a token in the batch has multiple sequences, they are equivalent. + for (int h = 0; h < 1; ++h) { + for (int s = 0; s < n_seqs; ++s) { + const llama_seq_id seq_id = ubatch->seq_id[s][0]; + + for (int j = 0; j < n_seq_tokens; ++j) { + const llama_pos pos = ubatch->pos[s*n_seq_tokens + j]; + + for (int i = 0; i < n_kv; ++i) { + float f; + if (!kv_self->cells[i].has_seq_id(seq_id) || kv_self->cells[i].pos > pos) { + f = -INFINITY; + } else { + if (hparams.use_alibi) { + f = -std::abs(kv_self->cells[i].pos - pos); + } else { + f = 0.0f; + } + } + + if (data) { + data[h*(n_kv*n_tokens) + s*(n_kv*n_seq_tokens) + j*n_kv + i] = f; + } + + // may need to cut off old tokens for sliding window + if (data_swa) { + if (pos - kv_self->cells[i].pos >= (int32_t)hparams.n_swa) { + f = -INFINITY; + } + data_swa[h*(n_kv*n_tokens) + s*(n_kv*n_seq_tokens) + j*n_kv + i] = f; + } + } + } + } + + if (data) { + for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) { + for (int j = 0; j < n_kv; ++j) { + data[h*(n_kv*n_tokens) + i*n_kv + j] = -INFINITY; + } + } + } + + if (data_swa) { + for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) { + for (int j = 0; j < n_kv; ++j) { + data_swa[h*(n_kv*n_tokens) + i*n_kv + j] = -INFINITY; + } + } + } + } + } else { + const int64_t n_tokens = ubatch->n_tokens; + const int64_t n_seq_tokens = ubatch->n_seq_tokens; + const int64_t n_seqs = ubatch->n_seqs; + // when using kv cache, the mask needs to match the kv cache size + const int64_t n_stride = n_tokens; + + GGML_ASSERT(ggml_backend_buffer_is_host(self_kq_mask->buffer)); + + float * data = (float *) self_kq_mask->data; + + for (int h = 0; h < 1; ++h) { + for (int s1 = 0; s1 < n_seqs; ++s1) { + const llama_seq_id seq_id = ubatch->seq_id[s1][0]; + + for (int j = 0; j < n_seq_tokens; ++j) { + const int32_t tj = s1*n_seq_tokens + j; + + for (int s0 = 0; s0 < n_seqs; ++s0) { + for (int i = 0; i < n_seq_tokens; ++i) { + const int32_t ti = s0*n_seq_tokens + i; + float f = -INFINITY; + + for (int s = 0; s < ubatch->n_seq_id[s0]; ++s) { + if (ubatch->seq_id[s0][s] == seq_id) { + if (hparams.use_alibi) { + f = -std::abs(ubatch->pos[ti] - ubatch->pos[tj]); + } else { + f = 0.0f; + } + break; + } + } + + data[h*(n_tokens*n_tokens) + tj*n_stride + ti] = f; + } + } + + for (int i = n_tokens; i < n_stride; ++i) { + data[h*(n_tokens*n_tokens) + tj*n_stride + i] = -INFINITY; + } + } + } + } + } + } +} + +void llm_graph_input_attn_cross::set_input(const llama_ubatch * ubatch) { + if (cross_kq_mask) { + const int64_t n_enc = cross_kq_mask->ne[0]; + const int64_t n_tokens = ubatch->n_tokens; + + GGML_ASSERT(ggml_backend_buffer_is_host(cross_kq_mask->buffer)); + GGML_ASSERT(!ubatch->equal_seqs); // TODO: use ubatch->n_seqs instead of failing + + float * data = (float *) cross_kq_mask->data; + + for (int h = 0; h < 1; ++h) { + for (int j = 0; j < n_tokens; ++j) { + for (int i = 0; i < n_enc; ++i) { + float f = -INFINITY; + for (int s = 0; s < ubatch->n_seq_id[j]; ++s) { + const llama_seq_id seq_id = ubatch->seq_id[j][s]; + if (cross->seq_ids_enc[i].find(seq_id) != cross->seq_ids_enc[i].end()) { + f = 0.0f; + } + } + data[h*(n_enc*n_tokens) + j*n_enc + i] = f; + } + } + + for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) { + for (int j = 0; j < n_enc; ++j) { + data[h*(n_enc*n_tokens) + i*n_enc + j] = -INFINITY; + } + } + } + } +} + +// +// llm_graph_context +// + +llm_graph_context::llm_graph_context(const llm_graph_params & params) : + arch (params.arch), + hparams (params.hparams), + cparams (params.cparams), + ubatch (params.ubatch), + n_embd (hparams.n_embd), + n_layer (hparams.n_layer), + n_rot (hparams.n_rot), + n_ctx (cparams.n_ctx), + n_ctx_per_seq (cparams.n_ctx / cparams.n_seq_max), + n_head (hparams.n_head()), + n_head_kv (hparams.n_head_kv()), + n_embd_head_k (hparams.n_embd_head_k), + n_embd_k_gqa (hparams.n_embd_k_gqa()), + n_embd_head_v (hparams.n_embd_head_v), + n_embd_v_gqa (hparams.n_embd_v_gqa()), + n_expert (hparams.n_expert), + n_expert_used (hparams.n_expert_used), + freq_base (cparams.rope_freq_base), + freq_scale (cparams.rope_freq_scale), + ext_factor (cparams.yarn_ext_factor), + attn_factor (cparams.yarn_attn_factor), + beta_fast (cparams.yarn_beta_fast), + beta_slow (cparams.yarn_beta_slow), + norm_eps (hparams.f_norm_eps), + norm_rms_eps (hparams.f_norm_rms_eps), + n_tokens (ubatch.n_tokens), + n_outputs (params.n_outputs), + n_ctx_orig (cparams.n_ctx_orig_yarn), + pooling_type (cparams.pooling_type), + rope_type (hparams.rope_type), + ctx0 (params.ctx), + sched (params.sched), + backend_cpu (params.backend_cpu), + cvec (params.cvec), + loras (params.loras), + memory (params.memory), + cross (params.cross), + cb_func (params.cb), + res (std::make_unique()) { + } + +int64_t llm_graph_context::n_pos_per_token() const { + return arch == LLM_ARCH_QWEN2VL ? 4 : 1; +} + +void llm_graph_context::cb(ggml_tensor * cur, const char * name, int il) const { + if (cb_func) { + cb_func(ubatch, cur, name, il); + } +} + +ggml_tensor * llm_graph_context::build_cvec( + ggml_tensor * cur, + int il) const { + return cvec->apply_to(ctx0, cur, il); +} + +ggml_tensor * llm_graph_context::build_lora_mm( + ggml_tensor * w, + ggml_tensor * cur) const { + ggml_tensor * res = ggml_mul_mat(ctx0, w, cur); + + for (const auto & lora : *loras) { + llama_adapter_lora_weight * lw = lora.first->get_weight(w); + if (lw == nullptr) { + continue; + } + + const float adapter_scale = lora.second; + const float scale = lw->get_scale(lora.first->alpha, adapter_scale); + + ggml_tensor * ab_cur = ggml_mul_mat( + ctx0, lw->b, + ggml_mul_mat(ctx0, lw->a, cur) + ); + + ab_cur = ggml_scale(ctx0, ab_cur, scale); + res = ggml_add(ctx0, res, ab_cur); + } + + return res; +} + +ggml_tensor * llm_graph_context::build_lora_mm_id( + ggml_tensor * w, // ggml_tensor * as + ggml_tensor * cur, // ggml_tensor * b + ggml_tensor * ids) const { + ggml_tensor * res = ggml_mul_mat_id(ctx0, w, cur, ids); + for (const auto & lora : *loras) { + llama_adapter_lora_weight * lw = lora.first->get_weight(w); + if (lw == nullptr) { + continue; + } + + const float alpha = lora.first->alpha; + const float rank = (float) lw->b->ne[0]; + const float scale = alpha ? lora.second * alpha / rank : lora.second; + + ggml_tensor * ab_cur = ggml_mul_mat_id( + ctx0, lw->b, + ggml_mul_mat_id(ctx0, lw->a, cur, ids), + ids + ); + + ab_cur = ggml_scale(ctx0, ab_cur, scale); + res = ggml_add(ctx0, res, ab_cur); + } + + return res; +} + +ggml_tensor * llm_graph_context::build_norm( + ggml_tensor * cur, + ggml_tensor * mw, + ggml_tensor * mb, + llm_norm_type type, + int il) const { + switch (type) { + case LLM_NORM: cur = ggml_norm (ctx0, cur, hparams.f_norm_eps); break; + case LLM_NORM_RMS: cur = ggml_rms_norm(ctx0, cur, hparams.f_norm_rms_eps); break; + case LLM_NORM_GROUP: + { + cur = ggml_reshape_3d(ctx0, cur, cur->ne[0], 1, cur->ne[1]); + cur = ggml_group_norm(ctx0, cur, hparams.n_norm_groups, hparams.f_norm_group_eps); + cur = ggml_reshape_2d(ctx0, cur, cur->ne[0], cur->ne[2]); + } break; + } + + if (mw || mb) { + cb(cur, "norm", il); + } + + if (mw) { + cur = ggml_mul(ctx0, cur, mw); + if (mb) { + cb(cur, "norm_w", il); + } + } + + if (mb) { + cur = ggml_add(ctx0, cur, mb); + } + + return cur; +} + +ggml_tensor * llm_graph_context::build_ffn( + ggml_tensor * cur, + ggml_tensor * up, + ggml_tensor * up_b, + ggml_tensor * up_s, + ggml_tensor * gate, + ggml_tensor * gate_b, + ggml_tensor * gate_s, + ggml_tensor * down, + ggml_tensor * down_b, + ggml_tensor * down_s, + ggml_tensor * act_scales, + llm_ffn_op_type type_op, + llm_ffn_gate_type type_gate, + int il) const { + ggml_tensor * tmp = up ? build_lora_mm(up, cur) : cur; + cb(tmp, "ffn_up", il); + + if (up_b) { + tmp = ggml_add(ctx0, tmp, up_b); + cb(tmp, "ffn_up_b", il); + } + + if (up_s) { + tmp = ggml_mul(ctx0, tmp, up_s); + cb(tmp, "ffn_up_s", il); + } + + if (gate) { + switch (type_gate) { + case LLM_FFN_SEQ: + { + cur = build_lora_mm(gate, tmp); + cb(cur, "ffn_gate", il); + } break; + case LLM_FFN_PAR: + { + cur = build_lora_mm(gate, cur); + cb(cur, "ffn_gate", il); + } break; + } + + if (gate_b) { + cur = ggml_add(ctx0, cur, gate_b); + cb(cur, "ffn_gate_b", il); + } + + if (gate_s) { + cur = ggml_mul(ctx0, cur, gate_s); + cb(cur, "ffn_gate_s", il); + } + + } else { + cur = tmp; + } + + switch (type_op) { + case LLM_FFN_SILU: + { + cur = ggml_silu(ctx0, cur); + cb(cur, "ffn_silu", il); + } break; + case LLM_FFN_GELU: + { + cur = ggml_gelu(ctx0, cur); + cb(cur, "ffn_gelu", il); + if (act_scales != NULL) { + cur = ggml_div(ctx0, cur, act_scales); + cb(cur, "ffn_act", il); + } + } break; + case LLM_FFN_RELU: + { + cur = ggml_relu(ctx0, cur); + cb(cur, "ffn_relu", il); + } break; + case LLM_FFN_RELU_SQR: + { + cur = ggml_relu(ctx0, cur); + cb(cur, "ffn_relu", il); + + cur = ggml_sqr(ctx0, cur); + cb(cur, "ffn_sqr(relu)", il); + } break; + case LLM_FFN_SWIGLU: + { + // Project to 4h. If using swiglu double the output width, see https://arxiv.org/pdf/2002.05202.pdf + int64_t split_point = cur->ne[0] / 2; + ggml_tensor * x0 = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, split_point, cur->ne[1], cur->nb[1], 0)); + ggml_tensor * x1 = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, split_point, cur->ne[1], cur->nb[1], split_point * ggml_element_size(cur))); + + x0 = ggml_silu(ctx0, x0); + cb(cur, "ffn_silu", il); + + cur = ggml_mul(ctx0, x0, x1); + cb(cur, "ffn_mul", il); + } break; + } + + if (type_gate == LLM_FFN_PAR) { + cur = ggml_mul(ctx0, cur, tmp); + cb(cur, "ffn_gate_par", il); + } + + if (down) { + cur = build_lora_mm(down, cur); + } + + if (down_b) { + cb(cur, "ffn_down", il); + } + + if (down_b) { + cur = ggml_add(ctx0, cur, down_b); + } + + if (down_s) { + cur = ggml_mul(ctx0, cur, down_s); + cb(cur, "ffn_down_s", il); + } + + return cur; +} + +ggml_tensor * llm_graph_context::build_moe_ffn( + ggml_tensor * cur, + ggml_tensor * gate_inp, + ggml_tensor * up_exps, + ggml_tensor * gate_exps, + ggml_tensor * down_exps, + ggml_tensor * exp_probs_b, + int64_t n_expert, + int64_t n_expert_used, + llm_ffn_op_type type_op, + bool norm_w, + bool scale_w, + float w_scale, + llama_expert_gating_func_type gating_op, + int il) const { + int64_t n_embd = cur->ne[0]; + int64_t n_tokens = cur->ne[1]; + + ggml_tensor * logits = build_lora_mm(gate_inp, cur); // [n_expert, n_tokens] + cb(logits, "ffn_moe_logits", il); + + ggml_tensor * probs = nullptr; + switch (gating_op) { + case LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX: + { + probs = ggml_soft_max(ctx0, logits); // [n_expert, n_tokens] + } break; + case LLAMA_EXPERT_GATING_FUNC_TYPE_SIGMOID: + { + probs = ggml_sigmoid(ctx0, logits); // [n_expert, n_tokens] + } break; + default: + GGML_ABORT("fatal error"); + } + cb(probs, "ffn_moe_probs", il); + + // add experts selection bias - introduced in DeepSeek V3 + // leave probs unbiased as it's later used to get expert weights + ggml_tensor * selection_probs = probs; + if (exp_probs_b != nullptr) { + selection_probs = ggml_add(ctx0, probs, exp_probs_b); + cb(selection_probs, "ffn_moe_probs_biased", il); + } + + // select experts + ggml_tensor * selected_experts = ggml_top_k(ctx0, selection_probs, n_expert_used); // [n_expert_used, n_tokens] + cb(selected_experts->src[0], "ffn_moe_argsort", il); + cb(selected_experts, "ffn_moe_topk", il); + + ggml_tensor * weights = ggml_get_rows(ctx0, + ggml_reshape_3d(ctx0, probs, 1, n_expert, n_tokens), selected_experts); // [1, n_expert_used, n_tokens] + cb(weights, "ffn_moe_weights", il); + + if (norm_w) { + weights = ggml_reshape_2d(ctx0, weights, n_expert_used, n_tokens); + + ggml_tensor * weights_sum = ggml_sum_rows(ctx0, weights); // [1, n_tokens] + cb(weights_sum, "ffn_moe_weights_sum", il); + + weights = ggml_div(ctx0, weights, weights_sum); // [n_expert_used, n_tokens] + cb(weights, "ffn_moe_weights_norm", il); + + weights = ggml_reshape_3d(ctx0, weights, 1, n_expert_used, n_tokens); + } + if (scale_w) { + weights = ggml_scale(ctx0, weights, w_scale); + cb(weights, "ffn_moe_weights_scaled", il); + } + + cur = ggml_reshape_3d(ctx0, cur, n_embd, 1, n_tokens); + ggml_tensor * up = build_lora_mm_id(up_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens] + cb(up, "ffn_moe_up", il); + + ggml_tensor * gate = build_lora_mm_id(gate_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens] + cb(gate, "ffn_moe_gate", il); + + switch (type_op) { + case LLM_FFN_SILU: + { + gate = ggml_silu(ctx0, gate); + cb(gate, "ffn_moe_silu", il); + } break; + case LLM_FFN_GELU: + { + gate = ggml_gelu(ctx0, gate); + cb(gate, "ffn_moe_gelu", il); + } break; + default: + GGML_ABORT("fatal error"); + } + + ggml_tensor * par = ggml_mul(ctx0, up, gate); // [n_ff, n_expert_used, n_tokens] + cb(par, "ffn_moe_gate_par", il); + + ggml_tensor * experts = build_lora_mm_id(down_exps, par, selected_experts); // [n_embd, n_expert_used, n_tokens] + cb(experts, "ffn_moe_down", il); + + experts = ggml_mul(ctx0, experts, weights); + + // aggregate experts + ggml_tensor * moe_out = nullptr; + for (int i = 0; i < n_expert_used; ++i) { + ggml_tensor * cur_expert = ggml_view_2d(ctx0, experts, n_embd, n_tokens, + experts->nb[2], i*experts->nb[1]); + + if (i == 0) { + moe_out = cur_expert; + } else { + moe_out = ggml_add(ctx0, moe_out, cur_expert); + } + } + + if (n_expert_used == 1) { + // avoid returning a non-contiguous tensor + moe_out = ggml_cont(ctx0, moe_out); + } + + return moe_out; +} + +// input embeddings with optional lora +ggml_tensor * llm_graph_context::build_inp_embd(ggml_tensor * tok_embd) const { + const int64_t n_embd = hparams.n_embd; + + auto inp = std::make_unique(); + + ggml_tensor * cur = nullptr; + + if (ubatch.token) { + inp->tokens = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, ubatch.n_tokens); + //cb(inp->tokens, "inp_tokens", -1); + ggml_set_input(inp->tokens); + + cur = ggml_get_rows(ctx0, tok_embd, inp->tokens); + + // apply lora for embedding tokens if needed + for (const auto & lora : *loras) { + llama_adapter_lora_weight * lw = lora.first->get_weight(tok_embd); + if (lw == nullptr) { + continue; + } + + const float adapter_scale = lora.second; + const float scale = lw->get_scale(lora.first->alpha, adapter_scale); + + ggml_tensor * inpL_delta = ggml_scale(ctx0, ggml_mul_mat( + ctx0, lw->b, // non-transposed lora_b + ggml_get_rows(ctx0, lw->a, inp->tokens) + ), scale); + + cur = ggml_add(ctx0, cur, inpL_delta); + } + } else { + inp->embd = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_embd, ubatch.n_tokens); + ggml_set_input(inp->embd); + + cur = inp->embd; + } + + // For Granite architecture + if (hparams.f_embedding_scale != 0.0f) { + cur = ggml_scale(ctx0, cur, hparams.f_embedding_scale); + } + + cb(cur, "inp_embd", -1); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_pos() const { + auto inp = std::make_unique(n_pos_per_token()); + + auto & cur = inp->pos; + + cur = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_tokens*n_pos_per_token()); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_out_ids() const { + auto inp = std::make_unique(hparams, cparams, n_outputs); + + auto & cur = inp->out_ids; + + cur = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_outputs); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_mean() const { + auto inp = std::make_unique(cparams); + + auto & cur = inp->mean; + + cur = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_tokens, n_tokens); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_cls() const { + auto inp = std::make_unique(cparams); + + auto & cur = inp->cls; + + cur = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_tokens); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_s_copy() const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + auto inp = std::make_unique(kv_self); + + const auto n_kv = kv_self->n; + + auto & cur = inp->s_copy; + + cur = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_kv); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_s_mask() const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + auto inp = std::make_unique(kv_self); + + const auto n_kv = kv_self->n; + + auto & cur = inp->s_mask; + + cur = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, 1, n_kv); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_cross_embd() const { + auto inp = std::make_unique(cross); + + auto & cur = inp->cross_embd; + + // if we have the output embeddings from the encoder, use them directly + // TODO: needs more work to be correct, for now just use the tensor shape + //if (cross->t_embd) { + // cur = ggml_view_tensor(ctx0, cross->t_embd); + + // return cur; + //} + + const auto n_embd = !cross->v_embd.empty() ? cross->n_embd : hparams.n_embd; + const auto n_enc = !cross->v_embd.empty() ? cross->n_enc : hparams.n_ctx_train; + + cur = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_embd, n_enc); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_pos_bucket_enc() const { + auto inp = std::make_unique(hparams); + + auto & cur = inp->pos_bucket; + + cur = ggml_new_tensor_2d(ctx0, GGML_TYPE_I32, n_tokens, n_tokens); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_inp_pos_bucket_dec() const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + auto inp = std::make_unique(hparams, kv_self); + + const auto n_kv = kv_self->n; + + auto & cur = inp->pos_bucket; + + cur = ggml_new_tensor_2d(ctx0, GGML_TYPE_I32, n_kv, n_tokens); + ggml_set_input(cur); + + res->add_input(std::move(inp)); + + return cur; +} + +ggml_tensor * llm_graph_context::build_pos_bias(ggml_tensor * pos_bucket, ggml_tensor * attn_rel_b) const { + ggml_tensor * pos_bucket_1d = ggml_reshape_1d(ctx0, pos_bucket, pos_bucket->ne[0] * pos_bucket->ne[1]); + cb(pos_bucket_1d, "pos_bucket_1d", -1); + + ggml_tensor * pos_bias = ggml_get_rows(ctx0, attn_rel_b, pos_bucket_1d); + + pos_bias = ggml_reshape_3d(ctx0, pos_bias, pos_bias->ne[0], pos_bucket->ne[0], pos_bucket->ne[1]); + pos_bias = ggml_permute (ctx0, pos_bias, 2, 0, 1, 3); + pos_bias = ggml_cont (ctx0, pos_bias); + + cb(pos_bias, "pos_bias", -1); + + return pos_bias; +} + +ggml_tensor * llm_graph_context::build_attn_mha( + ggml_cgraph * gf, + ggml_tensor * q, + ggml_tensor * k, + ggml_tensor * v, + ggml_tensor * kq_b, + ggml_tensor * kq_mask, + bool v_trans, + float kq_scale) const { + //const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); + //const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il); + + //const int64_t n_head = hparams.n_head(il); + //const int64_t n_head_kv = hparams.n_head_kv(il); + + //const auto & n_embd_head_k = hparams.n_embd_head_k; + //const auto & n_embd_head_v = hparams.n_embd_head_v; + + const auto n_embd_head_v = v_trans ? v->ne[1] : v->ne[0]; + + const auto n_tokens = q->ne[1]; + const auto n_head = q->ne[2]; + const auto n_kv = k->ne[1]; + + ggml_tensor * cur; + + // TODO: replace hardcoded padding with ggml-provided padding + if (cparams.flash_attn && (n_kv % 256 == 0) && kq_b == nullptr) { + GGML_ASSERT(kq_b == nullptr && "Flash attention does not support KQ bias yet"); + + if (v_trans) { + v = ggml_transpose(ctx0, v); + } + + cur = ggml_flash_attn_ext(ctx0, q, k, v, kq_mask, kq_scale, hparams.f_max_alibi_bias, + hparams.attn_soft_cap ? hparams.f_attn_logit_softcapping : 0.0f); + + ggml_flash_attn_ext_set_prec(cur, GGML_PREC_F32); + + cur = ggml_reshape_2d(ctx0, cur, n_embd_head_v*n_head, n_tokens); + } else { + ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); + + // note: this op tends to require high floating point range + // while for some models F16 is enough, for others it is not, so we default to F32 here + ggml_mul_mat_set_prec(kq, GGML_PREC_F32); + + if (arch == LLM_ARCH_GROK) { + // need to do the following: + // multiply by attn_output_multiplyer of 0.08838834764831845 + // and then : + // kq = 30 * tanh(kq / 30) + // before the softmax below + + kq = ggml_tanh(ctx0, ggml_scale(ctx0, kq, 0.08838834764831845f/30.0f)); + kq = ggml_scale(ctx0, kq, 30); + } + + if (hparams.attn_soft_cap) { + kq = ggml_scale(ctx0, kq, 1.0f / hparams.f_attn_logit_softcapping); + kq = ggml_tanh (ctx0, kq); + kq = ggml_scale(ctx0, kq, hparams.f_attn_logit_softcapping); + } + + if (kq_b) { + kq = ggml_add(ctx0, kq, kq_b); + } + + kq = ggml_soft_max_ext(ctx0, kq, kq_mask, kq_scale, hparams.f_max_alibi_bias); + + if (!v_trans) { + // note: avoid this branch + v = ggml_cont(ctx0, ggml_transpose(ctx0, v)); + } + + ggml_tensor * kqv = ggml_mul_mat(ctx0, v, kq); + + ggml_tensor * kqv_merged = ggml_permute(ctx0, kqv, 0, 2, 1, 3); + + cur = ggml_cont_2d(ctx0, kqv_merged, n_embd_head_v*n_head, n_tokens); + + if (!cparams.offload_kqv) { + // all nodes between the KV store and the attention output are run on the CPU + ggml_backend_sched_set_tensor_backend(sched, cur, backend_cpu); + } + } + + ggml_build_forward_expand(gf, cur); + + return cur; +} + +llm_graph_input_attn_no_cache * llm_graph_context::build_attn_inp_no_cache() const { + auto inp = std::make_unique(hparams, cparams); + + // note: there is no KV cache, so the number of KV values is equal to the number of tokens in the batch + inp->kq_mask = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_tokens, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)); + //cb(inp_kq_mask, "KQ_mask", -1); + ggml_set_input(inp->kq_mask); + + inp->kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->kq_mask, GGML_TYPE_F16) : inp->kq_mask; + + return (llm_graph_input_attn_no_cache *) res->add_input(std::move(inp)); +} + +ggml_tensor * llm_graph_context::build_attn( + llm_graph_input_attn_no_cache * inp, + ggml_cgraph * gf, + ggml_tensor * wo, + ggml_tensor * wo_b, + ggml_tensor * q_cur, + ggml_tensor * k_cur, + ggml_tensor * v_cur, + ggml_tensor * kq_b, + float kq_scale, + int il) const { + GGML_UNUSED(n_tokens); + + // these nodes are added to the graph together so that they are not reordered + // by doing so, the number of splits in the graph is reduced + ggml_build_forward_expand(gf, q_cur); + ggml_build_forward_expand(gf, k_cur); + ggml_build_forward_expand(gf, v_cur); + + const auto & kq_mask = inp->get_kq_mask(); + + ggml_tensor * q = ggml_permute(ctx0, q_cur, 0, 2, 1, 3); + //cb(q, "q", il); + + ggml_tensor * k = ggml_permute(ctx0, k_cur, 0, 2, 1, 3); + //cb(k, "k", il); + + ggml_tensor * v = ggml_permute(ctx0, v_cur, 0, 2, 1, 3); + //cb(k, "v", il); + + ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, false, kq_scale); + + cb(cur, "kqv_out", il); + + if (wo) { + cur = build_lora_mm(wo, cur); + } + + if (wo_b) { + //cb(cur, "kqv_wo", il); + } + + if (wo_b) { + cur = ggml_add(ctx0, cur, wo_b); + } + + return cur; +} + +llm_graph_input_attn_kv_unified * llm_graph_context::build_attn_inp_kv_unified( + bool causal, + bool swa) const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + auto inp = std::make_unique(hparams, cparams, kv_self); + + const auto n_kv = kv_self->n; + + inp->self_kq_mask = causal + ? ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)) + : ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_tokens, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)); + //cb(inp->self_kq_mask, "KQ_mask", -1); + ggml_set_input(inp->self_kq_mask); + + inp->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask, GGML_TYPE_F16) : inp->self_kq_mask; + + if (swa) { + GGML_ASSERT(hparams.n_swa > 0); + + inp->self_kq_mask_swa = causal + ? ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)) + : ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_tokens, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)); + //cb(inp->self_kq_mask_swa, "KQ_mask_swa", -1); + ggml_set_input(inp->self_kq_mask_swa); + + inp->self_kq_mask_swa_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask_swa, GGML_TYPE_F16) : inp->self_kq_mask_swa; + } + + return (llm_graph_input_attn_kv_unified *) res->add_input(std::move(inp)); +} + +ggml_tensor * llm_graph_context::build_attn( + llm_graph_input_attn_kv_unified * inp, + ggml_cgraph * gf, + ggml_tensor * wo, + ggml_tensor * wo_b, + ggml_tensor * q_cur, + ggml_tensor * k_cur, + ggml_tensor * v_cur, + ggml_tensor * kq_b, + float kq_scale, + int il) const { + // these nodes are added to the graph together so that they are not reordered + // by doing so, the number of splits in the graph is reduced + ggml_build_forward_expand(gf, q_cur); + ggml_build_forward_expand(gf, k_cur); + ggml_build_forward_expand(gf, v_cur); + + const llama_kv_cache_unified * kv_self = static_cast(memory); + const auto & n_ctx = cparams.n_ctx; + + const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); + const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il); + + const auto n_tokens = q_cur->ne[2]; + + const bool v_trans = !cparams.flash_attn; + + // store to KV cache + { + GGML_ASSERT(!kv_self->recurrent); + + const auto kv_head = kv_self->head; + + GGML_ASSERT(kv_self->size == n_ctx); + + ggml_tensor * k_cache_view = ggml_view_1d(ctx0, kv_self->k_l[il], n_tokens*n_embd_k_gqa, ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa)*kv_head); + //cb(k_cache_view, "k_cache_view", il); + + // note: storing RoPE-ed version of K in the KV cache + ggml_build_forward_expand(gf, ggml_cpy(ctx0, k_cur, k_cache_view)); + + assert(v_cur->ne[0] == n_embd_v_gqa && v_cur->ne[1] == n_tokens); + + ggml_tensor * v_cache_view = nullptr; + + if (!v_trans) { + v_cache_view = ggml_view_1d(ctx0, kv_self->v_l[il], n_tokens*n_embd_v_gqa, ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa)*kv_head); + } else { + // note: the V cache is transposed when not using flash attention + v_cache_view = ggml_view_2d(ctx0, kv_self->v_l[il], n_tokens, n_embd_v_gqa, + ( n_ctx)*ggml_element_size(kv_self->v_l[il]), + (kv_head)*ggml_element_size(kv_self->v_l[il])); + + v_cur = ggml_transpose(ctx0, v_cur); + } + //cb(v_cache_view, "v_cache_view", il); + + ggml_build_forward_expand(gf, ggml_cpy(ctx0, v_cur, v_cache_view)); + } + + // TODO: improve + bool is_sliding = false; + + switch (arch) { + case LLM_ARCH_COHERE2: + { + const int32_t sliding_window_pattern = 4; + is_sliding = il % sliding_window_pattern < (sliding_window_pattern - 1); + } break; + case LLM_ARCH_GEMMA2: + { + const int32_t sliding_window_pattern = 2; + is_sliding = il % sliding_window_pattern < (sliding_window_pattern - 1); + } break; + case LLM_ARCH_GEMMA3: + { + const int32_t sliding_window_pattern = 6; + is_sliding = il % sliding_window_pattern < (sliding_window_pattern - 1); + } break; + case LLM_ARCH_PHI3: + { + is_sliding = hparams.n_swa > 0; + } break; + default: + { + is_sliding = false; + } + }; + + const auto & kq_mask = is_sliding ? inp->get_kq_mask_swa() : inp->get_kq_mask(); + + const auto n_kv = kv_self->n; + + const int64_t n_head_kv = hparams.n_head_kv(il); + + const auto & n_embd_head_k = hparams.n_embd_head_k; + const auto & n_embd_head_v = hparams.n_embd_head_v; + + ggml_tensor * q = ggml_permute(ctx0, q_cur, 0, 2, 1, 3); + //cb(q, "q", il); + + ggml_tensor * k = + ggml_view_3d(ctx0, kv_self->k_l[il], + n_embd_head_k, n_kv, n_head_kv, + ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa), + ggml_row_size(kv_self->k_l[il]->type, n_embd_head_k), + 0); + //cb(k, "k", il); + + ggml_tensor * v = !v_trans ? + ggml_view_3d(ctx0, kv_self->v_l[il], + n_embd_head_v, n_kv, n_head_kv, + ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa), + ggml_row_size(kv_self->v_l[il]->type, n_embd_head_v), + 0) : + ggml_view_3d(ctx0, kv_self->v_l[il], + n_kv, n_embd_head_v, n_head_kv, + ggml_element_size(kv_self->v_l[il])*n_ctx, + ggml_element_size(kv_self->v_l[il])*n_ctx*n_embd_head_v, + 0); + + ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_trans, kq_scale); + cb(cur, "kqv_out", il); + + if (wo) { + cur = build_lora_mm(wo, cur); + } + + if (wo_b) { + //cb(cur, "kqv_wo", il); + } + + if (wo_b) { + cur = ggml_add(ctx0, cur, wo_b); + } + + return cur; +} + +llm_graph_input_attn_cross * llm_graph_context::build_attn_inp_cross() const { + auto inp = std::make_unique(cross); + + const int32_t n_enc = !cross->v_embd.empty() ? cross->n_enc : hparams.n_ctx_train; + + inp->cross_kq_mask = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_enc, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)); + ggml_set_input(inp->cross_kq_mask); + + inp->cross_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->cross_kq_mask, GGML_TYPE_F16) : inp->cross_kq_mask; + + return (llm_graph_input_attn_cross *) res->add_input(std::move(inp)); +} + +ggml_tensor * llm_graph_context::build_attn( + llm_graph_input_attn_cross * inp, + ggml_cgraph * gf, + ggml_tensor * wo, + ggml_tensor * wo_b, + ggml_tensor * q_cur, + ggml_tensor * k_cur, + ggml_tensor * v_cur, + ggml_tensor * kq_b, + float kq_scale, + int il) const { + // these nodes are added to the graph together so that they are not reordered + // by doing so, the number of splits in the graph is reduced + ggml_build_forward_expand(gf, q_cur); + ggml_build_forward_expand(gf, k_cur); + ggml_build_forward_expand(gf, v_cur); + + const auto & kq_mask = inp->get_kq_mask_cross(); + + ggml_tensor * q = ggml_permute(ctx0, q_cur, 0, 2, 1, 3); + //cb(q, "q", il); + + ggml_tensor * k = ggml_permute(ctx0, k_cur, 0, 2, 1, 3); + //cb(k, "k", il); + + ggml_tensor * v = ggml_permute(ctx0, v_cur, 0, 2, 1, 3); + //cb(k, "v", il); + + ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, false, kq_scale); + + cb(cur, "kqv_out", il); + + if (wo) { + cur = build_lora_mm(wo, cur); + } + + if (wo_b) { + //cb(cur, "kqv_wo", il); + } + + if (wo_b) { + cur = ggml_add(ctx0, cur, wo_b); + } + + return cur; +} + +ggml_tensor * llm_graph_context::build_copy_mask_state( + ggml_cgraph * gf, + ggml_tensor * s, + ggml_tensor * state_copy, + ggml_tensor * state_mask, + int32_t n_state, + int32_t n_seqs) const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + const auto n_kv = kv_self->n; + const auto kv_head = kv_self->head; + + ggml_tensor * states = ggml_reshape_2d(ctx0, s, n_state, kv_self->size); + + // copy states + // NOTE: assuming the copy destinations are ALL contained between kv_head and kv_head + n_kv + // this shrinks the tensors's ne[1] to n_kv + states = ggml_get_rows(ctx0, states, state_copy); + + // clear states of sequences which are starting at the beginning of this batch + // FIXME: zero-out NANs? + states = ggml_mul(ctx0, states, state_mask); + + // copy states which won't be changed further (between n_seqs and n_kv) + ggml_build_forward_expand(gf, + ggml_cpy(ctx0, + ggml_view_1d(ctx0, states, n_state*(n_kv - n_seqs), (n_seqs )*n_state*ggml_element_size(states)), + ggml_view_1d(ctx0, s, n_state*(n_kv - n_seqs), (kv_head + n_seqs)*n_state*ggml_element_size(s)))); + + // the part of the states that will be used and modified + return ggml_view_2d(ctx0, states, n_state, n_seqs, states->nb[1], 0); +} + +ggml_tensor * llm_graph_context::build_rwkv_token_shift_load( + ggml_cgraph * gf, + ggml_tensor * state_copy, + ggml_tensor * state_mask, + const llama_ubatch & ubatch, + int il) const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + const auto token_shift_count = hparams.token_shift_count; + + const int64_t n_seqs = ubatch.n_seqs; + + ggml_tensor * token_shift_all = kv_self->k_l[il]; + + ggml_tensor * token_shift = build_copy_mask_state( + gf, token_shift_all, state_copy, state_mask, + hparams.n_embd_k_s(), n_seqs); + + token_shift = ggml_reshape_3d(ctx0, token_shift, hparams.n_embd, token_shift_count, n_seqs); + + return token_shift; +} + +ggml_tensor * llm_graph_context::build_rwkv_token_shift_store( + ggml_tensor * token_shift, + const llama_ubatch & ubatch, + int il) const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + const auto token_shift_count = hparams.token_shift_count; + const auto n_embd = hparams.n_embd; + + const int64_t n_seqs = ubatch.n_seqs; + + const auto kv_head = kv_self->head; + + return ggml_cpy( + ctx0, + ggml_view_1d(ctx0, token_shift, n_embd * n_seqs * token_shift_count, 0), + ggml_view_1d(ctx0, kv_self->k_l[il], hparams.n_embd_k_s() * n_seqs, hparams.n_embd_k_s() * kv_head * ggml_element_size(kv_self->k_l[il])) + ); +} + +void llm_graph_context::build_pooling( + ggml_cgraph * gf, + ggml_tensor * cls, + ggml_tensor * cls_b, + ggml_tensor * cls_out, + ggml_tensor * cls_out_b) const { + if (!cparams.embeddings) { + return; + } + + ggml_tensor * inp = res->t_embd; + + //// find result_norm tensor for input + //for (int i = ggml_graph_n_nodes(gf) - 1; i >= 0; --i) { + // inp = ggml_graph_node(gf, i); + // if (strcmp(inp->name, "result_norm") == 0 || strcmp(inp->name, "result_embd") == 0) { + // break; + // } + + // inp = nullptr; + //} + + GGML_ASSERT(inp != nullptr && "missing result_norm/result_embd tensor"); + + ggml_tensor * cur; + + switch (pooling_type) { + case LLAMA_POOLING_TYPE_NONE: + { + cur = inp; + } break; + case LLAMA_POOLING_TYPE_MEAN: + { + ggml_tensor * inp_mean = build_inp_mean(); + cur = ggml_mul_mat(ctx0, ggml_cont(ctx0, ggml_transpose(ctx0, inp)), inp_mean); + } break; + case LLAMA_POOLING_TYPE_CLS: + case LLAMA_POOLING_TYPE_LAST: + { + ggml_tensor * inp_cls = build_inp_cls(); + cur = ggml_get_rows(ctx0, inp, inp_cls); + } break; + case LLAMA_POOLING_TYPE_RANK: + { + ggml_tensor * inp_cls = build_inp_cls(); + inp = ggml_get_rows(ctx0, inp, inp_cls); + + // classification head + // https://github.com/huggingface/transformers/blob/5af7d41e49bbfc8319f462eb45253dcb3863dfb7/src/transformers/models/roberta/modeling_roberta.py#L1566 + GGML_ASSERT(cls != nullptr); + GGML_ASSERT(cls_b != nullptr); + + cur = ggml_add (ctx0, ggml_mul_mat(ctx0, cls, inp), cls_b); + cur = ggml_tanh(ctx0, cur); + + // some models don't have `cls_out`, for example: https://huggingface.co/jinaai/jina-reranker-v1-tiny-en + // https://huggingface.co/jinaai/jina-reranker-v1-tiny-en/blob/cb5347e43979c3084a890e3f99491952603ae1b7/modeling_bert.py#L884-L896 + if (cls_out) { + GGML_ASSERT(cls_out_b != nullptr); + + cur = ggml_add (ctx0, ggml_mul_mat(ctx0, cls_out, cur), cls_out_b); + } + } break; + default: + { + GGML_ABORT("unknown pooling type"); + } + } + + cb(cur, "result_embd_pooled", -1); + res->t_embd_pooled = cur; + + ggml_build_forward_expand(gf, cur); +} + diff --git a/src/llama-graph.h b/src/llama-graph.h new file mode 100644 index 000000000..b7a66d189 --- /dev/null +++ b/src/llama-graph.h @@ -0,0 +1,576 @@ +#pragma once + +#include "llama-arch.h" +#include "llama-hparams.h" +#include "llama-adapter.h" + +#include +#include +#include +#include +#include + +struct ggml_cgraph; +struct ggml_context; +struct ggml_tensor; + +struct llama_ubatch; +struct llama_cparams; + +class llama_memory_i; +class llama_kv_cache_unified; + +// certain models (typically multi-modal) can produce different types of graphs +enum llm_graph_type { + LLM_GRAPH_TYPE_DEFAULT, + LLM_GRAPH_TYPE_ENCODER, + LLM_GRAPH_TYPE_DECODER, +}; + +enum llm_ffn_op_type { + LLM_FFN_SILU, + LLM_FFN_GELU, + LLM_FFN_RELU, + LLM_FFN_RELU_SQR, + LLM_FFN_SWIGLU, +}; + +enum llm_ffn_gate_type { + LLM_FFN_SEQ, + LLM_FFN_PAR, // ffn_gate is parallel to ffn_up +}; + +enum llm_norm_type { + LLM_NORM, + LLM_NORM_RMS, + LLM_NORM_GROUP, +}; + +// TODO: tmp - need something better to pass the data from the encoder to the decoder +struct llama_cross { + // the output embeddings from the encoder as a ggml tensor + // TODO: this needs more work to be correct, for now copy the embeddings data to host memory + // ref: https://github.com/ggml-org/llama.cpp/pull/11213#discussion_r1969892524 + //ggml_tensor * t_embd = nullptr; + + int64_t n_embd = 0; + int64_t n_enc = 0; + + // embeddings data copied to host memory (tmp) + std::vector v_embd; + + // needed to construct the cross-attention mask in the decoder + std::vector> seq_ids_enc; +}; + +// +// llm_graph_input +// + +class llm_graph_input_i { +public: + virtual ~llm_graph_input_i() = default; + + virtual void set_input(const llama_ubatch * ubatch) = 0; +}; + +using llm_graph_input_ptr = std::unique_ptr; + + +class llm_graph_input_embd : public llm_graph_input_i { +public: + llm_graph_input_embd() = default; + virtual ~llm_graph_input_embd() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * tokens = nullptr; // I32 [n_batch] + ggml_tensor * embd = nullptr; // F32 [n_embd, n_batch] +}; + +class llm_graph_input_pos : public llm_graph_input_i { +public: + llm_graph_input_pos(int64_t n_pos_per_token) : n_pos_per_token(n_pos_per_token) {} + virtual ~llm_graph_input_pos() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * pos = nullptr; // I32 [n_batch] + + const int64_t n_pos_per_token = 1; +}; + +class llm_graph_input_pos_bucket : public llm_graph_input_i { +public: + llm_graph_input_pos_bucket(const llama_hparams & hparams) : hparams(hparams) {} + virtual ~llm_graph_input_pos_bucket() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * pos_bucket = nullptr; // I32 [n_batch, n_batch] + + const llama_hparams & hparams; +}; + +class llm_graph_input_pos_bucket_kv : public llm_graph_input_i { +public: + llm_graph_input_pos_bucket_kv( + const llama_hparams & hparams, + const llama_kv_cache_unified * kv_self) : hparams(hparams), kv_self(kv_self) {} + virtual ~llm_graph_input_pos_bucket_kv() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * pos_bucket = nullptr; // I32 [n_kv, n_batch] + + const llama_hparams & hparams; + const llama_kv_cache_unified * kv_self; +}; + +class llm_graph_input_out_ids : public llm_graph_input_i { +public: + llm_graph_input_out_ids( + const llama_hparams & hparams, + const llama_cparams & cparams, + int32_t n_outputs) : hparams(hparams), cparams(cparams), n_outputs(n_outputs) {} + virtual ~llm_graph_input_out_ids() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * out_ids; // I32 [n_outputs] + + const llama_hparams & hparams; + const llama_cparams & cparams; + + const int32_t n_outputs; +}; + +class llm_graph_input_mean : public llm_graph_input_i { +public: + llm_graph_input_mean(const llama_cparams & cparams) : cparams(cparams) {} + virtual ~llm_graph_input_mean() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * mean; // F32 [n_batch, n_batch] + + const llama_cparams & cparams; +}; + +class llm_graph_input_cls : public llm_graph_input_i { +public: + llm_graph_input_cls(const llama_cparams & cparams) : cparams(cparams) {} + virtual ~llm_graph_input_cls() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * cls; // I32 [n_batch] + + const llama_cparams & cparams; +}; + +class llm_graph_input_s_copy : public llm_graph_input_i { +public: + llm_graph_input_s_copy(const llama_kv_cache_unified * kv_self) : kv_self(kv_self) {} + virtual ~llm_graph_input_s_copy() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * s_copy; // I32 [kv_size] + + const llama_kv_cache_unified * kv_self; +}; + +class llm_graph_input_s_mask : public llm_graph_input_i { +public: + llm_graph_input_s_mask(const llama_kv_cache_unified * kv_self) : kv_self(kv_self) {} + virtual ~llm_graph_input_s_mask() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * s_mask; // F32 [1, n_kv] + + const llama_kv_cache_unified * kv_self; +}; + +class llm_graph_input_cross_embd : public llm_graph_input_i { +public: + llm_graph_input_cross_embd( + const llama_cross * cross) : cross(cross) {} + virtual ~llm_graph_input_cross_embd() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * cross_embd; // F32 [n_embd, n_outputs_enc] + + const llama_cross * cross; +}; + +class llm_graph_input_attn_no_cache : public llm_graph_input_i { +public: + llm_graph_input_attn_no_cache(const llama_hparams & hparams, const llama_cparams & cparams) : + hparams(hparams), + cparams(cparams) { + } + ~llm_graph_input_attn_no_cache() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * get_kq_mask() const { return kq_mask_cnv; } + + ggml_tensor * kq_mask = nullptr; // F32 [n_tokens, n_batch] + ggml_tensor * kq_mask_cnv = nullptr; // [n_tokens, n_batch] + + const llama_hparams & hparams; + const llama_cparams & cparams; +}; + +class llm_graph_input_attn_kv_unified : public llm_graph_input_i { +public: + llm_graph_input_attn_kv_unified( + const llama_hparams & hparams, + const llama_cparams & cparams, + const llama_kv_cache_unified * kv_self) : + hparams(hparams), + cparams(cparams), + kv_self(kv_self) { + } + ~llm_graph_input_attn_kv_unified() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * get_kq_mask() const { return self_kq_mask_cnv; } + ggml_tensor * get_kq_mask_swa() const { return self_kq_mask_swa_cnv; } + + ggml_tensor * self_kq_mask = nullptr; // F32 [n_kv, n_batch] + ggml_tensor * self_kq_mask_cnv = nullptr; // [n_kv, n_batch] + ggml_tensor * self_kq_mask_swa = nullptr; // F32 [n_kv, n_batch] + ggml_tensor * self_kq_mask_swa_cnv = nullptr; // [n_kv, n_batch] + + const llama_hparams & hparams; + const llama_cparams & cparams; + + const llama_kv_cache_unified * kv_self; +}; + +class llm_graph_input_attn_cross : public llm_graph_input_i { +public: + llm_graph_input_attn_cross(const llama_cross * cross) : cross(cross) {} + ~llm_graph_input_attn_cross() = default; + + void set_input(const llama_ubatch * ubatch) override; + + ggml_tensor * get_kq_mask_cross() const { return cross_kq_mask_cnv; } + + ggml_tensor * cross_kq_mask = nullptr; // F32 [n_outputs_enc, n_batch] + ggml_tensor * cross_kq_mask_cnv = nullptr; // F32 [n_outputs_enc, n_batch] + + const llama_cross * cross = nullptr; +}; + +// +// llm_graph_result +// + +// these objects deliver the result from the graph build process back to the llama_context +// note that the input tensors created for the graph are referenced here - the goal is to be able to populate their +// specific data, by calling the set_inputs() method +// along with the input tensors, the object also provides commonly used outputs tensors, such as logits, embeddings, etc. +// these are used by the llama_context to extact the relevant data, based on the compute parameters + +class llm_graph_result_i { +public: + virtual ~llm_graph_result_i() = default; + + virtual ggml_tensor * get_logits() = 0; + virtual ggml_tensor * get_embd() = 0; + virtual ggml_tensor * get_embd_pooled() = 0; + + virtual void set_inputs(const llama_ubatch * ubatch) = 0; +}; + +using llm_graph_result_ptr = std::unique_ptr; + + +class llm_graph_result : public llm_graph_result_i { +public: + virtual ~llm_graph_result() = default; + + ggml_tensor * get_logits() override { return t_logits; } + ggml_tensor * get_embd() override { return t_embd; } + ggml_tensor * get_embd_pooled() override { return t_embd_pooled; } + + void set_inputs(const llama_ubatch * ubatch) override { + for (auto & input : inputs) { + input->set_input(ubatch); + } + } + + llm_graph_input_i * add_input(llm_graph_input_ptr input) { + inputs.emplace_back(std::move(input)); + return inputs.back().get(); + } + + // important graph nodes + ggml_tensor * t_logits = nullptr; + ggml_tensor * t_embd = nullptr; + ggml_tensor * t_embd_pooled = nullptr; + + std::vector inputs; +}; + +// +// llm_graph_context +// + +// callback that allows us to apply custom logic to each tensor (e.g. ggml-alloc, offloading, etc.) +using llm_graph_cb = std::function; + +struct llm_graph_params { + ggml_context * ctx; + + const llm_arch arch; + + const llama_hparams & hparams; + const llama_cparams & cparams; + const llama_ubatch & ubatch; + + ggml_backend_sched * sched; + ggml_backend * backend_cpu; + + const llama_adapter_cvec * cvec; + const llama_adapter_loras * loras; + const llama_memory_i * memory; + const llama_cross * cross; + + int32_t n_outputs; + + const llm_graph_cb & cb; +}; + +struct llm_graph_context { + const llm_arch arch; + + const llama_hparams & hparams; + const llama_cparams & cparams; + const llama_ubatch & ubatch; + + const int64_t n_embd; + const int64_t n_layer; + const int64_t n_rot; + const int64_t n_ctx; // user-specified context size (can be different from n_ctx_train) + const int64_t n_ctx_per_seq; + const int64_t n_head; + const int64_t n_head_kv; + const int64_t n_embd_head_k; + const int64_t n_embd_k_gqa; + const int64_t n_embd_head_v; + const int64_t n_embd_v_gqa; + const int64_t n_expert; + const int64_t n_expert_used; + + const float freq_base; + const float freq_scale; + const float ext_factor; + const float attn_factor; + const float beta_fast; + const float beta_slow; + const float norm_eps; + const float norm_rms_eps; + + const int32_t n_tokens; + const int32_t n_outputs; + const int32_t n_ctx_orig; // yarn + + const enum llama_pooling_type pooling_type; + const enum llama_rope_type rope_type; + + ggml_context * ctx0 = nullptr; + + ggml_backend_sched * sched; + + ggml_backend * backend_cpu; // TODO: needed by build_attn_mha, figure out a way to remove? + + const llama_adapter_cvec * cvec; + const llama_adapter_loras * loras; + const llama_memory_i * memory; + const llama_cross * cross; + + const llm_graph_cb & cb_func; + + std::unique_ptr res; + + llm_graph_context(const llm_graph_params & params); + + int64_t n_pos_per_token() const; + + void cb(ggml_tensor * cur, const char * name, int il) const; + + // + // common + // + + ggml_tensor * build_cvec( + ggml_tensor * cur, + int il) const; + + // do mat_mul, while optionally apply lora + ggml_tensor * build_lora_mm( + ggml_tensor * w, + ggml_tensor * cur) const; + + // do mat_mul_id, while optionally apply lora + ggml_tensor * build_lora_mm_id( + ggml_tensor * w, // ggml_tensor * as + ggml_tensor * cur, // ggml_tensor * b + ggml_tensor * ids) const; + + ggml_tensor * build_norm( + ggml_tensor * cur, + ggml_tensor * mw, + ggml_tensor * mb, + llm_norm_type type, + int il) const; + + ggml_tensor * build_ffn( + ggml_tensor * cur, + ggml_tensor * up, + ggml_tensor * up_b, + ggml_tensor * up_s, + ggml_tensor * gate, + ggml_tensor * gate_b, + ggml_tensor * gate_s, + ggml_tensor * down, + ggml_tensor * down_b, + ggml_tensor * down_s, + ggml_tensor * act_scales, + llm_ffn_op_type type_op, + llm_ffn_gate_type type_gate, + int il) const; + + ggml_tensor * build_moe_ffn( + ggml_tensor * cur, + ggml_tensor * gate_inp, + ggml_tensor * up_exps, + ggml_tensor * gate_exps, + ggml_tensor * down_exps, + ggml_tensor * exp_probs_b, + int64_t n_expert, + int64_t n_expert_used, + llm_ffn_op_type type_op, + bool norm_w, + bool scale_w, + float w_scale, + llama_expert_gating_func_type gating_op, + int il) const; + + // + // inputs + // + + ggml_tensor * build_inp_embd(ggml_tensor * tok_embd) const; + ggml_tensor * build_inp_pos() const; + ggml_tensor * build_inp_out_ids() const; + ggml_tensor * build_inp_mean() const; + ggml_tensor * build_inp_cls() const; + ggml_tensor * build_inp_s_copy() const; + ggml_tensor * build_inp_s_mask() const; + + ggml_tensor * build_inp_cross_embd() const; + ggml_tensor * build_inp_pos_bucket_enc() const; + ggml_tensor * build_inp_pos_bucket_dec() const; + ggml_tensor * build_pos_bias(ggml_tensor * pos_bucket, ggml_tensor * attn_rel_b) const; + + // + // attention + // + + ggml_tensor * build_attn_mha( + ggml_cgraph * gf, + ggml_tensor * q, + ggml_tensor * k, + ggml_tensor * v, + ggml_tensor * kq_b, + ggml_tensor * kq_mask, + bool v_trans, + float kq_scale) const; + + llm_graph_input_attn_no_cache * build_attn_inp_no_cache() const; + + ggml_tensor * build_attn( + llm_graph_input_attn_no_cache * inp, + ggml_cgraph * gf, + ggml_tensor * wo, + ggml_tensor * wo_b, + ggml_tensor * q_cur, + ggml_tensor * k_cur, + ggml_tensor * v_cur, + ggml_tensor * kq_b, + float kq_scale, + int il) const; + + llm_graph_input_attn_kv_unified * build_attn_inp_kv_unified( + bool causal, + bool swa) const; + + ggml_tensor * build_attn( + llm_graph_input_attn_kv_unified * inp, + ggml_cgraph * gf, + ggml_tensor * wo, + ggml_tensor * wo_b, + ggml_tensor * q_cur, + ggml_tensor * k_cur, + ggml_tensor * v_cur, + ggml_tensor * kq_b, + float kq_scale, + int il) const; + + llm_graph_input_attn_cross * build_attn_inp_cross() const; + + ggml_tensor * build_attn( + llm_graph_input_attn_cross * inp, + ggml_cgraph * gf, + ggml_tensor * wo, + ggml_tensor * wo_b, + ggml_tensor * q_cur, + ggml_tensor * k_cur, + ggml_tensor * v_cur, + ggml_tensor * kq_b, + float kq_scale, + int il) const; + + // + // recurrent + // + + ggml_tensor * build_copy_mask_state( + ggml_cgraph * gf, + ggml_tensor * s, + ggml_tensor * state_copy, + ggml_tensor * state_mask, + int32_t n_state, + int32_t n_seqs) const; + + ggml_tensor * build_rwkv_token_shift_load( + ggml_cgraph * gf, + ggml_tensor * state_copy, + ggml_tensor * state_mask, + const llama_ubatch & ubatch, + int il) const; + + ggml_tensor * build_rwkv_token_shift_store( + ggml_tensor * token_shift, + const llama_ubatch & ubatch, + int il) const; + + // + // pooling + // + + void build_pooling( + ggml_cgraph * gf, + ggml_tensor * cls, + ggml_tensor * cls_b, + ggml_tensor * cls_out, + ggml_tensor * cls_out_b) const; +}; diff --git a/src/llama-io.cpp b/src/llama-io.cpp new file mode 100644 index 000000000..7ad70d163 --- /dev/null +++ b/src/llama-io.cpp @@ -0,0 +1,15 @@ +#include "llama-io.h" + +void llama_io_write_i::write_string(const std::string & str) { + uint32_t str_size = str.size(); + + write(&str_size, sizeof(str_size)); + write(str.data(), str_size); +} + +void llama_io_read_i::read_string(std::string & str) { + uint32_t str_size; + read_to(&str_size, sizeof(str_size)); + + str.assign((const char *) read(str_size), str_size); +} diff --git a/src/llama-io.h b/src/llama-io.h new file mode 100644 index 000000000..ce9216b83 --- /dev/null +++ b/src/llama-io.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +struct ggml_tensor; + +class llama_io_write_i { +public: + llama_io_write_i() = default; + virtual ~llama_io_write_i() = default; + + virtual void write(const void * src, size_t size) = 0; + virtual void write_tensor(const ggml_tensor * tensor, size_t offset, size_t size) = 0; + + // bytes written so far + virtual size_t n_bytes() = 0; + + void write_string(const std::string & str); +}; + +class llama_io_read_i { +public: + llama_io_read_i() = default; + virtual ~llama_io_read_i() = default; + + virtual const uint8_t * read(size_t size) = 0; + virtual void read_to(void * dst, size_t size) = 0; + + // bytes read so far + virtual size_t n_bytes() = 0; + + void read_string(std::string & str); +}; diff --git a/src/llama-kv-cache.cpp b/src/llama-kv-cache.cpp index feffdf0de..14c8933b4 100644 --- a/src/llama-kv-cache.cpp +++ b/src/llama-kv-cache.cpp @@ -6,86 +6,92 @@ #include "llama-model.h" #include +#include #include #include +#include static const llama_kv_cache_slot_info llama_kv_cache_slot_info_failed{false}; -uint32_t llama_kv_cache_get_padding(const struct llama_cparams & cparams) { - // the FA kernels require padding to avoid extra runtime boundary checks - return cparams.flash_attn ? 256u : 32u; +llama_kv_cache_unified::llama_kv_cache_unified(const llama_hparams & hparams, callbacks cbs) : hparams(hparams), cbs(std::move(cbs)) { } -bool llama_kv_cache_init( - struct llama_kv_cache & cache, - const llama_model & model, - const llama_cparams & cparams, - ggml_type type_k, - ggml_type type_v, - uint32_t kv_size, - bool offload) { - const struct llama_hparams & hparams = model.hparams; - +bool llama_kv_cache_unified::init( + const llama_model & model, + const llama_cparams & cparams, + ggml_type type_k, + ggml_type type_v, + uint32_t kv_size, + bool offload) { const int32_t n_layer = hparams.n_layer; - cache.has_shift = false; + has_shift = false; - cache.recurrent = llama_model_is_recurrent(&model); - cache.v_trans = !cache.recurrent && !cparams.flash_attn; - cache.can_shift = !cache.recurrent && model.arch != LLM_ARCH_DEEPSEEK2; // not supported due to MLA + recurrent = llama_model_is_recurrent(&model); + v_trans = !recurrent && !cparams.flash_attn; + can_shift = !recurrent && model.arch != LLM_ARCH_DEEPSEEK2; // not supported due to MLA LLAMA_LOG_INFO("%s: kv_size = %d, offload = %d, type_k = '%s', type_v = '%s', n_layer = %d, can_shift = %d\n", - __func__, kv_size, offload, ggml_type_name(type_k), ggml_type_name(type_v), n_layer, cache.can_shift); + __func__, kv_size, offload, ggml_type_name(type_k), ggml_type_name(type_v), n_layer, can_shift); - cache.head = 0; - cache.size = kv_size; - cache.used = 0; + head = 0; + size = kv_size; + used = 0; - cache.type_k = type_k; - cache.type_v = type_v; + this->type_k = type_k; + this->type_v = type_v; - cache.cells.clear(); - cache.cells.resize(kv_size); + cells.clear(); + cells.resize(kv_size); // create a context for each buffer type std::map ctx_map; auto ctx_for_buft = [&](ggml_backend_buffer_type_t buft) -> ggml_context * { auto it = ctx_map.find(buft); if (it == ctx_map.end()) { - struct ggml_init_params params = { + ggml_init_params params = { /*.mem_size =*/ size_t(2u*n_layer*ggml_tensor_overhead()), /*.mem_buffer =*/ NULL, /*.no_alloc =*/ true, }; + ggml_context * ctx = ggml_init(params); if (!ctx) { return nullptr; } + ctx_map[buft] = ctx; - cache.ctxs.emplace_back(ctx); + ctxs.emplace_back(ctx); + return ctx; } + return it->second; }; - cache.k_l.reserve(n_layer); - cache.v_l.reserve(n_layer); + k_l.reserve(n_layer); + v_l.reserve(n_layer); for (int i = 0; i < n_layer; i++) { const uint32_t n_embd_k_gqa = hparams.n_embd_k_gqa(i) + hparams.n_embd_k_s(); const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(i) + hparams.n_embd_v_s(); - LLAMA_LOG_DEBUG("%s: layer %d: n_embd_k_gqa = %d, n_embd_v_gqa = %d\n", __func__, i, n_embd_k_gqa, n_embd_v_gqa); + const char * dev_name = "CPU"; ggml_backend_buffer_type_t buft; if (offload) { auto * dev = model.dev_layer(i); buft = ggml_backend_dev_buffer_type(dev); + + dev_name = ggml_backend_dev_name(dev); } else { buft = ggml_backend_cpu_buffer_type(); } - ggml_context * ctx = ctx_for_buft(buft); + LLAMA_LOG_DEBUG("%s: layer %3d: n_embd_k_gqa = %d, n_embd_v_gqa = %d, dev = %s\n", __func__, + i, n_embd_k_gqa, n_embd_v_gqa, dev_name); + + ggml_context * ctx = ctx_for_buft(buft); if (!ctx) { LLAMA_LOG_ERROR("%s: failed to create ggml context for kv cache\n", __func__); return false; @@ -95,8 +101,8 @@ bool llama_kv_cache_init( ggml_tensor * v = ggml_new_tensor_1d(ctx, type_v, n_embd_v_gqa*kv_size); ggml_format_name(k, "cache_k_l%d", i); ggml_format_name(v, "cache_v_l%d", i); - cache.k_l.push_back(k); - cache.v_l.push_back(v); + k_l.push_back(k); + v_l.push_back(v); } // allocate tensors and initialize the buffers to avoid NaNs in the padding @@ -111,280 +117,80 @@ bool llama_kv_cache_init( } ggml_backend_buffer_clear(buf, 0); LLAMA_LOG_INFO("%s: %10s KV buffer size = %8.2f MiB\n", __func__, ggml_backend_buffer_name(buf), ggml_backend_buffer_get_size(buf)/1024.0/1024.0); - cache.bufs.emplace_back(buf); + bufs.emplace_back(buf); } return true; } -struct llama_kv_cache_slot_info llama_kv_cache_find_slot( - struct llama_kv_cache & cache, - const struct llama_ubatch & ubatch) { - const uint32_t n_tokens = ubatch.n_tokens; - const uint32_t n_seqs = ubatch.n_seqs; - const uint32_t n_seq_tokens = ubatch.n_seq_tokens; +int32_t llama_kv_cache_unified::get_n_tokens() const { + int32_t result = 0; - if (cache.recurrent) { - // For recurrent state architectures (like Mamba or RWKV), - // each cache cell can store the state for a whole sequence. - // A slot should be always be contiguous. - - // can only process batches with an equal number of new tokens in each sequence - GGML_ASSERT(ubatch.equal_seqs); - - int32_t min = cache.size - 1; - int32_t max = 0; - - // everything should fit if all seq_ids are smaller than the max - for (uint32_t s = 0; s < n_seqs; ++s) { - const uint32_t n_seq_id = ubatch.n_seq_id[s]; - for (uint32_t j = 0; j < n_seq_id; ++j) { - const llama_seq_id seq_id = ubatch.seq_id[s][j]; - - if (seq_id < 0 || (uint32_t) seq_id >= cache.size) { - // too big seq_id - // TODO: would it be possible to resize the cache instead? - LLAMA_LOG_ERROR("%s: seq_id=%d >= n_seq_max=%d Try using a bigger --parallel value\n", __func__, seq_id, cache.size); - return llama_kv_cache_slot_info_failed; - } - if (j > 0) { - llama_kv_cell & seq = cache.cells[seq_id]; - if (seq.tail >= 0) { - llama_kv_cell & cell = cache.cells[seq.tail]; - // clear cells from seq_ids that become shared - // (should not normally happen, but let's handle it anyway) - cell.seq_id.erase(seq_id); - seq.tail = -1; - if (cell.seq_id.empty()) { - cell.pos = -1; - cell.src = -1; - cache.used -= 1; - } - } - } - } - } - -#ifndef NDEBUG - { - std::vector tails_verif; - tails_verif.assign(cache.size, -1); - for (uint32_t i = 0; i < cache.size; ++i) { - llama_kv_cell & cell = cache.cells[i]; - for (llama_seq_id seq_id : cell.seq_id) { - if (tails_verif[seq_id] != -1) { - LLAMA_LOG_ERROR("%s: duplicate tail for seq_id %d in cell %d and %d\n", __func__, seq_id, i, tails_verif[seq_id]); - } - tails_verif[seq_id] = i; - } - } - for (uint32_t i = 0; i < cache.size; ++i) { - if (tails_verif[i] != cache.cells[i].tail) { - LLAMA_LOG_ERROR("%s: wrong tail for seq_id %d, (%d instead of %d)\n", __func__, i, cache.cells[i].tail, tails_verif[i]); - } - } - } -#endif - - // find next empty cell - uint32_t next_empty_cell = cache.head; - - for (uint32_t i = 0; i < cache.size; ++i) { - if (next_empty_cell >= cache.size) { next_empty_cell -= cache.size; } - llama_kv_cell & cell = cache.cells[next_empty_cell]; - if (cell.is_empty()) { break; } - next_empty_cell += 1; - } - - // find usable cell range - for (uint32_t s = 0; s < n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; - llama_kv_cell & seq_meta = cache.cells[seq_id]; - bool has_cell = false; - if (seq_meta.tail >= 0) { - llama_kv_cell & cell = cache.cells[seq_meta.tail]; - GGML_ASSERT(cell.has_seq_id(seq_id)); - // does this seq_id "own" the cell? - if (cell.seq_id.size() == 1) { has_cell = true; } - } - if (!has_cell) { - llama_kv_cell & empty_cell = cache.cells[next_empty_cell]; - GGML_ASSERT(empty_cell.is_empty()); - // copy old tail into the empty cell - if (seq_meta.tail >= 0) { - llama_kv_cell & orig_cell = cache.cells[seq_meta.tail]; - empty_cell.pos = orig_cell.pos; - empty_cell.src = orig_cell.src; - orig_cell.seq_id.erase(seq_id); - empty_cell.seq_id.insert(seq_id); // will be overwritten - } - seq_meta.tail = next_empty_cell; - // find next empty cell - if (s + 1 < n_seqs) { - next_empty_cell += 1; - for (uint32_t i = 0; i < cache.size; ++i) { - if (next_empty_cell >= cache.size) { next_empty_cell -= cache.size; } - llama_kv_cell & cell = cache.cells[next_empty_cell]; - if (cell.is_empty()) { break; } - next_empty_cell += 1; - } - } - } - if (min > seq_meta.tail) { min = seq_meta.tail; } - if (max < seq_meta.tail) { max = seq_meta.tail; } - } - - // gather and re-order - for (uint32_t s = 0; s < n_seqs; ++s) { - int32_t dst_id = s + min; - int32_t src_id = cache.cells[ubatch.seq_id[s][0]].tail; - if (dst_id != src_id) { - llama_kv_cell & dst_cell = cache.cells[dst_id]; - llama_kv_cell & src_cell = cache.cells[src_id]; - - std::swap(dst_cell.pos, src_cell.pos); - std::swap(dst_cell.src, src_cell.src); - std::swap(dst_cell.seq_id, src_cell.seq_id); - - // swap tails (assuming they NEVER overlap) - for (const llama_seq_id seq_id : src_cell.seq_id) { - cache.cells[seq_id].tail = src_id; - } - for (const llama_seq_id seq_id : dst_cell.seq_id) { - cache.cells[seq_id].tail = dst_id; - } - } - } - - // update the pos of the used seqs - for (uint32_t s = 0; s < n_seqs; ++s) { - const llama_pos last_pos = ubatch.pos[n_seq_tokens * s + n_seq_tokens - 1]; - int32_t cell_id = s + min; - llama_kv_cell & cell = cache.cells[cell_id]; - - if (cell.pos >= 0 && last_pos != cell.pos + (llama_pos) n_seq_tokens) { - // What should happen when the pos backtracks or skips a value? - // Clearing the state mid-batch would require special-casing which isn't done. - LLAMA_LOG_WARN("%s: non-consecutive token position %d after %d for sequence %d with %u new tokens\n", - __func__, last_pos, cell.pos, ubatch.seq_id[s][0], n_seq_tokens); - } - cell.pos = last_pos; - cell.seq_id.clear(); - for (int32_t j = 0; j < ubatch.n_seq_id[s]; ++j) { - const llama_seq_id seq_id = ubatch.seq_id[s][j]; - cell.seq_id.insert(seq_id); - cache.cells[seq_id].tail = cell_id; - } - } - - // allow getting the range of used cells, from head to head + n - cache.head = min; - cache.n = max - min + 1; - cache.used = std::count_if(cache.cells.begin(), cache.cells.end(), - [](const llama_kv_cell& cell){ return !cell.is_empty(); }); - - // sanity check - return llama_kv_cache_slot_info(cache.n >= n_seqs); - } - // otherwise, one cell per token. - - if (n_tokens > cache.size) { - LLAMA_LOG_ERROR("%s: n_tokens=%d > cache.size=%d\n", __func__, n_tokens, cache.size); - return llama_kv_cache_slot_info_failed; + for (uint32_t i = 0; i < size; i++) { + result += cells[i].seq_id.size(); } - uint32_t n_tested = 0; - - while (true) { - if (cache.head + n_tokens > cache.size) { - n_tested += cache.size - cache.head; - cache.head = 0; - continue; - } - - bool found = true; - for (uint32_t i = 0; i < n_tokens; i++) { - if (cache.cells[cache.head + i].pos >= 0) { - found = false; - cache.head += i + 1; - n_tested += i + 1; - break; - } - } - - if (found) { - break; - } - - if (n_tested >= cache.size) { - //LLAMA_LOG_ERROR("%s: failed to find a slot for %d tokens\n", __func__, n_tokens); - return llama_kv_cache_slot_info_failed; - } - } - - for (uint32_t s = 0; s < n_seqs; s++) { - for (uint32_t i = 0; i < n_seq_tokens; ++i) { - uint32_t k = s*n_seq_tokens + i; - cache.cells[cache.head + k].pos = ubatch.pos[k]; - - for (int32_t j = 0; j < ubatch.n_seq_id[s]; j++) { - cache.cells[cache.head + k].seq_id.insert(ubatch.seq_id[s][j]); - } - } - } - - cache.used += n_tokens; - - return llama_kv_cache_slot_info(cache.head, cache.head + n_tokens); + return result; } -uint32_t llama_kv_cache_cell_max(const struct llama_kv_cache & cache) { - for (uint32_t i = cache.size; i > 0; --i) { - const llama_kv_cell & cell = cache.cells[i - 1]; - - if (cell.pos >= 0 && !cell.is_empty()) { - return i; - } - } - - return 0; +uint32_t llama_kv_cache_unified::get_used_cells() const { + return used; } -void llama_kv_cache_clear(struct llama_kv_cache & cache) { - for (int32_t i = 0; i < (int32_t) cache.size; ++i) { - cache.cells[i].pos = -1; - cache.cells[i].seq_id.clear(); - cache.cells[i].src = -1; - cache.cells[i].tail = -1; +size_t llama_kv_cache_unified::total_size() const { + size_t size = 0; + for (const auto & buf : bufs) { + size += ggml_backend_buffer_get_size(buf.get()); } - cache.head = 0; - cache.used = 0; - for (auto & buf : cache.bufs) { + return size; +} + +llama_pos llama_kv_cache_unified::pos_max() const { + llama_pos pos_max = -1; + for (const auto & cell : cells) { + pos_max = std::max(pos_max, cell.pos); + } + + return pos_max; +} + +void llama_kv_cache_unified::clear() { + for (int32_t i = 0; i < (int32_t) size; ++i) { + cells[i].pos = -1; + cells[i].seq_id.clear(); + cells[i].src = -1; + cells[i].tail = -1; + } + head = 0; + used = 0; + + for (auto & buf : bufs) { ggml_backend_buffer_clear(buf.get(), 0); } } -bool llama_kv_cache_seq_rm( - struct llama_kv_cache & cache, - llama_seq_id seq_id, - llama_pos p0, - llama_pos p1) { - uint32_t new_head = cache.size; +bool llama_kv_cache_unified::seq_rm(llama_seq_id seq_id, llama_pos p0, llama_pos p1) { + uint32_t new_head = size; - if (p0 < 0) p0 = 0; - if (p1 < 0) p1 = std::numeric_limits::max(); + if (p0 < 0) { + p0 = 0; + } + + if (p1 < 0) { + p1 = std::numeric_limits::max(); + } // models like Mamba or RWKV can't have a state partially erased - if (cache.recurrent) { - if (seq_id >= (int64_t) cache.size) { + if (recurrent) { + if (seq_id >= (int64_t) size) { // could be fatal return false; } if (0 <= seq_id) { - int32_t & tail_id = cache.cells[seq_id].tail; + int32_t & tail_id = cells[seq_id].tail; if (tail_id >= 0) { - const llama_kv_cell & cell = cache.cells[tail_id]; + const llama_kv_cell & cell = cells[tail_id]; // partial intersection is invalid if ((0 < p0 && p0 <= cell.pos) || (0 < p1 && p1 <= cell.pos)) { return false; @@ -402,48 +208,59 @@ bool llama_kv_cache_seq_rm( } } - for (uint32_t i = 0; i < cache.size; ++i) { - if (cache.cells[i].pos >= p0 && cache.cells[i].pos < p1) { + for (uint32_t i = 0; i < size; ++i) { + if (cells[i].pos >= p0 && cells[i].pos < p1) { if (seq_id < 0) { - cache.cells[i].seq_id.clear(); - } else if (cache.cells[i].has_seq_id(seq_id)) { - cache.cells[i].seq_id.erase(seq_id); + cells[i].seq_id.clear(); + } else if (cells[i].has_seq_id(seq_id)) { + cells[i].seq_id.erase(seq_id); } else { continue; } - if (cache.cells[i].is_empty()) { + if (cells[i].is_empty()) { // keep count of the number of used cells - if (cache.cells[i].pos >= 0) cache.used--; + if (cells[i].pos >= 0) { + used--; + } - cache.cells[i].pos = -1; - cache.cells[i].src = -1; - if (new_head == cache.size) new_head = i; + cells[i].pos = -1; + cells[i].src = -1; + + if (new_head == size) { + new_head = i; + } } } } // If we freed up a slot, set head to it so searching can start there. - if (new_head != cache.size && new_head < cache.head) cache.head = new_head; + if (new_head != size && new_head < head) { + head = new_head; + } return true; } -void llama_kv_cache_seq_cp( - struct llama_kv_cache & cache, - llama_seq_id seq_id_src, - llama_seq_id seq_id_dst, - llama_pos p0, - llama_pos p1) { - if (p0 < 0) p0 = 0; - if (p1 < 0) p1 = std::numeric_limits::max(); +void llama_kv_cache_unified::seq_cp(llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) { + if (seq_id_src == seq_id_dst) { + return; + } - if (cache.recurrent) { - if ((uint32_t) seq_id_dst < cache.size && (uint32_t) seq_id_src < cache.size) { - llama_kv_cell & tail_src = cache.cells[seq_id_src]; - llama_kv_cell & tail_dst = cache.cells[seq_id_dst]; + if (p0 < 0) { + p0 = 0; + } + + if (p1 < 0) { + p1 = std::numeric_limits::max(); + } + + if (recurrent) { + if ((uint32_t) seq_id_dst < size && (uint32_t) seq_id_src < size) { + llama_kv_cell & tail_src = cells[seq_id_src]; + llama_kv_cell & tail_dst = cells[seq_id_dst]; if (tail_dst.tail >= 0) { // clear destination seq_id if it wasn't empty - llama_kv_cell & cell_dst = cache.cells[tail_dst.tail]; + llama_kv_cell & cell_dst = cells[tail_dst.tail]; cell_dst.seq_id.erase(seq_id_dst); tail_dst.tail = -1; @@ -451,11 +268,11 @@ void llama_kv_cache_seq_cp( cell_dst.pos = -1; cell_dst.delta = -1; cell_dst.src = -1; - cache.used -= 1; + used -= 1; } } if (tail_src.tail >= 0) { - llama_kv_cell & cell_src = cache.cells[tail_src.tail]; + llama_kv_cell & cell_src = cells[tail_src.tail]; cell_src.seq_id.insert(seq_id_dst); tail_dst.tail = tail_src.tail; @@ -464,59 +281,75 @@ void llama_kv_cache_seq_cp( return; } - // otherwise, this is the KV cache of a Transformer-like model - cache.head = 0; + // otherwise, this is the KV of a Transformer-like model + head = 0; - for (uint32_t i = 0; i < cache.size; ++i) { - if (cache.cells[i].has_seq_id(seq_id_src) && cache.cells[i].pos >= p0 && cache.cells[i].pos < p1) { - cache.cells[i].seq_id.insert(seq_id_dst); + for (uint32_t i = 0; i < size; ++i) { + if (cells[i].has_seq_id(seq_id_src) && cells[i].pos >= p0 && cells[i].pos < p1) { + cells[i].seq_id.insert(seq_id_dst); } } } -void llama_kv_cache_seq_keep(struct llama_kv_cache & cache, llama_seq_id seq_id) { - uint32_t new_head = cache.size; +void llama_kv_cache_unified::seq_keep(llama_seq_id seq_id) { + uint32_t new_head = size; - for (uint32_t i = 0; i < cache.size; ++i) { - if (cache.recurrent && (llama_seq_id) i != seq_id) { - cache.cells[i].tail = -1; + for (uint32_t i = 0; i < size; ++i) { + if (recurrent && (llama_seq_id) i != seq_id) { + cells[i].tail = -1; } - if (!cache.cells[i].has_seq_id(seq_id)) { - if (cache.cells[i].pos >= 0) cache.used--; - cache.cells[i].pos = -1; - cache.cells[i].src = -1; - cache.cells[i].seq_id.clear(); - if (new_head == cache.size) new_head = i; + + if (!cells[i].has_seq_id(seq_id)) { + if (cells[i].pos >= 0) { + used--; + } + + cells[i].pos = -1; + cells[i].src = -1; + cells[i].seq_id.clear(); + + if (new_head == size){ + new_head = i; + } } else { - cache.cells[i].seq_id.clear(); - cache.cells[i].seq_id.insert(seq_id); + cells[i].seq_id.clear(); + cells[i].seq_id.insert(seq_id); } } // If we freed up a slot, set head to it so searching can start there. - if (new_head != cache.size && new_head < cache.head) cache.head = new_head; + if (new_head != size && new_head < head) { + head = new_head; + } } -void llama_kv_cache_seq_add( - struct llama_kv_cache & cache, - llama_seq_id seq_id, - llama_pos p0, - llama_pos p1, - llama_pos delta) { - uint32_t new_head = cache.size; +void llama_kv_cache_unified::seq_add(llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta) { + if (delta == 0) { + return; + } - if (p0 < 0) p0 = 0; - if (p1 < 0) p1 = std::numeric_limits::max(); - // If there is no range then return early to avoid looping over the cache. - if (p0 == p1) return; + uint32_t new_head = size; - if (cache.recurrent) { + if (p0 < 0) { + p0 = 0; + } + + if (p1 < 0) { + p1 = std::numeric_limits::max(); + } + + // If there is no range then return early to avoid looping over the + if (p0 == p1) { + return; + } + + if (recurrent) { // for Mamba-like or RWKV models, only the pos needs to be shifted - if (0 <= seq_id && seq_id < (int64_t) cache.size) { - const int32_t tail_id = cache.cells[seq_id].tail; + if (0 <= seq_id && seq_id < (int64_t) size) { + const int32_t tail_id = cells[seq_id].tail; if (tail_id >= 0) { - llama_kv_cell & cell = cache.cells[tail_id]; + llama_kv_cell & cell = cells[tail_id]; if (cell.has_seq_id(seq_id) && p0 <= cell.pos && cell.pos < p1) { cell.pos += delta; } @@ -525,19 +358,19 @@ void llama_kv_cache_seq_add( return; } - for (uint32_t i = 0; i < cache.size; ++i) { - if (cache.cells[i].has_seq_id(seq_id) && cache.cells[i].pos >= p0 && cache.cells[i].pos < p1) { - cache.has_shift = true; - cache.cells[i].pos += delta; - cache.cells[i].delta += delta; + for (uint32_t i = 0; i < size; ++i) { + if (cells[i].has_seq_id(seq_id) && cells[i].pos >= p0 && cells[i].pos < p1) { + has_shift = true; + cells[i].pos += delta; + cells[i].delta += delta; - if (cache.cells[i].pos < 0) { - if (!cache.cells[i].is_empty()) { - cache.used--; + if (cells[i].pos < 0) { + if (!cells[i].is_empty()) { + used--; } - cache.cells[i].pos = -1; - cache.cells[i].seq_id.clear(); - if (new_head == cache.size) { + cells[i].pos = -1; + cells[i].seq_id.clear(); + if (new_head == size) { new_head = i; } } @@ -546,93 +379,968 @@ void llama_kv_cache_seq_add( // If we freed up a slot, set head to it so searching can start there. // Otherwise we just start the next search from the beginning. - cache.head = new_head != cache.size ? new_head : 0; + head = new_head != size ? new_head : 0; } -void llama_kv_cache_seq_div( - struct llama_kv_cache & cache, - llama_seq_id seq_id, - llama_pos p0, - llama_pos p1, - int d) { - if (p0 < 0) p0 = 0; - if (p1 < 0) p1 = std::numeric_limits::max(); - // If there is no range then return early to avoid looping over the cache. - if (p0 == p1) return; +void llama_kv_cache_unified::seq_div(llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) { + if (d == 1) { + return; + } - if (cache.recurrent) { + if (p0 < 0) { + p0 = 0; + } + + if (p1 < 0) { + p1 = std::numeric_limits::max(); + } + + // If there is no range then return early to avoid looping over the cache. + if (p0 == p1) { + return; + } + + if (recurrent) { // for Mamba-like or RWKV models, only the pos needs to be changed - if (0 <= seq_id && seq_id < (int64_t) cache.size) { - const int32_t tail_id = cache.cells[seq_id].tail; + if (0 <= seq_id && seq_id < (int64_t) size) { + const int32_t tail_id = cells[seq_id].tail; if (tail_id >= 0) { - llama_kv_cell & cell = cache.cells[tail_id]; + llama_kv_cell & cell = cells[tail_id]; if (cell.has_seq_id(seq_id) && p0 <= cell.pos && cell.pos < p1) { cell.pos /= d; } } } + return; } - for (uint32_t i = 0; i < cache.size; ++i) { - if (cache.cells[i].has_seq_id(seq_id) && cache.cells[i].pos >= p0 && cache.cells[i].pos < p1) { - cache.has_shift = true; + for (uint32_t i = 0; i < size; ++i) { + if (cells[i].has_seq_id(seq_id) && cells[i].pos >= p0 && cells[i].pos < p1) { + has_shift = true; { - llama_pos p_old = cache.cells[i].pos; - cache.cells[i].pos /= d; - cache.cells[i].delta += cache.cells[i].pos - p_old; + llama_pos p_old = cells[i].pos; + cells[i].pos /= d; + cells[i].delta += cells[i].pos - p_old; } } } } -llama_pos llama_kv_cache_seq_pos_max(struct llama_kv_cache & cache, llama_seq_id seq_id) { +llama_pos llama_kv_cache_unified::seq_pos_max(llama_seq_id seq_id) { llama_pos result = 0; - for (uint32_t i = 0; i < cache.size; ++i) { - if (cache.cells[i].has_seq_id(seq_id)) { - result = std::max(result, cache.cells[i].pos); + for (uint32_t i = 0; i < size; ++i) { + if (cells[i].has_seq_id(seq_id)) { + result = std::max(result, cells[i].pos); } } return result; } -void llama_kv_cache_defrag(struct llama_kv_cache & cache) { - if (!cache.recurrent) { - cache.do_defrag = true; +void llama_kv_cache_unified::defrag() { + if (!recurrent) { + do_defrag = true; } } -int32_t llama_get_kv_cache_token_count(const struct llama_kv_cache & kv) { - int result = 0; +bool llama_kv_cache_unified::get_can_shift() const { + return can_shift; +} - for (uint32_t i = 0; i < kv.size; i++) { - result += kv.cells[i].seq_id.size(); +llama_kv_cache_slot_info llama_kv_cache_unified::find_slot( + const llama_ubatch & ubatch) { + const uint32_t n_tokens = ubatch.n_tokens; + const uint32_t n_seqs = ubatch.n_seqs; + const uint32_t n_seq_tokens = ubatch.n_seq_tokens; + + if (recurrent) { + // For recurrent state architectures (like Mamba or RWKV), + // each cache cell can store the state for a whole sequence. + // A slot should be always be contiguous. + + // can only process batches with an equal number of new tokens in each sequence + GGML_ASSERT(ubatch.equal_seqs); + + int32_t min = size - 1; + int32_t max = 0; + + // everything should fit if all seq_ids are smaller than the max + for (uint32_t s = 0; s < n_seqs; ++s) { + const uint32_t n_seq_id = ubatch.n_seq_id[s]; + for (uint32_t j = 0; j < n_seq_id; ++j) { + const llama_seq_id seq_id = ubatch.seq_id[s][j]; + + if (seq_id < 0 || (uint32_t) seq_id >= size) { + // too big seq_id + // TODO: would it be possible to resize the cache instead? + LLAMA_LOG_ERROR("%s: seq_id=%d >= n_seq_max=%d Try using a bigger --parallel value\n", __func__, seq_id, size); + return llama_kv_cache_slot_info_failed; + } + if (j > 0) { + llama_kv_cell & seq = cells[seq_id]; + if (seq.tail >= 0) { + llama_kv_cell & cell = cells[seq.tail]; + // clear cells from seq_ids that become shared + // (should not normally happen, but let's handle it anyway) + cell.seq_id.erase(seq_id); + seq.tail = -1; + if (cell.seq_id.empty()) { + cell.pos = -1; + cell.src = -1; + used -= 1; + } + } + } + } + } + +#ifndef NDEBUG + { + std::vector tails_verif; + tails_verif.assign(size, -1); + for (uint32_t i = 0; i < size; ++i) { + llama_kv_cell & cell = cells[i]; + for (llama_seq_id seq_id : cell.seq_id) { + if (tails_verif[seq_id] != -1) { + LLAMA_LOG_ERROR("%s: duplicate tail for seq_id %d in cell %d and %d\n", __func__, seq_id, i, tails_verif[seq_id]); + } + tails_verif[seq_id] = i; + } + } + for (uint32_t i = 0; i < size; ++i) { + if (tails_verif[i] != cells[i].tail) { + LLAMA_LOG_ERROR("%s: wrong tail for seq_id %d, (%d instead of %d)\n", __func__, i, cells[i].tail, tails_verif[i]); + } + } + } +#endif + + // find next empty cell + uint32_t next_empty_cell = head; + + for (uint32_t i = 0; i < size; ++i) { + if (next_empty_cell >= size) { next_empty_cell -= size; } + llama_kv_cell & cell = cells[next_empty_cell]; + if (cell.is_empty()) { break; } + next_empty_cell += 1; + } + + // find usable cell range + for (uint32_t s = 0; s < n_seqs; ++s) { + const llama_seq_id seq_id = ubatch.seq_id[s][0]; + llama_kv_cell & seq_meta = cells[seq_id]; + bool has_cell = false; + if (seq_meta.tail >= 0) { + llama_kv_cell & cell = cells[seq_meta.tail]; + GGML_ASSERT(cell.has_seq_id(seq_id)); + // does this seq_id "own" the cell? + if (cell.seq_id.size() == 1) { has_cell = true; } + } + if (!has_cell) { + llama_kv_cell & empty_cell = cells[next_empty_cell]; + GGML_ASSERT(empty_cell.is_empty()); + // copy old tail into the empty cell + if (seq_meta.tail >= 0) { + llama_kv_cell & orig_cell = cells[seq_meta.tail]; + empty_cell.pos = orig_cell.pos; + empty_cell.src = orig_cell.src; + orig_cell.seq_id.erase(seq_id); + empty_cell.seq_id.insert(seq_id); // will be overwritten + } + seq_meta.tail = next_empty_cell; + // find next empty cell + if (s + 1 < n_seqs) { + next_empty_cell += 1; + for (uint32_t i = 0; i < size; ++i) { + if (next_empty_cell >= size) { next_empty_cell -= size; } + llama_kv_cell & cell = cells[next_empty_cell]; + if (cell.is_empty()) { break; } + next_empty_cell += 1; + } + } + } + if (min > seq_meta.tail) { min = seq_meta.tail; } + if (max < seq_meta.tail) { max = seq_meta.tail; } + } + + // gather and re-order + for (uint32_t s = 0; s < n_seqs; ++s) { + int32_t dst_id = s + min; + int32_t src_id = cells[ubatch.seq_id[s][0]].tail; + if (dst_id != src_id) { + llama_kv_cell & dst_cell = cells[dst_id]; + llama_kv_cell & src_cell = cells[src_id]; + + std::swap(dst_cell.pos, src_cell.pos); + std::swap(dst_cell.src, src_cell.src); + std::swap(dst_cell.seq_id, src_cell.seq_id); + + // swap tails (assuming they NEVER overlap) + for (const llama_seq_id seq_id : src_cell.seq_id) { + cells[seq_id].tail = src_id; + } + for (const llama_seq_id seq_id : dst_cell.seq_id) { + cells[seq_id].tail = dst_id; + } + } + } + + // update the pos of the used seqs + for (uint32_t s = 0; s < n_seqs; ++s) { + const llama_pos last_pos = ubatch.pos[n_seq_tokens * s + n_seq_tokens - 1]; + int32_t cell_id = s + min; + llama_kv_cell & cell = cells[cell_id]; + + if (cell.pos >= 0 && last_pos != cell.pos + (llama_pos) n_seq_tokens) { + // What should happen when the pos backtracks or skips a value? + // Clearing the state mid-batch would require special-casing which isn't done. + LLAMA_LOG_WARN("%s: non-consecutive token position %d after %d for sequence %d with %u new tokens\n", + __func__, last_pos, cell.pos, ubatch.seq_id[s][0], n_seq_tokens); + } + cell.pos = last_pos; + cell.seq_id.clear(); + for (int32_t j = 0; j < ubatch.n_seq_id[s]; ++j) { + const llama_seq_id seq_id = ubatch.seq_id[s][j]; + cell.seq_id.insert(seq_id); + cells[seq_id].tail = cell_id; + } + } + + // allow getting the range of used cells, from head to head + n + head = min; + n = max - min + 1; + used = std::count_if(cells.begin(), cells.end(), + [](const llama_kv_cell& cell){ return !cell.is_empty(); }); + + // sanity check + return llama_kv_cache_slot_info(n >= n_seqs); } - return result; + // otherwise, one cell per token. + + if (n_tokens > size) { + LLAMA_LOG_ERROR("%s: n_tokens = %d > size = %d\n", __func__, n_tokens, size); + return llama_kv_cache_slot_info_failed; + } + + uint32_t n_tested = 0; + + while (true) { + if (head + n_tokens > size) { + n_tested += size - head; + head = 0; + continue; + } + + bool found = true; + for (uint32_t i = 0; i < n_tokens; i++) { + if (cells[head + i].pos >= 0) { + found = false; + head += i + 1; + n_tested += i + 1; + break; + } + } + + if (found) { + break; + } + + if (n_tested >= size) { + //LLAMA_LOG_ERROR("%s: failed to find a slot for %d tokens\n", __func__, n_tokens); + return llama_kv_cache_slot_info_failed; + } + } + + for (uint32_t s = 0; s < n_seqs; s++) { + for (uint32_t i = 0; i < n_seq_tokens; ++i) { + uint32_t k = s*n_seq_tokens + i; + cells[head + k].pos = ubatch.pos[k]; + + for (int32_t j = 0; j < ubatch.n_seq_id[s]; j++) { + cells[head + k].seq_id.insert(ubatch.seq_id[s][j]); + } + } + } + + used += n_tokens; + + return llama_kv_cache_slot_info(head, head + n_tokens); } -int32_t llama_get_kv_cache_used_cells(const struct llama_kv_cache & kv) { - return kv.used; +uint32_t llama_kv_cache_unified::get_padding(const llama_cparams & cparams) const { + // the FA kernels require padding to avoid extra runtime boundary checks + return cparams.flash_attn ? 256u : 32u; } -bool llama_kv_cache_can_shift(const struct llama_kv_cache & kv) { - return kv.can_shift; +uint32_t llama_kv_cache_unified::cell_max() const { + for (uint32_t i = size; i > 0; --i) { + const llama_kv_cell & cell = cells[i - 1]; + + if (cell.pos >= 0 && !cell.is_empty()) { + return i; + } + } + + return 0; +} + +size_t llama_kv_cache_unified::size_k_bytes() const { + size_t size_k_bytes = 0; + + for (const auto & k : k_l) { + size_k_bytes += ggml_nbytes(k); + } + + return size_k_bytes; +} + +size_t llama_kv_cache_unified::size_v_bytes() const { + size_t size_v_bytes = 0; + + for (const auto & v : v_l) { + size_v_bytes += ggml_nbytes(v); + } + + return size_v_bytes; +} + +bool llama_kv_cache_unified::defrag_prepare(int32_t n_max_nodes) { + const uint32_t n_layer = hparams.n_layer; + + const uint32_t n_kv = cell_max(); + const uint32_t n_used = used; + + assert(n_used <= n_kv); + + //const int64_t t_start = ggml_time_us(); + + // number of cells moved + uint32_t n_moves = 0; + + // each move requires 6*n_layer tensors (see graph_build_kv_self_defrag) + // - source view, destination view, copy operation + // - x2 for keys and values + //const uint32_t max_moves = max_nodes()/(6*n_layer); + // TODO: tmp fix https://github.com/ggerganov/llama.cpp/issues/6685#issuecomment-2057579516 + const uint32_t max_moves = (n_max_nodes - 2*n_layer)/(6*n_layer); + + // determine which KV cells to move where + // + // cell i moves to ids[i] + // + // if ids[i] == i || ids[i] == n_kv, then cell i is not moved + // + auto & ids = defrag_info.ids; + + ids.clear(); + ids.resize(n_kv, n_kv); + + for (uint32_t i0 = 0; i0 < n_used; ++i0) { + const auto & cell0 = cells[i0]; + + if (!cell0.is_empty()) { + ids[i0] = i0; + + continue; + } + + // found a hole - fill it with data from the end of the cache + + uint32_t nh = 1; + + // determine the size of the hole + while (i0 + nh < n_used && cells[i0 + nh].is_empty()) { + nh++; + } + + uint32_t nf = 0; + uint32_t is = n_kv - 1; + + // starting from the end, find nh non-empty cells + for (; is > i0; --is) { + const auto & cell1 = cells[is]; + + if (cell1.is_empty() || ids[is] != n_kv) { + continue; + } + + // non-empty cell which is not yet moved + nf++; + + if (nf == nh) { + break; + } + } + + // this can only happen if `n_used` is not accurate, which would be a bug + GGML_ASSERT(nf == nh && "KV defrag bug: nf != nh"); + + nf = 0; + + uint32_t i1 = is; + + // are we moving a continuous block of memory? + bool cont = false; + + // should we stop searching for the next move? + bool stop = false; + + // go back and move the nf cells to the hole + for (; i1 < n_kv; ++i1) { + auto & cell1 = cells[i1]; + + if (cell1.is_empty() || ids[i1] != n_kv) { + if (n_moves == max_moves) { + stop = true; + break; + } + + cont = false; + continue; + } + + // this cell goes to (i0 + nf) + ids[i1] = i0 + nf; + + // move the cell meta data + cells[i0 + nf] = cell1; + + // clear the old cell and move the head there + cell1 = llama_kv_cell(); + head = n_used; + + if (!cont) { + n_moves++; + cont = true; + } + + nf++; + + if (nf == nh) { + break; + } + } + + if (stop || n_moves == max_moves) { + break; + } + + //LLAMA_LOG_INFO("(tmp log) KV defrag: move [%u, %u) to [%u, %u)\n", is, i1 + 1, i0, i0 + nh); + + i0 += nh - 1; + } + + if (n_moves == 0) { + return false; + } + + LLAMA_LOG_DEBUG("(tmp log) KV defrag cell moves: %u\n", n_moves); + + LLAMA_LOG_DEBUG("expected gf nodes: %u\n", 6*n_moves*n_layer); + + return true; +} + +void llama_kv_cache_unified::state_write(llama_io_write_i & io, llama_seq_id seq_id) const { + std::vector> cell_ranges; // ranges, from inclusive, to exclusive + uint32_t cell_count = 0; + + // Count the number of cells with the specified seq_id + // Find all the ranges of cells with this seq id (or all, when -1) + uint32_t cell_range_begin = size; + for (uint32_t i = 0; i < size; ++i) { + const auto & cell = cells[i]; + if ((seq_id == -1 && !cell.is_empty()) || cell.has_seq_id(seq_id)) { + ++cell_count; + if (cell_range_begin == size) { + cell_range_begin = i; + } + } else { + if (cell_range_begin != size) { + cell_ranges.emplace_back(cell_range_begin, i); + cell_range_begin = size; + } + } + } + if (cell_range_begin != size) { + cell_ranges.emplace_back(cell_range_begin, size); + } + + // DEBUG CHECK: Sum of cell counts in ranges should equal the total cell count + uint32_t cell_count_check = 0; + for (const auto & range : cell_ranges) { + cell_count_check += range.second - range.first; + } + GGML_ASSERT(cell_count == cell_count_check); + + io.write(&cell_count, sizeof(cell_count)); + + state_write_meta(io, cell_ranges, seq_id); + state_write_data(io, cell_ranges); +} + +void llama_kv_cache_unified::state_read(llama_io_read_i & io, llama_seq_id seq_id) { + uint32_t cell_count; + io.read_to(&cell_count, sizeof(cell_count)); + + bool res = true; + res = res && state_read_meta(io, cell_count, seq_id); + res = res && state_read_data(io, cell_count); + + if (!res) { + if (seq_id == -1) { + clear(); + } else { + seq_rm(seq_id, -1, -1); + } + throw std::runtime_error("failed to restore kv cache"); + } +} + +void llama_kv_cache_unified::state_write_meta(llama_io_write_i & io, const std::vector> & cell_ranges, llama_seq_id seq_id) const { + for (const auto & range : cell_ranges) { + for (uint32_t i = range.first; i < range.second; ++i) { + const auto & cell = cells[i]; + const llama_pos pos = cell.pos; + const uint32_t n_seq_id = seq_id == -1 ? cell.seq_id.size() : 0; + + io.write(&pos, sizeof(pos)); + io.write(&n_seq_id, sizeof(n_seq_id)); + + if (n_seq_id) { + for (auto seq_id : cell.seq_id) { + io.write(&seq_id, sizeof(seq_id)); + } + } + } + } +} + +void llama_kv_cache_unified::state_write_data(llama_io_write_i & io, const std::vector> & cell_ranges) const { + const uint32_t v_trans = this->v_trans ? 1 : 0; + const uint32_t n_layer = hparams.n_layer; + + io.write(&v_trans, sizeof(v_trans)); + io.write(&n_layer, sizeof(n_layer)); + + std::vector tmp_buf; + + // Iterate and write all the keys first, each row is a cell + // Get whole range at a time + for (uint32_t il = 0; il < n_layer; ++il) { + const uint32_t n_embd_k_gqa = hparams.n_embd_k_gqa(il) + hparams.n_embd_k_s(); + + // Write key type + const int32_t k_type_i = (int32_t)k_l[il]->type; + io.write(&k_type_i, sizeof(k_type_i)); + + // Write row size of key + const uint64_t k_size_row = ggml_row_size(k_l[il]->type, n_embd_k_gqa); + io.write(&k_size_row, sizeof(k_size_row)); + + // Read each range of cells of k_size length each into tmp_buf and write out + for (const auto & range : cell_ranges) { + const size_t range_size = range.second - range.first; + const size_t buf_size = range_size * k_size_row; + io.write_tensor(k_l[il], range.first * k_size_row, buf_size); + } + } + + if (!v_trans) { + for (uint32_t il = 0; il < n_layer; ++il) { + const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); + + // Write value type + const int32_t v_type_i = (int32_t)v_l[il]->type; + io.write(&v_type_i, sizeof(v_type_i)); + + // Write row size of value + const uint64_t v_size_row = ggml_row_size(v_l[il]->type, n_embd_v_gqa); + io.write(&v_size_row, sizeof(v_size_row)); + + // Read each range of cells of v_size length each into tmp_buf and write out + for (const auto & range : cell_ranges) { + const size_t range_size = range.second - range.first; + const size_t buf_size = range_size * v_size_row; + io.write_tensor(v_l[il], range.first * v_size_row, buf_size); + } + } + } else { + // When v is transposed, we also need the element size and get the element ranges from each row + const uint32_t kv_size = size; + for (uint32_t il = 0; il < n_layer; ++il) { + const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); + + // Write value type + const int32_t v_type_i = (int32_t)v_l[il]->type; + io.write(&v_type_i, sizeof(v_type_i)); + + // Write element size + const uint32_t v_size_el = ggml_type_size(v_l[il]->type); + io.write(&v_size_el, sizeof(v_size_el)); + + // Write GQA embedding size + io.write(&n_embd_v_gqa, sizeof(n_embd_v_gqa)); + + // For each row, we get the element values of each cell + for (uint32_t j = 0; j < n_embd_v_gqa; ++j) { + // Read each range of cells of v_size_el length each into tmp_buf and write out + for (const auto & range : cell_ranges) { + const size_t range_size = range.second - range.first; + const size_t src_offset = (range.first + j * kv_size) * v_size_el; + const size_t buf_size = range_size * v_size_el; + io.write_tensor(v_l[il], src_offset, buf_size); + } + } + } + } +} + +bool llama_kv_cache_unified::state_read_meta(llama_io_read_i & io, uint32_t cell_count, llama_seq_id dest_seq_id) { + if (dest_seq_id != -1) { + // single sequence + + seq_rm(dest_seq_id, -1, -1); + + llama_sbatch sbatch; + llama_ubatch batch = sbatch.reserve_ubatch(cell_count, /* has_embd */ false); + + batch.n_tokens = cell_count; + batch.n_seq_tokens = cell_count; + batch.n_seqs = 1; + + for (uint32_t i = 0; i < cell_count; ++i) { + llama_pos pos; + uint32_t n_seq_id; + + io.read_to(&pos, sizeof(pos)); + io.read_to(&n_seq_id, sizeof(n_seq_id)); + + if (n_seq_id != 0) { + LLAMA_LOG_ERROR("%s: invalid seq_id-agnostic kv cell\n", __func__); + return false; + } + + batch.pos[i] = pos; + } + batch.n_seq_id[0] = 1; + batch.seq_id[0] = &dest_seq_id; + if (!find_slot(batch)) { + LLAMA_LOG_ERROR("%s: failed to find available cells in kv cache\n", __func__); + return false; + } + + // DEBUG CHECK: kv.head should be our first cell, kv.head + cell_count - 1 should be our last cell (verify seq_id and pos values) + // Assume that this is one contiguous block of cells + GGML_ASSERT(head + cell_count <= size); + GGML_ASSERT(cells[head].pos == batch.pos[0]); + GGML_ASSERT(cells[head + cell_count - 1].pos == batch.pos[cell_count - 1]); + GGML_ASSERT(cells[head].has_seq_id(dest_seq_id)); + GGML_ASSERT(cells[head + cell_count - 1].has_seq_id(dest_seq_id)); + } else { + // whole KV cache restore + + if (cell_count > size) { + LLAMA_LOG_ERROR("%s: not enough cells in kv cache\n", __func__); + return false; + } + + clear(); + + for (uint32_t i = 0; i < cell_count; ++i) { + llama_kv_cell & cell = cells[i]; + + llama_pos pos; + uint32_t n_seq_id; + + io.read_to(&pos, sizeof(pos)); + io.read_to(&n_seq_id, sizeof(n_seq_id)); + + cell.pos = pos; + + for (uint32_t j = 0; j < n_seq_id; ++j) { + llama_seq_id seq_id; + io.read_to(&seq_id, sizeof(seq_id)); + + // TODO: llama_kv_cache_unified should have a notion of max sequences + //if (seq_id < 0 || (uint32_t) seq_id >= llama_n_seq_max(ctx)) { + if (seq_id < 0) { + //LLAMA_LOG_ERROR("%s: invalid seq_id, %d is out of range [0, %u)\n", __func__, seq_id, llama_n_seq_max(ctx)); + LLAMA_LOG_ERROR("%s: invalid seq_id, %d is out of range [0, inf)\n", __func__, seq_id); + return false; + } + + cell.seq_id.insert(seq_id); + + if (recurrent) { + int32_t & tail = cells[seq_id].tail; + if (tail != -1) { + LLAMA_LOG_ERROR("%s: duplicate tail for seq_id %d in cell %d and %d\n", __func__, seq_id, i, tail); + return false; + } + tail = i; + } + } + } + + head = 0; + used = cell_count; + } + + if (recurrent) { + for (uint32_t i = 0; i < cell_count; ++i) { + uint32_t cell_id = head + i; + // make sure the recurrent states will keep their restored state + cells[cell_id].src = cell_id; + } + } + + return true; +} + +bool llama_kv_cache_unified::state_read_data(llama_io_read_i & io, uint32_t cell_count) { + uint32_t v_trans; + uint32_t n_layer; + io.read_to(&v_trans, sizeof(v_trans)); + io.read_to(&n_layer, sizeof(n_layer)); + + if (n_layer != hparams.n_layer) { + LLAMA_LOG_ERROR("%s: mismatched layer count (%u instead of %u)\n", __func__, n_layer, hparams.n_layer); + return false; + } + if (cell_count > size) { + LLAMA_LOG_ERROR("%s: not enough cells in kv cache to restore state (%u > %u)\n", __func__, cell_count, size); + return false; + } + if (v_trans != (bool) v_trans) { + LLAMA_LOG_ERROR("%s: incompatible V transposition\n", __func__); + return false; + } + + // For each layer, read the keys for each cell, one row is one cell, read as one contiguous block + for (uint32_t il = 0; il < n_layer; ++il) { + const uint32_t n_embd_k_gqa = hparams.n_embd_k_gqa(il) + hparams.n_embd_k_s(); + + // Read type of key + int32_t k_type_i_ref; + io.read_to(&k_type_i_ref, sizeof(k_type_i_ref)); + const int32_t k_type_i = (int32_t) k_l[il]->type; + if (k_type_i != k_type_i_ref) { + LLAMA_LOG_ERROR("%s: mismatched key type (%d != %d, layer %d)\n", __func__, k_type_i, k_type_i_ref, il); + return false; + } + + // Read row size of key + uint64_t k_size_row_ref; + io.read_to(&k_size_row_ref, sizeof(k_size_row_ref)); + const size_t k_size_row = ggml_row_size(k_l[il]->type, n_embd_k_gqa); + if (k_size_row != k_size_row_ref) { + LLAMA_LOG_ERROR("%s: mismatched key row size (%zu != %zu, layer %d)\n", __func__, k_size_row, (size_t) k_size_row_ref, il); + return false; + } + + if (cell_count) { + // Read and set the keys for the whole cell range + ggml_backend_tensor_set(k_l[il], io.read(cell_count * k_size_row), head * k_size_row, cell_count * k_size_row); + } + } + + if (!v_trans) { + for (uint32_t il = 0; il < n_layer; ++il) { + const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); + + // Read type of value + int32_t v_type_i_ref; + io.read_to(&v_type_i_ref, sizeof(v_type_i_ref)); + const int32_t v_type_i = (int32_t)v_l[il]->type; + if (v_type_i != v_type_i_ref) { + LLAMA_LOG_ERROR("%s: mismatched value type (%d != %d, layer %d)\n", __func__, v_type_i, v_type_i_ref, il); + return false; + } + + // Read row size of value + uint64_t v_size_row_ref; + io.read_to(&v_size_row_ref, sizeof(v_size_row_ref)); + const size_t v_size_row = ggml_row_size(v_l[il]->type, n_embd_v_gqa); + if (v_size_row != v_size_row_ref) { + LLAMA_LOG_ERROR("%s: mismatched value row size (%zu != %zu, layer %d)\n", __func__, v_size_row, (size_t) v_size_row_ref, il); + return false; + } + + if (cell_count) { + // Read and set the values for the whole cell range + ggml_backend_tensor_set(v_l[il], io.read(cell_count * v_size_row), head * v_size_row, cell_count * v_size_row); + } + } + } else { + // For each layer, read the values for each cell (transposed) + for (uint32_t il = 0; il < n_layer; ++il) { + const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(il) + hparams.n_embd_v_s(); + + // Read type of value + int32_t v_type_i_ref; + io.read_to(&v_type_i_ref, sizeof(v_type_i_ref)); + const int32_t v_type_i = (int32_t)v_l[il]->type; + if (v_type_i != v_type_i_ref) { + LLAMA_LOG_ERROR("%s: mismatched value type (%d != %d, layer %d)\n", __func__, v_type_i, v_type_i_ref, il); + return false; + } + + // Read element size of value + uint32_t v_size_el_ref; + io.read_to(&v_size_el_ref, sizeof(v_size_el_ref)); + const size_t v_size_el = ggml_type_size(v_l[il]->type); + if (v_size_el != v_size_el_ref) { + LLAMA_LOG_ERROR("%s: mismatched value element size (%zu != %zu, layer %d)\n", __func__, v_size_el, (size_t) v_size_el_ref, il); + return false; + } + + // Read GQA embedding size + uint32_t n_embd_v_gqa_ref; + io.read_to(&n_embd_v_gqa_ref, sizeof(n_embd_v_gqa_ref)); + if (n_embd_v_gqa != n_embd_v_gqa_ref) { + LLAMA_LOG_ERROR("%s: mismatched GQA embedding size (%u != %u, layer %d)\n", __func__, n_embd_v_gqa, n_embd_v_gqa_ref, il); + return false; + } + + if (cell_count) { + // For each row in the transposed matrix, read the values for the whole cell range + for (uint32_t j = 0; j < n_embd_v_gqa; ++j) { + const size_t dst_offset = (head + j * size) * v_size_el; + ggml_backend_tensor_set(v_l[il], io.read(cell_count * v_size_el), dst_offset, cell_count * v_size_el); + } + } + } + } + + return true; +} + +// +// interface implementation +// + +int32_t llama_kv_cache_n_tokens(const llama_kv_cache * kv) { + if (!kv) { + return 0; + } + + return kv->get_n_tokens(); +} + +int32_t llama_kv_cache_used_cells(const llama_kv_cache * kv) { + if (!kv) { + return 0; + } + + return kv->get_used_cells(); +} + +void llama_kv_cache_clear(llama_kv_cache * kv) { + if (!kv) { + return; + } + + kv->clear(); +} + +bool llama_kv_cache_seq_rm( + llama_kv_cache * kv, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1) { + if (!kv) { + return true; + } + + return kv->seq_rm(seq_id, p0, p1); +} + +void llama_kv_cache_seq_cp( + llama_kv_cache * kv, + llama_seq_id seq_id_src, + llama_seq_id seq_id_dst, + llama_pos p0, + llama_pos p1) { + if (!kv) { + return; + } + + kv->seq_cp(seq_id_src, seq_id_dst, p0, p1); +} + +void llama_kv_cache_seq_keep(llama_kv_cache * kv, llama_seq_id seq_id) { + if (!kv) { + return; + } + + kv->seq_keep(seq_id); +} + +void llama_kv_cache_seq_add( + llama_kv_cache * kv, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + llama_pos delta) { + if (!kv) { + return; + } + + kv->seq_add(seq_id, p0, p1, delta); +} + +void llama_kv_cache_seq_div( + llama_kv_cache * kv, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + int d) { + if (!kv) { + return; + } + + kv->seq_div(seq_id, p0, p1, d); +} + +llama_pos llama_kv_cache_seq_pos_max(llama_kv_cache * kv, llama_seq_id seq_id) { + if (!kv) { + return 0; + } + + return kv->seq_pos_max(seq_id); +} + +void llama_kv_cache_defrag(llama_kv_cache * kv) { + if (!kv) { + return; + } + + kv->defrag(); +} + +bool llama_kv_cache_can_shift(const llama_kv_cache * kv) { + if (!kv) { + return false; + } + + return kv->get_can_shift(); } // // kv cache view // -struct llama_kv_cache_view llama_kv_cache_view_init(const struct llama_kv_cache & kv, int32_t n_seq_max) { - struct llama_kv_cache_view result = { +llama_kv_cache_view llama_kv_cache_view_init(const llama_kv_cache & kv, int32_t n_seq_max) { + llama_kv_cache_view result = { /*.n_cells = */ 0, /*.n_seq_max = */ n_seq_max, /*.token_count = */ 0, - /*.used_cells = */ llama_get_kv_cache_used_cells(kv), + /*.used_cells = */ llama_kv_cache_used_cells(&kv), /*.max_contiguous = */ 0, /*.max_contiguous_idx = */ -1, /*.cells = */ nullptr, @@ -642,7 +1350,7 @@ struct llama_kv_cache_view llama_kv_cache_view_init(const struct llama_kv_cache return result; } -void llama_kv_cache_view_free(struct llama_kv_cache_view * view) { +void llama_kv_cache_view_free(llama_kv_cache_view * view) { if (view->cells != nullptr) { free(view->cells); view->cells = nullptr; @@ -653,18 +1361,25 @@ void llama_kv_cache_view_free(struct llama_kv_cache_view * view) { } } -void llama_kv_cache_view_update(struct llama_kv_cache_view * view, const struct llama_kv_cache & kv) { - if (uint32_t(view->n_cells) < kv.size || view->cells == nullptr) { - view->n_cells = int32_t(kv.size); - void * p = realloc(view->cells, sizeof(struct llama_kv_cache_view_cell) * view->n_cells); +void llama_kv_cache_view_update(llama_kv_cache_view * view, const llama_kv_cache * kv) { + // TODO: rework this in the future, for now quick hack + const llama_kv_cache_unified * kvu = dynamic_cast(kv); + if (kvu == nullptr) { + LLAMA_LOG_ERROR("%s: the kv_cache_view currently works only with llama_kv_cache_unified\n", __func__); + return; + } + + if (uint32_t(view->n_cells) < kvu->size || view->cells == nullptr) { + view->n_cells = int32_t(kvu->size); + void * p = realloc(view->cells, sizeof(llama_kv_cache_view_cell) * view->n_cells); GGML_ASSERT(p != nullptr && "Failed to alloc kv_cache_view cells"); - view->cells = (struct llama_kv_cache_view_cell *)p; + view->cells = (llama_kv_cache_view_cell *)p; p = realloc(view->cells_sequences, sizeof(llama_seq_id) * view->n_seq_max * view->n_cells); GGML_ASSERT(p != nullptr && "Failed to alloc kv_cache_view cells sequences"); view->cells_sequences = (llama_seq_id *)p; } - const std::vector & kv_cells = kv.cells; + const std::vector & kv_cells = kvu->cells; llama_kv_cache_view_cell * c_curr = view->cells; llama_seq_id * cs_curr = view->cells_sequences; int32_t used_cells = 0; @@ -673,7 +1388,7 @@ void llama_kv_cache_view_update(struct llama_kv_cache_view * view, const struct uint32_t max_contig = 0; int32_t max_contig_idx = -1; - for (int32_t i = 0; i < int32_t(kv.size); i++, c_curr++, cs_curr += view->n_seq_max) { + for (int32_t i = 0; i < int32_t(kvu->size); i++, c_curr++, cs_curr += view->n_seq_max) { const size_t curr_size = kv_cells[i].seq_id.size(); token_count += curr_size; c_curr->pos = kv_cells[i].pos + kv_cells[i].delta; @@ -711,8 +1426,8 @@ void llama_kv_cache_view_update(struct llama_kv_cache_view * view, const struct view->max_contiguous_idx = max_contig_idx; view->token_count = token_count; view->used_cells = used_cells; - if (uint32_t(used_cells) != kv.used) { + if (uint32_t(used_cells) != kvu->used) { LLAMA_LOG_ERROR("%s: used cells mismatch. kv_cache says %d but we calculated %d\n", - __func__, kv.used, used_cells); + __func__, kvu->used, used_cells); } } diff --git a/src/llama-kv-cache.h b/src/llama-kv-cache.h index 1ce0850ec..0a7ff8a4e 100644 --- a/src/llama-kv-cache.h +++ b/src/llama-kv-cache.h @@ -1,12 +1,29 @@ #pragma once #include "llama.h" +#include "llama-io.h" +#include "llama-memory.h" #include "ggml-cpp.h" +#include #include #include -#include + +struct llama_cparams; +struct llama_hparams; +struct llama_ubatch; + +struct llama_kv_cache : public llama_memory_i { + using llama_memory_i::llama_memory_i; + + virtual int32_t get_n_tokens() const = 0; + virtual uint32_t get_used_cells() const = 0; // TODO: remove, this is too-specific to the unified cache + + virtual bool get_can_shift() const = 0; + + bool get_can_edit() const override { return get_can_shift(); } +}; struct llama_kv_cell { llama_pos pos = -1; @@ -29,11 +46,105 @@ struct llama_kv_cell { } }; +// a structure holds information about the slot found in llama_kv_cache_find_slot +struct llama_kv_cache_slot_info { + std::pair boundaries; // slot boundaries [begin, end) + bool found = false; // the slot was found + + explicit llama_kv_cache_slot_info(bool found_) : found{found_} {} + llama_kv_cache_slot_info(uint32_t begin, uint32_t end) : boundaries{begin, end}, found{true} {} + + operator bool() const { return found; } +}; + // ring-buffer of cached KV data -struct llama_kv_cache { +// TODO: pimpl +// TODO: add notion of max sequences +class llama_kv_cache_unified : public llama_kv_cache { +public: + // can be used to query data from the model if needed + struct callbacks { + std::function get_rope_factors; + }; + + llama_kv_cache_unified( + const llama_hparams & hparams, + callbacks cbs); + + virtual ~llama_kv_cache_unified() = default; + + // TODO: become constructor + bool init( + const llama_model & model, // TODO: do not reference the model + const llama_cparams & cparams, + ggml_type type_k, + ggml_type type_v, + uint32_t kv_size, + bool offload); + + int32_t get_n_tokens() const override; + uint32_t get_used_cells() const override; + + size_t total_size() const; + + // TODO: better data structures to reduce the cost of this operation + llama_pos pos_max() const; + + void clear() override; + void defrag() override; + + bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) override; + void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) override; + void seq_keep(llama_seq_id seq_id) override; + void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta) override; + void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) override; + + llama_pos seq_pos_max(llama_seq_id seq_id) override; + + bool get_can_shift() const override; + + // find an empty slot of size "n_tokens" in the cache + // updates the cache head + // returns a structure holding information about the slot found + // Note: On success, it's important that cache.head points + // to the first cell of the slot. + llama_kv_cache_slot_info find_slot(const llama_ubatch & batch); + + // TODO: maybe not needed + uint32_t get_padding(const llama_cparams & cparams) const; + + // find how many cells are currently in use + uint32_t cell_max() const; + + size_t size_k_bytes() const; + size_t size_v_bytes() const; + + // defrag + + struct { + std::vector ids; + } defrag_info; + + // return true if cells have been moved + bool defrag_prepare(int32_t n_max_nodes); + + // state save/load + + void state_write(llama_io_write_i & io, llama_seq_id seq_id = -1) const; + void state_read (llama_io_read_i & io, llama_seq_id seq_id = -1); + + // members + + const llama_hparams & hparams; + + callbacks cbs; + bool has_shift = false; bool do_defrag = false; + + // TODO: remove this and implement llama_kv_cache_recurrent instead bool recurrent = false; // with recurrent state models, a cell can hold the state for more than one past token + bool v_trans = true; // the value tensor is transposed bool can_shift = false; @@ -47,124 +158,30 @@ struct llama_kv_cache { // computed before each graph build uint32_t n = 0; + std::vector cells; + + std::vector k_l; // per layer + std::vector v_l; + +private: ggml_type type_k = GGML_TYPE_F16; ggml_type type_v = GGML_TYPE_F16; - std::vector cells; - - std::vector k_l; // per layer - std::vector v_l; - - std::vector ctxs; + std::vector ctxs; std::vector bufs; - size_t total_size() const { - size_t size = 0; - for (const auto & buf : bufs) { - size += ggml_backend_buffer_get_size(buf.get()); - } + void state_write_meta(llama_io_write_i & io, const std::vector> & cell_ranges, llama_seq_id seq_id = -1) const; + void state_write_data(llama_io_write_i & io, const std::vector> & cell_ranges) const; - return size; - } - - // TODO: better data structures to reduce the cost of this operation - llama_pos max_pos() const { - llama_pos max_pos = -1; - for (const auto & cell : cells) { - max_pos = std::max(max_pos, cell.pos); - } - - return max_pos; - } + bool state_read_meta(llama_io_read_i & io, uint32_t cell_count, llama_seq_id dest_seq_id = -1); + bool state_read_data(llama_io_read_i & io, uint32_t cell_count); }; -// a structure holds information about the slot found in llama_kv_cache_find_slot -struct llama_kv_cache_slot_info { - std::pair boundaries; // slot boundaries [begin, end) - bool found = false; // the slot was found - - explicit llama_kv_cache_slot_info(bool found_) : found{found_} {} - llama_kv_cache_slot_info(uint32_t begin, uint32_t end) : boundaries{begin, end}, found{true} {} - - operator bool() const { return found; } -}; - -// TODO: maybe not needed -uint32_t llama_kv_cache_get_padding(const struct llama_cparams & cparams); - -bool llama_kv_cache_init( - struct llama_kv_cache & cache, - const llama_model & model, - const llama_cparams & cparams, - ggml_type type_k, - ggml_type type_v, - uint32_t kv_size, - bool offload); - -// find an empty slot of size "n_tokens" in the cache -// updates the cache head -// returns a structure holding information about the slot found -// Note: On success, it's important that cache.head points -// to the first cell of the slot. -struct llama_kv_cache_slot_info llama_kv_cache_find_slot( - struct llama_kv_cache & cache, - const struct llama_ubatch & batch); - -// find how many cells are currently in use -uint32_t llama_kv_cache_cell_max(const struct llama_kv_cache & cache); - -void llama_kv_cache_clear(struct llama_kv_cache & cache); - -bool llama_kv_cache_seq_rm( - struct llama_kv_cache & cache, - llama_seq_id seq_id, - llama_pos p0, - llama_pos p1); - -void llama_kv_cache_seq_cp( - struct llama_kv_cache & cache, - llama_seq_id seq_id_src, - llama_seq_id seq_id_dst, - llama_pos p0, - llama_pos p1); - -void llama_kv_cache_seq_keep( - struct llama_kv_cache & cache, - llama_seq_id seq_id); - -void llama_kv_cache_seq_add( - struct llama_kv_cache & cache, - llama_seq_id seq_id, - llama_pos p0, - llama_pos p1, - llama_pos delta); - -void llama_kv_cache_seq_div( - struct llama_kv_cache & cache, - llama_seq_id seq_id, - llama_pos p0, - llama_pos p1, - int d); - -llama_pos llama_kv_cache_seq_pos_max( - struct llama_kv_cache & cache, - llama_seq_id seq_id); - -void llama_kv_cache_defrag(struct llama_kv_cache & cache); - -int32_t llama_get_kv_cache_token_count(const struct llama_kv_cache & kv); - -int32_t llama_get_kv_cache_used_cells(const struct llama_kv_cache & kv); - -bool llama_kv_cache_can_shift(const struct llama_kv_cache & kv); - -// -// kv cache view -// - -struct llama_kv_cache_view llama_kv_cache_view_init(const struct llama_kv_cache & kv, int32_t n_seq_max); - -void llama_kv_cache_view_update(struct llama_kv_cache_view * view, const struct llama_kv_cache & kv); +// TODO: temporary reusing llama_kv_cache_unified -- implement recurrent cache and simplify llama_kv_cache_unified +//class llama_kv_cache_recurrent : public llama_kv_cache_unified { +//public: +// using llama_kv_cache_unified::llama_kv_cache_unified; +//}; // // kv cache restore @@ -184,13 +201,15 @@ struct llama_kv_slot_restorer { bool do_restore = false; - explicit llama_kv_slot_restorer(const struct llama_kv_cache & cache) { + llama_kv_cache_unified & cache; + + explicit llama_kv_slot_restorer(llama_kv_cache_unified & cache) : cache(cache) { old_state.head = cache.head; old_state.n = cache.n; } // saves a slot information for future restoration - void save(const struct llama_kv_cache_slot_info & slot) { + void save(const llama_kv_cache_slot_info & slot) { if (slot) { do_restore = true; if (slot.boundaries.first != slot.boundaries.second) { @@ -201,19 +220,68 @@ struct llama_kv_slot_restorer { // must be explicitly called to restore the kv_cache state // and rollback changes from all llama_kv_cache_find_slot calls - void restore(struct llama_kv_cache & cache) { + void restore() { if (do_restore) { cache.head = old_state.head; cache.n = old_state.n; if (cache.recurrent) { // recurrent models like Mamba or RWKV can't have a state partially erased - llama_kv_cache_seq_rm(cache, -1, -1, -1); + cache.seq_rm(-1, -1, -1); } else { for (auto & slot : slot_boundaries) { - llama_kv_cache_seq_rm(cache, -1, slot.first, slot.second); + cache.seq_rm(-1, slot.first, slot.second); } } } } }; +// TODO: maybe become part of the public llama_kv_cache in the future +int32_t llama_kv_cache_n_tokens(const llama_kv_cache * kv); + +int32_t llama_kv_cache_used_cells(const llama_kv_cache * kv); + +void llama_kv_cache_clear(llama_kv_cache * kv); + +bool llama_kv_cache_seq_rm( + llama_kv_cache * kv, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1); + +void llama_kv_cache_seq_cp( + llama_kv_cache * kv, + llama_seq_id seq_id_src, + llama_seq_id seq_id_dst, + llama_pos p0, + llama_pos p1); + +void llama_kv_cache_seq_keep(llama_kv_cache * kv, llama_seq_id seq_id); + +void llama_kv_cache_seq_add( + llama_kv_cache * kv, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + llama_pos delta); + +void llama_kv_cache_seq_div( + llama_kv_cache * kv, + llama_seq_id seq_id, + llama_pos p0, + llama_pos p1, + int d); + +llama_pos llama_kv_cache_seq_pos_max(llama_kv_cache * kv, llama_seq_id seq_id); + +void llama_kv_cache_defrag(llama_kv_cache * kv); + +bool llama_kv_cache_can_shift(const llama_kv_cache * kv); + +// +// kv cache view +// + +llama_kv_cache_view llama_kv_cache_view_init(const llama_kv_cache & kv, int32_t n_seq_max); + +void llama_kv_cache_view_update(llama_kv_cache_view * view, const llama_kv_cache * kv); diff --git a/src/llama-memory.cpp b/src/llama-memory.cpp new file mode 100644 index 000000000..10173253e --- /dev/null +++ b/src/llama-memory.cpp @@ -0,0 +1 @@ +#include "llama-memory.h" diff --git a/src/llama-memory.h b/src/llama-memory.h new file mode 100644 index 000000000..69e6e34ca --- /dev/null +++ b/src/llama-memory.h @@ -0,0 +1,21 @@ +#pragma once + +#include "llama.h" + +// general concept of LLM memory +// the KV cache is a type of LLM memory, but there can be other types +class llama_memory_i { +public: + virtual void clear() = 0; + virtual void defrag() = 0; + + virtual bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) = 0; + virtual void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) = 0; + virtual void seq_keep(llama_seq_id seq_id) = 0; + virtual void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta) = 0; + virtual void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) = 0; + + virtual llama_pos seq_pos_max(llama_seq_id seq_id) = 0; + + virtual bool get_can_edit() const = 0; +}; diff --git a/src/llama-model.cpp b/src/llama-model.cpp index 9f75589d8..522219c01 100644 --- a/src/llama-model.cpp +++ b/src/llama-model.cpp @@ -2,12 +2,17 @@ #include "llama-impl.h" #include "llama-mmap.h" +#include "llama-batch.h" +#include "llama-cparams.h" #include "llama-model-loader.h" +#include "llama-kv-cache.h" #include "ggml-cpp.h" #include #include +#include +#include #include #include #include @@ -244,6 +249,7 @@ static ggml_backend_buffer_type_t select_weight_buft(const llama_hparams & hpara return cur_buft; } } + return nullptr; } @@ -302,7 +308,7 @@ static buft_list_t make_cpu_buft_list(const std::vector & de } // GPU: split if LLAMA_SPLIT_MODE_ROW -> GPU -static buft_list_t make_gpu_buft_list(ggml_backend_dev_t dev, enum llama_split_mode split_mode, const float * tensor_split) { +static buft_list_t make_gpu_buft_list(ggml_backend_dev_t dev, llama_split_mode split_mode, const float * tensor_split) { buft_list_t buft_list; // add the device split buffer type if requested and available @@ -369,7 +375,7 @@ struct llama_model::impl { std::vector dev_layer; }; -llama_model::llama_model(const struct llama_model_params & params) : params(params), pimpl(std::make_unique()) { +llama_model::llama_model(const llama_model_params & params) : params(params), pimpl(std::make_unique()) { } llama_model::~llama_model() {} @@ -391,7 +397,7 @@ void llama_model::load_hparams(llama_model_loader & ml) { // get metadata as string for (int i = 0; i < gguf_get_n_kv(ctx); i++) { - enum gguf_type type = gguf_get_kv_type(ctx, i); + gguf_type type = gguf_get_kv_type(ctx, i); if (type == GGUF_TYPE_ARRAY) { continue; } @@ -1444,7 +1450,10 @@ bool llama_model::load_tensors(llama_model_loader & ml) { // skip unused tensors if (info.op == GGML_OP_NONE) { - LLAMA_LOG_WARN("model has unused tensor %s -- ignoring\n", tn.str().c_str()); + const size_t nbytes = ggml_nbytes(t_meta); + LLAMA_LOG_WARN("model has unused tensor %s (size = %zu bytes) -- ignoring\n", tn.str().c_str(), nbytes); + + ml.size_data -= nbytes; ml.n_created++; return nullptr; @@ -3631,8 +3640,8 @@ size_t llama_model::size() const { return pimpl->n_bytes; } -size_t llama_model::max_nodes() const { - return std::max(8192, tensors_by_name.size()*5); +size_t llama_model::n_tensors() const { + return tensors_by_name.size(); } size_t llama_model::n_devices() const { @@ -3745,7 +3754,7 @@ void llama_model::print_info() const { LLAMA_LOG_INFO("%s: n_expert_shared = %d\n", __func__, hparams.n_expert_shared); LLAMA_LOG_INFO("%s: expert_weights_scale = %.1f\n", __func__, hparams.expert_weights_scale); LLAMA_LOG_INFO("%s: expert_weights_norm = %d\n", __func__, hparams.expert_weights_norm); - LLAMA_LOG_INFO("%s: expert_gating_func = %s\n", __func__, llama_expert_gating_func_name((enum llama_expert_gating_func_type) hparams.expert_gating_func)); + LLAMA_LOG_INFO("%s: expert_gating_func = %s\n", __func__, llama_expert_gating_func_name((llama_expert_gating_func_type) hparams.expert_gating_func)); LLAMA_LOG_INFO("%s: rope_yarn_log_mul = %.4f\n", __func__, hparams.rope_yarn_log_mul); } @@ -3821,9 +3830,9 @@ ggml_backend_buffer_type_t llama_model::select_buft(int il) const { }); } -const struct ggml_tensor * llama_model::get_tensor(const char * name) const { +const ggml_tensor * llama_model::get_tensor(const char * name) const { auto it = std::find_if(tensors_by_name.begin(), tensors_by_name.end(), - [name](const std::pair & it) { + [name](const std::pair & it) { return it.first == name; }); if (it == tensors_by_name.end()) { @@ -3833,12 +3842,7309 @@ const struct ggml_tensor * llama_model::get_tensor(const char * name) const { return it->second; } +struct llm_build_llama : public llm_graph_context { + llm_build_llama(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale; + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // rope freq factors for llama3; may return nullptr for llama2 and other models + ggml_tensor * rope_factors = static_cast(memory)->cbs.get_rope_factors(n_ctx_per_seq, il); + + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, kq_scale, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + // For Granite architecture + if (hparams.f_residual_scale) { + cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + if (model.layers[il].ffn_gate_inp == nullptr) { + + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + model.layers[il].ffn_gate, model.layers[il].ffn_gate_b, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } else { + // MoE branch + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_SILU, true, + false, 0.0, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(cur, "ffn_moe_out", il); + } + + // For Granite architecture + if (hparams.f_residual_scale) { + cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + // For Granite architecture + if (hparams.f_logit_scale) { + cur = ggml_scale(ctx0, cur, 1.0f / hparams.f_logit_scale); + } + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_deci : public llm_graph_context { + llm_build_deci(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale; + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + const int64_t n_head_kv = hparams.n_head_kv(il); + const int64_t n_head = hparams.n_head(il); + + if (n_head == 0) { + // attention-free layer of Llama-3_1-Nemotron-51B + cur = inpL; + } else { + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + } + + if (n_head > 0 && n_head_kv == 0) { + // "linear attention" of Llama-3_1-Nemotron-51B + cur = build_lora_mm(model.layers[il].wo, cur); + cb(cur, "wo", il); + } else if (n_head > 0) { + // self-attention + // rope freq factors for llama3; may return nullptr for llama2 and other models + ggml_tensor * rope_factors = static_cast(memory)->cbs.get_rope_factors(n_ctx_per_seq, il); + + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, kq_scale, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + // For Granite architecture + if (hparams.f_residual_scale) { + cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); + } + + // modified to support attention-free layer of Llama-3_1-Nemotron-51B + ggml_tensor * ffn_inp = cur; + if (n_head > 0) { + ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + } + + // feed-forward network + if (model.layers[il].ffn_gate_inp == nullptr) { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + model.layers[il].ffn_gate, model.layers[il].ffn_gate_b, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + // For Granite architecture + if (hparams.f_residual_scale) { + cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + // For Granite architecture + if (hparams.f_logit_scale) { + cur = ggml_scale(ctx0, cur, 1.0f / hparams.f_logit_scale); + } + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_baichuan : public llm_graph_context { + llm_build_baichuan(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = model.type == LLM_TYPE_7B ? build_inp_pos() : nullptr; + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + switch (model.type) { + case LLM_TYPE_7B: + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + break; + case LLM_TYPE_13B: + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd/n_head, n_head, n_tokens); + Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd/n_head, n_head, n_tokens); + break; + default: + GGML_ABORT("fatal error"); + } + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_xverse : public llm_graph_context { + llm_build_xverse(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, model.output_norm, NULL, LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_falcon : public llm_graph_context { + llm_build_falcon(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * attn_norm; + + attn_norm = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(attn_norm, "attn_norm", il); + + // self-attention + { + if (model.layers[il].attn_norm_2) { + // Falcon-40B + cur = build_norm(inpL, + model.layers[il].attn_norm_2, + model.layers[il].attn_norm_2_b, + LLM_NORM, il); + cb(cur, "attn_norm_2", il); + } else { + cur = attn_norm; + } + + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", 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); + + // using mode = 2 for neox mode + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + attn_norm = ggml_get_rows(ctx0, attn_norm, inp_out_ids); + } + + ggml_tensor * ffn_inp = cur; + + // feed forward + { + cur = build_ffn(attn_norm, // !! use the attn norm, not the result + model.layers[il].ffn_up, NULL, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + cur = ggml_add(ctx0, cur, inpL); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + // norm + cur = build_norm(cur, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_grok : public llm_graph_context { + llm_build_grok(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // multiply by embedding_multiplier_scale of 78.38367176906169 + inpL = ggml_scale(ctx0, inpL, 78.38367176906169f); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + // Grok + // if attn_out_norm is present then apply it before adding the input + if (model.layers[il].attn_out_norm) { + cur = build_norm(cur, + model.layers[il].attn_out_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_out_norm", il); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + // MoE branch + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_GELU, true, + false, 0.0, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(cur, "ffn_moe_out", il); + + // Grok + // if layer_out_norm is present then apply it before adding the input + // Idea: maybe ffn_out_norm is a better name + if (model.layers[il].layer_out_norm) { + cur = build_norm(cur, + model.layers[il].layer_out_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "layer_out_norm", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + // Grok + // multiply logits by output_multiplier_scale of 0.5773502691896257 + + cur = ggml_scale(ctx0, cur, 0.5773502691896257f); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_dbrx : public llm_graph_context { + llm_build_dbrx(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = nullptr; + ggml_tensor * Kcur = nullptr; + ggml_tensor * Vcur = nullptr; + + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_clamp(ctx0, cur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); + cb(cur, "wqkv_clamped", il); + + Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + // MoE branch + cur = build_norm(ffn_inp, + model.layers[il].attn_out_norm, NULL, + LLM_NORM, il); + cb(cur, "attn_out_norm", il); + + cur = build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_SILU, true, + false, 0.0, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(cur, "ffn_moe_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_starcoder : public llm_graph_context { + llm_build_starcoder(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + ggml_tensor * pos = ggml_get_rows(ctx0, model.pos_embd, inp_pos); + cb(pos, "pos_embd", -1); + + inpL = ggml_add(ctx0, inpL, pos); + cb(inpL, "inpL", -1); + + for (int il = 0; il < n_layer; ++il) { + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // add the input + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // FF + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_refact : public llm_graph_context { + llm_build_refact(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens); + cb(Kcur, "Kcur", il); + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + cb(Qcur, "Qcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_bert : public llm_graph_context { + llm_build_bert(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + ggml_tensor * inp_pos = nullptr; + + if (model.arch != LLM_ARCH_JINA_BERT_V2) { + inp_pos = build_inp_pos(); + } + + // construct input embeddings (token, type, position) + inpL = build_inp_embd(model.tok_embd); + + // token types are hardcoded to zero ("Sentence A") + ggml_tensor * type_row0 = ggml_view_1d(ctx0, model.type_embd, n_embd, 0); + inpL = ggml_add(ctx0, inpL, type_row0); + if (model.arch == LLM_ARCH_BERT) { + inpL = ggml_add(ctx0, ggml_get_rows(ctx0, model.pos_embd, inp_pos), inpL); + } + cb(inpL, "inp_embd", -1); + + // embed layer norm + inpL = build_norm(inpL, model.tok_norm, model.tok_norm_b, LLM_NORM, -1); + cb(inpL, "inp_norm", -1); + + auto * inp_attn = build_attn_inp_no_cache(); + + // iterate layers + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * cur = inpL; + + ggml_tensor * Qcur; + ggml_tensor * Kcur; + ggml_tensor * Vcur; + + // self-attention + if (model.arch == LLM_ARCH_BERT || model.arch == LLM_ARCH_JINA_BERT_V2) { + Qcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wq, cur), model.layers[il].bq); + + if (model.layers[il].attn_q_norm) { + Qcur = build_norm(Qcur, + model.layers[il].attn_q_norm, + model.layers[il].attn_q_norm_b, + LLM_NORM, il); + } + + Kcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wk, cur), model.layers[il].bk); + + if (model.layers[il].attn_k_norm) { + Kcur = build_norm(Kcur, + model.layers[il].attn_k_norm, + model.layers[il].attn_k_norm_b, + LLM_NORM, il); + } + + Vcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wv, cur), model.layers[il].bv); + + 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); + } else { + // compute Q and K and RoPE them + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head, n_head_kv, n_tokens); + } + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + cb(cur, "kqv_out", il); + + if (il == n_layer - 1 && pooling_type == LLAMA_POOLING_TYPE_NONE) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // re-add the layer input + cur = ggml_add(ctx0, cur, inpL); + + // attention layer norm + cur = build_norm(cur, model.layers[il].attn_out_norm, model.layers[il].attn_out_norm_b, LLM_NORM, il); + + if (model.layers[il].attn_norm_2 != nullptr) { + cur = ggml_add(ctx0, cur, inpL); // re-add the layer input + cur = build_norm(cur, model.layers[il].attn_norm_2, model.layers[il].attn_norm_2_b, LLM_NORM, il); + } + + ggml_tensor * ffn_inp = cur; + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + if (model.arch == LLM_ARCH_BERT) { + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + } else if (model.arch == LLM_ARCH_JINA_BERT_V2) { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_PAR, il); + } else { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + } + cb(cur, "ffn_out", il); + + // attentions bypass the intermediate layer + cur = ggml_add(ctx0, cur, ffn_inp); + + // output layer norm + cur = build_norm(cur, model.layers[il].layer_out_norm, model.layers[il].layer_out_norm_b, LLM_NORM, il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cb(cur, "result_embd", -1); + res->t_embd = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_bloom : public llm_graph_context { + llm_build_bloom(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + inpL = build_norm(inpL, + model.tok_norm, + model.tok_norm_b, + LLM_NORM, -1); + cb(inpL, "inp_norm", -1); + + for (int il = 0; il < n_layer; ++il) { + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // Add the input + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // FF + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_mpt : public llm_graph_context { + llm_build_mpt(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * pos; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + if (model.pos_embd) { + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + pos = ggml_get_rows(ctx0, model.pos_embd, inp_pos); + cb(pos, "pos_embd", -1); + + inpL = ggml_add(ctx0, inpL, pos); + cb(inpL, "inpL", -1); + } + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * attn_norm; + + attn_norm = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(attn_norm, "attn_norm", il); + + // self-attention + { + cur = attn_norm; + + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + if (model.layers[il].bqkv){ + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + } + + if (hparams.f_clamp_kqv > 0.0f) { + cur = ggml_clamp(ctx0, cur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); + cb(cur, "wqkv_clamped", il); + } + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + // Q/K Layernorm + if (model.layers[il].attn_q_norm) { + Qcur = build_norm(Qcur, + model.layers[il].attn_q_norm, + model.layers[il].attn_q_norm_b, + LLM_NORM, il); + cb(Qcur, "Qcur", il); + + Kcur = build_norm(Kcur, + model.layers[il].attn_k_norm, + model.layers[il].attn_k_norm_b, + LLM_NORM, il); + cb(Kcur, "Kcur", 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); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } else { + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // Add the input + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // feed forward + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + model.layers[il].ffn_act, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_stablelm : public llm_graph_context { + llm_build_stablelm(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + ggml_tensor * inpSA = cur; + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + cb(Qcur, "Qcur", il); + Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens); + cb(Kcur, "Kcur", il); + + if (model.layers[il].attn_q_norm) { + Qcur = build_norm(Qcur, + model.layers[il].attn_q_norm, + NULL, + LLM_NORM, il); + cb(Qcur, "Qcur", il); + } + if (model.layers[il].attn_k_norm) { + Kcur = build_norm(Kcur, + model.layers[il].attn_k_norm, + NULL, + LLM_NORM, il); + cb(Kcur, "Kcur", il); + } + + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + if (model.layers[il].ffn_norm) { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + } else { + // parallel residual + cur = inpSA; + } + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_qwen : public llm_graph_context { + llm_build_qwen(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 2*sizeof(float)*(n_embd))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", 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); + + // using mode = 2 for neox mode + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward forward + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_qwen2 : public llm_graph_context { + llm_build_qwen2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_qwen2vl : public llm_graph_context { + llm_build_qwen2vl(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + int sections[4]; + std::copy(std::begin(hparams.rope_sections), std::begin(hparams.rope_sections) + 4, sections); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_multi( + ctx0, + ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, sections, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_multi( + ctx0, + ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, sections, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_qwen2moe : public llm_graph_context { + llm_build_qwen2moe(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self_attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // MoE branch + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + ggml_tensor * moe_out = + build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_SILU, false, + false, 0.0, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(cur, "ffn_moe_out", il); + + // FFN shared expert + { + ggml_tensor * cur_gate_inp = build_lora_mm(model.layers[il].ffn_gate_inp_shexp, cur); + cb(cur_gate_inp, "ffn_shexp_gate_inp", il); + + // sigmoid + ggml_tensor * cur_gate = ggml_div(ctx0, ggml_silu(ctx0, cur_gate_inp), cur_gate_inp); + cb(cur_gate, "ffn_shexp_gate", il); + + ggml_tensor * cur_ffn = build_ffn(cur, + model.layers[il].ffn_up_shexp, NULL, NULL, + model.layers[il].ffn_gate_shexp, NULL, NULL, + model.layers[il].ffn_down_shexp, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur_ffn, "ffn_shexp", il); + + ggml_tensor * ffn_shexp_out = ggml_mul(ctx0, cur_ffn, cur_gate); + cb(ffn_shexp_out, "ffn_shexp_out", il); + + moe_out = ggml_add(ctx0, moe_out, ffn_shexp_out); + cb(moe_out, "ffn_out", il); + + cur = moe_out; + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_phi2 : public llm_graph_context { + llm_build_phi2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * attn_norm_output; + ggml_tensor * ffn_output; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + attn_norm_output = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(attn_norm_output, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = nullptr; + ggml_tensor * Kcur = nullptr; + ggml_tensor * Vcur = nullptr; + + if (model.layers[il].wqkv) { + cur = build_lora_mm(model.layers[il].wqkv, attn_norm_output); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + } else { + Qcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wq, attn_norm_output), model.layers[il].bq); + Kcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wk, attn_norm_output), model.layers[il].bk); + Vcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wv, attn_norm_output), model.layers[il].bv); + } + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", 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); + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + // with phi2, we scale the Q to avoid precision issues + // ref: https://github.com/ml-explore/mlx-examples/blob/08e862336ade809bc37d1035f94b359e7d1a5152/phi2/phi2.py#L64-L66 + Qcur = ggml_scale(ctx0, Qcur, 1.0f/sqrtf(float(n_embd_head))); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + attn_norm_output = ggml_get_rows(ctx0, attn_norm_output, inp_out_ids); + } + + // FF + { + ffn_output = build_ffn(attn_norm_output, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(ffn_output, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_output); + cur = ggml_add(ctx0, cur, inpL); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + cb(cur, "result_output_no_bias", -1); + + cur = ggml_add(ctx0, cur, model.output_b); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_phi3 : public llm_graph_context { + llm_build_phi3(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, true); + + for (int il = 0; il < n_layer; ++il) { + auto * residual = inpL; + + // self-attention + { + // rope freq factors for 128k context + ggml_tensor * rope_factors = static_cast(memory)->cbs.get_rope_factors(n_ctx_per_seq, il); + + ggml_tensor* attn_norm_output = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM_RMS, il); + cb(attn_norm_output, "attn_norm", il); + + ggml_tensor * Qcur = nullptr; + ggml_tensor * Kcur = nullptr; + ggml_tensor * Vcur = nullptr; + + if (model.layers[il].wqkv) { + cur = build_lora_mm(model.layers[il].wqkv, attn_norm_output); + cb(cur, "wqkv", il); + + Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0 * sizeof(float) * (n_embd))); + Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1 * sizeof(float) * (n_embd))); + Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1 * sizeof(float) * (n_embd + n_embd_gqa))); + } else { + Qcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wq, attn_norm_output), model.layers[il].bq); + Kcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wk, attn_norm_output), model.layers[il].bk); + Vcur = ggml_add(ctx0, build_lora_mm(model.layers[il].wv, attn_norm_output), model.layers[il].bv); + } + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", 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); + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, rope_factors, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd_head))); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, rope_factors, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor* inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + residual = ggml_get_rows(ctx0, residual, inp_out_ids); + } + + cur = ggml_add(ctx0, cur, residual); + residual = cur; + + cur = build_norm(cur, + model.layers[il].ffn_norm, model.layers[il].ffn_norm_b, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + // feed-forward network + if (model.layers[il].ffn_gate_inp == nullptr) { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SWIGLU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + } else { + // MoE branch + cur = build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_SILU, true, + false, 0.0, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(cur, "ffn_moe_out", il); + } + + cur = ggml_add(ctx0, residual, cur); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + if (model.output_b != nullptr) { + cb(cur, "result_output_no_bias", -1); + cur = ggml_add(ctx0, cur, model.output_b); + } + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_plamo : public llm_graph_context { + llm_build_plamo(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + ggml_tensor * attention_norm = cur; + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_rot, n_head, n_tokens), inp_pos, nullptr, + n_embd_head, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_rot, n_head_kv, n_tokens), inp_pos, nullptr, + n_embd_head, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + ggml_tensor * sa_out = cur; + + cur = attention_norm; + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + sa_out = ggml_get_rows(ctx0, sa_out, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // feed-forward network + { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, sa_out); + cur = ggml_add(ctx0, cur, inpL); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_gpt2 : public llm_graph_context { + llm_build_gpt2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * pos; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + pos = ggml_get_rows(ctx0, model.pos_embd, inp_pos); + cb(pos, "pos_embd", -1); + + inpL = ggml_add(ctx0, inpL, pos); + cb(inpL, "inpL", -1); + + for (int il = 0; il < n_layer; ++il) { + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // add the input + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // FF + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_codeshell : public llm_graph_context { + llm_build_codeshell(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + ggml_tensor * tmpq = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * tmpk = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(tmpq, "tmpq", il); + cb(tmpk, "tmpk", il); + cb(Vcur, "Vcur", il); + + ggml_tensor * Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, tmpq, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, tmpk, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // add the input + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // FF + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_orion : public llm_graph_context { + llm_build_orion(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + // if (model.layers[il].bq) { + // Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + // cb(Qcur, "Qcur", il); + // } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + // if (model.layers[il].bk) { + // Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + // cb(Kcur, "Kcur", il); + // } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + // if (model.layers[il].bv) { + // Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + // cb(Vcur, "Vcur", il); + // } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_internlm2 : public llm_graph_context { + llm_build_internlm2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_minicpm3 : public llm_graph_context { + llm_build_minicpm3(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + //TODO: if the model varies, these parameters need to be read from the model + const int64_t n_embd_base = 256; + const float scale_embd = 12.0f; + const float scale_depth = 1.4f; + const float kq_scale = 1.0f / sqrtf(float(hparams.n_embd_head_k)); + + const uint32_t n_embd_head_qk_rope = hparams.n_rot; + const uint32_t n_embd_head_qk_nope = hparams.n_embd_head_k - hparams.n_rot; + const uint32_t kv_lora_rank = hparams.n_lora_kv; + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // scale the input embeddings + inpL = ggml_scale(ctx0, inpL, scale_embd); + cb(inpL, "inp_scaled", -1); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + ggml_tensor * rope_factors = static_cast(memory)->cbs.get_rope_factors(n_ctx_per_seq, il); + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self_attention + { + ggml_tensor * q = NULL; + // {n_embd, q_lora_rank} * {n_embd, n_tokens} -> {q_lora_rank, n_tokens} + q = ggml_mul_mat(ctx0, model.layers[il].wq_a, cur); + cb(q, "q", il); + + q = build_norm(q, + model.layers[il].attn_q_a_norm, NULL, + LLM_NORM_RMS, il); + cb(q, "q", il); + + // {q_lora_rank, n_head * hparams.n_embd_head_k} * {q_lora_rank, n_tokens} -> {n_head * hparams.n_embd_head_k, n_tokens} + q = ggml_mul_mat(ctx0, model.layers[il].wq_b, q); + cb(q, "q", il); + + // split into {n_head * n_embd_head_qk_nope, n_tokens} + ggml_tensor * q_nope = ggml_view_3d(ctx0, q, n_embd_head_qk_nope, n_head, n_tokens, + ggml_row_size(q->type, hparams.n_embd_head_k), + ggml_row_size(q->type, hparams.n_embd_head_k * n_head), + 0); + cb(q_nope, "q_nope", il); + + // and {n_head * n_embd_head_qk_rope, n_tokens} + ggml_tensor * q_pe = ggml_view_3d(ctx0, q, n_embd_head_qk_rope, n_head, n_tokens, + ggml_row_size(q->type, hparams.n_embd_head_k), + ggml_row_size(q->type, hparams.n_embd_head_k * n_head), + ggml_row_size(q->type, n_embd_head_qk_nope)); + cb(q_pe, "q_pe", il); + + // {n_embd, kv_lora_rank + n_embd_head_qk_rope} * {n_embd, n_tokens} -> {kv_lora_rank + n_embd_head_qk_rope, n_tokens} + ggml_tensor * kv_pe_compresseed = ggml_mul_mat(ctx0, model.layers[il].wkv_a_mqa, cur); + cb(kv_pe_compresseed, "kv_pe_compresseed", il); + + // split into {kv_lora_rank, n_tokens} + ggml_tensor * kv_compressed = ggml_view_2d(ctx0, kv_pe_compresseed, kv_lora_rank, n_tokens, + kv_pe_compresseed->nb[1], + 0); + cb(kv_compressed, "kv_compressed", il); + + // and {n_embd_head_qk_rope, n_tokens} + ggml_tensor * k_pe = ggml_view_3d(ctx0, kv_pe_compresseed, n_embd_head_qk_rope, 1, n_tokens, + kv_pe_compresseed->nb[1], + kv_pe_compresseed->nb[1], + ggml_row_size(kv_pe_compresseed->type, kv_lora_rank)); + cb(k_pe, "k_pe", il); + + // TODO: the CUDA backend used to not support non-cont. (RMS) norm, investigate removing ggml_cont + kv_compressed = ggml_cont(ctx0, kv_compressed); + kv_compressed = build_norm(kv_compressed, + model.layers[il].attn_kv_a_norm, NULL, + LLM_NORM_RMS, il); + cb(kv_compressed, "kv_compressed", il); + + // {kv_lora_rank, n_head * (n_embd_head_qk_nope + n_embd_head_v)} * {kv_lora_rank, n_tokens} -> {n_head * (n_embd_head_qk_nope + n_embd_head_v), n_tokens} + ggml_tensor * kv = ggml_mul_mat(ctx0, model.layers[il].wkv_b, kv_compressed); + cb(kv, "kv", il); + + // split into {n_head * n_embd_head_qk_nope, n_tokens} + ggml_tensor * k_nope = ggml_view_3d(ctx0, kv, n_embd_head_qk_nope, n_head, n_tokens, + ggml_row_size(kv->type, n_embd_head_qk_nope + hparams.n_embd_head_v), + ggml_row_size(kv->type, n_head * (n_embd_head_qk_nope + hparams.n_embd_head_v)), + 0); + cb(k_nope, "k_nope", il); + + // and {n_head * n_embd_head_v, n_tokens} + ggml_tensor * v_states = ggml_view_3d(ctx0, kv, hparams.n_embd_head_v, n_head, n_tokens, + ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)), + ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)*n_head), + ggml_row_size(kv->type, (n_embd_head_qk_nope))); + cb(v_states, "v_states", il); + + v_states = ggml_cont(ctx0, v_states); + cb(v_states, "v_states", il); + + v_states = ggml_view_2d(ctx0, v_states, hparams.n_embd_head_v * n_head, n_tokens, + ggml_row_size(kv->type, hparams.n_embd_head_v * n_head), + 0); + cb(v_states, "v_states", il); + + q_pe = ggml_cont(ctx0, q_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this + q_pe = ggml_rope_ext( + ctx0, q_pe, inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(q_pe, "q_pe", il); + + // shared RoPE key + k_pe = ggml_cont(ctx0, k_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this + k_pe = ggml_rope_ext( + ctx0, k_pe, inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(k_pe, "k_pe", il); + + ggml_tensor * q_states = ggml_concat(ctx0, q_nope, q_pe, 0); + cb(q_states, "q_states", il); + + ggml_tensor * k_states = ggml_concat(ctx0, k_nope, ggml_repeat(ctx0, k_pe, q_pe), 0); + cb(k_states, "k_states", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + q_states, k_states, v_states, nullptr, kq_scale, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + // scale_res - scale the hidden states for residual connection + const float scale_res = scale_depth/sqrtf(float(n_layer)); + cur = ggml_scale(ctx0, cur, scale_res); + cb(cur, "hidden_scaled", il); + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + // scale the hidden states for residual connection + cur = ggml_scale(ctx0, cur, scale_res); + cb(cur, "hidden_scaled_ffn", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head scaling + const float scale_lmhead = float(n_embd_base)/float(n_embd); + cur = ggml_scale(ctx0, cur, scale_lmhead); + cb(cur, "lmhead_scaling", -1); + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_gemma : public llm_graph_context { + llm_build_gemma(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head_k = hparams.n_embd_head_k; + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + inpL = ggml_scale(ctx0, inpL, sqrtf(n_embd)); + cb(inpL, "inp_scaled", -1); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head_k, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Qcur, "Qcur", il); + + Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd_head_k))); + cb(Qcur, "Qcur_scaled", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + ggml_tensor * sa_out = ggml_add(ctx0, cur, inpL); + cb(sa_out, "sa_out", il); + + cur = build_norm(sa_out, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + // feed-forward network + { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, sa_out); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_gemma2 : public llm_graph_context { + llm_build_gemma2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head_k = hparams.n_embd_head_k; + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + inpL = ggml_scale(ctx0, inpL, sqrtf(n_embd)); + cb(inpL, "inp_scaled", -1); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, true); + + for (int il = 0; il < n_layer; ++il) { + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head_k, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Qcur, "Qcur", il); + + // ref: https://github.com/google/gemma_pytorch/commit/03e657582d17cb5a8617ebf333c1c16f3694670e + switch (model.type) { + case LLM_TYPE_2B: + case LLM_TYPE_9B: Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd_head_k))); break; + case LLM_TYPE_27B: Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd / n_head))); break; + default: GGML_ABORT("fatal error"); + }; + cb(Qcur, "Qcur_scaled", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f, il); + } + + cur = build_norm(cur, + model.layers[il].attn_post_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_post_norm", il); + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + ggml_tensor * sa_out = ggml_add(ctx0, cur, inpL); + cb(sa_out, "sa_out", il); + + cur = build_norm(sa_out, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + // feed-forward network + { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = build_norm(cur, + model.layers[il].ffn_post_norm, NULL, + LLM_NORM_RMS, -1); + cb(cur, "ffn_post_norm", -1); + + cur = ggml_add(ctx0, cur, sa_out); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + // final logit soft-capping + cur = ggml_scale(ctx0, cur, 1.0f / hparams.f_final_logit_softcapping); + cur = ggml_tanh(ctx0, cur); + cur = ggml_scale(ctx0, cur, hparams.f_final_logit_softcapping); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_gemma3 : public llm_graph_context { + llm_build_gemma3(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head_k = hparams.n_embd_head_k; + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // important: do not normalize weights for raw embeddings input (i.e. encoded image emdeddings) + if (ubatch.token) { + inpL = ggml_scale(ctx0, inpL, sqrtf(n_embd)); + cb(inpL, "inp_scaled", -1); + } + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + // TODO: is causal == true correct? might need some changes + auto * inp_attn = build_attn_inp_kv_unified(true, true); + + // "5-to-1 interleaved attention" + // 5 layers of local attention followed by 1 layer of global attention + static const int sliding_window_pattern = 6; + + for (int il = 0; il < n_layer; ++il) { + const bool is_sliding = il % sliding_window_pattern < (sliding_window_pattern - 1); + + const float freq_base_l = is_sliding ? 10000.0f : freq_base; + const float freq_scale_l = is_sliding ? 1.0f : freq_scale; + + // norm + cur = build_norm(inpL, model.layers[il].attn_norm, NULL, LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head_k, n_head, n_tokens); + Qcur = build_norm(Qcur, model.layers[il].attn_q_norm, NULL, LLM_NORM_RMS, il); + cb(Qcur, "Qcur_normed", il); + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Qcur, "Qcur", il); + + Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_kv, n_tokens); + Kcur = build_norm(Kcur, model.layers[il].attn_k_norm, NULL, LLM_NORM_RMS, il); + cb(Kcur, "Kcur_normed", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, + ext_factor, attn_factor, beta_fast, beta_slow); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, hparams.f_attention_scale, il); + } + + cur = build_norm(cur, + model.layers[il].attn_post_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_post_norm", il); + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + ggml_tensor * sa_out = ggml_add(ctx0, cur, inpL); + cb(sa_out, "sa_out", il); + + cur = build_norm(sa_out, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + // feed-forward network + { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = build_norm(cur, + model.layers[il].ffn_post_norm, NULL, + LLM_NORM_RMS, -1); + cb(cur, "ffn_post_norm", -1); + + cur = ggml_add(ctx0, cur, sa_out); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +// TODO: move up next to build_starcoder +struct llm_build_starcoder2 : public llm_graph_context { + llm_build_starcoder2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_mamba : public llm_graph_context { + const llama_model & model; + + llm_build_mamba(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params), model(model) { + ggml_tensor * cur; + ggml_tensor * inpL; + + // {n_embd, n_tokens} + inpL = build_inp_embd(model.tok_embd); + + ggml_tensor * state_copy = build_inp_s_copy(); + ggml_tensor * state_mask = build_inp_s_mask(); + + for (int il = 0; il < n_layer; ++il) { + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + //cur = build_mamba_layer(gf, cur, state_copy, state_mask, il); + cur = build_mamba_layer(gf, cur, state_copy, state_mask, ubatch, il); + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // residual + cur = ggml_add(ctx0, cur, inpL); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + // final rmsnorm + cur = build_norm(inpL, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } + + // TODO: split + ggml_tensor * build_mamba_layer( + ggml_cgraph * gf, + ggml_tensor * cur, + ggml_tensor * state_copy, + ggml_tensor * state_mask, + const llama_ubatch & ubatch, + int il) const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + const auto kv_head = kv_self->head; + + const int64_t d_conv = hparams.ssm_d_conv; + const int64_t d_inner = hparams.ssm_d_inner; + const int64_t d_state = hparams.ssm_d_state; + const int64_t dt_rank = hparams.ssm_dt_rank; + const int64_t n_seqs = ubatch.n_seqs; + // Some variants of Mamba arch (e.g. FalconMamba do apply layer norm on B and Dt layers) + const bool ssm_dt_b_c_rms = hparams.ssm_dt_b_c_rms; + // Use the same RMS norm as the final layer norm + const float norm_rms_eps = hparams.f_norm_rms_eps; + + const int64_t n_seq_tokens = ubatch.n_seq_tokens; + + GGML_ASSERT(n_seqs != 0); + GGML_ASSERT(ubatch.equal_seqs); + GGML_ASSERT(ubatch.n_tokens == n_seq_tokens * n_seqs); + + ggml_tensor * conv_states_all = kv_self->k_l[il]; + ggml_tensor * ssm_states_all = kv_self->v_l[il]; + + // (ab)using the KV cache to store the states + ggml_tensor * conv = build_copy_mask_state( + gf, conv_states_all, state_copy, state_mask, + hparams.n_embd_k_s(), n_seqs); + conv = ggml_reshape_3d(ctx0, conv, d_conv - 1, d_inner, n_seqs); + ggml_tensor * ssm = build_copy_mask_state( + gf, ssm_states_all, state_copy, state_mask, + hparams.n_embd_v_s(), n_seqs); + ssm = ggml_reshape_3d(ctx0, ssm, d_state, d_inner, n_seqs); + + // {n_embd, n_tokens} => {n_embd, n_seq_tokens, n_seqs} + cur = ggml_reshape_3d(ctx0, cur, cur->ne[0], n_seq_tokens, n_seqs); + + // {n_embd, 2*d_inner} @ {n_embd, n_seq_tokens, n_seqs} => {2*d_inner, n_seq_tokens, n_seqs} + ggml_tensor * xz = build_lora_mm(model.layers[il].ssm_in, cur); + // split the above in two + // => {d_inner, n_seq_tokens, n_seqs} + ggml_tensor * x = ggml_view_3d(ctx0, xz, d_inner, xz->ne[1], xz->ne[2], xz->nb[1], xz->nb[2], 0); + ggml_tensor * z = ggml_view_3d(ctx0, xz, d_inner, xz->ne[1], xz->ne[2], xz->nb[1], xz->nb[2], d_inner*ggml_element_size(xz)); + + // conv + { + // => {d_conv - 1 + n_seq_tokens, d_inner, n_seqs} + ggml_tensor * conv_x = ggml_concat(ctx0, conv, ggml_transpose(ctx0, x), 0); + + // copy last (d_conv - 1) columns back into the state cache + ggml_tensor * last_conv = ggml_view_3d(ctx0, conv_x, d_conv - 1, d_inner, n_seqs, conv_x->nb[1], conv_x->nb[2], n_seq_tokens*(conv_x->nb[0])); + + ggml_build_forward_expand(gf, + ggml_cpy(ctx0, last_conv, + ggml_view_1d(ctx0, conv_states_all, + (d_conv - 1)*(d_inner)*(n_seqs), + kv_head*(d_conv - 1)*(d_inner)*ggml_element_size(conv_states_all)))); + + // 1D convolution + // The equivalent is to make a self-overlapping view of conv_x + // over d_conv columns at each stride in the 3rd dimension, + // then element-wise multiply that with the conv1d weight, + // then sum the elements of each row, + // (the last two steps are a dot product over rows (also doable with mul_mat)) + // then permute away the ne[0] dimension, + // and then you're left with the resulting x tensor. + // For simultaneous sequences, all sequences need to have the same length. + x = ggml_ssm_conv(ctx0, conv_x, model.layers[il].ssm_conv1d); + + // bias + x = ggml_add(ctx0, x, model.layers[il].ssm_conv1d_b); + + x = ggml_silu(ctx0, x); + } + + // ssm + { + // {d_inner, dt_rank + 2*d_state} @ {d_inner, n_seq_tokens, n_seqs} => {dt_rank + 2*d_state, n_seq_tokens, n_seqs} + ggml_tensor * x_db = build_lora_mm(model.layers[il].ssm_x, x); + // split + ggml_tensor * dt = ggml_view_3d(ctx0, x_db, dt_rank, n_seq_tokens, n_seqs, x_db->nb[1], x_db->nb[2], 0); + ggml_tensor * B = ggml_view_3d(ctx0, x_db, d_state, n_seq_tokens, n_seqs, x_db->nb[1], x_db->nb[2], ggml_element_size(x_db)*dt_rank); + ggml_tensor * C = ggml_view_3d(ctx0, x_db, d_state, n_seq_tokens, n_seqs, x_db->nb[1], x_db->nb[2], ggml_element_size(x_db)*(dt_rank+d_state)); + + // Some Mamba variants (e.g. FalconMamba) apply RMS norm in B, C & Dt layers + if (ssm_dt_b_c_rms) { + dt = ggml_rms_norm(ctx0, dt, norm_rms_eps); + B = ggml_rms_norm(ctx0, B, norm_rms_eps); + C = ggml_rms_norm(ctx0, C, norm_rms_eps); + } + + // {dt_rank, d_inner} @ {dt_rank, n_seq_tokens, n_seqs} => {d_inner, n_seq_tokens, n_seqs} + dt = build_lora_mm(model.layers[il].ssm_dt, dt); + dt = ggml_add(ctx0, dt, model.layers[il].ssm_dt_b); + + // Custom operator to optimize the parallel associative scan + // as described in the Annex D of the Mamba paper. + // => {d_inner, n_seq_tokens, n_seqs} and {d_state, d_inner, n_seqs} + ggml_tensor * y_ssm = ggml_ssm_scan(ctx0, ssm, x, dt, model.layers[il].ssm_a, B, C); + + // store last states + ggml_build_forward_expand(gf, + ggml_cpy(ctx0, + ggml_view_1d(ctx0, y_ssm, d_state*d_inner*n_seqs, x->nb[3]), + ggml_view_1d(ctx0, ssm_states_all, d_state*d_inner*n_seqs, kv_head*d_state*d_inner*ggml_element_size(ssm_states_all)))); + + ggml_tensor * y = ggml_view_3d(ctx0, y_ssm, d_inner, n_seq_tokens, n_seqs, x->nb[1], x->nb[2], 0); + + // TODO: skip computing output earlier for unused tokens + + // {d_inner, n_seq_tokens, n_seqs} * {d_inner} => {d_inner, n_seq_tokens, n_seqs} + y = ggml_add(ctx0, y, ggml_mul(ctx0, x, model.layers[il].ssm_d)); + y = ggml_mul(ctx0, y, ggml_silu(ctx0, ggml_cont(ctx0, z))); + + // {d_inner, n_embd} @ {d_inner, n_seq_tokens, n_seqs} => {n_embd, n_seq_tokens, n_seqs} + cur = build_lora_mm(model.layers[il].ssm_out, y); + } + + // {n_embd, n_seq_tokens, n_seqs} => {n_embd, n_tokens} + cur = ggml_reshape_2d(ctx0, cur, cur->ne[0], n_seq_tokens * n_seqs); + //cb(cur, "mamba_out", il); + + return cur; + } +}; + +struct llm_build_command_r : public llm_graph_context { + llm_build_command_r(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + const float f_logit_scale = hparams.f_logit_scale; + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM, il); + cb(cur, "attn_norm", il); + ggml_tensor * ffn_inp = cur; + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + if (model.layers[il].attn_q_norm) { + Qcur = ggml_view_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens, + ggml_element_size(Qcur) * n_embd_head, + ggml_element_size(Qcur) * n_embd_head * n_head, + 0); + cb(Qcur, "Qcur", il); + Kcur = ggml_view_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens, + ggml_element_size(Kcur) * n_embd_head, + ggml_element_size(Kcur) * n_embd_head * n_head_kv, + 0); + cb(Kcur, "Kcur", il); + + Qcur = build_norm(Qcur, + model.layers[il].attn_q_norm, + NULL, + LLM_NORM, il); + cb(Qcur, "Qcur", il); + + Kcur = build_norm(Kcur, + model.layers[il].attn_k_norm, + NULL, + LLM_NORM, il); + cb(Kcur, "Kcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + ffn_inp = ggml_get_rows(ctx0, ffn_inp, inp_out_ids); + } + + ggml_tensor * attn_out = cur; + + // feed-forward network + { + cur = build_ffn(ffn_inp, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + // add together residual + FFN + self-attention + cur = ggml_add(ctx0, cur, inpL); + cur = ggml_add(ctx0, cur, attn_out); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + if (f_logit_scale) { + cur = ggml_scale(ctx0, cur, f_logit_scale); + } + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_cohere2 : public llm_graph_context { + llm_build_cohere2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + const float f_logit_scale = hparams.f_logit_scale; + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, true); + + // sliding window switch pattern + const int32_t sliding_window_pattern = 4; + + for (int il = 0; il < n_layer; ++il) { + // three layers sliding window attention (window size 4096) and ROPE + // fourth layer uses global attention without positional embeddings + const bool is_sliding = il % sliding_window_pattern < (sliding_window_pattern - 1); + + // norm + cur = build_norm(inpL, model.layers[il].attn_norm, NULL, LLM_NORM, il); + cb(cur, "attn_norm", il); + ggml_tensor * ffn_inp = cur; + + // self-attention + { + // rope freq factors for 128k context + ggml_tensor * rope_factors = static_cast(memory)->cbs.get_rope_factors(n_ctx_per_seq, il); + + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + if (is_sliding) { + Qcur = ggml_rope_ext(ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, ext_factor, attn_factor, + beta_fast, beta_slow); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext(ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, + rope_factors, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, ext_factor, + attn_factor, beta_fast, beta_slow); + cb(Kcur, "Kcur", il); + } else { + // For non-sliding layers, just reshape without applying RoPE + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + cb(Qcur, "Qcur", il); + + Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens); + cb(Kcur, "Kcur", il); + } + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + ffn_inp = ggml_get_rows(ctx0, ffn_inp, inp_out_ids); + } + + ggml_tensor * attn_out = cur; + + // feed-forward network + { + cur = build_ffn(ffn_inp, model.layers[il].ffn_up, NULL, NULL, model.layers[il].ffn_gate, + NULL, NULL, model.layers[il].ffn_down, NULL, NULL, NULL, LLM_FFN_SILU, LLM_FFN_PAR, + il); + cb(cur, "ffn_out", il); + } + + // add together residual + FFN + self-attention + cur = ggml_add(ctx0, cur, inpL); + cur = ggml_add(ctx0, cur, attn_out); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, model.output_norm, NULL, LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + if (f_logit_scale) { + cur = ggml_scale(ctx0, cur, f_logit_scale); + } + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +// ref: https://allenai.org/olmo +// based on the original build_llama() function, changes: +// * non-parametric layer norm +// * clamp qkv +// * removed bias +// * removed MoE +struct llm_build_olmo : public llm_graph_context { + llm_build_olmo(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + NULL, NULL, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (hparams.f_clamp_kqv > 0.0f) { + Qcur = ggml_clamp(ctx0, Qcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (hparams.f_clamp_kqv > 0.0f) { + Kcur = ggml_clamp(ctx0, Kcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (hparams.f_clamp_kqv > 0.0f) { + Vcur = ggml_clamp(ctx0, Vcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, nullptr, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + NULL, NULL, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + NULL, NULL, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_olmo2 : public llm_graph_context { + llm_build_olmo2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + cur = inpL; + + // self_attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = build_norm(Qcur, model.layers[il].attn_q_norm, NULL, + LLM_NORM_RMS, il); + cb(Qcur, "Qcur_normed", il); + + Kcur = build_norm(Kcur, model.layers[il].attn_k_norm, NULL, + LLM_NORM_RMS, il); + cb(Kcur, "Kcur_normed", 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); + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur_rope", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur_rope", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + cur = build_norm(cur, + model.layers[il].attn_post_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_post_norm", il); + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_ffn(ffn_inp, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = build_norm(cur, + model.layers[il].ffn_post_norm, NULL, + LLM_NORM_RMS, -1); + cb(cur, "ffn_post_norm", -1); + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +// based on the build_qwen2moe() function, changes: +// * removed shared experts +// * removed bias +// * added q, k norm +struct llm_build_olmoe : public llm_graph_context { + llm_build_olmoe(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self_attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = build_norm(Qcur, model.layers[il].attn_q_norm, NULL, + LLM_NORM_RMS, il); + cb(Qcur, "Qcur_normed", il); + + Kcur = build_norm(Kcur, model.layers[il].attn_k_norm, NULL, + LLM_NORM_RMS, il); + cb(Kcur, "Kcur_normed", 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); + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur_rope", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur_rope", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // MoE branch + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_SILU, false, + false, 0.0, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(cur, "ffn_moe_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_openelm : public llm_graph_context { + llm_build_openelm(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + const int64_t n_head = hparams.n_head(il); + const int64_t n_head_kv = hparams.n_head_kv(il); + const int64_t n_head_qkv = 2*n_head_kv + n_head; + + cur = inpL; + ggml_tensor * residual = cur; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_reshape_3d(ctx0, cur, n_embd_head_k, n_head_qkv, n_tokens); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_3d(ctx0, cur, n_embd_head, n_head, n_tokens, cur->nb[1], cur->nb[2], 0)); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_3d(ctx0, cur, n_embd_head, n_head_kv, n_tokens, cur->nb[1], cur->nb[2], cur->nb[1]*n_head)); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_3d(ctx0, cur, n_embd_head, n_head_kv, n_tokens, cur->nb[1], cur->nb[2], cur->nb[1]*(n_head+n_head_kv))); + cb(Vcur, "Vcur", il); + + Qcur = build_norm(Qcur, + model.layers[il].attn_q_norm, NULL, + LLM_NORM_RMS, il); + cb(Qcur, "Qcur", il); + + Kcur = build_norm(Kcur, + model.layers[il].attn_k_norm, NULL, + LLM_NORM_RMS, il); + cb(Kcur, "Kcur", il); + + Qcur = ggml_rope_ext( + ctx0, Qcur, inp_pos, NULL, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, Kcur, inp_pos, NULL, n_rot, rope_type, n_ctx_orig, + freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + Vcur = ggml_reshape_2d(ctx0, Vcur, n_embd_head * n_head_kv, n_tokens); + cb(Qcur, "Vcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + residual = ggml_get_rows(ctx0, residual, inp_out_ids); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, residual, cur); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + inpL = cur; + } + + cur = inpL; + + // norm + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_gptneox : public llm_graph_context { + llm_build_gptneox(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // ffn + if (hparams.use_par_res) { + // attention and ffn are computed in parallel + // x = x + attn(ln1(x)) + ffn(ln2(x)) + + ggml_tensor * attn_out = cur; + + cur = build_norm(inpL, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, inpL); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, attn_out); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } else { + // attention and ffn are computed sequentially + // x = x + attn(ln1(x)) + // x = x + ffn(ln2(x)) + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_arctic : public llm_graph_context { + llm_build_arctic(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + ggml_tensor * ffn_out = ggml_add(ctx0, cur, ffn_inp); + cb(ffn_out, "ffn_out", il); + + // MoE + cur = build_norm(inpSA, + model.layers[il].ffn_norm_exps, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm_exps", il); + + cur = build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_SILU, true, + false, 0.0, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(cur, "ffn_moe_out", il); + + cur = ggml_add(ctx0, cur, ffn_out); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_deepseek : public llm_graph_context { + llm_build_deepseek(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale; + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // rope freq factors for llama3; may return nullptr for llama2 and other models + ggml_tensor * rope_factors = static_cast(memory)->cbs.get_rope_factors(n_ctx_per_seq, il); + + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, kq_scale, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + if ((uint32_t) il < hparams.n_layer_dense_lead) { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } else { + // MoE branch + ggml_tensor * moe_out = + build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + nullptr, + n_expert, n_expert_used, + LLM_FFN_SILU, false, + false, hparams.expert_weights_scale, + LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, + il); + cb(moe_out, "ffn_moe_out", il); + + // FFN shared expert + { + ggml_tensor * ffn_shexp = build_ffn(cur, + model.layers[il].ffn_up_shexp, NULL, NULL, + model.layers[il].ffn_gate_shexp, NULL, NULL, + model.layers[il].ffn_down_shexp, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(ffn_shexp, "ffn_shexp", il); + + cur = ggml_add(ctx0, moe_out, ffn_shexp); + cb(cur, "ffn_out", il); + } + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_deepseek2 : public llm_graph_context { + llm_build_deepseek2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + bool is_lite = (hparams.n_layer == 27); + + // We have to pre-scale kq_scale and attn_factor to make the YaRN RoPE work correctly. + // See https://github.com/ggerganov/llama.cpp/discussions/7416 for detailed explanation. + const float mscale = attn_factor * (1.0f + hparams.rope_yarn_log_mul * logf(1.0f / freq_scale)); + const float kq_scale = 1.0f*mscale*mscale/sqrtf(float(hparams.n_embd_head_k)); + const float attn_factor_scaled = 1.0f / (1.0f + 0.1f * logf(1.0f / freq_scale)); + + const uint32_t n_embd_head_qk_rope = hparams.n_rot; + const uint32_t n_embd_head_qk_nope = hparams.n_embd_head_k - hparams.n_rot; + const uint32_t kv_lora_rank = hparams.n_lora_kv; + + ggml_tensor * cur; + ggml_tensor * inpL; + + // {n_embd, n_tokens} + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self_attention + { + ggml_tensor * q = NULL; + if (!is_lite) { + // {n_embd, q_lora_rank} * {n_embd, n_tokens} -> {q_lora_rank, n_tokens} + q = ggml_mul_mat(ctx0, model.layers[il].wq_a, cur); + cb(q, "q", il); + + q = build_norm(q, + model.layers[il].attn_q_a_norm, NULL, + LLM_NORM_RMS, il); + cb(q, "q", il); + + // {q_lora_rank, n_head * hparams.n_embd_head_k} * {q_lora_rank, n_tokens} -> {n_head * hparams.n_embd_head_k, n_tokens} + q = ggml_mul_mat(ctx0, model.layers[il].wq_b, q); + cb(q, "q", il); + } else { + q = ggml_mul_mat(ctx0, model.layers[il].wq, cur); + cb(q, "q", il); + } + + // split into {n_head * n_embd_head_qk_nope, n_tokens} + ggml_tensor * q_nope = ggml_view_3d(ctx0, q, n_embd_head_qk_nope, n_head, n_tokens, + ggml_row_size(q->type, hparams.n_embd_head_k), + ggml_row_size(q->type, hparams.n_embd_head_k * n_head), + 0); + cb(q_nope, "q_nope", il); + + // and {n_head * n_embd_head_qk_rope, n_tokens} + ggml_tensor * q_pe = ggml_view_3d(ctx0, q, n_embd_head_qk_rope, n_head, n_tokens, + ggml_row_size(q->type, hparams.n_embd_head_k), + ggml_row_size(q->type, hparams.n_embd_head_k * n_head), + ggml_row_size(q->type, n_embd_head_qk_nope)); + cb(q_pe, "q_pe", il); + + // {n_embd, kv_lora_rank + n_embd_head_qk_rope} * {n_embd, n_tokens} -> {kv_lora_rank + n_embd_head_qk_rope, n_tokens} + ggml_tensor * kv_pe_compresseed = ggml_mul_mat(ctx0, model.layers[il].wkv_a_mqa, cur); + cb(kv_pe_compresseed, "kv_pe_compresseed", il); + + // split into {kv_lora_rank, n_tokens} + ggml_tensor * kv_compressed = ggml_view_2d(ctx0, kv_pe_compresseed, kv_lora_rank, n_tokens, + kv_pe_compresseed->nb[1], + 0); + cb(kv_compressed, "kv_compressed", il); + + // and {n_embd_head_qk_rope, n_tokens} + ggml_tensor * k_pe = ggml_view_3d(ctx0, kv_pe_compresseed, n_embd_head_qk_rope, 1, n_tokens, + kv_pe_compresseed->nb[1], + kv_pe_compresseed->nb[1], + ggml_row_size(kv_pe_compresseed->type, kv_lora_rank)); + cb(k_pe, "k_pe", il); + + // TODO: the CUDA backend used to not support non-cont. (RMS) norm, investigate removing ggml_cont + kv_compressed = ggml_cont(ctx0, kv_compressed); + kv_compressed = build_norm(kv_compressed, + model.layers[il].attn_kv_a_norm, NULL, + LLM_NORM_RMS, il); + cb(kv_compressed, "kv_compressed", il); + + // {kv_lora_rank, n_head * (n_embd_head_qk_nope + n_embd_head_v)} * {kv_lora_rank, n_tokens} -> {n_head * (n_embd_head_qk_nope + n_embd_head_v), n_tokens} + ggml_tensor * kv = ggml_mul_mat(ctx0, model.layers[il].wkv_b, kv_compressed); + cb(kv, "kv", il); + + // split into {n_head * n_embd_head_qk_nope, n_tokens} + ggml_tensor * k_nope = ggml_view_3d(ctx0, kv, n_embd_head_qk_nope, n_head, n_tokens, + ggml_row_size(kv->type, n_embd_head_qk_nope + hparams.n_embd_head_v), + ggml_row_size(kv->type, n_head * (n_embd_head_qk_nope + hparams.n_embd_head_v)), + 0); + cb(k_nope, "k_nope", il); + + // and {n_head * n_embd_head_v, n_tokens} + ggml_tensor * v_states = ggml_view_3d(ctx0, kv, hparams.n_embd_head_v, n_head, n_tokens, + ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)), + ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)*n_head), + ggml_row_size(kv->type, (n_embd_head_qk_nope))); + cb(v_states, "v_states", il); + + v_states = ggml_cont(ctx0, v_states); + cb(v_states, "v_states", il); + + v_states = ggml_view_2d(ctx0, v_states, hparams.n_embd_head_v * n_head, n_tokens, + ggml_row_size(kv->type, hparams.n_embd_head_v * n_head), + 0); + cb(v_states, "v_states", il); + + q_pe = ggml_cont(ctx0, q_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this + q_pe = ggml_rope_ext( + ctx0, q_pe, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor_scaled, beta_fast, beta_slow + ); + cb(q_pe, "q_pe", il); + + // shared RoPE key + k_pe = ggml_cont(ctx0, k_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this + k_pe = ggml_rope_ext( + ctx0, k_pe, inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor_scaled, beta_fast, beta_slow + ); + cb(k_pe, "k_pe", il); + + ggml_tensor * q_states = ggml_concat(ctx0, q_nope, q_pe, 0); + cb(q_states, "q_states", il); + + ggml_tensor * k_states = ggml_concat(ctx0, k_nope, ggml_repeat(ctx0, k_pe, q_pe), 0); + cb(k_states, "k_states", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + q_states, k_states, v_states, nullptr, kq_scale, il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + if ((uint32_t) il < hparams.n_layer_dense_lead) { + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } else { + // MoE branch + ggml_tensor * moe_out = + build_moe_ffn(cur, + model.layers[il].ffn_gate_inp, + model.layers[il].ffn_up_exps, + model.layers[il].ffn_gate_exps, + model.layers[il].ffn_down_exps, + model.layers[il].ffn_exp_probs_b, + n_expert, n_expert_used, + LLM_FFN_SILU, hparams.expert_weights_norm, + true, hparams.expert_weights_scale, + (llama_expert_gating_func_type) hparams.expert_gating_func, + il); + cb(moe_out, "ffn_moe_out", il); + + // FFN shared expert + { + ggml_tensor * ffn_shexp = build_ffn(cur, + model.layers[il].ffn_up_shexp, NULL, NULL, + model.layers[il].ffn_gate_shexp, NULL, NULL, + model.layers[il].ffn_down_shexp, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(ffn_shexp, "ffn_shexp", il); + + cur = ggml_add(ctx0, moe_out, ffn_shexp); + cb(cur, "ffn_out", il); + } + } + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = ggml_mul_mat(ctx0, model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_bitnet : public llm_graph_context { + llm_build_bitnet(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + if (model.layers[il].wq_scale) { + Qcur = ggml_mul(ctx0, Qcur, model.layers[il].wq_scale); + } + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + // B1.K + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + if (model.layers[il].wk_scale) { + Kcur = ggml_mul(ctx0, Kcur, model.layers[il].wk_scale); + } + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + // B1.V + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + if (model.layers[il].wv_scale) { + Vcur = ggml_mul(ctx0, Vcur, model.layers[il].wv_scale); + } + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + NULL, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + + cur = build_norm(cur, + model.layers[il].attn_sub_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_sub_norm", il); + + cur = build_lora_mm(model.layers[il].wo, cur); + if (model.layers[il].wo_scale) { + cur = ggml_mul(ctx0, cur, model.layers[il].wo_scale); + } + if (model.layers[il].bo) { + cur = ggml_add(ctx0, cur, model.layers[il].bo); + } + cb(cur, "attn_o_out", il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward forward + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, model.layers[il].ffn_up_scale, + model.layers[il].ffn_gate, NULL, model.layers[il].ffn_gate_scale, + NULL, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_sub_out", il); + + cur = build_norm(cur, + model.layers[il].ffn_sub_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_sub_norm", il); + + cur = build_lora_mm(model.layers[il].ffn_down, cur); + if (model.layers[il].ffn_down_scale) { + cur = ggml_mul(ctx0, cur, model.layers[il].ffn_down_scale); + } + cb(cur, "ffn_down", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + // FIXME: do not use model.tok_embd directly, duplicate as model.output + cur = build_lora_mm(model.tok_embd, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_t5_enc : public llm_graph_context { + llm_build_t5_enc(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + ggml_tensor * pos_bucket_enc = build_inp_pos_bucket_enc(); + + auto * inp_attn = build_attn_inp_no_cache(); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm_enc, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq_enc, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk_enc, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv_enc, cur); + cb(Vcur, "Vcur", 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); + + ggml_tensor * attn_rel_b = model.layers[il].attn_rel_b_enc ? model.layers[il].attn_rel_b_enc : model.layers[0].attn_rel_b_enc; + ggml_tensor * kq_b = build_pos_bias(pos_bucket_enc, attn_rel_b); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo_enc, nullptr, + Qcur, Kcur, Vcur, kq_b, 1.0f, il); + cb(cur, "kqv_out", il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm_enc, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + // T5 uses relu, flan-T5 uses gelu-gated + cur = build_ffn(cur, + model.layers[il].ffn_up_enc, NULL, NULL, + model.layers[il].ffn_gate_enc, NULL, NULL, + model.layers[il].ffn_down_enc, NULL, NULL, + NULL, + model.layers[il].ffn_gate_enc ? LLM_FFN_GELU : LLM_FFN_RELU, + model.layers[il].ffn_gate_enc ? LLM_FFN_PAR : LLM_FFN_SEQ, + il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + cb(cur, "result_embd", -1); + + cur = build_norm(cur, + model.output_norm_enc, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_t5_dec : public llm_graph_context { + llm_build_t5_dec(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + //const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + ggml_tensor * embd_enc = build_inp_cross_embd(); + ggml_tensor * pos_bucket_dec = build_inp_pos_bucket_dec(); + + const int64_t n_outputs_enc = embd_enc->ne[1]; + + auto * inp_attn_self = build_attn_inp_kv_unified(true, false); + auto * inp_attn_cross = build_attn_inp_cross(); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", 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); + + ggml_tensor * attn_rel_b = model.layers[il].attn_rel_b ? model.layers[il].attn_rel_b : model.layers[0].attn_rel_b; + ggml_tensor * kq_b = build_pos_bias(pos_bucket_dec, attn_rel_b); + + cur = build_attn(inp_attn_self, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, kq_b, 1.0f, il); + cb(cur, "kqv_out", il); + } + + cur = ggml_add(ctx0, cur, inpSA); + cb(cur, "cross_inp", il); + + ggml_tensor * inpCA = cur; + + // norm + cur = build_norm(cur, + model.layers[il].attn_norm_cross, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm_cross", il); + + // cross-attention + { + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq_cross, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk_cross, embd_enc); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv_cross, embd_enc); + cb(Vcur, "Vcur", 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_outputs_enc); + Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head, n_head_kv, n_outputs_enc); + + cur = build_attn(inp_attn_cross, gf, + model.layers[il].wo_cross, nullptr, + Qcur, Kcur, Vcur, nullptr, 1.0f, il); + cb(cur, "kqv_out", il); + + //ggml_tensor * q = ggml_permute(ctx0, Qcur, 0, 2, 1, 3); + //ggml_tensor * k = ggml_cont(ctx0, ggml_permute(ctx0, Kcur, 0, 2, 1, 3)); + + //ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); + //cb(kq, "kq", il); + + //kq = ggml_soft_max_ext(ctx0, kq, KQ_mask_cross, 1.0f, hparams.f_max_alibi_bias); + //cb(kq, "kq_soft_max_ext", il); + + //ggml_tensor * v = ggml_cont(ctx0, ggml_transpose(ctx0, ggml_reshape_2d(ctx0, Vcur, n_embd_gqa, n_outputs_enc))); + //cb(v, "v", il); + + //ggml_tensor * kqv = ggml_mul_mat(ctx0, ggml_reshape_3d(ctx0, v, n_outputs_enc, n_embd_head, n_head_kv), kq); + //cb(kqv, "kqv", il); + + //ggml_tensor * kqv_merged = ggml_permute(ctx0, kqv, 0, 2, 1, 3); + //cb(kqv_merged, "kqv_merged", il); + + //cur = ggml_cont_2d(ctx0, kqv_merged, n_embd_gqa, n_tokens); + //cb(cur, "kqv_merged_cont", il); + + //ggml_build_forward_expand(gf, cur); + + //cur = build_lora_mm(model.layers[il].wo_cross, cur); + //cb(cur, "kqv_out", il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + inpCA = ggml_get_rows(ctx0, inpCA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpCA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + // T5 uses relu, flan-T5 uses gelu-gated + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + model.layers[il].ffn_gate_enc ? LLM_FFN_GELU : LLM_FFN_RELU, + model.layers[il].ffn_gate_enc ? LLM_FFN_PAR : LLM_FFN_SEQ, + il); + cb(cur, "ffn_out", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + cb(cur, "result_embd", -1); + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_jais : public llm_graph_context { + llm_build_jais(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + + ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*cur->nb[0]*(n_embd))); + ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*cur->nb[0]*(n_embd))); + ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*cur->nb[0]*(n_embd + n_embd_gqa))); + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/float(n_embd_head), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); + } + + // add the input + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // FF + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + model.layers[il].ffn_gate, model.layers[il].ffn_gate_b, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + } + + inpL = ggml_add(ctx0, cur, ffn_inp); + cb(inpL, "l_out", il); + } + + cur = build_norm(inpL, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_chatglm : public llm_graph_context { + llm_build_chatglm(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + cur = build_norm(inpL, + model.layers[il].attn_norm, + NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + ggml_tensor * Qcur = nullptr; + ggml_tensor * Kcur = nullptr; + ggml_tensor * Vcur = nullptr; + + if (model.layers[il].wqkv == nullptr) { + Qcur = build_lora_mm(model.layers[il].wq, cur); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + } + Kcur = build_lora_mm(model.layers[il].wk, cur); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + } + Vcur = build_lora_mm(model.layers[il].wv, cur); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + } + } else { + cur = build_lora_mm(model.layers[il].wqkv, cur); + cb(cur, "wqkv", il); + if (model.layers[il].bqkv) { + cur = ggml_add(ctx0, cur, model.layers[il].bqkv); + cb(cur, "bqkv", il); + } + Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); + Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); + Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); + } + + cb(Qcur, "Qcur", il); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", il); + + //printf("freq_base: %f freq_scale: %f ext_factor: %f attn_factor: %f\n", freq_base, freq_scale, ext_factor, attn_factor); + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur_rope", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur_rope", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, NULL, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + // Add the input + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // FF + { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SWIGLU, LLM_FFN_SEQ, il); + cb(cur, "ffn_out", il); + + } + + inpL = ggml_add(ctx0, cur, ffn_inp); + cb(inpL, "l_out", il); + } + + cur = build_norm(inpL, + model.output_norm, + NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_nemotron : public llm_graph_context { + llm_build_nemotron(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + //GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, + model.layers[il].attn_norm_b, + LLM_NORM, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, + model.layers[il].ffn_norm_b, + LLM_NORM, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, + NULL, NULL, NULL, + model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, + NULL, + LLM_FFN_RELU_SQR, LLM_FFN_SEQ, il); + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, model.output_norm_b, + LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_exaone : public llm_graph_context { + llm_build_exaone(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + + // self-attention + { + // rope freq factors for llama3; may return nullptr for llama2 and other models + ggml_tensor * rope_factors = static_cast(memory)->cbs.get_rope_factors(n_ctx_per_seq, il); + + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + if (model.layers[il].bq) { + Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); + cb(Qcur, "Qcur", il); + } + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + if (model.layers[il].bk) { + Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); + cb(Kcur, "Kcur", il); + } + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + if (model.layers[il].bv) { + Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); + cb(Vcur, "Vcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, model.layers[il].bo, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_rwkv6_base : public llm_graph_context { + const llama_model & model; + + llm_build_rwkv6_base(const llama_model & model, const llm_graph_params & params) : llm_graph_context(params), model(model) { + } + + ggml_tensor * build_rwkv6_channel_mix( + const llama_layer * layer, + ggml_tensor * cur, + ggml_tensor * x_prev, + llm_arch arch) const { + ggml_tensor * sx = ggml_sub(ctx0, x_prev, cur); + switch (arch) { + case LLM_ARCH_RWKV6: + { + ggml_tensor * xk = ggml_add(ctx0, ggml_mul(ctx0, sx, layer->channel_mix_lerp_k), cur); + ggml_tensor * xr = ggml_add(ctx0, ggml_mul(ctx0, sx, layer->channel_mix_lerp_r), cur); + + ggml_tensor * r = ggml_sigmoid(ctx0, build_lora_mm(layer->channel_mix_receptance, xr)); + ggml_tensor * k = ggml_sqr( + ctx0, + ggml_relu( + ctx0, + build_lora_mm(layer->channel_mix_key, xk) + ) + ); + cur = ggml_mul(ctx0, r, build_lora_mm(layer->channel_mix_value, k)); + } break; + default: + GGML_ABORT("fatal error"); + } + + return cur; + } + + ggml_tensor * build_rwkv6_time_mix( + ggml_cgraph * gf, + ggml_tensor * cur, + ggml_tensor * x_prev, + ggml_tensor * state_copy, + ggml_tensor * state_mask, + const llama_ubatch & ubatch, + int il) const { + const llama_kv_cache_unified * kv_self = static_cast(memory); + + const auto n_tokens = ubatch.n_tokens; + const auto n_seqs = ubatch.n_seqs; + const auto n_embd = hparams.n_embd; + const auto head_size = hparams.wkv_head_size; + const auto n_head = n_embd / head_size; + const auto n_head_kv = hparams.n_head_kv(il); + + const auto kv_head = kv_self->head; + + const auto & layer = model.layers[il]; + + bool is_qrwkv = layer.time_mix_first == nullptr; + + ggml_tensor * sx = ggml_sub(ctx0, x_prev, cur); + ggml_tensor * xxx = ggml_add(ctx0, ggml_mul(ctx0, sx, layer.time_mix_lerp_x), cur); + + xxx = ggml_reshape_4d( + ctx0, + ggml_tanh( + ctx0, + ggml_mul_mat(ctx0, layer.time_mix_w1, xxx) + ), + layer.time_mix_w1->ne[1] / 5, 1, 5, n_tokens + ); + + xxx = ggml_cont(ctx0, ggml_permute(ctx0, xxx, 0, 1, 3, 2)); + + xxx = ggml_mul_mat( + ctx0, + ggml_reshape_4d( + ctx0, + layer.time_mix_w2, + layer.time_mix_w2->ne[0], layer.time_mix_w2->ne[1], 1, 5 + ), + xxx + ); + + ggml_tensor *xw, *xk, *xv, *xr, *xg; + if (layer.time_mix_lerp_fused) { + // fusing these weights makes some performance improvement + sx = ggml_reshape_3d(ctx0, sx, n_embd, 1, n_tokens); + cur = ggml_reshape_3d(ctx0, cur, n_embd, 1, n_tokens); + xxx = ggml_add(ctx0, ggml_mul(ctx0, ggml_add(ctx0, xxx, layer.time_mix_lerp_fused), sx), cur); + xw = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], 0); + xk = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * sizeof(float)); + xv = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 2 * sizeof(float)); + xr = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 3 * sizeof(float)); + xg = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 4 * sizeof(float)); + } else { + // for backward compatibility + xw = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], 0); + xk = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * sizeof(float)); + xv = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 2 * sizeof(float)); + xr = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 3 * sizeof(float)); + xg = ggml_view_2d(ctx0, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 4 * sizeof(float)); + + xw = ggml_add(ctx0, ggml_mul(ctx0, ggml_add(ctx0, xw, layer.time_mix_lerp_w), sx), cur); + xk = ggml_add(ctx0, ggml_mul(ctx0, ggml_add(ctx0, xk, layer.time_mix_lerp_k), sx), cur); + xv = ggml_add(ctx0, ggml_mul(ctx0, ggml_add(ctx0, xv, layer.time_mix_lerp_v), sx), cur); + xr = ggml_add(ctx0, ggml_mul(ctx0, ggml_add(ctx0, xr, layer.time_mix_lerp_r), sx), cur); + xg = ggml_add(ctx0, ggml_mul(ctx0, ggml_add(ctx0, xg, layer.time_mix_lerp_g), sx), cur); + } + + ggml_tensor * r = build_lora_mm(layer.time_mix_receptance, xr); + ggml_tensor * k = build_lora_mm(layer.time_mix_key, xk); + ggml_tensor * v = build_lora_mm(layer.time_mix_value, xv); + if (layer.time_mix_receptance_b) { + r = ggml_add(ctx0, r, layer.time_mix_receptance_b); + } + if (layer.time_mix_key_b) { + k = ggml_add(ctx0, k, layer.time_mix_key_b); + } + if (layer.time_mix_value_b) { + v = ggml_add(ctx0, v, layer.time_mix_value_b); + } + + ggml_tensor * g = build_lora_mm(layer.time_mix_gate, xg); + if (is_qrwkv) { + g = ggml_sigmoid(ctx0, g); + } else { + g = ggml_silu(ctx0, g); + } + + if (n_head_kv != 0 && n_head_kv != n_head) { + GGML_ASSERT(n_head % n_head_kv == 0); + k = ggml_reshape_4d(ctx0, k, head_size, 1, n_head_kv, n_tokens); + v = ggml_reshape_4d(ctx0, v, head_size, 1, n_head_kv, n_tokens); + ggml_tensor * tmp = ggml_new_tensor_4d(ctx0, GGML_TYPE_F32, head_size, n_head / n_head_kv, n_head_kv, n_tokens); + k = ggml_repeat(ctx0, k, tmp); + v = ggml_repeat(ctx0, v, tmp); + } + + k = ggml_reshape_3d(ctx0, k, head_size, n_head, n_tokens); + v = ggml_reshape_3d(ctx0, v, head_size, n_head, n_tokens); + r = ggml_reshape_3d(ctx0, r, head_size, n_head, n_tokens); + + ggml_tensor * w = ggml_mul_mat( + ctx0, + layer.time_mix_decay_w2, + ggml_tanh( + ctx0, + ggml_mul_mat(ctx0, layer.time_mix_decay_w1, xw) + ) + ); + + w = ggml_add(ctx0, w, layer.time_mix_decay); + w = ggml_exp(ctx0, ggml_neg(ctx0, ggml_exp(ctx0, w))); + w = ggml_reshape_3d(ctx0, w, head_size, n_head, n_tokens); + + if (is_qrwkv) { + // k = k * (1 - w) + k = ggml_sub(ctx0, k, ggml_mul(ctx0, k, w)); + } + + ggml_tensor * wkv_state = build_copy_mask_state( + gf, kv_self->v_l[il], state_copy, state_mask, + hparams.n_embd_v_s(), n_seqs); + + ggml_tensor * wkv_output; + if (is_qrwkv) { + wkv_output = ggml_gated_linear_attn(ctx0, k, v, r, w, wkv_state, pow(head_size, -0.5f)); + } else { + wkv_output = ggml_rwkv_wkv6(ctx0, k, v, r, layer.time_mix_first, w, wkv_state); + } + cur = ggml_view_1d(ctx0, wkv_output, n_embd * n_tokens, 0); + wkv_state = ggml_view_1d(ctx0, wkv_output, n_embd * head_size * n_seqs, n_embd * n_tokens * sizeof(float)); + + ggml_build_forward_expand( + gf, + ggml_cpy( + ctx0, + wkv_state, + ggml_view_1d( + ctx0, + kv_self->v_l[il], + hparams.n_embd_v_s() * n_seqs, + hparams.n_embd_v_s() * kv_head * ggml_element_size(kv_self->v_l[il]) + ) + ) + ); + + if (!is_qrwkv) { + // group norm with head_count groups + cur = ggml_reshape_3d(ctx0, cur, n_embd / n_head, n_head, n_tokens); + cur = ggml_norm(ctx0, cur, 64e-5f); + + // Convert back to regular vectors. + cur = ggml_reshape_2d(ctx0, cur, n_embd, n_tokens); + cur = ggml_add(ctx0, ggml_mul(ctx0, cur, layer.time_mix_ln), layer.time_mix_ln_b); + } else { + cur = ggml_reshape_2d(ctx0, cur, n_embd, n_tokens); + } + + cur = ggml_mul(ctx0, cur, g); + cur = build_lora_mm(layer.time_mix_output, cur); + + return cur; + } +}; + +struct llm_build_rwkv6 : public llm_build_rwkv6_base { + llm_build_rwkv6(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_build_rwkv6_base(model, params) { + GGML_ASSERT(hparams.token_shift_count == 2); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + inpL = build_norm(inpL, model.tok_norm, model.tok_norm_b, LLM_NORM, -1); + + ggml_tensor * state_copy = build_inp_s_copy(); + ggml_tensor * state_mask = build_inp_s_mask(); + + const auto n_embd = hparams.n_embd; + const auto n_seq_tokens = ubatch.n_seq_tokens; + const auto n_seqs = ubatch.n_seqs; + + for (int il = 0; il < n_layer; ++il) { + const llama_layer * layer = &model.layers[il]; + + ggml_tensor * token_shift = build_rwkv_token_shift_load( + gf, state_copy, state_mask, ubatch, il + ); + + ggml_tensor * att_shift = ggml_view_3d(ctx0, token_shift, n_embd, 1, n_seqs, token_shift->nb[1], token_shift->nb[2], 0); + ggml_tensor * ffn_shift = ggml_view_3d(ctx0, token_shift, n_embd, 1, n_seqs, token_shift->nb[1], token_shift->nb[2], n_embd * ggml_element_size(token_shift)); + + ggml_tensor * att_norm = build_norm(inpL, layer->attn_norm, layer->attn_norm_b, LLM_NORM, il); + cb(att_norm, "attn_norm", il); + + ggml_tensor * x_prev = ggml_concat( + ctx0, + att_shift, + ggml_view_3d(ctx0, att_norm, n_embd, n_seq_tokens - 1, n_seqs, att_norm->nb[1], att_norm->nb[2], 0), + 1 + ); + + cur = build_rwkv6_time_mix(gf, att_norm, x_prev, state_copy, state_mask, ubatch, il); + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + ggml_tensor * ffn_norm = build_norm(ffn_inp, layer->attn_norm_2, layer->attn_norm_2_b, LLM_NORM, il); + cb(ffn_norm, "ffn_norm", il); + + x_prev = ggml_concat( + ctx0, + ffn_shift, + ggml_view_3d(ctx0, ffn_norm, n_embd, n_seq_tokens - 1, n_seqs, ffn_norm->nb[1], ffn_norm->nb[2], 0), + 1 + ); + + cur = build_rwkv6_channel_mix(layer, ffn_norm, x_prev, LLM_ARCH_RWKV6); + cur = ggml_add(ctx0, cur, ffn_inp); + + token_shift = ggml_concat(ctx0, + ggml_view_3d(ctx0, att_norm, n_embd, 1, n_seqs, att_norm->nb[1], att_norm->nb[2], (n_seq_tokens-1)*n_embd*ggml_element_size(att_norm)), + ggml_view_3d(ctx0, ffn_norm, n_embd, 1, n_seqs, ffn_norm->nb[1], ffn_norm->nb[2], (n_seq_tokens-1)*n_embd*ggml_element_size(ffn_norm)), + 1 + ); + ggml_build_forward_expand(gf, build_rwkv_token_shift_store(token_shift, ubatch, il)); + + if (hparams.rescale_every_n_layers != 0 && (il + 1) % hparams.rescale_every_n_layers == 0) { + cur = ggml_scale(ctx0, cur, 0.5F); + } + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + ggml_tensor * inp_out_ids = build_inp_out_ids(); + + cur = ggml_reshape_2d(ctx0, cur, n_embd, n_tokens); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + + cur = build_norm(cur, model.output_norm, model.output_norm_b, LLM_NORM, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +// ref: https://huggingface.co/recursal/QRWKV6-32B-Instruct-Preview-v0.1/blob/main/modeling_rwkv6qwen2.py +struct llm_build_rwkv6qwen2 : public llm_build_rwkv6_base { + llm_build_rwkv6qwen2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_build_rwkv6_base(model, params) { + GGML_ASSERT(n_embd == hparams.n_embd_k_s()); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + ggml_tensor * state_copy = build_inp_s_copy(); + ggml_tensor * state_mask = build_inp_s_mask(); + + const auto n_embd = hparams.n_embd; + const auto n_seq_tokens = ubatch.n_seq_tokens; + const auto n_seqs = ubatch.n_seqs; + + inpL = build_inp_embd(model.tok_embd); + + for (int il = 0; il < n_layer; ++il) { + const llama_layer * layer = &model.layers[il]; + + ggml_tensor * token_shift = build_rwkv_token_shift_load( + gf, state_copy, state_mask, ubatch, il + ); + + ggml_tensor * att_norm = build_norm(inpL, layer->attn_norm, layer->attn_norm_b, LLM_NORM_RMS, il); + cb(att_norm, "attn_norm", il); + + ggml_tensor * x_prev = ggml_concat( + ctx0, + token_shift, + ggml_view_3d(ctx0, att_norm, n_embd, n_seq_tokens - 1, n_seqs, att_norm->nb[1], att_norm->nb[2], 0), + 1 + ); + + cur = build_rwkv6_time_mix(gf, att_norm, x_prev, state_copy, state_mask, ubatch, il); + + token_shift = ggml_view_3d(ctx0, att_norm, n_embd, 1, n_seqs, att_norm->nb[1], att_norm->nb[2], (n_seq_tokens-1)*n_embd*ggml_element_size(att_norm)); + ggml_build_forward_expand(gf, build_rwkv_token_shift_store(token_shift, ubatch, il)); + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + cur = ggml_add(ctx0, cur, ffn_inp); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_reshape_2d(ctx0, cur, n_embd, n_tokens); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + + cur = build_norm(cur, model.output_norm, model.output_norm_b, LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + cur = build_lora_mm(model.output, cur); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +// ref: https://github.com/facebookresearch/chameleon +// based on the original build_llama() function, changes: +// * qk-norm +// * swin-norm +// * removed bias +// * removed MoE +struct llm_build_chameleon : public llm_graph_context { + llm_build_chameleon(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + const int64_t n_embd_head = hparams.n_embd_head_v; + + GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); + GGML_ASSERT(n_embd_head == hparams.n_rot); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + auto * inp_attn = build_attn_inp_kv_unified(true, false); + + for (int il = 0; il < n_layer; ++il) { + ggml_tensor * inpSA = inpL; + + // norm + if (hparams.swin_norm) { + cur = inpL; + } else { + cur = build_norm(inpL, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "attn_norm", il); + } + + // self-attention + { + // compute Q and K and RoPE them + ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur); + cb(Vcur, "Vcur", il); + + if (model.layers[il].attn_q_norm) { + Qcur = ggml_view_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens, + ggml_element_size(Qcur) * n_embd_head, + ggml_element_size(Qcur) * n_embd_head * n_head, + 0); + cb(Qcur, "Qcur", il); + + Qcur = build_norm(Qcur, + model.layers[il].attn_q_norm, + model.layers[il].attn_q_norm_b, + LLM_NORM, il); + cb(Qcur, "Qcur", il); + } + + if (model.layers[il].attn_k_norm) { + Kcur = ggml_view_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens, + ggml_element_size(Kcur) * n_embd_head, + ggml_element_size(Kcur) * n_embd_head * n_head_kv, + 0); + cb(Kcur, "Kcur", il); + + Kcur = build_norm(Kcur, + model.layers[il].attn_k_norm, + model.layers[il].attn_k_norm_b, + LLM_NORM, il); + cb(Kcur, "Kcur", il); + } + + Qcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Qcur, "Qcur", il); + + Kcur = ggml_rope_ext( + ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, + n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + cb(Kcur, "Kcur", il); + + cur = build_attn(inp_attn, gf, + model.layers[il].wo, nullptr, + Qcur, Kcur, Vcur, nullptr, 1.0f/sqrtf(float(n_embd_head)), il); + + if (hparams.swin_norm) { + cur = build_norm(cur, + model.layers[il].attn_norm, NULL, + LLM_NORM_RMS, il); + } + } + + if (il == n_layer - 1) { + // skip computing output for unused tokens + ggml_tensor * inp_out_ids = build_inp_out_ids(); + cur = ggml_get_rows(ctx0, cur, inp_out_ids); + inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); + } + + ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); + cb(ffn_inp, "ffn_inp", il); + + // feed-forward network + if (!hparams.swin_norm) { + cur = build_norm(ffn_inp, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + } + + cur = build_ffn(cur, + model.layers[il].ffn_up, NULL, NULL, + model.layers[il].ffn_gate, NULL, NULL, + model.layers[il].ffn_down, NULL, NULL, + NULL, + LLM_FFN_SILU, LLM_FFN_PAR, il); + cb(cur, "ffn_out", il); + + if (hparams.swin_norm) { + cur = build_norm(cur, + model.layers[il].ffn_norm, NULL, + LLM_NORM_RMS, il); + cb(cur, "ffn_norm", il); + } + + cur = ggml_add(ctx0, cur, ffn_inp); + cb(cur, "ffn_out", il); + + cur = build_cvec(cur, il); + cb(cur, "l_out", il); + + // input for next layer + inpL = cur; + } + + cur = inpL; + + cur = build_norm(cur, + model.output_norm, NULL, + LLM_NORM_RMS, -1); + + cb(cur, "result_norm", -1); + res->t_embd = cur; + + // lm_head + cur = build_lora_mm(model.output, cur); + cb(cur, "result_output_with_img_logits", -1); + + // TODO: this suppresses the output of image tokens, which is required to enable text-only outputs. + // Needs to be removed once image outputs are supported. + int img_token_end_idx = 8196; + int img_token_start_idx = 4; + int num_img_tokens = img_token_end_idx - img_token_start_idx; + // creates 1d tensor of size num_img_tokens and values -FLT_MAX, + // which ensures that text token values are always at least larger than image token values + ggml_tensor * img_logits = ggml_new_tensor_1d(ctx0, GGML_TYPE_F32, num_img_tokens); + img_logits = ggml_clamp(ctx0, img_logits, -FLT_MAX, -FLT_MAX); + cb(img_logits, "img_logits", -1); + + cur = ggml_set_1d(ctx0, cur, img_logits, ggml_element_size(cur) * img_token_start_idx); + + cb(cur, "result_output", -1); + res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +struct llm_build_wavtokenizer_dec : public llm_graph_context { + llm_build_wavtokenizer_dec(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) { + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = build_inp_embd(model.tok_embd); + + cur = ggml_cont(ctx0, ggml_transpose(ctx0, inpL)); + + cur = ggml_conv_1d_ph(ctx0, model.conv1d, cur, 1, 1); + cur = ggml_add(ctx0, cur, model.conv1d_b); + + // posnet + for (uint32_t il = 0; il < hparams.posnet.n_layer; ++il) { + const auto & layer = model.layers[il].posnet; + + inpL = cur; + + switch (il) { + case 0: + case 1: + case 3: + case 4: + { + cur = build_norm(cur, + layer.norm1, + layer.norm1_b, + LLM_NORM_GROUP, 0); + + cur = ggml_mul(ctx0, ggml_sigmoid(ctx0, cur), cur); + + cur = ggml_conv_1d_ph(ctx0, layer.conv1, cur, 1, 1); + cur = ggml_add(ctx0, cur, layer.conv1_b); + + cur = build_norm(cur, + layer.norm2, + layer.norm2_b, + LLM_NORM_GROUP, 0); + + cur = ggml_mul(ctx0, ggml_sigmoid(ctx0, cur), cur); + + cur = ggml_conv_1d_ph(ctx0, layer.conv2, cur, 1, 1); + cur = ggml_add(ctx0, cur, layer.conv2_b); + + cur = ggml_add(ctx0, cur, inpL); + } break; + case 2: + { + cur = build_norm(cur, + layer.attn_norm, + layer.attn_norm_b, + LLM_NORM_GROUP, 0); + + ggml_tensor * q; + ggml_tensor * k; + ggml_tensor * v; + + q = ggml_conv_1d_ph(ctx0, layer.attn_q, cur, 1, 1); + k = ggml_conv_1d_ph(ctx0, layer.attn_k, cur, 1, 1); + v = ggml_conv_1d_ph(ctx0, layer.attn_v, cur, 1, 1); + + q = ggml_add(ctx0, q, layer.attn_q_b); + k = ggml_add(ctx0, k, layer.attn_k_b); + v = ggml_add(ctx0, v, layer.attn_v_b); + + q = ggml_cont(ctx0, ggml_transpose(ctx0, q)); + k = ggml_cont(ctx0, ggml_transpose(ctx0, k)); + + ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); + + kq = ggml_soft_max_ext(ctx0, kq, nullptr, 1.0f/sqrtf(float(hparams.posnet.n_embd)), 0.0f); + + cur = ggml_mul_mat(ctx0, kq, v); + + cur = ggml_conv_1d_ph(ctx0, layer.attn_o, cur, 1, 1); + cur = ggml_add(ctx0, cur, layer.attn_o_b); + + cur = ggml_add(ctx0, cur, inpL); + } break; + case 5: + { + cur = build_norm(cur, + layer.norm, + layer.norm_b, + LLM_NORM_GROUP, 0); + } break; + default: GGML_ABORT("unknown posnet layer"); + }; + } + + cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); + + cur = build_norm(cur, + model.tok_norm, + model.tok_norm_b, + LLM_NORM, -1); + + cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); + + inpL = cur; + + // convnext + for (uint32_t il = 0; il < hparams.convnext.n_layer; ++il) { + const auto & layer = model.layers[il].convnext; + + cur = inpL; + + cur = ggml_conv_1d_dw_ph(ctx0, layer.dw, cur, 1, 1); + cur = ggml_add(ctx0, cur, layer.dw_b); + + cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); + + cur = build_norm(cur, + layer.norm, + layer.norm_b, + LLM_NORM, -1); + + cur = build_ffn(cur, + layer.pw1, layer.pw1_b, NULL, + NULL, NULL, NULL, + layer.pw2, layer.pw2_b, NULL, + NULL, + LLM_FFN_GELU, LLM_FFN_SEQ, il); + + cur = ggml_mul(ctx0, cur, layer.gamma); + + cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); + + inpL = ggml_add(ctx0, cur, inpL); + } + + cur = inpL; + + cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); + + cur = build_norm(cur, + model.output_norm, + model.output_norm_b, + LLM_NORM, -1); + + // lm_head + cur = build_lora_mm(model.output, cur); + + cur = ggml_add(ctx0, cur, model.output_b); + + cb(cur, "result_embd", -1); + res->t_embd = cur; + + ggml_build_forward_expand(gf, cur); + } +}; + +llama_memory_i * llama_model::create_memory() const { + llama_memory_i * res; + + switch (arch) { + case LLM_ARCH_RWKV6: + case LLM_ARCH_RWKV6QWEN2: + case LLM_ARCH_MAMBA: + { + res = new llama_kv_cache_unified(hparams, { + /*.get_rope_factors =*/ nullptr + }); + } break; + default: + { + res = new llama_kv_cache_unified(hparams, { + /*.get_rope_factors =*/ [this](uint32_t n_ctx_per_seq, int il) { + // choose long/short freq factors based on the context size + if (layers[il].rope_freqs != nullptr) { + return layers[il].rope_freqs; + } + + if (n_ctx_per_seq > hparams.n_ctx_orig_yarn) { + return layers[il].rope_long; + } + + return layers[il].rope_short; + } + }); + } + } + + return res; +} + +llm_graph_result_ptr llama_model::build_graph( + const llm_graph_params & params, + ggml_cgraph * gf, + llm_graph_type type) const { + std::unique_ptr llm; + + switch (arch) { + case LLM_ARCH_LLAMA: + case LLM_ARCH_MINICPM: + case LLM_ARCH_GRANITE: + case LLM_ARCH_GRANITE_MOE: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_DECI: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_BAICHUAN: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_FALCON: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_GROK: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_STARCODER: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_REFACT: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_BERT: + case LLM_ARCH_JINA_BERT_V2: + case LLM_ARCH_NOMIC_BERT: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_BLOOM: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_MPT: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_STABLELM: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_QWEN: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_QWEN2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_QWEN2VL: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_QWEN2MOE: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_PHI2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_PHI3: + case LLM_ARCH_PHIMOE: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_PLAMO: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_GPT2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_CODESHELL: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_ORION: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_INTERNLM2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_MINICPM3: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_GEMMA: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_GEMMA2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_GEMMA3: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_STARCODER2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_MAMBA: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_XVERSE: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_COMMAND_R: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_COHERE2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_DBRX: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_OLMO: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_OLMO2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_OLMOE: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_OPENELM: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_GPTNEOX: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_ARCTIC: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_DEEPSEEK: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_DEEPSEEK2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_CHATGLM: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_BITNET: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_T5: + { + switch (type) { + case LLM_GRAPH_TYPE_ENCODER: + llm = std::make_unique(*this, params, gf); + break; + case LLM_GRAPH_TYPE_DEFAULT: + case LLM_GRAPH_TYPE_DECODER: + llm = std::make_unique(*this, params, gf); + break; + default: + GGML_ABORT("invalid graph type"); + }; + } break; + //case LLM_ARCH_T5ENCODER: + // { + // llm.build_t5_enc(gf); + // } break; + case LLM_ARCH_JAIS: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_NEMOTRON: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_EXAONE: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_RWKV6: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_RWKV6QWEN2: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_CHAMELEON: + { + llm = std::make_unique(*this, params, gf); + } break; + case LLM_ARCH_WAVTOKENIZER_DEC: + { + llm = std::make_unique(*this, params, gf); + } break; + default: + GGML_ABORT("fatal error"); + } + + // add on pooling layer + llm->build_pooling(gf, cls, cls_b, cls_out, cls_out_b); + + return std::move(llm->res); +} + // // interface implementation // -struct llama_model_params llama_model_default_params() { - struct llama_model_params result = { +llama_model_params llama_model_default_params() { + llama_model_params result = { /*.devices =*/ nullptr, /*.n_gpu_layers =*/ 0, /*.split_mode =*/ LLAMA_SPLIT_MODE_LAYER, @@ -3861,59 +11167,59 @@ struct llama_model_params llama_model_default_params() { return result; } -const struct llama_vocab * llama_model_get_vocab(const struct llama_model * model) { +const llama_vocab * llama_model_get_vocab(const llama_model * model) { return &model->vocab; } -void llama_free_model(struct llama_model * model) { +void llama_free_model(llama_model * model) { llama_model_free(model); } -void llama_model_free(struct llama_model * model) { +void llama_model_free(llama_model * model) { delete model; } -int32_t llama_model_n_ctx_train(const struct llama_model * model) { +int32_t llama_model_n_ctx_train(const llama_model * model) { return model->hparams.n_ctx_train; } -int32_t llama_model_n_embd(const struct llama_model * model) { +int32_t llama_model_n_embd(const llama_model * model) { return model->hparams.n_embd; } -int32_t llama_model_n_layer(const struct llama_model * model) { +int32_t llama_model_n_layer(const llama_model * model) { return model->hparams.n_layer; } -int32_t llama_model_n_head(const struct llama_model * model) { +int32_t llama_model_n_head(const llama_model * model) { return model->hparams.n_head(); } -int32_t llama_model_n_head_kv(const struct llama_model * model) { +int32_t llama_model_n_head_kv(const llama_model * model) { return model->hparams.n_head_kv(); } // deprecated -int32_t llama_n_ctx_train(const struct llama_model * model) { +int32_t llama_n_ctx_train(const llama_model * model) { return llama_model_n_ctx_train(model); } // deprecated -int32_t llama_n_embd(const struct llama_model * model) { +int32_t llama_n_embd(const llama_model * model) { return llama_model_n_embd(model); } // deprecated -int32_t llama_n_layer(const struct llama_model * model) { +int32_t llama_n_layer(const llama_model * model) { return llama_model_n_layer(model); } // deprecated -int32_t llama_n_head(const struct llama_model * model) { +int32_t llama_n_head(const llama_model * model) { return llama_model_n_head(model); } -enum llama_rope_type llama_model_rope_type(const struct llama_model * model) { +llama_rope_type llama_model_rope_type(const llama_model * model) { switch (model->arch) { // these models do not use RoPE case LLM_ARCH_GPT2: @@ -3992,11 +11298,11 @@ enum llama_rope_type llama_model_rope_type(const struct llama_model * model) { return LLAMA_ROPE_TYPE_NONE; } -float llama_model_rope_freq_scale_train(const struct llama_model * model) { +float llama_model_rope_freq_scale_train(const llama_model * model) { return model->hparams.rope_freq_scale_train; } -int32_t llama_model_meta_val_str(const struct llama_model * model, const char * key, char * buf, size_t buf_size) { +int32_t llama_model_meta_val_str(const llama_model * model, const char * key, char * buf, size_t buf_size) { const auto & it = model->gguf_kv.find(key); if (it == model->gguf_kv.end()) { if (buf_size > 0) { @@ -4007,11 +11313,11 @@ int32_t llama_model_meta_val_str(const struct llama_model * model, const char * return snprintf(buf, buf_size, "%s", it->second.c_str()); } -int32_t llama_model_meta_count(const struct llama_model * model) { +int32_t llama_model_meta_count(const llama_model * model) { return (int)model->gguf_kv.size(); } -int32_t llama_model_meta_key_by_index(const struct llama_model * model, int i, char * buf, size_t buf_size) { +int32_t llama_model_meta_key_by_index(const llama_model * model, int i, char * buf, size_t buf_size) { if (i < 0 || i >= (int)model->gguf_kv.size()) { if (buf_size > 0) { buf[0] = '\0'; @@ -4023,7 +11329,7 @@ int32_t llama_model_meta_key_by_index(const struct llama_model * model, int i, c return snprintf(buf, buf_size, "%s", it->first.c_str()); } -int32_t llama_model_meta_val_str_by_index(const struct llama_model * model, int32_t i, char * buf, size_t buf_size) { +int32_t llama_model_meta_val_str_by_index(const llama_model * model, int32_t i, char * buf, size_t buf_size) { if (i < 0 || i >= (int)model->gguf_kv.size()) { if (buf_size > 0) { buf[0] = '\0'; @@ -4035,15 +11341,15 @@ int32_t llama_model_meta_val_str_by_index(const struct llama_model * model, int3 return snprintf(buf, buf_size, "%s", it->second.c_str()); } -int32_t llama_model_desc(const struct llama_model * model, char * buf, size_t buf_size) { +int32_t llama_model_desc(const llama_model * model, char * buf, size_t buf_size) { return snprintf(buf, buf_size, "%s", model->desc().c_str()); } -uint64_t llama_model_size(const struct llama_model * model) { +uint64_t llama_model_size(const llama_model * model) { return model->size(); } -const char * llama_model_chat_template(const struct llama_model * model, const char * name) { +const char * llama_model_chat_template(const llama_model * model, const char * name) { const auto key = name ? LLM_KV(model->arch, name)(LLM_KV_TOKENIZER_CHAT_TEMPLATE_N) : LLM_KV(model->arch)(LLM_KV_TOKENIZER_CHAT_TEMPLATE); const auto & it = model->gguf_kv.find(key); @@ -4054,11 +11360,11 @@ const char * llama_model_chat_template(const struct llama_model * model, const c return it->second.c_str(); } -uint64_t llama_model_n_params(const struct llama_model * model) { +uint64_t llama_model_n_params(const llama_model * model) { return model->n_elements(); } -bool llama_model_has_encoder(const struct llama_model * model) { +bool llama_model_has_encoder(const llama_model * model) { switch (model->arch) { case LLM_ARCH_T5: return true; case LLM_ARCH_T5ENCODER: return true; @@ -4066,22 +11372,26 @@ bool llama_model_has_encoder(const struct llama_model * model) { } } -bool llama_model_has_decoder(const struct llama_model * model) { +bool llama_model_has_decoder(const llama_model * model) { switch (model->arch) { case LLM_ARCH_T5ENCODER: return false; default: return true; } } -llama_token llama_model_decoder_start_token(const struct llama_model * model) { +llama_token llama_model_decoder_start_token(const llama_model * model) { return model->hparams.dec_start_token_id; } -bool llama_model_is_recurrent(const struct llama_model * model) { +bool llama_model_is_recurrent(const llama_model * model) { switch (model->arch) { - case LLM_ARCH_MAMBA: return true; - case LLM_ARCH_RWKV6: return true; - case LLM_ARCH_RWKV6QWEN2: return true; - default: return false; + case LLM_ARCH_MAMBA: return true; + case LLM_ARCH_RWKV6: return true; + case LLM_ARCH_RWKV6QWEN2: return true; + default: return false; } } + +const std::vector> & llama_internal_get_tensor_map(const llama_model * model) { + return model->tensors_by_name; +} diff --git a/src/llama-model.h b/src/llama-model.h index a7c304447..55c26a92b 100644 --- a/src/llama-model.h +++ b/src/llama-model.h @@ -2,7 +2,9 @@ #include "llama.h" #include "llama-arch.h" +#include "llama-graph.h" #include "llama-hparams.h" +#include "llama-memory.h" #include "llama-vocab.h" #include @@ -10,6 +12,8 @@ #include #include +struct llama_cparams; +struct llama_ubatch; struct llama_model_loader; // available models @@ -347,7 +351,7 @@ struct llama_model { std::string desc() const; size_t size() const; - size_t max_nodes() const; + size_t n_tensors() const; size_t n_devices() const; // total number of parameters in the model @@ -362,9 +366,22 @@ struct llama_model { const struct ggml_tensor * get_tensor(const char * name) const; + // TODO: move this to new llm_arch_model_i interface + llama_memory_i * create_memory() const; // TODO: params + + // TODO: move this to new llm_arch_model_i interface + llm_graph_result_ptr build_graph( + const llm_graph_params & params, + ggml_cgraph * gf, + llm_graph_type type) const; + private: struct impl; std::unique_ptr pimpl; }; const char * llm_type_name(llm_type type); + +// For internal test use +// TODO: remove +const std::vector> & llama_internal_get_tensor_map(const llama_model * model); diff --git a/src/llama.cpp b/src/llama.cpp index 4a4e91490..81e1dd1d0 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -2,9517 +2,28 @@ #include "llama-chat.h" #include "llama-mmap.h" -#include "llama-context.h" #include "llama-vocab.h" -#include "llama-sampling.h" -#include "llama-kv-cache.h" #include "llama-model-loader.h" #include "llama-model.h" #include "ggml.h" -#include "ggml-alloc.h" #include "ggml-backend.h" -#include "ggml-cpp.h" #include -#include -#include -#include -#include #include #include #include #include #include -#include #if defined(_MSC_VER) #pragma warning(disable: 4244 4267) // possible loss of data #endif -// Returns 0 on success, -1 on error, and -2 on cancellation via llama_progress_callback -static int llama_model_load(const std::string & fname, std::vector & splits, llama_model & model, llama_model_params & params) { - // loading time will be recalculated after the first eval, so - // we take page faults deferred by mmap() into consideration - model.t_load_us = 0; - time_meas tm(model.t_load_us); - - model.t_start_us = tm.t_start_us; - - try { - llama_model_loader ml(fname, splits, params.use_mmap, params.check_tensors, params.kv_overrides); - - ml.print_info(); - - model.hparams.vocab_only = params.vocab_only; - - try { - model.load_arch(ml); - } catch(const std::exception & e) { - throw std::runtime_error("error loading model architecture: " + std::string(e.what())); - } - try { - model.load_hparams(ml); - } catch(const std::exception & e) { - throw std::runtime_error("error loading model hyperparameters: " + std::string(e.what())); - } - try { - model.load_vocab(ml); - } catch(const std::exception & e) { - throw std::runtime_error("error loading model vocabulary: " + std::string(e.what())); - } - - model.load_stats(ml); - model.print_info(); - - if (params.vocab_only) { - LLAMA_LOG_INFO("%s: vocab only - skipping tensors\n", __func__); - return 0; - } - - if (!model.load_tensors(ml)) { - return -2; - } - } catch (const std::exception & err) { - LLAMA_LOG_ERROR("%s: error loading model: %s\n", __func__, err.what()); - return -1; - } - - return 0; -} - -// -// llm_build -// - -using llm_build_cb = std::function; - -enum llm_ffn_op_type { - LLM_FFN_SILU, - LLM_FFN_GELU, - LLM_FFN_RELU, - LLM_FFN_RELU_SQR, - LLM_FFN_SWIGLU, -}; - -enum llm_ffn_gate_type { - LLM_FFN_SEQ, - LLM_FFN_PAR, // ffn_gate is parallel to ffn_up -}; - -enum llm_norm_type { - LLM_NORM, - LLM_NORM_RMS, - LLM_NORM_GROUP, -}; - -static struct ggml_tensor * llm_build_inp_embd( - struct ggml_context * ctx, - struct llama_context & lctx, - const llama_hparams & hparams, - const llama_ubatch & ubatch, - struct ggml_tensor * tok_embd, - const llm_build_cb & cb) { - const int64_t n_embd = hparams.n_embd; - - struct ggml_tensor * inpL; - - if (ubatch.token) { - lctx.inp_tokens = ggml_new_tensor_1d(ctx, GGML_TYPE_I32, ubatch.n_tokens); - cb(lctx.inp_tokens, "inp_tokens", -1); - ggml_set_input(lctx.inp_tokens); - - inpL = ggml_get_rows(ctx, tok_embd, lctx.inp_tokens); - - // apply lora for embedding tokens if needed - for (auto & it : lctx.lora) { - struct llama_adapter_lora_weight * lw = it.first->get_weight(tok_embd); - if (lw == nullptr) { - continue; - } - const float adapter_scale = it.second; - const float scale = lw->get_scale(it.first->alpha, adapter_scale); - struct ggml_tensor * inpL_delta = ggml_scale(ctx, ggml_mul_mat( - ctx, lw->b, // non-transposed lora_b - ggml_get_rows(ctx, lw->a, lctx.inp_tokens) - ), scale); - inpL = ggml_add(ctx, inpL, inpL_delta); - } - } else { - lctx.inp_embd = ggml_new_tensor_2d(ctx, GGML_TYPE_F32, n_embd, ubatch.n_tokens); - inpL = lctx.inp_embd; - ggml_set_input(lctx.inp_embd); - } - - // For Granite architecture - if (hparams.f_embedding_scale != 0.0f) { - inpL = ggml_scale(ctx, inpL, hparams.f_embedding_scale); - } - - cb(inpL, "inp_embd", -1); - - return inpL; -} - -static void llm_build_kv_store( - struct ggml_context * ctx, - const llama_hparams & hparams, - const llama_cparams & cparams, - const llama_kv_cache & kv, - struct ggml_cgraph * graph, - struct ggml_tensor * k_cur, - struct ggml_tensor * v_cur, - int32_t n_tokens, - int32_t kv_head, - const llm_build_cb & cb, - int64_t il) { - const int64_t n_ctx = cparams.n_ctx; - - const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); - const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il); - - GGML_ASSERT(kv.size == n_ctx); - - struct ggml_tensor * k_cache_view = ggml_view_1d(ctx, kv.k_l[il], n_tokens*n_embd_k_gqa, ggml_row_size(kv.k_l[il]->type, n_embd_k_gqa)*kv_head); - cb(k_cache_view, "k_cache_view", il); - - // note: storing RoPE-ed version of K in the KV cache - ggml_build_forward_expand(graph, ggml_cpy(ctx, k_cur, k_cache_view)); - - assert(v_cur->ne[0] == n_embd_v_gqa && v_cur->ne[1] == n_tokens); - - struct ggml_tensor * v_cache_view = nullptr; - - if (cparams.flash_attn) { - v_cache_view = ggml_view_1d(ctx, kv.v_l[il], n_tokens*n_embd_v_gqa, ggml_row_size(kv.v_l[il]->type, n_embd_v_gqa)*kv_head); - } else { - // note: the V cache is transposed when not using flash attention - v_cache_view = ggml_view_2d(ctx, kv.v_l[il], n_tokens, n_embd_v_gqa, - ( n_ctx)*ggml_element_size(kv.v_l[il]), - (kv_head)*ggml_element_size(kv.v_l[il])); - - v_cur = ggml_transpose(ctx, v_cur); - } - cb(v_cache_view, "v_cache_view", il); - - ggml_build_forward_expand(graph, ggml_cpy(ctx, v_cur, v_cache_view)); -} - -// do mat_mul, while optionally apply lora -static struct ggml_tensor * llm_build_lora_mm( - struct llama_context & lctx, - struct ggml_context * ctx0, - struct ggml_tensor * w, - struct ggml_tensor * cur) { - struct ggml_tensor * res = ggml_mul_mat(ctx0, w, cur); - for (auto & it : lctx.lora) { - struct llama_adapter_lora_weight * lw = it.first->get_weight(w); - if (lw == nullptr) { - continue; - } - const float adapter_scale = it.second; - const float scale = lw->get_scale(it.first->alpha, adapter_scale); - struct ggml_tensor * ab_cur = ggml_mul_mat( - ctx0, lw->b, - ggml_mul_mat(ctx0, lw->a, cur) - ); - ab_cur = ggml_scale(ctx0, ab_cur, scale); - res = ggml_add(ctx0, res, ab_cur); - } - return res; -} - -// do mat_mul_id, while optionally apply lora -static struct ggml_tensor * llm_build_lora_mm_id( - struct llama_context & lctx, - struct ggml_context * ctx0, - struct ggml_tensor * w, // struct ggml_tensor * as - struct ggml_tensor * cur, // struct ggml_tensor * b - struct ggml_tensor * ids) { - struct ggml_tensor * res = ggml_mul_mat_id(ctx0, w, cur, ids); - for (auto & it : lctx.lora) { - struct llama_adapter_lora_weight * lw = it.first->get_weight(w); - if (lw == nullptr) { - continue; - } - const float alpha = it.first->alpha; - const float rank = (float) lw->b->ne[0]; - const float scale = alpha ? it.second * alpha / rank : it.second; - struct ggml_tensor * ab_cur = ggml_mul_mat_id( - ctx0, lw->b, - ggml_mul_mat_id(ctx0, lw->a, cur, ids), - ids - ); - ab_cur = ggml_scale(ctx0, ab_cur, scale); - res = ggml_add(ctx0, res, ab_cur); - } - return res; -} - -static struct ggml_tensor * llm_build_norm( - struct ggml_context * ctx, - struct ggml_tensor * cur, - const llama_hparams & hparams, - struct ggml_tensor * mw, - struct ggml_tensor * mb, - llm_norm_type type, - const llm_build_cb & cb, - int il) { - switch (type) { - case LLM_NORM: cur = ggml_norm (ctx, cur, hparams.f_norm_eps); break; - case LLM_NORM_RMS: cur = ggml_rms_norm (ctx, cur, hparams.f_norm_rms_eps); break; - case LLM_NORM_GROUP: - { - cur = ggml_reshape_3d(ctx, cur, cur->ne[0], 1, cur->ne[1]); - cur = ggml_group_norm(ctx, cur, hparams.n_norm_groups, hparams.f_norm_group_eps); - cur = ggml_reshape_2d(ctx, cur, cur->ne[0], cur->ne[2]); - } break; - } - - if (mw || mb) { - cb(cur, "norm", il); - } - - if (mw) { - cur = ggml_mul(ctx, cur, mw); - if (mb) { - cb(cur, "norm_w", il); - } - } - - if (mb) { - cur = ggml_add(ctx, cur, mb); - } - - return cur; -} - -static struct ggml_tensor * llm_build_ffn( - struct ggml_context * ctx, - struct llama_context & lctx, - struct ggml_tensor * cur, - struct ggml_tensor * up, - struct ggml_tensor * up_b, - struct ggml_tensor * up_s, - struct ggml_tensor * gate, - struct ggml_tensor * gate_b, - struct ggml_tensor * gate_s, - struct ggml_tensor * down, - struct ggml_tensor * down_b, - struct ggml_tensor * down_s, - struct ggml_tensor * act_scales, - llm_ffn_op_type type_op, - llm_ffn_gate_type type_gate, - const llm_build_cb & cb, - int il) { - struct ggml_tensor * tmp = up ? llm_build_lora_mm(lctx, ctx, up, cur) : cur; - cb(tmp, "ffn_up", il); - - if (up_b) { - tmp = ggml_add(ctx, tmp, up_b); - cb(tmp, "ffn_up_b", il); - } - - if (up_s) { - tmp = ggml_mul(ctx, tmp, up_s); - cb(tmp, "ffn_up_s", il); - } - - if (gate) { - switch (type_gate) { - case LLM_FFN_SEQ: - { - cur = llm_build_lora_mm(lctx, ctx, gate, tmp); - cb(cur, "ffn_gate", il); - } break; - case LLM_FFN_PAR: - { - cur = llm_build_lora_mm(lctx, ctx, gate, cur); - cb(cur, "ffn_gate", il); - } break; - } - - if (gate_b) { - cur = ggml_add(ctx, cur, gate_b); - cb(cur, "ffn_gate_b", il); - } - - if (gate_s) { - cur = ggml_mul(ctx, cur, gate_s); - cb(cur, "ffn_gate_s", il); - } - - } else { - cur = tmp; - } - - switch (type_op) { - case LLM_FFN_SILU: - { - cur = ggml_silu(ctx, cur); - cb(cur, "ffn_silu", il); - } break; - case LLM_FFN_GELU: - { - cur = ggml_gelu(ctx, cur); - cb(cur, "ffn_gelu", il); - if (act_scales != NULL) { - cur = ggml_div(ctx, cur, act_scales); - cb(cur, "ffn_act", il); - } - } break; - case LLM_FFN_RELU: - { - cur = ggml_relu(ctx, cur); - cb(cur, "ffn_relu", il); - } break; - case LLM_FFN_RELU_SQR: - { - cur = ggml_relu(ctx, cur); - cb(cur, "ffn_relu", il); - - cur = ggml_sqr(ctx, cur); - cb(cur, "ffn_sqr(relu)", il); - } break; - case LLM_FFN_SWIGLU: - { - // Project to 4h. If using swiglu double the output width, see https://arxiv.org/pdf/2002.05202.pdf - int64_t split_point = cur->ne[0] / 2; - struct ggml_tensor * x0 = ggml_cont(ctx, ggml_view_2d(ctx, cur, split_point, cur->ne[1], cur->nb[1], 0)); - struct ggml_tensor * x1 = ggml_cont(ctx, ggml_view_2d(ctx, cur, split_point, cur->ne[1], cur->nb[1], split_point * ggml_element_size(cur))); - - x0 = ggml_silu(ctx, x0); - cb(cur, "ffn_silu", il); - - cur = ggml_mul(ctx, x0, x1); - cb(cur, "ffn_mul", il); - } break; - } - - if (type_gate == LLM_FFN_PAR) { - cur = ggml_mul(ctx, cur, tmp); - cb(cur, "ffn_gate_par", il); - } - - if (down) { - cur = llm_build_lora_mm(lctx, ctx, down, cur); - } - - if (down_b) { - cb(cur, "ffn_down", il); - } - - if (down_b) { - cur = ggml_add(ctx, cur, down_b); - } - - if (down_s) { - cur = ggml_mul(ctx, cur, down_s); - cb(cur, "ffn_down_s", il); - } - - return cur; -} - -static struct ggml_tensor * llm_build_moe_ffn( - struct ggml_context * ctx, - struct llama_context & lctx, - struct ggml_tensor * cur, - struct ggml_tensor * gate_inp, - struct ggml_tensor * up_exps, - struct ggml_tensor * gate_exps, - struct ggml_tensor * down_exps, - struct ggml_tensor * exp_probs_b, - int64_t n_expert, - int64_t n_expert_used, - llm_ffn_op_type type_op, - bool norm_w, - bool scale_w, - float w_scale, -llama_expert_gating_func_type gating_op, - const llm_build_cb & cb, - int il) { - int64_t n_embd = cur->ne[0]; - int64_t n_tokens = cur->ne[1]; - - ggml_tensor * logits = llm_build_lora_mm(lctx, ctx, gate_inp, cur); // [n_expert, n_tokens] - cb(logits, "ffn_moe_logits", il); - - ggml_tensor * probs = nullptr; - switch (gating_op) { - case LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX: - { - probs = ggml_soft_max(ctx, logits); // [n_expert, n_tokens] - } break; - case LLAMA_EXPERT_GATING_FUNC_TYPE_SIGMOID: - { - probs = ggml_sigmoid(ctx, logits); // [n_expert, n_tokens] - } break; - default: - GGML_ABORT("fatal error"); - } - cb(probs, "ffn_moe_probs", il); - - // add experts selection bias - introduced in DeepSeek V3 - // leave probs unbiased as it's later used to get expert weights - ggml_tensor * selection_probs = probs; - if (exp_probs_b != nullptr) { - selection_probs = ggml_add(ctx, probs, exp_probs_b); - cb(selection_probs, "ffn_moe_probs_biased", il); - } - - // select experts - ggml_tensor * selected_experts = ggml_top_k(ctx, selection_probs, n_expert_used); // [n_expert_used, n_tokens] - cb(selected_experts->src[0], "ffn_moe_argsort", il); - cb(selected_experts, "ffn_moe_topk", il); - - ggml_tensor * weights = ggml_get_rows(ctx, - ggml_reshape_3d(ctx, probs, 1, n_expert, n_tokens), selected_experts); // [1, n_expert_used, n_tokens] - cb(weights, "ffn_moe_weights", il); - - if (norm_w) { - weights = ggml_reshape_2d(ctx, weights, n_expert_used, n_tokens); - - ggml_tensor * weights_sum = ggml_sum_rows(ctx, weights); // [1, n_tokens] - cb(weights_sum, "ffn_moe_weights_sum", il); - - weights = ggml_div(ctx, weights, weights_sum); // [n_expert_used, n_tokens] - cb(weights, "ffn_moe_weights_norm", il); - - weights = ggml_reshape_3d(ctx, weights, 1, n_expert_used, n_tokens); - } - if (scale_w) { - weights = ggml_scale(ctx, weights, w_scale); - cb(weights, "ffn_moe_weights_scaled", il); - } - - cur = ggml_reshape_3d(ctx, cur, n_embd, 1, n_tokens); - ggml_tensor * up = llm_build_lora_mm_id(lctx, ctx, up_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens] - cb(up, "ffn_moe_up", il); - - ggml_tensor * gate = llm_build_lora_mm_id(lctx, ctx, gate_exps, cur, selected_experts); // [n_ff, n_expert_used, n_tokens] - cb(gate, "ffn_moe_gate", il); - - switch (type_op) { - case LLM_FFN_SILU: - { - gate = ggml_silu(ctx, gate); - cb(gate, "ffn_moe_silu", il); - } break; - case LLM_FFN_GELU: - { - gate = ggml_gelu(ctx, gate); - cb(gate, "ffn_moe_gelu", il); - } break; - default: - GGML_ABORT("fatal error"); - } - - ggml_tensor * par = ggml_mul(ctx, up, gate); // [n_ff, n_expert_used, n_tokens] - cb(par, "ffn_moe_gate_par", il); - - ggml_tensor * experts = llm_build_lora_mm_id(lctx, ctx, down_exps, par, selected_experts); // [n_embd, n_expert_used, n_tokens] - cb(experts, "ffn_moe_down", il); - - experts = ggml_mul(ctx, experts, weights); - - // aggregate experts - ggml_tensor * moe_out = nullptr; - for (int i = 0; i < n_expert_used; ++i) { - ggml_tensor * cur_expert = ggml_view_2d(ctx, experts, n_embd, n_tokens, - experts->nb[2], i*experts->nb[1]); - - if (i == 0) { - moe_out = cur_expert; - } else { - moe_out = ggml_add(ctx, moe_out, cur_expert); - } - } - - if (n_expert_used == 1) { - // avoid returning a non-contiguous tensor - moe_out = ggml_cont(ctx, moe_out); - } - - return moe_out; -} - -static struct ggml_tensor * llm_build_kqv( - struct ggml_context * ctx, - struct llama_context & lctx, - const llama_kv_cache & kv, - struct ggml_cgraph * graph, - struct ggml_tensor * wo, - struct ggml_tensor * wo_b, - struct ggml_tensor * q_cur, - struct ggml_tensor * kq_mask, - int32_t n_tokens, - int32_t n_kv, - float kq_scale, - const llm_build_cb & cb, - int il) { - const llama_model & model = lctx.model; - const llama_hparams & hparams = lctx.model.hparams; - const llama_cparams & cparams = lctx.cparams; - - const int64_t n_ctx = cparams.n_ctx; - const int64_t n_head = hparams.n_head(il); - const int64_t n_head_kv = hparams.n_head_kv(il); - const int64_t n_embd_head_k = hparams.n_embd_head_k; - const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); - const int64_t n_embd_head_v = hparams.n_embd_head_v; - const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il); - - struct ggml_tensor * q = ggml_permute(ctx, q_cur, 0, 2, 1, 3); - cb(q, "q", il); - - struct ggml_tensor * k = - ggml_view_3d(ctx, kv.k_l[il], - n_embd_head_k, n_kv, n_head_kv, - ggml_row_size(kv.k_l[il]->type, n_embd_k_gqa), - ggml_row_size(kv.k_l[il]->type, n_embd_head_k), - 0); - cb(k, "k", il); - - struct ggml_tensor * cur; - - if (cparams.flash_attn) { - GGML_UNUSED(model); - GGML_UNUSED(n_ctx); - - // split cached v into n_head heads (not transposed) - struct ggml_tensor * v = - ggml_view_3d(ctx, kv.v_l[il], - n_embd_head_v, n_kv, n_head_kv, - ggml_row_size(kv.v_l[il]->type, n_embd_v_gqa), - ggml_row_size(kv.v_l[il]->type, n_embd_head_v), - 0); - cb(v, "v", il); - - cur = ggml_flash_attn_ext(ctx, q, k, v, kq_mask, kq_scale, hparams.f_max_alibi_bias, - hparams.attn_soft_cap ? hparams.f_attn_logit_softcapping : 0.0f); - - ggml_flash_attn_ext_set_prec(cur, GGML_PREC_F32); - - cur = ggml_reshape_2d(ctx, cur, n_embd_head_v*n_head, n_tokens); - } else { - struct ggml_tensor * kq = ggml_mul_mat(ctx, k, q); - cb(kq, "kq", il); - - // note: this op tends to require high floating point range - // while for some models F16 is enough, for others it is not, so we default to F32 here - ggml_mul_mat_set_prec(kq, GGML_PREC_F32); - - if (model.arch == LLM_ARCH_GROK) { - // need to do the following: - // multiply by attn_output_multiplyer of 0.08838834764831845 - // and then : - // kq = 30 * tanh(kq / 30) - // before the softmax below - - kq = ggml_tanh(ctx, ggml_scale(ctx, kq, 0.08838834764831845f/30.0f)); - kq = ggml_scale(ctx, kq, 30); - } - - if (hparams.attn_soft_cap) { - kq = ggml_scale(ctx, kq, 1.0f / hparams.f_attn_logit_softcapping); - kq = ggml_tanh(ctx, kq); - kq = ggml_scale(ctx, kq, hparams.f_attn_logit_softcapping); - } - - kq = ggml_soft_max_ext(ctx, kq, kq_mask, kq_scale, hparams.f_max_alibi_bias); - cb(kq, "kq_soft_max_ext", il); - - GGML_ASSERT(kv.size == n_ctx); - - // split cached v into n_head heads - struct ggml_tensor * v = - ggml_view_3d(ctx, kv.v_l[il], - n_kv, n_embd_head_v, n_head_kv, - ggml_element_size(kv.v_l[il])*n_ctx, - ggml_element_size(kv.v_l[il])*n_ctx*n_embd_head_v, - 0); - cb(v, "v", il); - - struct ggml_tensor * kqv = ggml_mul_mat(ctx, v, kq); - cb(kqv, "kqv", il); - - struct ggml_tensor * kqv_merged = ggml_permute(ctx, kqv, 0, 2, 1, 3); - cb(kqv_merged, "kqv_merged", il); - - cur = ggml_cont_2d(ctx, kqv_merged, n_embd_head_v*n_head, n_tokens); - cb(cur, "kqv_merged_cont", il); - } - - ggml_build_forward_expand(graph, cur); - - if (wo) { - cur = llm_build_lora_mm(lctx, ctx, wo, cur); - } - - if (wo_b) { - cb(cur, "kqv_wo", il); - } - - if (wo_b) { - cur = ggml_add(ctx, cur, wo_b); - } - - return cur; -} - -static struct ggml_tensor * llm_build_kv( - struct ggml_context * ctx, - struct llama_context & lctx, - const llama_kv_cache & kv, - struct ggml_cgraph * graph, - struct ggml_tensor * wo, - struct ggml_tensor * wo_b, - struct ggml_tensor * k_cur, - struct ggml_tensor * v_cur, - struct ggml_tensor * q_cur, - struct ggml_tensor * kq_mask, - int32_t n_tokens, - int32_t kv_head, - int32_t n_kv, - float kq_scale, - const llm_build_cb & cb, - int il) { - const llama_hparams & hparams = lctx.model.hparams; - const llama_cparams & cparams = lctx.cparams; - - // these nodes are added to the graph together so that they are not reordered - // by doing so, the number of splits in the graph is reduced - ggml_build_forward_expand(graph, q_cur); - ggml_build_forward_expand(graph, k_cur); - ggml_build_forward_expand(graph, v_cur); - - llm_build_kv_store(ctx, hparams, cparams, kv, graph, k_cur, v_cur, n_tokens, kv_head, cb, il); - - struct ggml_tensor * cur; - - cur = llm_build_kqv(ctx, lctx, kv, graph, wo, wo_b, q_cur, kq_mask, n_tokens, n_kv, kq_scale, cb, il); - cb(cur, "kqv_out", il); - - return cur; -} - -static struct ggml_tensor * llm_build_copy_mask_state( - struct ggml_context * ctx, - struct ggml_cgraph * graph, - struct ggml_tensor * s, - struct ggml_tensor * state_copy, - struct ggml_tensor * state_mask, - int32_t n_state, - int32_t kv_size, - int32_t kv_head, - int32_t n_kv, - int32_t n_seqs) { - struct ggml_tensor * states = ggml_reshape_2d(ctx, s, n_state, kv_size); - - // copy states - // NOTE: assuming the copy destinations are ALL contained between kv_head and kv_head + n_kv - // this shrinks the tensors's ne[1] to n_kv - states = ggml_get_rows(ctx, states, state_copy); - - // clear states of sequences which are starting at the beginning of this batch - // FIXME: zero-out NANs? - states = ggml_mul(ctx, states, state_mask); - - // copy states which won't be changed further (between n_seqs and n_kv) - ggml_build_forward_expand(graph, - ggml_cpy(ctx, - ggml_view_1d(ctx, states, n_state*(n_kv - n_seqs), n_seqs*n_state*ggml_element_size(states)), - ggml_view_1d(ctx, s, n_state*(n_kv - n_seqs), (kv_head + n_seqs)*n_state*ggml_element_size(s)))); - - // the part of the states that will be used and modified - return ggml_view_2d(ctx, states, n_state, n_seqs, states->nb[1], 0); -} - -// TODO: split -static struct ggml_tensor * llm_build_mamba( - struct ggml_context * ctx, - struct llama_context & lctx, - const llama_ubatch & ubatch, - struct ggml_cgraph * graph, - struct ggml_tensor * cur, - struct ggml_tensor * state_copy, - struct ggml_tensor * state_mask, - int32_t kv_head, - int32_t n_kv, - const llm_build_cb & cb, - int il) { - const llama_model & model = lctx.model; - const llama_hparams & hparams = model.hparams; - const llama_kv_cache & kv = lctx.kv_self; - const int64_t d_conv = hparams.ssm_d_conv; - const int64_t d_inner = hparams.ssm_d_inner; - const int64_t d_state = hparams.ssm_d_state; - const int64_t dt_rank = hparams.ssm_dt_rank; - const int64_t n_seqs = ubatch.n_seqs; - // Some variants of Mamba arch (e.g. FalconMamba do apply layer norm on B and Dt layers) - const bool ssm_dt_b_c_rms = hparams.ssm_dt_b_c_rms; - // Use the same RMS norm as the final layer norm - const float norm_rms_eps = hparams.f_norm_rms_eps; - - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - - GGML_ASSERT(n_seqs != 0); - GGML_ASSERT(ubatch.equal_seqs); - GGML_ASSERT(ubatch.n_tokens == n_seq_tokens * n_seqs); - - struct ggml_tensor * conv_states_all = kv.k_l[il]; - struct ggml_tensor * ssm_states_all = kv.v_l[il]; - - // (ab)using the KV cache to store the states - struct ggml_tensor * conv = llm_build_copy_mask_state(ctx, - graph, conv_states_all, state_copy, state_mask, - hparams.n_embd_k_s(), kv.size, kv_head, n_kv, n_seqs); - conv = ggml_reshape_3d(ctx, conv, d_conv - 1, d_inner, n_seqs); - struct ggml_tensor * ssm = llm_build_copy_mask_state(ctx, - graph, ssm_states_all, state_copy, state_mask, - hparams.n_embd_v_s(), kv.size, kv_head, n_kv, n_seqs); - ssm = ggml_reshape_3d(ctx, ssm, d_state, d_inner, n_seqs); - - // {n_embd, n_tokens} => {n_embd, n_seq_tokens, n_seqs} - cur = ggml_reshape_3d(ctx, cur, cur->ne[0], n_seq_tokens, n_seqs); - - // {n_embd, 2*d_inner} @ {n_embd, n_seq_tokens, n_seqs} => {2*d_inner, n_seq_tokens, n_seqs} - struct ggml_tensor * xz = llm_build_lora_mm(lctx, ctx, model.layers[il].ssm_in, cur); - // split the above in two - // => {d_inner, n_seq_tokens, n_seqs} - struct ggml_tensor * x = ggml_view_3d(ctx, xz, d_inner, xz->ne[1], xz->ne[2], xz->nb[1], xz->nb[2], 0); - struct ggml_tensor * z = ggml_view_3d(ctx, xz, d_inner, xz->ne[1], xz->ne[2], xz->nb[1], xz->nb[2], d_inner*ggml_element_size(xz)); - - // conv - { - // => {d_conv - 1 + n_seq_tokens, d_inner, n_seqs} - struct ggml_tensor * conv_x = ggml_concat(ctx, conv, ggml_transpose(ctx, x), 0); - - // copy last (d_conv - 1) columns back into the state cache - struct ggml_tensor * last_conv = ggml_view_3d(ctx, conv_x, d_conv - 1, d_inner, n_seqs, conv_x->nb[1], conv_x->nb[2], n_seq_tokens*(conv_x->nb[0])); - - ggml_build_forward_expand(graph, - ggml_cpy(ctx, last_conv, - ggml_view_1d(ctx, conv_states_all, - (d_conv - 1)*(d_inner)*(n_seqs), - kv_head*(d_conv - 1)*(d_inner)*ggml_element_size(conv_states_all)))); - - // 1D convolution - // The equivalent is to make a self-overlapping view of conv_x - // over d_conv columns at each stride in the 3rd dimension, - // then element-wise multiply that with the conv1d weight, - // then sum the elements of each row, - // (the last two steps are a dot product over rows (also doable with mul_mat)) - // then permute away the ne[0] dimension, - // and then you're left with the resulting x tensor. - // For simultaneous sequences, all sequences need to have the same length. - x = ggml_ssm_conv(ctx, conv_x, model.layers[il].ssm_conv1d); - - // bias - x = ggml_add(ctx, x, model.layers[il].ssm_conv1d_b); - - x = ggml_silu(ctx, x); - } - - // ssm - { - // {d_inner, dt_rank + 2*d_state} @ {d_inner, n_seq_tokens, n_seqs} => {dt_rank + 2*d_state, n_seq_tokens, n_seqs} - struct ggml_tensor * x_db = llm_build_lora_mm(lctx, ctx, model.layers[il].ssm_x, x); - // split - struct ggml_tensor * dt = ggml_view_3d(ctx, x_db, dt_rank, n_seq_tokens, n_seqs, x_db->nb[1], x_db->nb[2], 0); - struct ggml_tensor * B = ggml_view_3d(ctx, x_db, d_state, n_seq_tokens, n_seqs, x_db->nb[1], x_db->nb[2], ggml_element_size(x_db)*dt_rank); - struct ggml_tensor * C = ggml_view_3d(ctx, x_db, d_state, n_seq_tokens, n_seqs, x_db->nb[1], x_db->nb[2], ggml_element_size(x_db)*(dt_rank+d_state)); - - // Some Mamba variants (e.g. FalconMamba) apply RMS norm in B, C & Dt layers - if (ssm_dt_b_c_rms) { - dt = ggml_rms_norm(ctx, dt, norm_rms_eps); - B = ggml_rms_norm(ctx, B, norm_rms_eps); - C = ggml_rms_norm(ctx, C, norm_rms_eps); - } - - // {dt_rank, d_inner} @ {dt_rank, n_seq_tokens, n_seqs} => {d_inner, n_seq_tokens, n_seqs} - dt = llm_build_lora_mm(lctx, ctx, model.layers[il].ssm_dt, dt); - dt = ggml_add(ctx, dt, model.layers[il].ssm_dt_b); - - // Custom operator to optimize the parallel associative scan - // as described in the Annex D of the Mamba paper. - // => {d_inner, n_seq_tokens, n_seqs} and {d_state, d_inner, n_seqs} - struct ggml_tensor * y_ssm = ggml_ssm_scan(ctx, ssm, x, dt, model.layers[il].ssm_a, B, C); - - // store last states - ggml_build_forward_expand(graph, - ggml_cpy(ctx, - ggml_view_1d(ctx, y_ssm, d_state*d_inner*n_seqs, x->nb[3]), - ggml_view_1d(ctx, ssm_states_all, d_state*d_inner*n_seqs, kv_head*d_state*d_inner*ggml_element_size(ssm_states_all)))); - - struct ggml_tensor * y = ggml_view_3d(ctx, y_ssm, d_inner, n_seq_tokens, n_seqs, x->nb[1], x->nb[2], 0); - - // TODO: skip computing output earlier for unused tokens - - // {d_inner, n_seq_tokens, n_seqs} * {d_inner} => {d_inner, n_seq_tokens, n_seqs} - y = ggml_add(ctx, y, ggml_mul(ctx, x, model.layers[il].ssm_d)); - y = ggml_mul(ctx, y, ggml_silu(ctx, ggml_cont(ctx, z))); - - // {d_inner, n_embd} @ {d_inner, n_seq_tokens, n_seqs} => {n_embd, n_seq_tokens, n_seqs} - cur = llm_build_lora_mm(lctx, ctx, model.layers[il].ssm_out, y); - } - - // {n_embd, n_seq_tokens, n_seqs} => {n_embd, n_tokens} - cur = ggml_reshape_2d(ctx, cur, cur->ne[0], n_seq_tokens * n_seqs); - cb(cur, "mamba_out", il); - - return cur; -} - -static struct ggml_tensor * llm_build_rwkv6_time_mix( - struct llama_context & lctx, - struct ggml_context * ctx, - const struct llama_layer * layer, - struct ggml_tensor * cur, - struct ggml_tensor * x_prev, - struct ggml_tensor ** wkv_state, - size_t wkv_head_size, - size_t head_count_kv) { - size_t n_embd = cur->ne[0]; - size_t n_seq_tokens = cur->ne[1]; - size_t n_seqs = cur->ne[2]; - - size_t head_size = wkv_head_size; - size_t head_count = n_embd / head_size; - - size_t n_tokens = n_seqs * n_seq_tokens; - - bool is_qrwkv = layer->time_mix_first == nullptr; - - struct ggml_tensor * sx = ggml_sub(ctx, x_prev, cur); - - sx = ggml_reshape_2d(ctx, sx, n_embd, n_tokens); - cur = ggml_reshape_2d(ctx, cur, n_embd, n_tokens); - - struct ggml_tensor * xxx = ggml_add(ctx, ggml_mul(ctx, sx, layer->time_mix_lerp_x), cur); - - xxx = ggml_reshape_4d( - ctx, - ggml_tanh( - ctx, - ggml_mul_mat(ctx, layer->time_mix_w1, xxx) - ), - layer->time_mix_w1->ne[1] / 5, 1, 5, n_tokens - ); - - xxx = ggml_cont(ctx, ggml_permute(ctx, xxx, 0, 1, 3, 2)); - - xxx = ggml_mul_mat( - ctx, - ggml_reshape_4d( - ctx, - layer->time_mix_w2, - layer->time_mix_w2->ne[0], layer->time_mix_w2->ne[1], 1, 5 - ), - xxx - ); - - struct ggml_tensor *xw, *xk, *xv, *xr, *xg; - if (layer->time_mix_lerp_fused) { - // fusing these weights makes some performance improvement - sx = ggml_reshape_3d(ctx, sx, n_embd, 1, n_tokens); - cur = ggml_reshape_3d(ctx, cur, n_embd, 1, n_tokens); - xxx = ggml_add(ctx, ggml_mul(ctx, ggml_add(ctx, xxx, layer->time_mix_lerp_fused), sx), cur); - xw = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], 0); - xk = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * sizeof(float)); - xv = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 2 * sizeof(float)); - xr = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 3 * sizeof(float)); - xg = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 4 * sizeof(float)); - } else { - // for backward compatibility - xw = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], 0); - xk = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * sizeof(float)); - xv = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 2 * sizeof(float)); - xr = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 3 * sizeof(float)); - xg = ggml_view_2d(ctx, xxx, n_embd, n_tokens, xxx->nb[1], n_embd * n_tokens * 4 * sizeof(float)); - - xw = ggml_add(ctx, ggml_mul(ctx, ggml_add(ctx, xw, layer->time_mix_lerp_w), sx), cur); - xk = ggml_add(ctx, ggml_mul(ctx, ggml_add(ctx, xk, layer->time_mix_lerp_k), sx), cur); - xv = ggml_add(ctx, ggml_mul(ctx, ggml_add(ctx, xv, layer->time_mix_lerp_v), sx), cur); - xr = ggml_add(ctx, ggml_mul(ctx, ggml_add(ctx, xr, layer->time_mix_lerp_r), sx), cur); - xg = ggml_add(ctx, ggml_mul(ctx, ggml_add(ctx, xg, layer->time_mix_lerp_g), sx), cur); - } - - struct ggml_tensor * r = llm_build_lora_mm(lctx, ctx, layer->time_mix_receptance, xr); - struct ggml_tensor * k = llm_build_lora_mm(lctx, ctx, layer->time_mix_key, xk); - struct ggml_tensor * v = llm_build_lora_mm(lctx, ctx, layer->time_mix_value, xv); - if (layer->time_mix_receptance_b) { - r = ggml_add(ctx, r, layer->time_mix_receptance_b); - } - if (layer->time_mix_key_b) { - k = ggml_add(ctx, k, layer->time_mix_key_b); - } - if (layer->time_mix_value_b) { - v = ggml_add(ctx, v, layer->time_mix_value_b); - } - - struct ggml_tensor * g = llm_build_lora_mm(lctx, ctx, layer->time_mix_gate, xg); - if (is_qrwkv) { - g = ggml_sigmoid(ctx, g); - } else { - g = ggml_silu(ctx, g); - } - - if (head_count_kv != head_count) { - GGML_ASSERT(head_count % head_count_kv == 0); - k = ggml_reshape_4d(ctx, k, head_size, 1, head_count_kv, n_tokens); - v = ggml_reshape_4d(ctx, v, head_size, 1, head_count_kv, n_tokens); - struct ggml_tensor * tmp = ggml_new_tensor_4d(ctx, GGML_TYPE_F32, head_size, head_count / head_count_kv, head_count_kv, n_tokens); - k = ggml_repeat(ctx, k, tmp); - v = ggml_repeat(ctx, v, tmp); - } - - k = ggml_reshape_3d(ctx, k, head_size, head_count, n_tokens); - v = ggml_reshape_3d(ctx, v, head_size, head_count, n_tokens); - r = ggml_reshape_3d(ctx, r, head_size, head_count, n_tokens); - - struct ggml_tensor * w = ggml_mul_mat( - ctx, - layer->time_mix_decay_w2, - ggml_tanh( - ctx, - ggml_mul_mat(ctx, layer->time_mix_decay_w1, xw) - ) - ); - - w = ggml_add(ctx, w, layer->time_mix_decay); - w = ggml_exp(ctx, ggml_neg(ctx, ggml_exp(ctx, w))); - w = ggml_reshape_3d(ctx, w, head_size, head_count, n_tokens); - - if (is_qrwkv) { - // k = k * (1 - w) - k = ggml_sub(ctx, k, ggml_mul(ctx, k, w)); - } - - struct ggml_tensor * wkv_output; - if (!layer->time_mix_first) { - wkv_output = ggml_gated_linear_attn(ctx, k, v, r, w, *wkv_state, pow(head_size, -0.5f)); - } else { - wkv_output = ggml_rwkv_wkv6(ctx, k, v, r, layer->time_mix_first, w, *wkv_state); - } - cur = ggml_view_1d(ctx, wkv_output, n_embd * n_tokens, 0); - *wkv_state = ggml_view_1d(ctx, wkv_output, n_embd * head_size * n_seqs, n_embd * n_tokens * sizeof(float)); - - if (!is_qrwkv) { - // group norm with head_count groups - cur = ggml_reshape_3d(ctx, cur, n_embd / head_count, head_count, n_tokens); - cur = ggml_norm(ctx, cur, 64e-5f); - - // Convert back to regular vectors. - cur = ggml_reshape_2d(ctx, cur, n_embd, n_tokens); - cur = ggml_add(ctx, ggml_mul(ctx, cur, layer->time_mix_ln), layer->time_mix_ln_b); - } else { - cur = ggml_reshape_2d(ctx, cur, n_embd, n_tokens); - } - - cur = ggml_mul(ctx, cur, g); - cur = llm_build_lora_mm(lctx, ctx, layer->time_mix_output, cur); - - return ggml_reshape_3d(ctx, cur, n_embd, n_seq_tokens, n_seqs); -} - -static struct ggml_tensor * llm_build_rwkv6_channel_mix( - struct llama_context & lctx, - struct ggml_context * ctx, - const struct llama_layer * layer, - struct ggml_tensor * cur, - struct ggml_tensor * x_prev) { - struct ggml_tensor * sx = ggml_sub(ctx, x_prev, cur); - struct ggml_tensor * xk = ggml_add(ctx, ggml_mul(ctx, sx, layer->channel_mix_lerp_k), cur); - struct ggml_tensor * xr = ggml_add(ctx, ggml_mul(ctx, sx, layer->channel_mix_lerp_r), cur); - - struct ggml_tensor * r = ggml_sigmoid(ctx, llm_build_lora_mm(lctx, ctx, layer->channel_mix_receptance, xr)); - struct ggml_tensor * k = ggml_sqr( - ctx, - ggml_relu( - ctx, - llm_build_lora_mm(lctx, ctx, layer->channel_mix_key, xk) - ) - ); - - return ggml_mul(ctx, r, llm_build_lora_mm(lctx, ctx, layer->channel_mix_value, k)); -} - -struct llm_build_context { - const llama_model & model; - llama_context & lctx; - const llama_hparams & hparams; - const llama_cparams & cparams; - const llama_ubatch & ubatch; - const llama_kv_cache & kv_self; - - const int64_t n_embd; - const int64_t n_layer; - const int64_t n_rot; - const int64_t n_ctx; // user-specified context size (can be different from n_ctx_train) - const int64_t n_head; - const int64_t n_head_kv; - const int64_t n_embd_head_k; - const int64_t n_embd_k_gqa; - const int64_t n_embd_head_v; - const int64_t n_embd_v_gqa; - const int64_t n_expert; - const int64_t n_expert_used; - - const float freq_base; - const float freq_scale; - const float ext_factor; - const float attn_factor; - const float beta_fast; - const float beta_slow; - const float norm_eps; - const float norm_rms_eps; - - const int32_t n_tokens; - const int32_t n_kv; // size of KV cache to consider (n_kv <= kv_self.size) - const int32_t n_outputs; - const int32_t n_outputs_enc; - const int32_t kv_head; // index of where we store new KV data in the cache - const int32_t n_ctx_orig; - - const bool flash_attn; - - const enum llama_pooling_type pooling_type; - const enum llama_rope_type rope_type; - - const llm_build_cb & cb; - - std::vector & buf_compute_meta; - - struct ggml_context * ctx0 = nullptr; - - // TODO: consider making the entire interface noexcept - llm_build_context( - llama_context & lctx, - const llama_ubatch & ubatch, - const llm_build_cb & cb, - bool worst_case) : - model (lctx.model), - lctx (lctx), - hparams (model.hparams), - cparams (lctx.cparams), - ubatch (ubatch), - kv_self (lctx.kv_self), - n_embd (hparams.n_embd), - n_layer (hparams.n_layer), - n_rot (hparams.n_rot), - n_ctx (cparams.n_ctx), - n_head (hparams.n_head()), - n_head_kv (hparams.n_head_kv()), - n_embd_head_k (hparams.n_embd_head_k), - n_embd_k_gqa (hparams.n_embd_k_gqa()), - n_embd_head_v (hparams.n_embd_head_v), - n_embd_v_gqa (hparams.n_embd_v_gqa()), - n_expert (hparams.n_expert), - n_expert_used (hparams.n_expert_used), - freq_base (cparams.rope_freq_base), - freq_scale (cparams.rope_freq_scale), - ext_factor (cparams.yarn_ext_factor), - attn_factor (cparams.yarn_attn_factor), - beta_fast (cparams.yarn_beta_fast), - beta_slow (cparams.yarn_beta_slow), - norm_eps (hparams.f_norm_eps), - norm_rms_eps (hparams.f_norm_rms_eps), - n_tokens (ubatch.n_tokens), - n_kv (worst_case ? kv_self.size : kv_self.n), - n_outputs (worst_case ? n_tokens : lctx.n_outputs), - n_outputs_enc (worst_case ? n_tokens : lctx.embd_enc.size() / hparams.n_embd), - kv_head (worst_case ? (kv_self.recurrent ? 0 : kv_self.size - n_tokens) : kv_self.head), - n_ctx_orig (cparams.n_ctx_orig_yarn), - flash_attn (cparams.flash_attn), - pooling_type (cparams.pooling_type), - rope_type (hparams.rope_type), - cb (cb), - buf_compute_meta (lctx.buf_compute_meta) { - // all initializations should be done in init() - } - - void init() { - struct ggml_init_params params = { - /*.mem_size =*/ buf_compute_meta.size(), - /*.mem_buffer =*/ buf_compute_meta.data(), - /*.no_alloc =*/ true, - }; - - ctx0 = ggml_init(params); - - lctx.inp_tokens = nullptr; - lctx.inp_embd = nullptr; - lctx.inp_pos = nullptr; - lctx.inp_out_ids = nullptr; - lctx.inp_KQ_mask = nullptr; - lctx.inp_KQ_mask_swa = nullptr; - lctx.inp_K_shift = nullptr; - lctx.inp_mean = nullptr; - lctx.inp_cls = nullptr; - lctx.inp_s_copy = nullptr; - lctx.inp_s_mask = nullptr; - lctx.inp_s_seq = nullptr; - lctx.inp_pos_bucket = nullptr; - lctx.inp_embd_enc = nullptr; - lctx.inp_KQ_mask_cross = nullptr; - } - - void free() { - ggml_free(ctx0); - ctx0 = nullptr; - } - - struct ggml_cgraph * build_k_shift() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - GGML_ASSERT(kv_self.size == n_ctx); - - lctx.inp_K_shift = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_ctx); - cb(lctx.inp_K_shift, "K_shift", -1); - ggml_set_input(lctx.inp_K_shift); - - for (int il = 0; il < n_layer; ++il) { - const int64_t n_head_kv = hparams.n_head_kv(il); - const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); - struct ggml_tensor * rope_factors = build_rope_factors(il); - struct ggml_tensor * k = - ggml_view_3d(ctx0, kv_self.k_l[il], - n_embd_head_k, n_head_kv, n_ctx, - ggml_row_size(kv_self.k_l[il]->type, n_embd_head_k), - ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa), - 0); - - struct ggml_tensor * tmp; - if (ggml_is_quantized(k->type)) { - // dequantize to f32 -> RoPE -> quantize back - tmp = ggml_cast(ctx0, k, GGML_TYPE_F32); - cb(tmp, "K_f32", il); - for (auto & backend : lctx.backends) { - // Figure out which backend KV cache belongs to - if (ggml_backend_supports_buft(backend.get(), ggml_backend_buffer_get_type(kv_self.k_l[il]->buffer))) { - ggml_backend_sched_set_tensor_backend(lctx.sched.get(), tmp, backend.get()); - break; - } - } - tmp = ggml_rope_ext_inplace(ctx0, tmp, - lctx.inp_K_shift, rope_factors, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(tmp, "K_shifted_f32", il); - tmp = ggml_cpy(ctx0, tmp, k); - } else { - // we rotate only the first n_rot dimensions - tmp = ggml_rope_ext_inplace(ctx0, k, - lctx.inp_K_shift, rope_factors, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - } - cb(tmp, "K_shifted", il); - ggml_build_forward_expand(gf, tmp); - } - - return gf; - } - - struct ggml_cgraph * build_defrag(const std::vector & ids) { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - for (uint32_t i = 0; i < ids.size(); ++i) { - const uint32_t id = ids[i]; - - if (i == id || id == ids.size()) { - continue; - } - - uint32_t nm = 1; - - while (i + nm < ids.size() && ids[i + nm] == id + nm) { - nm++; - } - - for (int il = 0; il < n_layer; ++il) { - const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il); - const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il); - - ggml_tensor * view_k_src = ggml_view_2d(ctx0, kv_self.k_l[il], - n_embd_k_gqa, nm, - ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa), - ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa*i)); - - ggml_tensor * view_k_dst = ggml_view_2d(ctx0, kv_self.k_l[il], - n_embd_k_gqa, nm, - ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa), - ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa*id)); - - ggml_tensor * view_v_src; - ggml_tensor * view_v_dst; - - if (flash_attn) { - // NOTE: the V cache is not transposed when using flash attention - view_v_src = ggml_view_2d(ctx0, kv_self.v_l[il], - n_embd_v_gqa, nm, - ggml_row_size(kv_self.v_l[il]->type, n_embd_v_gqa), - ggml_row_size(kv_self.v_l[il]->type, n_embd_v_gqa*i)); - - view_v_dst = ggml_view_2d(ctx0, kv_self.v_l[il], - n_embd_v_gqa, nm, - ggml_row_size(kv_self.v_l[il]->type, n_embd_v_gqa), - ggml_row_size(kv_self.v_l[il]->type, n_embd_v_gqa*id)); - } else { - view_v_src = ggml_view_2d(ctx0, kv_self.v_l[il], - nm, n_embd_v_gqa, - ggml_row_size(kv_self.v_l[il]->type, kv_self.size), - ggml_row_size(kv_self.v_l[il]->type, i)); - - view_v_dst = ggml_view_2d(ctx0, kv_self.v_l[il], - nm, n_embd_v_gqa, - ggml_row_size(kv_self.v_l[il]->type, kv_self.size), - ggml_row_size(kv_self.v_l[il]->type, id)); - } - - ggml_build_forward_expand(gf, ggml_cpy(ctx0, view_k_src, view_k_dst)); - ggml_build_forward_expand(gf, ggml_cpy(ctx0, view_v_src, view_v_dst)); - } - - i += nm - 1; - } - - //LLAMA_LOG_INFO("gf->n_nodes = %d\n", gf->n_nodes); - - return gf; - } - - struct ggml_tensor * build_inp_pos() { - lctx.inp_pos = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_tokens); - cb(lctx.inp_pos, "inp_pos", -1); - ggml_set_input(lctx.inp_pos); - return lctx.inp_pos; - } - - struct ggml_tensor * build_rope_factors(int il) { - // choose long/short freq factors based on the context size - const auto n_ctx_pre_seq = cparams.n_ctx / cparams.n_seq_max; - - if (model.layers[il].rope_freqs != nullptr) { - return model.layers[il].rope_freqs; - } - - if (n_ctx_pre_seq > hparams.n_ctx_orig_yarn) { - return model.layers[il].rope_long; - } - - return model.layers[il].rope_short; - } - - struct ggml_tensor * build_inp_out_ids() { - lctx.inp_out_ids = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_outputs); - cb(lctx.inp_out_ids, "inp_out_ids", -1); - ggml_set_input(lctx.inp_out_ids); - return lctx.inp_out_ids; - } - - struct ggml_tensor * build_inp_KQ_mask(bool causal = true) { - lctx.inp_KQ_mask = causal - ? ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)) - : ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_tokens, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)); - cb(lctx.inp_KQ_mask, "KQ_mask", -1); - ggml_set_input(lctx.inp_KQ_mask); - - return flash_attn ? ggml_cast(ctx0, lctx.inp_KQ_mask, GGML_TYPE_F16) : lctx.inp_KQ_mask; - } - - struct ggml_tensor * build_inp_KQ_mask_swa(bool causal = true) { - GGML_ASSERT(hparams.n_swa > 0); - - lctx.inp_KQ_mask_swa = causal - ? ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)) - : ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_tokens, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)); - cb(lctx.inp_KQ_mask_swa, "KQ_mask_swa", -1); - ggml_set_input(lctx.inp_KQ_mask_swa); - - return flash_attn ? ggml_cast(ctx0, lctx.inp_KQ_mask_swa, GGML_TYPE_F16) : lctx.inp_KQ_mask_swa; - } - - struct ggml_tensor * build_inp_mean() { - lctx.inp_mean = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_tokens, n_tokens); - cb(lctx.inp_mean, "inp_mean", -1); - ggml_set_input(lctx.inp_mean); - return lctx.inp_mean; - } - - struct ggml_tensor * build_inp_cls() { - lctx.inp_cls = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_tokens); - cb(lctx.inp_cls, "inp_cls", -1); - ggml_set_input(lctx.inp_cls); - return lctx.inp_cls; - } - - struct ggml_tensor * build_inp_s_copy() { - lctx.inp_s_copy = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_kv); - cb(lctx.inp_s_copy, "inp_s_copy", -1); - ggml_set_input(lctx.inp_s_copy); - return lctx.inp_s_copy; - } - - struct ggml_tensor * build_inp_s_mask() { - lctx.inp_s_mask = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, 1, n_kv); - cb(lctx.inp_s_mask, "inp_s_mask", -1); - ggml_set_input(lctx.inp_s_mask); - return lctx.inp_s_mask; - } - - struct ggml_cgraph * append_pooling(struct ggml_cgraph * gf) { - // find result_norm tensor for input - struct ggml_tensor * inp = nullptr; - for (int i = ggml_graph_n_nodes(gf) - 1; i >= 0; --i) { - inp = ggml_graph_node(gf, i); - if (strcmp(inp->name, "result_norm") == 0 || strcmp(inp->name, "result_embd") == 0) { - break; - } else { - inp = nullptr; - } - } - GGML_ASSERT(inp != nullptr && "missing result_norm/result_embd tensor"); - - struct ggml_tensor * cur; - - switch (pooling_type) { - case LLAMA_POOLING_TYPE_NONE: - { - cur = inp; - } break; - case LLAMA_POOLING_TYPE_MEAN: - { - struct ggml_tensor * inp_mean = build_inp_mean(); - cur = ggml_mul_mat(ctx0, ggml_cont(ctx0, ggml_transpose(ctx0, inp)), inp_mean); - } break; - case LLAMA_POOLING_TYPE_CLS: - case LLAMA_POOLING_TYPE_LAST: - { - struct ggml_tensor * inp_cls = build_inp_cls(); - cur = ggml_get_rows(ctx0, inp, inp_cls); - } break; - case LLAMA_POOLING_TYPE_RANK: - { - struct ggml_tensor * inp_cls = build_inp_cls(); - inp = ggml_get_rows(ctx0, inp, inp_cls); - - // classification head - // https://github.com/huggingface/transformers/blob/5af7d41e49bbfc8319f462eb45253dcb3863dfb7/src/transformers/models/roberta/modeling_roberta.py#L1566 - GGML_ASSERT(model.cls != nullptr); - GGML_ASSERT(model.cls_b != nullptr); - - cur = ggml_add (ctx0, ggml_mul_mat(ctx0, model.cls, inp), model.cls_b); - cur = ggml_tanh(ctx0, cur); - - // some models don't have `cls_out`, for example: https://huggingface.co/jinaai/jina-reranker-v1-tiny-en - // https://huggingface.co/jinaai/jina-reranker-v1-tiny-en/blob/cb5347e43979c3084a890e3f99491952603ae1b7/modeling_bert.py#L884-L896 - if (model.cls_out) { - GGML_ASSERT(model.cls_out_b != nullptr); - - cur = ggml_add (ctx0, ggml_mul_mat(ctx0, model.cls_out, cur), model.cls_out_b); - } - } break; - default: - { - GGML_ABORT("unknown pooling type"); - } - } - - cb(cur, "result_embd_pooled", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_tensor * llm_build_pos_bucket(bool causal) { - if (causal) { - lctx.inp_pos_bucket = ggml_new_tensor_2d(ctx0, GGML_TYPE_I32, n_kv, n_tokens); - } else { - lctx.inp_pos_bucket = ggml_new_tensor_2d(ctx0, GGML_TYPE_I32, n_tokens, n_tokens); - } - - ggml_set_input(lctx.inp_pos_bucket); - cb(lctx.inp_pos_bucket, "pos_bucket", -1); - - return lctx.inp_pos_bucket; - } - - struct ggml_tensor * llm_build_pos_bias(struct ggml_tensor * pos_bucket, struct ggml_tensor * attn_rel_b) { - struct ggml_tensor * pos_bucket_1d = ggml_view_1d(ctx0, pos_bucket, pos_bucket->ne[0] * pos_bucket->ne[1], 0); - cb(pos_bucket_1d, "pos_bucket_1d", -1); - - struct ggml_tensor * pos_bias = ggml_get_rows(ctx0, attn_rel_b, pos_bucket_1d); - cb(pos_bias, "pos_bias", -1); - - pos_bias = ggml_view_3d(ctx0, pos_bias, pos_bias->ne[0], lctx.inp_pos_bucket->ne[0], lctx.inp_pos_bucket->ne[1], ggml_element_size(pos_bias) * pos_bias->ne[0], ggml_element_size(pos_bias) * pos_bias->ne[0] * lctx.inp_pos_bucket->ne[0], 0); - cb(pos_bias, "pos_bias", -1); - - pos_bias = ggml_permute(ctx0, pos_bias, 2, 0, 1, 3); - cb(pos_bias, "pos_bias", -1); - - pos_bias = ggml_cont(ctx0, pos_bias); - cb(pos_bias, "pos_bias", -1); - - return pos_bias; - } - - struct ggml_tensor * llm_build_inp_embd_enc() { - const int64_t n_embd = hparams.n_embd; - lctx.inp_embd_enc = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_embd, n_outputs_enc); - ggml_set_input(lctx.inp_embd_enc); - cb(lctx.inp_embd_enc, "embd_enc", -1); - return lctx.inp_embd_enc; - } - - struct ggml_tensor * llm_build_inp_KQ_mask_cross() { - lctx.inp_KQ_mask_cross = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_outputs_enc, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD)); - ggml_set_input(lctx.inp_KQ_mask_cross); - cb(lctx.inp_KQ_mask_cross, "KQ_mask_cross", -1); - return lctx.inp_KQ_mask_cross; - } - - struct ggml_cgraph * build_llama() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale; - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // rope freq factors for llama3; may return nullptr for llama2 and other models - struct ggml_tensor * rope_factors = build_rope_factors(il); - - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, kq_scale, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - // For Granite architecture - if (hparams.f_residual_scale) { - cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - if (model.layers[il].ffn_gate_inp == nullptr) { - - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - model.layers[il].ffn_gate, model.layers[il].ffn_gate_b, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } else { - // MoE branch - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_SILU, true, - false, 0.0, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(cur, "ffn_moe_out", il); - } - - // For Granite architecture - if (hparams.f_residual_scale) { - cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - // For Granite architecture - if (hparams.f_logit_scale) { - cur = ggml_scale(ctx0, cur, 1.0f / hparams.f_logit_scale); - } - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_deci() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale; - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - const int64_t n_head_kv = hparams.n_head_kv(il); - const int64_t n_head = hparams.n_head(il); - - if (n_head == 0) { - // attention-free layer of Llama-3_1-Nemotron-51B - cur = inpL; - } else { - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - } - - if (n_head > 0 && n_head_kv == 0) { - // "linear attention" of Llama-3_1-Nemotron-51B - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wo, cur); - cb(cur, "wo", il); - } else if (n_head > 0) { - // self-attention - // rope freq factors for llama3; may return nullptr for llama2 and other models - struct ggml_tensor * rope_factors = build_rope_factors(il); - - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, kq_scale, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - // For Granite architecture - if (hparams.f_residual_scale) { - cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); - } - - // modified to support attention-free layer of Llama-3_1-Nemotron-51B - struct ggml_tensor * ffn_inp = cur; - if (n_head > 0) { - ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - } - - // feed-forward network - if (model.layers[il].ffn_gate_inp == nullptr) { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - model.layers[il].ffn_gate, model.layers[il].ffn_gate_b, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - // For Granite architecture - if (hparams.f_residual_scale) { - cur = ggml_scale(ctx0, cur, hparams.f_residual_scale); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - // For Granite architecture - if (hparams.f_logit_scale) { - cur = ggml_scale(ctx0, cur, 1.0f / hparams.f_logit_scale); - } - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_baichuan() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = model.type == LLM_TYPE_7B ? build_inp_pos() : nullptr; - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - switch (model.type) { - case LLM_TYPE_7B: - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - break; - case LLM_TYPE_13B: - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd/n_head, n_head, n_tokens); - Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd/n_head, n_head, n_tokens); - break; - default: - GGML_ABORT("fatal error"); - } - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_xverse() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, model.output_norm, NULL, LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_falcon() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * attn_norm; - - attn_norm = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(attn_norm, "attn_norm", il); - - // self-attention - { - if (model.layers[il].attn_norm_2) { - // Falcon-40B - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm_2, - model.layers[il].attn_norm_2_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm_2", il); - } else { - cur = attn_norm; - } - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", 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); - - // using mode = 2 for neox mode - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - attn_norm = ggml_get_rows(ctx0, attn_norm, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = cur; - - // feed forward - { - cur = llm_build_ffn(ctx0, lctx, attn_norm, // !! use the attn norm, not the result - model.layers[il].ffn_up, NULL, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = ggml_add(ctx0, cur, inpL); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - // norm - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_grok() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // multiply by embedding_multiplier_scale of 78.38367176906169 - inpL = ggml_scale(ctx0, inpL, 78.38367176906169f); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - // Grok - // if attn_out_norm is present then apply it before adding the input - if (model.layers[il].attn_out_norm) { - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].attn_out_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_out_norm", il); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - // MoE branch - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_GELU, true, - false, 0.0, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(cur, "ffn_moe_out", il); - - // Grok - // if layer_out_norm is present then apply it before adding the input - // Idea: maybe ffn_out_norm is a better name - if (model.layers[il].layer_out_norm) { - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].layer_out_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "layer_out_norm", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - // Grok - // multiply logits by output_multiplier_scale of 0.5773502691896257 - - cur = ggml_scale(ctx0, cur, 0.5773502691896257f); - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_dbrx() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = nullptr; - struct ggml_tensor * Kcur = nullptr; - struct ggml_tensor * Vcur = nullptr; - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_clamp(ctx0, cur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); - cb(cur, "wqkv_clamped", il); - - Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - // MoE branch - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].attn_out_norm, NULL, - LLM_NORM, cb, il); - cb(cur, "attn_out_norm", il); - - cur = llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_SILU, true, - false, 0.0, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(cur, "ffn_moe_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_starcoder() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - struct ggml_tensor * pos = ggml_get_rows(ctx0, model.pos_embd, inp_pos); - cb(pos, "pos_embd", -1); - - inpL = ggml_add(ctx0, inpL, pos); - cb(inpL, "inpL", -1); - - for (int il = 0; il < n_layer; ++il) { - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // add the input - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - // FF - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_refact() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens); - cb(Kcur, "Kcur", il); - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - cb(Qcur, "Qcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_bert() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - struct ggml_tensor * inp_pos = nullptr; - - if (model.arch != LLM_ARCH_JINA_BERT_V2) { - inp_pos = build_inp_pos(); - } - - // construct input embeddings (token, type, position) - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // token types are hardcoded to zero ("Sentence A") - struct ggml_tensor * type_row0 = ggml_view_1d(ctx0, model.type_embd, n_embd, 0); - inpL = ggml_add(ctx0, inpL, type_row0); - if (model.arch == LLM_ARCH_BERT) { - inpL = ggml_add(ctx0, ggml_get_rows(ctx0, model.pos_embd, inp_pos), inpL); - } - cb(inpL, "inp_embd", -1); - - // embed layer norm - inpL = llm_build_norm(ctx0, inpL, hparams, model.tok_norm, model.tok_norm_b, LLM_NORM, cb, -1); - cb(inpL, "inp_norm", -1); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(false); - - // iterate layers - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * cur = inpL; - - struct ggml_tensor * Qcur; - struct ggml_tensor * Kcur; - struct ggml_tensor * Vcur; - - // self-attention - if (model.arch == LLM_ARCH_BERT || model.arch == LLM_ARCH_JINA_BERT_V2) { - Qcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur), model.layers[il].bq); - cb(Qcur, "Qcur", il); - - if (model.layers[il].attn_q_norm) { - Qcur = llm_build_norm(ctx0, Qcur, hparams, - model.layers[il].attn_q_norm, - model.layers[il].attn_q_norm_b, - LLM_NORM, cb, il); - } - - Kcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur), model.layers[il].bk); - cb(Kcur, "Kcur", il); - - if (model.layers[il].attn_k_norm) { - Kcur = llm_build_norm(ctx0, Kcur, hparams, - model.layers[il].attn_k_norm, - model.layers[il].attn_k_norm_b, - LLM_NORM, cb, il); - } - Vcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur), model.layers[il].bv); - cb(Vcur, "Vcur", 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); - } else { - // compute Q and K and RoPE them - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * q = ggml_permute(ctx0, Qcur, 0, 2, 1, 3); - struct ggml_tensor * k = ggml_cont(ctx0, ggml_permute(ctx0, Kcur, 0, 2, 1, 3)); - - struct ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); - cb(kq, "kq", il); - - kq = ggml_soft_max_ext(ctx0, kq, KQ_mask, 1.0f/sqrtf(float(n_embd_head)), hparams.f_max_alibi_bias); - cb(kq, "kq_soft_max_ext", il); - - struct ggml_tensor * v = ggml_cont(ctx0, ggml_transpose(ctx0, ggml_reshape_2d(ctx0, Vcur, n_embd_gqa, n_tokens))); - cb(v, "v", il); - - struct ggml_tensor * kqv = ggml_mul_mat(ctx0, ggml_reshape_3d(ctx0, v, n_tokens, n_embd_head, n_head_kv), kq); - cb(kqv, "kqv", il); - - struct ggml_tensor * kqv_merged = ggml_permute(ctx0, kqv, 0, 2, 1, 3); - cb(kqv_merged, "kqv_merged", il); - - cur = ggml_cont_2d(ctx0, kqv_merged, n_embd_gqa, n_tokens); - cb(cur, "kqv_merged_cont", il); - - ggml_build_forward_expand(gf, cur); - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wo, cur); - if (model.layers[il].bo) { - cb(cur, "kqv_wo", il); - } - - if (model.layers[il].bo) { - cur = ggml_add(ctx0, cur, model.layers[il].bo); - } - cb(cur, "kqv_out", il); - - if (il == n_layer - 1 && pooling_type == LLAMA_POOLING_TYPE_NONE) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // re-add the layer input - cur = ggml_add(ctx0, cur, inpL); - - // attention layer norm - cur = llm_build_norm(ctx0, cur, hparams, model.layers[il].attn_out_norm, model.layers[il].attn_out_norm_b, LLM_NORM, cb, il); - - if (model.layers[il].attn_norm_2 != nullptr) { - cur = ggml_add(ctx0, cur, inpL); // re-add the layer input - cur = llm_build_norm(ctx0, cur, hparams, model.layers[il].attn_norm_2, model.layers[il].attn_norm_2_b, LLM_NORM, cb, il); - } - - struct ggml_tensor * ffn_inp = cur; - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - if (model.arch == LLM_ARCH_BERT) { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - } else if (model.arch == LLM_ARCH_JINA_BERT_V2) { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_PAR, cb, il); - } else { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - } - cb(cur, "ffn_out", il); - - // attentions bypass the intermediate layer - cur = ggml_add(ctx0, cur, ffn_inp); - - // output layer norm - cur = llm_build_norm(ctx0, cur, hparams, model.layers[il].layer_out_norm, model.layers[il].layer_out_norm_b, LLM_NORM, cb, il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cb(cur, "result_embd", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_bloom() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - inpL = llm_build_norm(ctx0, inpL, hparams, - model.tok_norm, - model.tok_norm_b, - LLM_NORM, cb, -1); - cb(inpL, "inp_norm", -1); - - for (int il = 0; il < n_layer; ++il) { - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // Add the input - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - // FF - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_mpt() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * pos; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - if (model.pos_embd) { - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - pos = ggml_get_rows(ctx0, model.pos_embd, inp_pos); - cb(pos, "pos_embd", -1); - - inpL = ggml_add(ctx0, inpL, pos); - cb(inpL, "inpL", -1); - } - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * attn_norm; - - attn_norm = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(attn_norm, "attn_norm", il); - - // self-attention - { - cur = attn_norm; - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - if (model.layers[il].bqkv){ - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - } - - if (hparams.f_clamp_kqv > 0.0f) { - cur = ggml_clamp(ctx0, cur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); - cb(cur, "wqkv_clamped", il); - } - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - // Q/K Layernorm - if (model.layers[il].attn_q_norm) { - Qcur = llm_build_norm(ctx0, Qcur, hparams, - model.layers[il].attn_q_norm, - model.layers[il].attn_q_norm_b, - LLM_NORM, cb, il); - cb(Qcur, "Qcur", il); - - Kcur = llm_build_norm(ctx0, Kcur, hparams, - model.layers[il].attn_k_norm, - model.layers[il].attn_k_norm_b, - LLM_NORM, cb, il); - cb(Kcur, "Kcur", 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); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } else { - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // Add the input - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - // feed forward - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - model.layers[il].ffn_act, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_stablelm() { - struct ggml_cgraph * gf = ggml_new_graph(ctx0); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - struct ggml_tensor * inpSA = cur; - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - cb(Qcur, "Qcur", il); - Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens); - cb(Kcur, "Kcur", il); - - if (model.layers[il].attn_q_norm) { - Qcur = llm_build_norm(ctx0, Qcur, hparams, - model.layers[il].attn_q_norm, - NULL, - LLM_NORM, cb, il); - cb(Qcur, "Qcur", il); - } - if (model.layers[il].attn_k_norm) { - Kcur = llm_build_norm(ctx0, Kcur, hparams, - model.layers[il].attn_k_norm, - NULL, - LLM_NORM, cb, il); - cb(Kcur, "Kcur", il); - } - - - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - if (model.layers[il].ffn_norm) { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - } else { - // parallel residual - cur = inpSA; - } - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_qwen() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 2*sizeof(float)*(n_embd))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", 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); - - // using mode = 2 for neox mode - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward forward - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_qwen2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_qwen2vl() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - lctx.inp_pos = ggml_new_tensor_1d(ctx0, GGML_TYPE_I32, n_tokens * 4); - cb(lctx.inp_pos, "inp_pos", -1); - ggml_set_input(lctx.inp_pos); - struct ggml_tensor * inp_pos = lctx.inp_pos; - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - int sections[4]; - std::copy(std::begin(hparams.rope_sections), std::begin(hparams.rope_sections) + 4, sections); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_multi( - ctx0, - ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, sections, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_multi( - ctx0, - ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, sections, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_qwen2moe() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self_attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // MoE branch - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - ggml_tensor * moe_out = - llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_SILU, false, - false, 0.0, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(cur, "ffn_moe_out", il); - - // FFN shared expert - { - ggml_tensor * cur_gate_inp = llm_build_lora_mm(lctx, ctx0, model.layers[il].ffn_gate_inp_shexp, cur); - cb(cur_gate_inp, "ffn_shexp_gate_inp", il); - - // sigmoid - ggml_tensor * cur_gate = ggml_div(ctx0, ggml_silu(ctx0, cur_gate_inp), cur_gate_inp); - cb(cur_gate, "ffn_shexp_gate", il); - - ggml_tensor * cur_ffn = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up_shexp, NULL, NULL, - model.layers[il].ffn_gate_shexp, NULL, NULL, - model.layers[il].ffn_down_shexp, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur_ffn, "ffn_shexp", il); - - ggml_tensor * ffn_shexp_out = ggml_mul(ctx0, cur_ffn, cur_gate); - cb(ffn_shexp_out, "ffn_shexp_out", il); - - moe_out = ggml_add(ctx0, moe_out, ffn_shexp_out); - cb(moe_out, "ffn_out", il); - - cur = moe_out; - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_phi2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * attn_norm_output; - struct ggml_tensor * ffn_output; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - attn_norm_output = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(attn_norm_output, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = nullptr; - struct ggml_tensor * Kcur = nullptr; - struct ggml_tensor * Vcur = nullptr; - - if (model.layers[il].wqkv) { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, attn_norm_output); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - } else { - Qcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, attn_norm_output), model.layers[il].bq); - Kcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, attn_norm_output), model.layers[il].bk); - Vcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, attn_norm_output), model.layers[il].bv); - } - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", 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); - - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - // with phi2, we scale the Q to avoid precision issues - // ref: https://github.com/ml-explore/mlx-examples/blob/08e862336ade809bc37d1035f94b359e7d1a5152/phi2/phi2.py#L64-L66 - Qcur = ggml_scale(ctx0, Qcur, 1.0f/sqrtf(float(n_embd_head))); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - attn_norm_output = ggml_get_rows(ctx0, attn_norm_output, inp_out_ids); - } - - // FF - { - ffn_output = llm_build_ffn(ctx0, lctx, attn_norm_output, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(ffn_output, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_output); - cur = ggml_add(ctx0, cur, inpL); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output_no_bias", -1); - - cur = ggml_add(ctx0, cur, model.output_b); - cb(cur, "result_output", -1); - ggml_build_forward_expand(gf, cur); - return gf; - } - - struct ggml_cgraph * build_phi3() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = nullptr; - if (hparams.n_swa == 0) { - // Phi-4 doesn't use sliding window attention - KQ_mask = build_inp_KQ_mask(); - } else { - KQ_mask = build_inp_KQ_mask_swa(); - } - - for (int il = 0; il < n_layer; ++il) { - auto residual = inpL; - - // self-attention - { - // rope freq factors for 128k context - struct ggml_tensor * rope_factors = build_rope_factors(il); - - struct ggml_tensor* attn_norm_output = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM_RMS, cb, il); - cb(attn_norm_output, "attn_norm", il); - - struct ggml_tensor * Qcur = nullptr; - struct ggml_tensor * Kcur = nullptr; - struct ggml_tensor * Vcur = nullptr; - - if (model.layers[il].wqkv) { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, attn_norm_output); - cb(cur, "wqkv", il); - - Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0 * sizeof(float) * (n_embd))); - Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1 * sizeof(float) * (n_embd))); - Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1 * sizeof(float) * (n_embd + n_embd_gqa))); - } else { - Qcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, attn_norm_output), model.layers[il].bq); - Kcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, attn_norm_output), model.layers[il].bk); - Vcur = ggml_add(ctx0, llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, attn_norm_output), model.layers[il].bv); - } - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", 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); - - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, rope_factors, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd_head))); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, rope_factors, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor* inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - residual = ggml_get_rows(ctx0, residual, inp_out_ids); - } - - cur = ggml_add(ctx0, cur, residual); - residual = cur; - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].ffn_norm, model.layers[il].ffn_norm_b, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - // feed-forward network - if (model.layers[il].ffn_gate_inp == nullptr) { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SWIGLU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - } else { - // MoE branch - cur = llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_SILU, true, - false, 0.0, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(cur, "ffn_moe_out", il); - } - - cur = ggml_add(ctx0, residual, cur); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - if (model.output_b != nullptr) { - cb(cur, "result_output_no_bias", -1); - cur = ggml_add(ctx0, cur, model.output_b); - } - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - - struct ggml_cgraph * build_plamo() { - struct ggml_cgraph * gf = ggml_new_graph(ctx0); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - struct ggml_tensor * attention_norm = cur; - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_rot, n_head, n_tokens), inp_pos, nullptr, - n_embd_head, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_rot, n_head_kv, n_tokens), inp_pos, nullptr, - n_embd_head, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - struct ggml_tensor * sa_out = cur; - - cur = attention_norm; - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - sa_out = ggml_get_rows(ctx0, sa_out, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // feed-forward network - { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, sa_out); - cur = ggml_add(ctx0, cur, inpL); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_gpt2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * pos; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - pos = ggml_get_rows(ctx0, model.pos_embd, inp_pos); - cb(pos, "pos_embd", -1); - - inpL = ggml_add(ctx0, inpL, pos); - cb(inpL, "inpL", -1); - - for (int il = 0; il < n_layer; ++il) { - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // add the input - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - // FF - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_codeshell() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - struct ggml_tensor * tmpq = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * tmpk = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(tmpq, "tmpq", il); - cb(tmpk, "tmpk", il); - cb(Vcur, "Vcur", il); - - struct ggml_tensor * Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, tmpq, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, tmpk, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // add the input - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - // FF - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_orion() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - // if (model.layers[il].bq) { - // Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - // cb(Qcur, "Qcur", il); - // } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - // if (model.layers[il].bk) { - // Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - // cb(Kcur, "Kcur", il); - // } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - // if (model.layers[il].bv) { - // Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - // cb(Vcur, "Vcur", il); - // } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_internlm2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_minicpm3() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - //TODO: if the model varies, these parameters need to be read from the model - const int64_t n_embd_base = 256; - const float scale_embd = 12.0f; - const float scale_depth = 1.4f; - const float kq_scale = 1.0f / sqrtf(float(hparams.n_embd_head_k)); - - const uint32_t n_embd_head_qk_rope = hparams.n_rot; - const uint32_t n_embd_head_qk_nope = hparams.n_embd_head_k - hparams.n_rot; - const uint32_t kv_lora_rank = hparams.n_lora_kv; - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // scale the input embeddings - inpL = ggml_scale(ctx0, inpL, scale_embd); - cb(inpL, "inp_scaled", -1); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - struct ggml_tensor * rope_factors = build_rope_factors(il); - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self_attention - { - struct ggml_tensor * q = NULL; - // {n_embd, q_lora_rank} * {n_embd, n_tokens} -> {q_lora_rank, n_tokens} - q = ggml_mul_mat(ctx0, model.layers[il].wq_a, cur); - cb(q, "q", il); - - q = llm_build_norm(ctx0, q, hparams, - model.layers[il].attn_q_a_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(q, "q", il); - - // {q_lora_rank, n_head * hparams.n_embd_head_k} * {q_lora_rank, n_tokens} -> {n_head * hparams.n_embd_head_k, n_tokens} - q = ggml_mul_mat(ctx0, model.layers[il].wq_b, q); - cb(q, "q", il); - - // split into {n_head * n_embd_head_qk_nope, n_tokens} - struct ggml_tensor * q_nope = ggml_view_3d(ctx0, q, n_embd_head_qk_nope, n_head, n_tokens, - ggml_row_size(q->type, hparams.n_embd_head_k), - ggml_row_size(q->type, hparams.n_embd_head_k * n_head), - 0); - cb(q_nope, "q_nope", il); - - // and {n_head * n_embd_head_qk_rope, n_tokens} - struct ggml_tensor * q_pe = ggml_view_3d(ctx0, q, n_embd_head_qk_rope, n_head, n_tokens, - ggml_row_size(q->type, hparams.n_embd_head_k), - ggml_row_size(q->type, hparams.n_embd_head_k * n_head), - ggml_row_size(q->type, n_embd_head_qk_nope)); - cb(q_pe, "q_pe", il); - - // {n_embd, kv_lora_rank + n_embd_head_qk_rope} * {n_embd, n_tokens} -> {kv_lora_rank + n_embd_head_qk_rope, n_tokens} - struct ggml_tensor * kv_pe_compresseed = ggml_mul_mat(ctx0, model.layers[il].wkv_a_mqa, cur); - cb(kv_pe_compresseed, "kv_pe_compresseed", il); - - // split into {kv_lora_rank, n_tokens} - struct ggml_tensor * kv_compressed = ggml_view_2d(ctx0, kv_pe_compresseed, kv_lora_rank, n_tokens, - kv_pe_compresseed->nb[1], - 0); - cb(kv_compressed, "kv_compressed", il); - - // and {n_embd_head_qk_rope, n_tokens} - struct ggml_tensor * k_pe = ggml_view_3d(ctx0, kv_pe_compresseed, n_embd_head_qk_rope, 1, n_tokens, - kv_pe_compresseed->nb[1], - kv_pe_compresseed->nb[1], - ggml_row_size(kv_pe_compresseed->type, kv_lora_rank)); - cb(k_pe, "k_pe", il); - - // TODO: the CUDA backend used to not support non-cont. (RMS) norm, investigate removing ggml_cont - kv_compressed = ggml_cont(ctx0, kv_compressed); - kv_compressed = llm_build_norm(ctx0, kv_compressed, hparams, - model.layers[il].attn_kv_a_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(kv_compressed, "kv_compressed", il); - - // {kv_lora_rank, n_head * (n_embd_head_qk_nope + n_embd_head_v)} * {kv_lora_rank, n_tokens} -> {n_head * (n_embd_head_qk_nope + n_embd_head_v), n_tokens} - struct ggml_tensor * kv = ggml_mul_mat(ctx0, model.layers[il].wkv_b, kv_compressed); - cb(kv, "kv", il); - - // split into {n_head * n_embd_head_qk_nope, n_tokens} - struct ggml_tensor * k_nope = ggml_view_3d(ctx0, kv, n_embd_head_qk_nope, n_head, n_tokens, - ggml_row_size(kv->type, n_embd_head_qk_nope + hparams.n_embd_head_v), - ggml_row_size(kv->type, n_head * (n_embd_head_qk_nope + hparams.n_embd_head_v)), - 0); - cb(k_nope, "k_nope", il); - - // and {n_head * n_embd_head_v, n_tokens} - struct ggml_tensor * v_states = ggml_view_3d(ctx0, kv, hparams.n_embd_head_v, n_head, n_tokens, - ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)), - ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)*n_head), - ggml_row_size(kv->type, (n_embd_head_qk_nope))); - cb(v_states, "v_states", il); - - v_states = ggml_cont(ctx0, v_states); - cb(v_states, "v_states", il); - - v_states = ggml_view_2d(ctx0, v_states, hparams.n_embd_head_v * n_head, n_tokens, - ggml_row_size(kv->type, hparams.n_embd_head_v * n_head), - 0); - cb(v_states, "v_states", il); - - q_pe = ggml_cont(ctx0, q_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this - q_pe = ggml_rope_ext( - ctx0, q_pe, inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(q_pe, "q_pe", il); - - // shared RoPE key - k_pe = ggml_cont(ctx0, k_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this - k_pe = ggml_rope_ext( - ctx0, k_pe, inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(k_pe, "k_pe", il); - - struct ggml_tensor * q_states = ggml_concat(ctx0, q_nope, q_pe, 0); - cb(q_states, "q_states", il); - - struct ggml_tensor * k_states = ggml_concat(ctx0, k_nope, ggml_repeat(ctx0, k_pe, q_pe), 0); - cb(k_states, "k_states", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - k_states, v_states, q_states, KQ_mask, n_tokens, kv_head, n_kv, kq_scale, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - // scale_res - scale the hidden states for residual connection - const float scale_res = scale_depth/sqrtf(float(n_layer)); - cur = ggml_scale(ctx0, cur, scale_res); - cb(cur, "hidden_scaled", il); - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - // scale the hidden states for residual connection - cur = ggml_scale(ctx0, cur, scale_res); - cb(cur, "hidden_scaled_ffn", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head scaling - const float scale_lmhead = float(n_embd_base)/float(n_embd); - cur = ggml_scale(ctx0, cur, scale_lmhead); - cb(cur, "lmhead_scaling", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_gemma() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head_k = hparams.n_embd_head_k; - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - inpL = ggml_scale(ctx0, inpL, sqrtf(n_embd)); - cb(inpL, "inp_scaled", -1); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head_k, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Qcur, "Qcur", il); - - Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd_head_k))); - cb(Qcur, "Qcur_scaled", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - struct ggml_tensor * sa_out = ggml_add(ctx0, cur, inpL); - cb(sa_out, "sa_out", il); - - cur = llm_build_norm(ctx0, sa_out, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - // feed-forward network - { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, sa_out); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_gemma2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head_k = hparams.n_embd_head_k; - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - inpL = ggml_scale(ctx0, inpL, sqrtf(n_embd)); - cb(inpL, "inp_scaled", -1); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - // gemma 2 requires different mask for layers using sliding window (SWA) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(true); - struct ggml_tensor * KQ_mask_swa = build_inp_KQ_mask_swa(true); - - for (int il = 0; il < n_layer; ++il) { - // (il % 2) layers use SWA - struct ggml_tensor * KQ_mask_l = (il % 2 == 0) ? KQ_mask_swa : KQ_mask; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head_k, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Qcur, "Qcur", il); - - // ref: https://github.com/google/gemma_pytorch/commit/03e657582d17cb5a8617ebf333c1c16f3694670e - switch (model.type) { - case LLM_TYPE_2B: - case LLM_TYPE_9B: Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd_head_k))); break; - case LLM_TYPE_27B: Qcur = ggml_scale(ctx0, Qcur, 1.0f / sqrtf(float(n_embd / n_head))); break; - default: GGML_ABORT("fatal error"); - }; - cb(Qcur, "Qcur_scaled", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask_l, n_tokens, kv_head, n_kv, 1.0f, cb, il); - } - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].attn_post_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_post_norm", il); - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - struct ggml_tensor * sa_out = ggml_add(ctx0, cur, inpL); - cb(sa_out, "sa_out", il); - - cur = llm_build_norm(ctx0, sa_out, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - // feed-forward network - { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].ffn_post_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "ffn_post_norm", -1); - - cur = ggml_add(ctx0, cur, sa_out); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - // final logit soft-capping - cur = ggml_scale(ctx0, cur, 1.0f / hparams.f_final_logit_softcapping); - cur = ggml_tanh(ctx0, cur); - cur = ggml_scale(ctx0, cur, hparams.f_final_logit_softcapping); - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_gemma3() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head_k = hparams.n_embd_head_k; - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // important: do not normalize weights for raw embeddings input (i.e. encoded image emdeddings) - if (ubatch.token) { - inpL = ggml_scale(ctx0, inpL, sqrtf(n_embd)); - cb(inpL, "inp_scaled", -1); - } - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - // gemma3 requires different mask for layers using sliding window (SWA) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(true); - struct ggml_tensor * KQ_mask_swa = build_inp_KQ_mask_swa(true); - - // "5-to-1 interleaved attention" - // 5 layers of local attention followed by 1 layer of global attention - static const int sliding_window_pattern = 6; - - for (int il = 0; il < n_layer; ++il) { - const bool is_sliding = (il + 1) % sliding_window_pattern; - const float freq_base_l = is_sliding ? 10000.0f : freq_base; - const float freq_scale_l = is_sliding ? 1.0f : freq_scale; - struct ggml_tensor * KQ_mask_l = is_sliding ? KQ_mask_swa : KQ_mask; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head_k, n_head, n_tokens); - Qcur = llm_build_norm(ctx0, Qcur, hparams, - model.layers[il].attn_q_norm, - NULL, - LLM_NORM_RMS, cb, il); - cb(Qcur, "Qcur_normed", il); - - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Qcur, "Qcur", il); - - Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_kv, n_tokens); - Kcur = llm_build_norm(ctx0, Kcur, hparams, - model.layers[il].attn_k_norm, - NULL, - LLM_NORM_RMS, cb, il); - cb(Kcur, "Kcur_normed", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, - ext_factor, attn_factor, beta_fast, beta_slow); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask_l, n_tokens, kv_head, n_kv, hparams.f_attention_scale, cb, il); - } - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].attn_post_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_post_norm", il); - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - struct ggml_tensor * sa_out = ggml_add(ctx0, cur, inpL); - cb(sa_out, "sa_out", il); - - cur = llm_build_norm(ctx0, sa_out, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - // feed-forward network - { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].ffn_post_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "ffn_post_norm", -1); - - cur = ggml_add(ctx0, cur, sa_out); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_starcoder2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_mamba() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - // {n_embd, n_tokens} - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - struct ggml_tensor * state_copy = build_inp_s_copy(); - struct ggml_tensor * state_mask = build_inp_s_mask(); - - for (int il = 0; il < n_layer; ++il) { - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - cur = llm_build_mamba(ctx0, lctx, ubatch, gf, cur, - state_copy, state_mask, - kv_head, n_kv, cb, il); - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // residual - cur = ggml_add(ctx0, cur, inpL); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - // final rmsnorm - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_command_r() { - - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - const float f_logit_scale = hparams.f_logit_scale; - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - struct ggml_tensor * ffn_inp = cur; - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - if (model.layers[il].attn_q_norm) { - Qcur = ggml_view_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens, - ggml_element_size(Qcur) * n_embd_head, - ggml_element_size(Qcur) * n_embd_head * n_head, - 0); - cb(Qcur, "Qcur", il); - Kcur = ggml_view_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens, - ggml_element_size(Kcur) * n_embd_head, - ggml_element_size(Kcur) * n_embd_head * n_head_kv, - 0); - cb(Kcur, "Kcur", il); - - Qcur = llm_build_norm(ctx0, Qcur, hparams, - model.layers[il].attn_q_norm, - NULL, - LLM_NORM, cb, il); - cb(Qcur, "Qcur", il); - - Kcur = llm_build_norm(ctx0, Kcur, hparams, - model.layers[il].attn_k_norm, - NULL, - LLM_NORM, cb, il); - cb(Kcur, "Kcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - ffn_inp = ggml_get_rows(ctx0, ffn_inp, inp_out_ids); - } - - struct ggml_tensor * attn_out = cur; - - // feed-forward network - { - cur = llm_build_ffn(ctx0, lctx, ffn_inp, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - // add together residual + FFN + self-attention - cur = ggml_add(ctx0, cur, inpL); - cur = ggml_add(ctx0, cur, attn_out); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - if (f_logit_scale) { - cur = ggml_scale(ctx0, cur, f_logit_scale); - } - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - - } - - struct ggml_cgraph * build_cohere2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - const float f_logit_scale = hparams.f_logit_scale; - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - // cohere2 requires different mask for layers using sliding window (SWA) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - struct ggml_tensor * KQ_mask_swa = build_inp_KQ_mask_swa(); - - // sliding window switch pattern - const int32_t sliding_window_pattern = 4; - - for (int il = 0; il < n_layer; ++il) { - // three layers sliding window attention (window size 4096) and ROPE - // fourth layer uses global attention without positional embeddings - const bool is_sliding = il % sliding_window_pattern < (sliding_window_pattern - 1); - struct ggml_tensor * KQ_mask_l = is_sliding ? KQ_mask_swa : KQ_mask; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, model.layers[il].attn_norm, NULL, LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - struct ggml_tensor * ffn_inp = cur; - - // self-attention - { - // rope freq factors for 128k context - struct ggml_tensor * rope_factors = build_rope_factors(il); - - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - if (is_sliding) { - Qcur = ggml_rope_ext(ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, ext_factor, attn_factor, - beta_fast, beta_slow); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext(ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, - rope_factors, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, ext_factor, - attn_factor, beta_fast, beta_slow); - cb(Kcur, "Kcur", il); - } else { - // For non-sliding layers, just reshape without applying RoPE - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - cb(Qcur, "Qcur", il); - - Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens); - cb(Kcur, "Kcur", il); - } - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, model.layers[il].wo, model.layers[il].bo, Kcur, Vcur, Qcur, - KQ_mask_l, n_tokens, kv_head, n_kv, 1.0f / sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - ffn_inp = ggml_get_rows(ctx0, ffn_inp, inp_out_ids); - } - - struct ggml_tensor * attn_out = cur; - - // feed-forward network - { - cur = llm_build_ffn(ctx0, lctx, ffn_inp, model.layers[il].ffn_up, NULL, NULL, model.layers[il].ffn_gate, - NULL, NULL, model.layers[il].ffn_down, NULL, NULL, NULL, LLM_FFN_SILU, LLM_FFN_PAR, - cb, il); - cb(cur, "ffn_out", il); - } - - // add together residual + FFN + self-attention - cur = ggml_add(ctx0, cur, inpL); - cur = ggml_add(ctx0, cur, attn_out); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, model.output_norm, NULL, LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - if (f_logit_scale) { - cur = ggml_scale(ctx0, cur, f_logit_scale); - } - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - // ref: https://allenai.org/olmo - // based on the original build_llama() function, changes: - // * non-parametric layer norm - // * clamp qkv - // * removed bias - // * removed MoE - struct ggml_cgraph * build_olmo() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - NULL, NULL, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (hparams.f_clamp_kqv > 0.0f) { - Qcur = ggml_clamp(ctx0, Qcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (hparams.f_clamp_kqv > 0.0f) { - Kcur = ggml_clamp(ctx0, Kcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (hparams.f_clamp_kqv > 0.0f) { - Vcur = ggml_clamp(ctx0, Vcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, nullptr, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - NULL, NULL, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - NULL, NULL, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_olmo2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - cur = inpL; - - // self_attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = llm_build_norm(ctx0, Qcur, hparams, model.layers[il].attn_q_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(Qcur, "Qcur_normed", il); - - Kcur = llm_build_norm(ctx0, Kcur, hparams, model.layers[il].attn_k_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(Kcur, "Kcur_normed", 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); - - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur_rope", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur_rope", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].attn_post_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_post_norm", il); - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_ffn(ctx0, lctx, ffn_inp, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].ffn_post_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "ffn_post_norm", -1); - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - // based on the build_qwen2moe() function, changes: - // * removed shared experts - // * removed bias - // * added q, k norm - struct ggml_cgraph * build_olmoe() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self_attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = llm_build_norm(ctx0, Qcur, hparams, model.layers[il].attn_q_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(Qcur, "Qcur_normed", il); - - Kcur = llm_build_norm(ctx0, Kcur, hparams, model.layers[il].attn_k_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(Kcur, "Kcur_normed", 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); - - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur_rope", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur_rope", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // MoE branch - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_SILU, false, - false, 0.0, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(cur, "ffn_moe_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_openelm() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - const int64_t n_head = hparams.n_head(il); - const int64_t n_head_kv = hparams.n_head_kv(il); - const int64_t n_head_qkv = 2*n_head_kv + n_head; - - cur = inpL; - struct ggml_tensor * residual = cur; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_reshape_3d(ctx0, cur, n_embd_head_k, n_head_qkv, n_tokens); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_3d(ctx0, cur, n_embd_head, n_head, n_tokens, cur->nb[1], cur->nb[2], 0)); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_3d(ctx0, cur, n_embd_head, n_head_kv, n_tokens, cur->nb[1], cur->nb[2], cur->nb[1]*n_head)); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_3d(ctx0, cur, n_embd_head, n_head_kv, n_tokens, cur->nb[1], cur->nb[2], cur->nb[1]*(n_head+n_head_kv))); - cb(Vcur, "Vcur", il); - - Qcur = llm_build_norm(ctx0, Qcur, hparams, - model.layers[il].attn_q_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(Qcur, "Qcur", il); - - Kcur = llm_build_norm(ctx0, Kcur, hparams, - model.layers[il].attn_k_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(Kcur, "Kcur", il); - - Qcur = ggml_rope_ext( - ctx0, Qcur, inp_pos, NULL, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, Kcur, inp_pos, NULL, n_rot, rope_type, n_ctx_orig, - freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - Vcur = ggml_reshape_2d(ctx0, Vcur, n_embd_head * n_head_kv, n_tokens); - cb(Qcur, "Vcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - residual = ggml_get_rows(ctx0, residual, inp_out_ids); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, residual, cur); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - inpL = cur; - } - - cur = inpL; - - // norm - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_gptneox() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // ffn - if (hparams.use_par_res) { - // attention and ffn are computed in parallel - // x = x + attn(ln1(x)) + ffn(ln2(x)) - - struct ggml_tensor * attn_out = cur; - - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, inpL); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, attn_out); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } else { - // attention and ffn are computed sequentially - // x = x + attn(ln1(x)) - // x = x + ffn(ln2(x)) - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_arctic() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - struct ggml_tensor * ffn_out = ggml_add(ctx0, cur, ffn_inp); - cb(ffn_out, "ffn_out", il); - - // MoE - cur = llm_build_norm(ctx0, inpSA, hparams, - model.layers[il].ffn_norm_exps, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm_exps", il); - - cur = llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_SILU, true, - false, 0.0, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(cur, "ffn_moe_out", il); - - cur = ggml_add(ctx0, cur, ffn_out); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_deepseek() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale; - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // rope freq factors for llama3; may return nullptr for llama2 and other models - struct ggml_tensor * rope_factors = build_rope_factors(il); - - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, kq_scale, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - if ((uint32_t) il < hparams.n_layer_dense_lead) { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } else { - // MoE branch - ggml_tensor * moe_out = - llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - nullptr, - n_expert, n_expert_used, - LLM_FFN_SILU, false, - false, hparams.expert_weights_scale, - LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX, - cb, il); - cb(moe_out, "ffn_moe_out", il); - - // FFN shared expert - { - ggml_tensor * ffn_shexp = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up_shexp, NULL, NULL, - model.layers[il].ffn_gate_shexp, NULL, NULL, - model.layers[il].ffn_down_shexp, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(ffn_shexp, "ffn_shexp", il); - - cur = ggml_add(ctx0, moe_out, ffn_shexp); - cb(cur, "ffn_out", il); - } - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_deepseek2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - bool is_lite = (hparams.n_layer == 27); - - // We have to pre-scale kq_scale and attn_factor to make the YaRN RoPE work correctly. - // See https://github.com/ggerganov/llama.cpp/discussions/7416 for detailed explanation. - const float mscale = attn_factor * (1.0f + hparams.rope_yarn_log_mul * logf(1.0f / freq_scale)); - const float kq_scale = 1.0f*mscale*mscale/sqrtf(float(hparams.n_embd_head_k)); - const float attn_factor_scaled = 1.0f / (1.0f + 0.1f * logf(1.0f / freq_scale)); - - const uint32_t n_embd_head_qk_rope = hparams.n_rot; - const uint32_t n_embd_head_qk_nope = hparams.n_embd_head_k - hparams.n_rot; - const uint32_t kv_lora_rank = hparams.n_lora_kv; - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - // {n_embd, n_tokens} - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self_attention - { - struct ggml_tensor * q = NULL; - if (!is_lite) { - // {n_embd, q_lora_rank} * {n_embd, n_tokens} -> {q_lora_rank, n_tokens} - q = ggml_mul_mat(ctx0, model.layers[il].wq_a, cur); - cb(q, "q", il); - - q = llm_build_norm(ctx0, q, hparams, - model.layers[il].attn_q_a_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(q, "q", il); - - // {q_lora_rank, n_head * hparams.n_embd_head_k} * {q_lora_rank, n_tokens} -> {n_head * hparams.n_embd_head_k, n_tokens} - q = ggml_mul_mat(ctx0, model.layers[il].wq_b, q); - cb(q, "q", il); - } else { - q = ggml_mul_mat(ctx0, model.layers[il].wq, cur); - cb(q, "q", il); - } - - // split into {n_head * n_embd_head_qk_nope, n_tokens} - struct ggml_tensor * q_nope = ggml_view_3d(ctx0, q, n_embd_head_qk_nope, n_head, n_tokens, - ggml_row_size(q->type, hparams.n_embd_head_k), - ggml_row_size(q->type, hparams.n_embd_head_k * n_head), - 0); - cb(q_nope, "q_nope", il); - - // and {n_head * n_embd_head_qk_rope, n_tokens} - struct ggml_tensor * q_pe = ggml_view_3d(ctx0, q, n_embd_head_qk_rope, n_head, n_tokens, - ggml_row_size(q->type, hparams.n_embd_head_k), - ggml_row_size(q->type, hparams.n_embd_head_k * n_head), - ggml_row_size(q->type, n_embd_head_qk_nope)); - cb(q_pe, "q_pe", il); - - // {n_embd, kv_lora_rank + n_embd_head_qk_rope} * {n_embd, n_tokens} -> {kv_lora_rank + n_embd_head_qk_rope, n_tokens} - struct ggml_tensor * kv_pe_compresseed = ggml_mul_mat(ctx0, model.layers[il].wkv_a_mqa, cur); - cb(kv_pe_compresseed, "kv_pe_compresseed", il); - - // split into {kv_lora_rank, n_tokens} - struct ggml_tensor * kv_compressed = ggml_view_2d(ctx0, kv_pe_compresseed, kv_lora_rank, n_tokens, - kv_pe_compresseed->nb[1], - 0); - cb(kv_compressed, "kv_compressed", il); - - // and {n_embd_head_qk_rope, n_tokens} - struct ggml_tensor * k_pe = ggml_view_3d(ctx0, kv_pe_compresseed, n_embd_head_qk_rope, 1, n_tokens, - kv_pe_compresseed->nb[1], - kv_pe_compresseed->nb[1], - ggml_row_size(kv_pe_compresseed->type, kv_lora_rank)); - cb(k_pe, "k_pe", il); - - // TODO: the CUDA backend used to not support non-cont. (RMS) norm, investigate removing ggml_cont - kv_compressed = ggml_cont(ctx0, kv_compressed); - kv_compressed = llm_build_norm(ctx0, kv_compressed, hparams, - model.layers[il].attn_kv_a_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(kv_compressed, "kv_compressed", il); - - // {kv_lora_rank, n_head * (n_embd_head_qk_nope + n_embd_head_v)} * {kv_lora_rank, n_tokens} -> {n_head * (n_embd_head_qk_nope + n_embd_head_v), n_tokens} - struct ggml_tensor * kv = ggml_mul_mat(ctx0, model.layers[il].wkv_b, kv_compressed); - cb(kv, "kv", il); - - // split into {n_head * n_embd_head_qk_nope, n_tokens} - struct ggml_tensor * k_nope = ggml_view_3d(ctx0, kv, n_embd_head_qk_nope, n_head, n_tokens, - ggml_row_size(kv->type, n_embd_head_qk_nope + hparams.n_embd_head_v), - ggml_row_size(kv->type, n_head * (n_embd_head_qk_nope + hparams.n_embd_head_v)), - 0); - cb(k_nope, "k_nope", il); - - // and {n_head * n_embd_head_v, n_tokens} - struct ggml_tensor * v_states = ggml_view_3d(ctx0, kv, hparams.n_embd_head_v, n_head, n_tokens, - ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)), - ggml_row_size(kv->type, (n_embd_head_qk_nope + hparams.n_embd_head_v)*n_head), - ggml_row_size(kv->type, (n_embd_head_qk_nope))); - cb(v_states, "v_states", il); - - v_states = ggml_cont(ctx0, v_states); - cb(v_states, "v_states", il); - - v_states = ggml_view_2d(ctx0, v_states, hparams.n_embd_head_v * n_head, n_tokens, - ggml_row_size(kv->type, hparams.n_embd_head_v * n_head), - 0); - cb(v_states, "v_states", il); - - q_pe = ggml_cont(ctx0, q_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this - q_pe = ggml_rope_ext( - ctx0, q_pe, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor_scaled, beta_fast, beta_slow - ); - cb(q_pe, "q_pe", il); - - // shared RoPE key - k_pe = ggml_cont(ctx0, k_pe); // TODO: the CUDA backend used to not support non-cont. RoPE, investigate removing this - k_pe = ggml_rope_ext( - ctx0, k_pe, inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor_scaled, beta_fast, beta_slow - ); - cb(k_pe, "k_pe", il); - - struct ggml_tensor * q_states = ggml_concat(ctx0, q_nope, q_pe, 0); - cb(q_states, "q_states", il); - - struct ggml_tensor * k_states = ggml_concat(ctx0, k_nope, ggml_repeat(ctx0, k_pe, q_pe), 0); - cb(k_states, "k_states", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - k_states, v_states, q_states, KQ_mask, n_tokens, kv_head, n_kv, kq_scale, cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - if ((uint32_t) il < hparams.n_layer_dense_lead) { - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } else { - // MoE branch - ggml_tensor * moe_out = - llm_build_moe_ffn(ctx0, lctx, cur, - model.layers[il].ffn_gate_inp, - model.layers[il].ffn_up_exps, - model.layers[il].ffn_gate_exps, - model.layers[il].ffn_down_exps, - model.layers[il].ffn_exp_probs_b, - n_expert, n_expert_used, - LLM_FFN_SILU, hparams.expert_weights_norm, - true, hparams.expert_weights_scale, - (enum llama_expert_gating_func_type) hparams.expert_gating_func, - cb, il); - cb(moe_out, "ffn_moe_out", il); - - // FFN shared expert - { - ggml_tensor * ffn_shexp = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up_shexp, NULL, NULL, - model.layers[il].ffn_gate_shexp, NULL, NULL, - model.layers[il].ffn_down_shexp, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(ffn_shexp, "ffn_shexp", il); - - cur = ggml_add(ctx0, moe_out, ffn_shexp); - cb(cur, "ffn_out", il); - } - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = ggml_mul_mat(ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_bitnet() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - if (model.layers[il].wq_scale) { - Qcur = ggml_mul(ctx0, Qcur, model.layers[il].wq_scale); - } - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - // B1.K - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - if (model.layers[il].wk_scale) { - Kcur = ggml_mul(ctx0, Kcur, model.layers[il].wk_scale); - } - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - // B1.V - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - if (model.layers[il].wv_scale) { - Vcur = ggml_mul(ctx0, Vcur, model.layers[il].wv_scale); - } - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - NULL, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].attn_sub_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_sub_norm", il); - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wo, cur); - if (model.layers[il].wo_scale) { - cur = ggml_mul(ctx0, cur, model.layers[il].wo_scale); - } - if (model.layers[il].bo) { - cur = ggml_add(ctx0, cur, model.layers[il].bo); - } - cb(cur, "attn_o_out", il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward forward - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, model.layers[il].ffn_up_scale, - model.layers[il].ffn_gate, NULL, model.layers[il].ffn_gate_scale, - NULL, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_sub_out", il); - - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].ffn_sub_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_sub_norm", il); - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].ffn_down, cur); - if (model.layers[il].ffn_down_scale) { - cur = ggml_mul(ctx0, cur, model.layers[il].ffn_down_scale); - } - cb(cur, "ffn_down", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - // FIXME: do not use model.tok_embd directly, duplicate as model.output - cur = llm_build_lora_mm(lctx, ctx0, model.tok_embd, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - return gf; - } - - struct ggml_cgraph * build_t5_enc() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - GGML_ASSERT(lctx.is_encoding); - struct ggml_tensor * pos_bucket_enc = llm_build_pos_bucket(false); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask_enc = build_inp_KQ_mask(false); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm_enc, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq_enc, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk_enc, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv_enc, cur); - cb(Vcur, "Vcur", 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); - - struct ggml_tensor * q = ggml_permute(ctx0, Qcur, 0, 2, 1, 3); - struct ggml_tensor * k = ggml_cont(ctx0, ggml_permute(ctx0, Kcur, 0, 2, 1, 3)); - - struct ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); - cb(kq, "kq", il); - - struct ggml_tensor * attn_rel_b = model.layers[il].attn_rel_b_enc ? model.layers[il].attn_rel_b_enc : model.layers[0].attn_rel_b_enc; - struct ggml_tensor * pos_bias = llm_build_pos_bias(pos_bucket_enc, attn_rel_b); - struct ggml_tensor * kq_b = ggml_add(ctx0, kq, pos_bias); - cb(kq_b, "kq_b", il); - - kq = ggml_soft_max_ext(ctx0, kq_b, KQ_mask_enc, 1.0f, hparams.f_max_alibi_bias); - cb(kq, "kq_soft_max_ext", il); - - struct ggml_tensor * v = ggml_cont(ctx0, ggml_transpose(ctx0, ggml_reshape_2d(ctx0, Vcur, n_embd_gqa, n_tokens))); - cb(v, "v", il); - - struct ggml_tensor * kqv = ggml_mul_mat(ctx0, ggml_reshape_3d(ctx0, v, n_tokens, n_embd_head, n_head_kv), kq); - cb(kqv, "kqv", il); - - struct ggml_tensor * kqv_merged = ggml_permute(ctx0, kqv, 0, 2, 1, 3); - cb(kqv_merged, "kqv_merged", il); - - cur = ggml_cont_2d(ctx0, kqv_merged, n_embd_gqa, n_tokens); - cb(cur, "kqv_merged_cont", il); - - ggml_build_forward_expand(gf, cur); - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wo_enc, cur); - cb(cur, "kqv_out", il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm_enc, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - // T5 uses relu, flan-T5 uses gelu-gated - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up_enc, NULL, NULL, - model.layers[il].ffn_gate_enc, NULL, NULL, - model.layers[il].ffn_down_enc, NULL, NULL, - NULL, - model.layers[il].ffn_gate_enc ? LLM_FFN_GELU : LLM_FFN_RELU, - model.layers[il].ffn_gate_enc ? LLM_FFN_PAR : LLM_FFN_SEQ, - cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - ggml_tensor * layer_dir = lctx.cvec.tensor_for(il); - if (layer_dir != nullptr) { - cur = ggml_add(ctx0, cur, layer_dir); - } - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - cb(cur, "result_embd", -1); - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm_enc, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_t5_dec() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - GGML_ASSERT(!lctx.is_encoding); - GGML_ASSERT(n_outputs_enc > 0 && "call llama_encode() first"); - - struct ggml_tensor * embd_enc = llm_build_inp_embd_enc(); - struct ggml_tensor * pos_bucket_dec = llm_build_pos_bucket(true); - - struct ggml_tensor * KQ_mask_dec = build_inp_KQ_mask(); - struct ggml_tensor * KQ_mask_cross = llm_build_inp_KQ_mask_cross(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - llm_build_kv_store(ctx0, hparams, cparams, kv_self, gf, Kcur, Vcur, n_tokens, kv_head, cb, il); - - struct ggml_tensor * k = - ggml_view_3d(ctx0, kv_self.k_l[il], - n_embd_head_k, n_kv, n_head_kv, - ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa), - ggml_row_size(kv_self.k_l[il]->type, n_embd_head_k), - 0); - cb(k, "k", il); - - struct ggml_tensor * v = - ggml_view_3d(ctx0, kv_self.v_l[il], - n_kv, n_embd_head_v, n_head_kv, - ggml_element_size(kv_self.v_l[il])*n_ctx, - ggml_element_size(kv_self.v_l[il])*n_ctx*n_embd_head_v, - 0); - cb(v, "v", il); - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - - struct ggml_tensor * q = ggml_permute(ctx0, Qcur, 0, 2, 1, 3); - - struct ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); - cb(kq, "kq", il); - - struct ggml_tensor * attn_rel_b = model.layers[il].attn_rel_b ? model.layers[il].attn_rel_b : model.layers[0].attn_rel_b; - struct ggml_tensor * pos_bias = llm_build_pos_bias(pos_bucket_dec, attn_rel_b); - struct ggml_tensor * kq_b = ggml_add(ctx0, kq, pos_bias); - cb(kq_b, "kq_b", il); - - kq = ggml_soft_max_ext(ctx0, kq_b, KQ_mask_dec, 1.0f, hparams.f_max_alibi_bias); - cb(kq, "kq_soft_max_ext", il); - - struct ggml_tensor * kqv = ggml_mul_mat(ctx0, v, kq); - cb(kqv, "kqv", il); - - struct ggml_tensor * kqv_merged = ggml_permute(ctx0, kqv, 0, 2, 1, 3); - cb(kqv_merged, "kqv_merged", il); - - cur = ggml_cont_2d(ctx0, kqv_merged, n_embd_gqa, n_tokens); - cb(cur, "kqv_merged_cont", il); - - ggml_build_forward_expand(gf, cur); - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wo, cur); - cb(cur, "kqv_out", il); - } - - cur = ggml_add(ctx0, cur, inpSA); - cb(cur, "cross_inp", il); - - struct ggml_tensor * inpCA = cur; - - // norm - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].attn_norm_cross, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm_cross", il); - - // cross-attention - { - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq_cross, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk_cross, embd_enc); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv_cross, embd_enc); - cb(Vcur, "Vcur", 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_outputs_enc); - - struct ggml_tensor * q = ggml_permute(ctx0, Qcur, 0, 2, 1, 3); - struct ggml_tensor * k = ggml_cont(ctx0, ggml_permute(ctx0, Kcur, 0, 2, 1, 3)); - - struct ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); - cb(kq, "kq", il); - - kq = ggml_soft_max_ext(ctx0, kq, KQ_mask_cross, 1.0f, hparams.f_max_alibi_bias); - cb(kq, "kq_soft_max_ext", il); - - struct ggml_tensor * v = ggml_cont(ctx0, ggml_transpose(ctx0, ggml_reshape_2d(ctx0, Vcur, n_embd_gqa, n_outputs_enc))); - cb(v, "v", il); - - struct ggml_tensor * kqv = ggml_mul_mat(ctx0, ggml_reshape_3d(ctx0, v, n_outputs_enc, n_embd_head, n_head_kv), kq); - cb(kqv, "kqv", il); - - struct ggml_tensor * kqv_merged = ggml_permute(ctx0, kqv, 0, 2, 1, 3); - cb(kqv_merged, "kqv_merged", il); - - cur = ggml_cont_2d(ctx0, kqv_merged, n_embd_gqa, n_tokens); - cb(cur, "kqv_merged_cont", il); - - ggml_build_forward_expand(gf, cur); - - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wo_cross, cur); - cb(cur, "kqv_out", il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - inpCA = ggml_get_rows(ctx0, inpCA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpCA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - // T5 uses relu, flan-T5 uses gelu-gated - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - model.layers[il].ffn_gate_enc ? LLM_FFN_GELU : LLM_FFN_RELU, - model.layers[il].ffn_gate_enc ? LLM_FFN_PAR : LLM_FFN_SEQ, - cb, il); - cb(cur, "ffn_out", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - ggml_tensor * layer_dir = lctx.cvec.tensor_for(il); - if (layer_dir != nullptr) { - cur = ggml_add(ctx0, cur, layer_dir); - } - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - cb(cur, "result_embd", -1); - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_jais() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - - struct ggml_tensor * Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*cur->nb[0]*(n_embd))); - struct ggml_tensor * Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*cur->nb[0]*(n_embd))); - struct ggml_tensor * Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*cur->nb[0]*(n_embd + n_embd_gqa))); - - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - - Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/float(n_embd_head), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpL = ggml_get_rows(ctx0, inpL, inp_out_ids); - } - - // add the input - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpL); - cb(ffn_inp, "ffn_inp", il); - - // FF - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - model.layers[il].ffn_gate, model.layers[il].ffn_gate_b, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - } - - inpL = ggml_add(ctx0, cur, ffn_inp); - cb(inpL, "l_out", il); - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_chatglm() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - const int64_t n_embd_gqa = hparams.n_embd_v_gqa(); - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - struct ggml_tensor * Qcur = nullptr; - struct ggml_tensor * Kcur = nullptr; - struct ggml_tensor * Vcur = nullptr; - if (model.layers[il].wqkv == nullptr) { - Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - } - Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - } - Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - } - } else { - cur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wqkv, cur); - cb(cur, "wqkv", il); - if (model.layers[il].bqkv) { - cur = ggml_add(ctx0, cur, model.layers[il].bqkv); - cb(cur, "bqkv", il); - } - Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd, n_tokens, cur->nb[1], 0*sizeof(float)*(n_embd))); - Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd))); - Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, cur, n_embd_gqa, n_tokens, cur->nb[1], 1*sizeof(float)*(n_embd + n_embd_gqa))); - } - cb(Qcur, "Qcur", il); - cb(Kcur, "Kcur", il); - cb(Vcur, "Vcur", il); - //printf("freq_base: %f freq_scale: %f ext_factor: %f attn_factor: %f\n", freq_base, freq_scale, ext_factor, attn_factor); - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur_rope", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur_rope", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, NULL, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - // Add the input - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // FF - { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SWIGLU, LLM_FFN_SEQ, cb, il); - cb(cur, "ffn_out", il); - - } - - inpL = ggml_add(ctx0, cur, ffn_inp); - cb(inpL, "l_out", il); - } - - cur = llm_build_norm(ctx0, inpL, hparams, - model.output_norm, - NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_nemotron() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - //GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, - model.layers[il].attn_norm_b, - LLM_NORM, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, - model.layers[il].ffn_norm_b, - LLM_NORM, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL, - NULL, NULL, NULL, - model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL, - NULL, - LLM_FFN_RELU_SQR, LLM_FFN_SEQ, cb, il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, model.output_norm_b, - LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_exaone() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - - // self-attention - { - // rope freq factors for llama3; may return nullptr for llama2 and other models - struct ggml_tensor * rope_factors = build_rope_factors(il); - - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - if (model.layers[il].bq) { - Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq); - cb(Qcur, "Qcur", il); - } - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - if (model.layers[il].bk) { - Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk); - cb(Kcur, "Kcur", il); - } - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - if (model.layers[il].bv) { - Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv); - cb(Vcur, "Vcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, rope_factors, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, model.layers[il].bo, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - ggml_cgraph * build_rwkv6() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // Token shift state dimensions should be 2 * n_emb - GGML_ASSERT(n_embd == hparams.n_embd_k_s() / 2); - - const int64_t n_seqs = ubatch.n_seqs; - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - const int64_t n_tokens = ubatch.n_tokens; - GGML_ASSERT(n_seqs != 0); - GGML_ASSERT(ubatch.equal_seqs); - GGML_ASSERT(n_tokens == n_seq_tokens * n_seqs); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - struct ggml_tensor * state_copy = build_inp_s_copy(); - struct ggml_tensor * state_mask = build_inp_s_mask(); - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - inpL = llm_build_norm(ctx0, inpL, hparams, model.tok_norm, model.tok_norm_b, LLM_NORM, cb, -1); - - for (int il = 0; il < n_layer; ++il) { - const llama_layer * layer = &model.layers[il]; - - // (ab)using the KV cache to store the states - struct ggml_tensor * token_shift = llm_build_copy_mask_state(ctx0, - gf, kv_self.k_l[il], state_copy, state_mask, - hparams.n_embd_k_s(), kv_self.size, kv_head, n_kv, n_seqs); - struct ggml_tensor * wkv_states = llm_build_copy_mask_state(ctx0, - gf, kv_self.v_l[il], state_copy, state_mask, - hparams.n_embd_v_s(), kv_self.size, kv_head, n_kv, n_seqs); - - cur = ggml_reshape_3d(ctx0, inpL, n_embd, n_seq_tokens, n_seqs); - token_shift = ggml_reshape_3d(ctx0, token_shift, n_embd, 2, n_seqs); - - struct ggml_tensor * att_shift = ggml_view_3d(ctx0, token_shift, n_embd, 1, n_seqs, token_shift->nb[1], token_shift->nb[2], 0); - struct ggml_tensor * ffn_shift = ggml_view_3d(ctx0, token_shift, n_embd, 1, n_seqs, token_shift->nb[1], token_shift->nb[2], n_embd * ggml_element_size(token_shift)); - - struct ggml_tensor * x_norm_att = llm_build_norm(ctx0, cur, hparams, layer->attn_norm, layer->attn_norm_b, LLM_NORM, cb, il); - struct ggml_tensor * x_prev = ggml_concat( - ctx0, - att_shift, - ggml_view_3d(ctx0, x_norm_att, n_embd, n_seq_tokens - 1, n_seqs, x_norm_att->nb[1], x_norm_att->nb[2], 0), - 1 - ); - - cur = ggml_add(ctx0, cur, llm_build_rwkv6_time_mix(lctx, ctx0, layer, x_norm_att, x_prev, &wkv_states, hparams.wkv_head_size, n_embd / hparams.wkv_head_size)); - ggml_build_forward_expand(gf, cur); - ggml_build_forward_expand( - gf, - ggml_cpy( - ctx0, - wkv_states, - ggml_view_1d( - ctx0, - kv_self.v_l[il], - hparams.n_embd_v_s() * n_seqs, - hparams.n_embd_v_s() * kv_head * ggml_element_size(kv_self.v_l[il]) - ) - ) - ); - - struct ggml_tensor * x_norm_ffn = llm_build_norm(ctx0, cur, hparams, layer->attn_norm_2, layer->attn_norm_2_b, LLM_NORM, cb, il); - x_prev = ggml_concat( - ctx0, - ffn_shift, - ggml_view_3d(ctx0, x_norm_ffn, n_embd, n_seq_tokens - 1, n_seqs, x_norm_ffn->nb[1], x_norm_ffn->nb[2], 0), - 1 - ); - cur = ggml_add(ctx0, cur, llm_build_rwkv6_channel_mix(lctx, ctx0, layer, x_norm_ffn, x_prev)); - ggml_build_forward_expand(gf, cur); - - struct ggml_tensor * last_norm_att = ggml_view_3d(ctx0, x_norm_att, n_embd, 1, n_seqs, x_norm_att->nb[1], x_norm_att->nb[2], (n_seq_tokens-1)*n_embd*ggml_element_size(x_norm_att)); - struct ggml_tensor * last_norm_ffn = ggml_view_3d(ctx0, x_norm_ffn, n_embd, 1, n_seqs, x_norm_ffn->nb[1], x_norm_ffn->nb[2], (n_seq_tokens-1)*n_embd*ggml_element_size(x_norm_ffn)); - - token_shift = ggml_concat(ctx0, last_norm_att, last_norm_ffn, 1); - - ggml_build_forward_expand( - gf, - ggml_cpy( - ctx0, - ggml_view_1d(ctx0, token_shift, n_embd * n_seqs * 2, 0), - ggml_view_1d(ctx0, kv_self.k_l[il], hparams.n_embd_k_s() * n_seqs, hparams.n_embd_k_s() * kv_head * ggml_element_size(kv_self.k_l[il])) - ) - ); - - if (hparams.rescale_every_n_layers != 0 && (il + 1) % hparams.rescale_every_n_layers == 0) { - cur = ggml_scale(ctx0, cur, 0.5F); - } - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_reshape_2d(ctx0, cur, n_embd, n_tokens); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - - cur = llm_build_norm(ctx0, cur, hparams, model.output_norm, model.output_norm_b, LLM_NORM, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - // ref: https://huggingface.co/recursal/QRWKV6-32B-Instruct-Preview-v0.1/blob/main/modeling_rwkv6qwen2.py - ggml_cgraph * build_rwkv6qwen2() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - GGML_ASSERT(n_embd == hparams.n_embd_k_s()); - - const int64_t n_seqs = ubatch.n_seqs; - const int64_t n_seq_tokens = ubatch.n_seq_tokens; - const int64_t n_tokens = ubatch.n_tokens; - GGML_ASSERT(n_seqs != 0); - GGML_ASSERT(ubatch.equal_seqs); - GGML_ASSERT(n_tokens == n_seq_tokens * n_seqs); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - struct ggml_tensor * state_copy = build_inp_s_copy(); - struct ggml_tensor * state_mask = build_inp_s_mask(); - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - for (int il = 0; il < n_layer; ++il) { - const llama_layer * layer = &model.layers[il]; - - // (ab)using the KV cache to store the states - struct ggml_tensor * token_shift = llm_build_copy_mask_state(ctx0, - gf, kv_self.k_l[il], state_copy, state_mask, - hparams.n_embd_k_s(), kv_self.size, kv_head, n_kv, n_seqs); - struct ggml_tensor * wkv_states = llm_build_copy_mask_state(ctx0, - gf, kv_self.v_l[il], state_copy, state_mask, - hparams.n_embd_v_s(), kv_self.size, kv_head, n_kv, n_seqs); - - cur = ggml_reshape_3d(ctx0, inpL, n_embd, n_seq_tokens, n_seqs); - token_shift = ggml_reshape_3d(ctx0, token_shift, n_embd, 1, n_seqs); - - struct ggml_tensor * x_norm_att = llm_build_norm(ctx0, cur, hparams, layer->attn_norm, layer->attn_norm_b, LLM_NORM_RMS, cb, il); - struct ggml_tensor * x_prev = ggml_concat( - ctx0, - token_shift, - ggml_view_3d(ctx0, x_norm_att, n_embd, n_seq_tokens - 1, n_seqs, x_norm_att->nb[1], x_norm_att->nb[2], 0), - 1 - ); - - struct ggml_tensor * last_norm_att = ggml_view_3d(ctx0, x_norm_att, n_embd, 1, n_seqs, x_norm_att->nb[1], x_norm_att->nb[2], (n_seq_tokens-1)*n_embd*ggml_element_size(x_norm_att)); - ggml_build_forward_expand( - gf, - ggml_cpy( - ctx0, - ggml_view_1d(ctx0, last_norm_att, n_embd * n_seqs, 0), - ggml_view_1d(ctx0, kv_self.k_l[il], hparams.n_embd_k_s() * n_seqs, hparams.n_embd_k_s() * kv_head * ggml_element_size(kv_self.k_l[il])) - ) - ); - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, llm_build_rwkv6_time_mix(lctx, ctx0, layer, x_norm_att, x_prev, &wkv_states, hparams.wkv_head_size, hparams.n_head_kv())); - ggml_build_forward_expand(gf, ffn_inp); - ggml_build_forward_expand( - gf, - ggml_cpy( - ctx0, - wkv_states, - ggml_view_1d( - ctx0, - kv_self.v_l[il], - hparams.n_embd_v_s() * n_seqs, - hparams.n_embd_v_s() * kv_head * ggml_element_size(kv_self.v_l[il]) - ) - ) - ); - - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - cur = ggml_add(ctx0, cur, ffn_inp); - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - cur = ggml_reshape_2d(ctx0, cur, n_embd, n_tokens); - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - - cur = llm_build_norm(ctx0, cur, hparams, model.output_norm, model.output_norm_b, LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - // ref: https://github.com/facebookresearch/chameleon - // based on the original build_llama() function, changes: - // * qk-norm - // * swin-norm - // * removed bias - // * removed MoE - struct ggml_cgraph * build_chameleon() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - // mutable variable, needed during the last layer of the computation to skip unused tokens - int32_t n_tokens = this->n_tokens; - - const int64_t n_embd_head = hparams.n_embd_head_v; - GGML_ASSERT(n_embd_head == hparams.n_embd_head_k); - GGML_ASSERT(n_embd_head == hparams.n_rot); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - // inp_pos - contains the positions - struct ggml_tensor * inp_pos = build_inp_pos(); - - // KQ_mask (mask for 1 head, it will be broadcasted to all heads) - struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); - - for (int il = 0; il < n_layer; ++il) { - struct ggml_tensor * inpSA = inpL; - - // norm - if (hparams.swin_norm) { - cur = inpL; - } else { - cur = llm_build_norm(ctx0, inpL, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "attn_norm", il); - } - - // self-attention - { - // compute Q and K and RoPE them - struct ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); - cb(Qcur, "Qcur", il); - - struct ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); - cb(Kcur, "Kcur", il); - - struct ggml_tensor * Vcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wv, cur); - cb(Vcur, "Vcur", il); - - if (model.layers[il].attn_q_norm) { - Qcur = ggml_view_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens, - ggml_element_size(Qcur) * n_embd_head, - ggml_element_size(Qcur) * n_embd_head * n_head, - 0); - cb(Qcur, "Qcur", il); - - Qcur = llm_build_norm(ctx0, Qcur, hparams, - model.layers[il].attn_q_norm, - model.layers[il].attn_q_norm_b, - LLM_NORM, cb, il); - cb(Qcur, "Qcur", il); - } - - if (model.layers[il].attn_k_norm) { - Kcur = ggml_view_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens, - ggml_element_size(Kcur) * n_embd_head, - ggml_element_size(Kcur) * n_embd_head * n_head_kv, - 0); - cb(Kcur, "Kcur", il); - - Kcur = llm_build_norm(ctx0, Kcur, hparams, - model.layers[il].attn_k_norm, - model.layers[il].attn_k_norm_b, - LLM_NORM, cb, il); - cb(Kcur, "Kcur", il); - } - - Qcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Qcur, "Qcur", il); - - Kcur = ggml_rope_ext( - ctx0, ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens), inp_pos, nullptr, - n_rot, rope_type, n_ctx_orig, freq_base, freq_scale, - ext_factor, attn_factor, beta_fast, beta_slow - ); - cb(Kcur, "Kcur", il); - - cur = llm_build_kv(ctx0, lctx, kv_self, gf, - model.layers[il].wo, nullptr, - Kcur, Vcur, Qcur, KQ_mask, n_tokens, kv_head, n_kv, 1.0f/sqrtf(float(n_embd_head)), cb, il); - - if (hparams.swin_norm) { - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].attn_norm, NULL, - LLM_NORM_RMS, cb, il); - } - } - - if (il == n_layer - 1) { - // skip computing output for unused tokens - struct ggml_tensor * inp_out_ids = build_inp_out_ids(); - n_tokens = n_outputs; - cur = ggml_get_rows(ctx0, cur, inp_out_ids); - inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids); - } - - struct ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA); - cb(ffn_inp, "ffn_inp", il); - - // feed-forward network - if (!hparams.swin_norm) { - cur = llm_build_norm(ctx0, ffn_inp, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - } - - cur = llm_build_ffn(ctx0, lctx, cur, - model.layers[il].ffn_up, NULL, NULL, - model.layers[il].ffn_gate, NULL, NULL, - model.layers[il].ffn_down, NULL, NULL, - NULL, - LLM_FFN_SILU, LLM_FFN_PAR, cb, il); - cb(cur, "ffn_out", il); - - if (hparams.swin_norm) { - cur = llm_build_norm(ctx0, cur, hparams, - model.layers[il].ffn_norm, NULL, - LLM_NORM_RMS, cb, il); - cb(cur, "ffn_norm", il); - } - - cur = ggml_add(ctx0, cur, ffn_inp); - cb(cur, "ffn_out", il); - - cur = lctx.cvec.apply_to(ctx0, cur, il); - cb(cur, "l_out", il); - - // input for next layer - inpL = cur; - } - - cur = inpL; - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, NULL, - LLM_NORM_RMS, cb, -1); - cb(cur, "result_norm", -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - cb(cur, "result_output_with_img_logits", -1); - - // TODO: this suppresses the output of image tokens, which is required to enable text-only outputs. - // Needs to be removed once image outputs are supported. - int img_token_end_idx = 8196; - int img_token_start_idx = 4; - int num_img_tokens = img_token_end_idx - img_token_start_idx; - // creates 1d tensor of size num_img_tokens and values -FLT_MAX, - // which ensures that text token values are always at least larger than image token values - struct ggml_tensor * img_logits = ggml_new_tensor_1d(ctx0, GGML_TYPE_F32, num_img_tokens); - img_logits = ggml_clamp(ctx0, img_logits, -FLT_MAX, -FLT_MAX); - cb(img_logits, "img_logits", -1); - cur = ggml_set_1d(ctx0, cur, img_logits, ggml_element_size(cur) * img_token_start_idx); - cb(cur, "result_output", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } - - struct ggml_cgraph * build_wavtokenizer_dec() { - struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, model.max_nodes(), false); - - struct ggml_tensor * cur; - struct ggml_tensor * inpL; - - inpL = llm_build_inp_embd(ctx0, lctx, hparams, ubatch, model.tok_embd, cb); - - cur = ggml_cont(ctx0, ggml_transpose(ctx0, inpL)); - - cur = ggml_conv_1d_ph(ctx0, model.conv1d, cur, 1, 1); - cur = ggml_add(ctx0, cur, model.conv1d_b); - - // posnet - for (uint32_t il = 0; il < hparams.posnet.n_layer; ++il) { - const auto & layer = model.layers[il].posnet; - - inpL = cur; - - switch (il) { - case 0: - case 1: - case 3: - case 4: - { - cur = llm_build_norm(ctx0, cur, hparams, - layer.norm1, - layer.norm1_b, - LLM_NORM_GROUP, cb, 0); - - cur = ggml_mul(ctx0, ggml_sigmoid(ctx0, cur), cur); - - cur = ggml_conv_1d_ph(ctx0, layer.conv1, cur, 1, 1); - cur = ggml_add(ctx0, cur, layer.conv1_b); - - cur = llm_build_norm(ctx0, cur, hparams, - layer.norm2, - layer.norm2_b, - LLM_NORM_GROUP, cb, 0); - - cur = ggml_mul(ctx0, ggml_sigmoid(ctx0, cur), cur); - - cur = ggml_conv_1d_ph(ctx0, layer.conv2, cur, 1, 1); - cur = ggml_add(ctx0, cur, layer.conv2_b); - - cur = ggml_add(ctx0, cur, inpL); - } break; - case 2: - { - cur = llm_build_norm(ctx0, cur, hparams, - layer.attn_norm, - layer.attn_norm_b, - LLM_NORM_GROUP, cb, 0); - - struct ggml_tensor * q; - struct ggml_tensor * k; - struct ggml_tensor * v; - - q = ggml_conv_1d_ph(ctx0, layer.attn_q, cur, 1, 1); - k = ggml_conv_1d_ph(ctx0, layer.attn_k, cur, 1, 1); - v = ggml_conv_1d_ph(ctx0, layer.attn_v, cur, 1, 1); - - q = ggml_add(ctx0, q, layer.attn_q_b); - k = ggml_add(ctx0, k, layer.attn_k_b); - v = ggml_add(ctx0, v, layer.attn_v_b); - - q = ggml_cont(ctx0, ggml_transpose(ctx0, q)); - k = ggml_cont(ctx0, ggml_transpose(ctx0, k)); - - struct ggml_tensor * kq = ggml_mul_mat(ctx0, k, q); - - kq = ggml_soft_max_ext(ctx0, kq, nullptr, 1.0f/sqrtf(float(hparams.posnet.n_embd)), 0.0f); - - cur = ggml_mul_mat(ctx0, kq, v); - - cur = ggml_conv_1d_ph(ctx0, layer.attn_o, cur, 1, 1); - cur = ggml_add(ctx0, cur, layer.attn_o_b); - - cur = ggml_add(ctx0, cur, inpL); - } break; - case 5: - { - cur = llm_build_norm(ctx0, cur, hparams, - layer.norm, - layer.norm_b, - LLM_NORM_GROUP, cb, 0); - } break; - default: GGML_ABORT("unknown posnet layer"); - }; - } - - cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); - - cur = llm_build_norm(ctx0, cur, hparams, - model.tok_norm, - model.tok_norm_b, - LLM_NORM, cb, -1); - - cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); - - inpL = cur; - - // convnext - for (uint32_t il = 0; il < hparams.convnext.n_layer; ++il) { - const auto & layer = model.layers[il].convnext; - - cur = inpL; - - cur = ggml_conv_1d_dw_ph(ctx0, layer.dw, cur, 1, 1); - cur = ggml_add(ctx0, cur, layer.dw_b); - - cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); - - cur = llm_build_norm(ctx0, cur, hparams, - layer.norm, - layer.norm_b, - LLM_NORM, cb, -1); - - cur = llm_build_ffn(ctx0, lctx, cur, - layer.pw1, layer.pw1_b, NULL, - NULL, NULL, NULL, - layer.pw2, layer.pw2_b, NULL, - NULL, - LLM_FFN_GELU, LLM_FFN_SEQ, cb, il); - - cur = ggml_mul(ctx0, cur, layer.gamma); - - cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); - - inpL = ggml_add(ctx0, cur, inpL); - } - - cur = inpL; - - cur = ggml_cont(ctx0, ggml_transpose(ctx0, cur)); - - cur = llm_build_norm(ctx0, cur, hparams, - model.output_norm, - model.output_norm_b, - LLM_NORM, cb, -1); - - // lm_head - cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); - - cur = ggml_add(ctx0, cur, model.output_b); - cb(cur, "result_embd", -1); - - ggml_build_forward_expand(gf, cur); - - return gf; - } -}; - -static struct ggml_cgraph * llama_build_graph_defrag(llama_context & lctx, const std::vector & ids) { - llama_ubatch dummy = {}; - dummy.equal_seqs = true; - - llm_build_cb cb = [&](struct ggml_tensor * , const char * , int ) { }; - - struct llm_build_context llm(lctx, dummy, cb, false); - - llm.init(); - - struct ggml_cgraph * result = llm.build_defrag(ids); - - llm.free(); - - return result; -} - -static struct ggml_cgraph * llama_build_graph_k_shift(llama_context & lctx) { - llama_ubatch dummy = {}; - dummy.equal_seqs = true; - - llm_build_cb cb = [&](struct ggml_tensor * , const char * , int ) { }; - - struct llm_build_context llm(lctx, dummy, cb, false); - - llm.init(); - - struct ggml_cgraph * result = llm.build_k_shift(); - - llm.free(); - - return result; -} - -static struct ggml_cgraph * llama_build_graph( - llama_context & lctx, - const llama_ubatch & ubatch, - bool worst_case) { - const auto & model = lctx.model; - - // this callback allows us to apply custom logic to each tensor (e.g. ggml-alloc, offloading, etc.) - llm_build_cb cb = [&](struct ggml_tensor * cur, const char * name, int il) { - if (il >= 0) { - ggml_format_name(cur, "%s-%d", name, il); - } else { - ggml_set_name(cur, name); - } - - if (!lctx.cparams.offload_kqv) { - if (strcmp(name, "kqv_merged_cont") == 0) { - // all nodes between the KV store and the attention output are run on the CPU - ggml_backend_sched_set_tensor_backend(lctx.sched.get(), cur, lctx.backend_cpu); - } - } - - // norm may be automatically assigned to the backend of the previous layer, increasing data transfer between backends - // FIXME: fix in ggml_backend_sched - const bool full_offload = lctx.model.params.n_gpu_layers > (int) lctx.model.hparams.n_layer; - if (ubatch.n_tokens < 32 || full_offload) { - if (il != -1 && strcmp(name, "norm") == 0) { - const auto & dev_layer = lctx.model.dev_layer(il); - for (auto & backend : lctx.backends) { - if (ggml_backend_get_device(backend.get()) == dev_layer) { - if (ggml_backend_supports_op(backend.get(), cur)) { - ggml_backend_sched_set_tensor_backend(lctx.sched.get(), cur, backend.get()); - } - } - } - } - } - }; - - struct ggml_cgraph * result = NULL; - - struct llm_build_context llm(lctx, ubatch, cb, worst_case); - - llm.init(); - - switch (model.arch) { - case LLM_ARCH_LLAMA: - case LLM_ARCH_MINICPM: - case LLM_ARCH_GRANITE: - case LLM_ARCH_GRANITE_MOE: - { - result = llm.build_llama(); - } break; - case LLM_ARCH_DECI: - { - result = llm.build_deci(); - } break; - case LLM_ARCH_BAICHUAN: - { - result = llm.build_baichuan(); - } break; - case LLM_ARCH_FALCON: - { - result = llm.build_falcon(); - } break; - case LLM_ARCH_GROK: - { - result = llm.build_grok(); - } break; - case LLM_ARCH_STARCODER: - { - result = llm.build_starcoder(); - } break; - case LLM_ARCH_REFACT: - { - result = llm.build_refact(); - } break; - case LLM_ARCH_BERT: - case LLM_ARCH_JINA_BERT_V2: - case LLM_ARCH_NOMIC_BERT: - { - result = llm.build_bert(); - } break; - case LLM_ARCH_BLOOM: - { - result = llm.build_bloom(); - } break; - case LLM_ARCH_MPT: - { - result = llm.build_mpt(); - } break; - case LLM_ARCH_STABLELM: - { - result = llm.build_stablelm(); - } break; - case LLM_ARCH_QWEN: - { - result = llm.build_qwen(); - } break; - case LLM_ARCH_QWEN2: - { - result = llm.build_qwen2(); - } break; - case LLM_ARCH_QWEN2VL: - { - lctx.n_pos_per_token = 4; - result = llm.build_qwen2vl(); - } break; - case LLM_ARCH_QWEN2MOE: - { - result = llm.build_qwen2moe(); - } break; - case LLM_ARCH_PHI2: - { - result = llm.build_phi2(); - } break; - case LLM_ARCH_PHI3: - case LLM_ARCH_PHIMOE: - { - result = llm.build_phi3(); - } break; - case LLM_ARCH_PLAMO: - { - result = llm.build_plamo(); - } break; - case LLM_ARCH_GPT2: - { - result = llm.build_gpt2(); - } break; - case LLM_ARCH_CODESHELL: - { - result = llm.build_codeshell(); - } break; - case LLM_ARCH_ORION: - { - result = llm.build_orion(); - } break; - case LLM_ARCH_INTERNLM2: - { - result = llm.build_internlm2(); - } break; - case LLM_ARCH_MINICPM3: - { - result = llm.build_minicpm3(); - } break; - case LLM_ARCH_GEMMA: - { - result = llm.build_gemma(); - } break; - case LLM_ARCH_GEMMA2: - { - result = llm.build_gemma2(); - } break; - case LLM_ARCH_GEMMA3: - { - result = llm.build_gemma3(); - } break; - case LLM_ARCH_STARCODER2: - { - result = llm.build_starcoder2(); - } break; - case LLM_ARCH_MAMBA: - { - result = llm.build_mamba(); - } break; - case LLM_ARCH_XVERSE: - { - result = llm.build_xverse(); - } break; - case LLM_ARCH_COMMAND_R: - { - result = llm.build_command_r(); - } break; - case LLM_ARCH_COHERE2: - { - result = llm.build_cohere2(); - } break; - case LLM_ARCH_DBRX: - { - result = llm.build_dbrx(); - } break; - case LLM_ARCH_OLMO: - { - result = llm.build_olmo(); - } break; - case LLM_ARCH_OLMO2: - { - result = llm.build_olmo2(); - } break; - case LLM_ARCH_OLMOE: - { - result = llm.build_olmoe(); - } break; - case LLM_ARCH_OPENELM: - { - result = llm.build_openelm(); - } break; - case LLM_ARCH_GPTNEOX: - { - result = llm.build_gptneox(); - } break; - case LLM_ARCH_ARCTIC: - { - result = llm.build_arctic(); - } break; - case LLM_ARCH_DEEPSEEK: - { - result = llm.build_deepseek(); - } break; - case LLM_ARCH_DEEPSEEK2: - { - result = llm.build_deepseek2(); - } break; - case LLM_ARCH_CHATGLM: - { - result = llm.build_chatglm(); - } break; - case LLM_ARCH_BITNET: - { - result = llm.build_bitnet(); - } break; - case LLM_ARCH_T5: - { - if (lctx.is_encoding) { - result = llm.build_t5_enc(); - } else { - result = llm.build_t5_dec(); - } - } break; - case LLM_ARCH_T5ENCODER: - { - result = llm.build_t5_enc(); - } break; - case LLM_ARCH_JAIS: - { - result = llm.build_jais(); - } break; - case LLM_ARCH_NEMOTRON: - { - result = llm.build_nemotron(); - } break; - case LLM_ARCH_EXAONE: - { - result = llm.build_exaone(); - } break; - case LLM_ARCH_RWKV6: - { - result = llm.build_rwkv6(); - } break; - case LLM_ARCH_RWKV6QWEN2: - { - result = llm.build_rwkv6qwen2(); - } break; - case LLM_ARCH_CHAMELEON: - { - result = llm.build_chameleon(); - } break; - case LLM_ARCH_WAVTOKENIZER_DEC: - { - result = llm.build_wavtokenizer_dec(); - } break; - default: - GGML_ABORT("fatal error"); - } - - // add on pooling layer - if (lctx.cparams.embeddings) { - result = llm.append_pooling(result); - } - - llm.free(); - - return result; -} - -// returns the result of ggml_backend_sched_graph_compute_async execution -static enum ggml_status llama_graph_compute( - llama_context & lctx, - ggml_cgraph * gf, - int n_threads, - ggml_threadpool * threadpool) { - if (lctx.backend_cpu != nullptr) { - auto * reg = ggml_backend_dev_backend_reg(ggml_backend_get_device(lctx.backend_cpu)); - auto * set_threadpool_fn = (decltype(ggml_backend_cpu_set_threadpool) *) ggml_backend_reg_get_proc_address(reg, "ggml_backend_cpu_set_threadpool"); - set_threadpool_fn(lctx.backend_cpu, threadpool); - } - - // set the number of threads for all the backends - for (const auto & set_n_threads_fn : lctx.set_n_threads_fns) { - set_n_threads_fn.second(set_n_threads_fn.first, n_threads); - } - - auto status = ggml_backend_sched_graph_compute_async(lctx.sched.get(), gf); - if (status != GGML_STATUS_SUCCESS) { - LLAMA_LOG_ERROR("%s: ggml_backend_sched_graph_compute_async failed with error %d\n", __func__, status); - } - - // fprintf(stderr, "splits: %d\n", ggml_backend_sched_get_n_splits(lctx.sched)); - - return status; -} - -static int llama_prepare_sbatch( - llama_context & lctx, - const llama_batch & batch, - uint32_t & n_outputs) { - const auto & model = lctx.model; - const auto & hparams = model.hparams; - const auto & cparams = lctx.cparams; - - const uint32_t n_tokens_all = batch.n_tokens; - const int64_t n_embd = hparams.n_embd; - - // this indicates we are doing pooled embedding, so we ignore batch.logits and output all tokens - const bool embd_pooled = cparams.embeddings && cparams.pooling_type != LLAMA_POOLING_TYPE_NONE; - - GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT - if (batch.token) { - for (uint32_t i = 0; i < n_tokens_all; ++i) { - if (batch.token[i] < 0 || uint32_t(batch.token[i]) >= model.vocab.n_tokens()) { - LLAMA_LOG_ERROR("%s: invalid token[%d] = %d\n", __func__, i, batch.token[i]); - return -1; - } - } - } - GGML_ASSERT(n_tokens_all <= cparams.n_batch); - GGML_ASSERT((cparams.causal_attn || cparams.n_ubatch >= n_tokens_all) && "non-causal attention requires n_ubatch >= n_tokens"); - - lctx.n_queued_tokens += n_tokens_all; - lctx.embd_seq.clear(); - - // count outputs - if (batch.logits && !embd_pooled) { - for (uint32_t i = 0; i < n_tokens_all; ++i) { - n_outputs += batch.logits[i] != 0; - } - } else if (lctx.logits_all || embd_pooled) { - n_outputs = n_tokens_all; - } else { - // keep last output only - n_outputs = 1; - } - - lctx.sbatch.from_batch(batch, n_embd, - /* simple_split */ !lctx.kv_self.recurrent, - /* logits_all */ n_outputs == n_tokens_all); - - // reserve output buffer - if (llama_output_reserve(lctx, n_outputs) < n_outputs) { - LLAMA_LOG_ERROR("%s: could not reserve space for batch with %u outputs\n", __func__, n_outputs); - return -2; - }; - - return 0; -} - -static int llama_prepare_ubatch( - llama_context & lctx, - llama_kv_slot_restorer & kv_slot_restorer, - llama_ubatch & ubatch, - const uint32_t n_outputs, - const uint32_t n_tokens_all) { - GGML_ASSERT(lctx.sbatch.n_tokens > 0); - - auto & kv_self = lctx.kv_self; - const auto & cparams = lctx.cparams; - const auto & hparams = lctx.model.hparams; - - // this indicates we are doing pooled embedding, so we ignore batch.logits and output all tokens - const bool embd_pooled = cparams.embeddings && cparams.pooling_type != LLAMA_POOLING_TYPE_NONE; - - if (lctx.kv_self.recurrent) { - if (embd_pooled) { - // Pooled embeddings cannot be split across ubatches (yet) - ubatch = lctx.sbatch.split_seq(cparams.n_ubatch); - } else { - // recurrent model architectures are easier to implement - // with equal-length sequences - ubatch = lctx.sbatch.split_equal(cparams.n_ubatch); - } - } else { - ubatch = lctx.sbatch.split_simple(cparams.n_ubatch); - } - - // count the outputs in this u_batch - { - int32_t n_outputs_new = 0; - - if (n_outputs == n_tokens_all) { - n_outputs_new = ubatch.n_tokens; - } else { - GGML_ASSERT(ubatch.output); - for (uint32_t i = 0; i < ubatch.n_tokens; i++) { - n_outputs_new += int32_t(ubatch.output[i] != 0); - } - } - - // needs to happen before the graph is built - lctx.n_outputs = n_outputs_new; - } - - // non-causal masks do not use the KV cache - if (hparams.causal_attn) { - llama_kv_cache_update(&lctx); - - // if we have enough unused cells before the current head -> - // better to start searching from the beginning of the cache, hoping to fill it - if (kv_self.head > kv_self.used + 2*ubatch.n_tokens) { - kv_self.head = 0; - } - - const auto slot = llama_kv_cache_find_slot(kv_self, ubatch); - if (!slot) { - return 1; - } - kv_slot_restorer.save(slot); - - if (!kv_self.recurrent) { - // a heuristic, to avoid attending the full cache if it is not yet utilized - // after enough generations, the benefit from this heuristic disappears - // if we start defragmenting the cache, the benefit from this will be more important - const uint32_t pad = llama_kv_cache_get_padding(cparams); - kv_self.n = std::min(kv_self.size, std::max(pad, GGML_PAD(llama_kv_cache_cell_max(kv_self), pad))); - //kv_self.n = llama_kv_cache_cell_max(kv_self); - } - } - - return 0; -} - -// decode a batch of tokens by evaluating the transformer -// in case of unsuccessful decoding (error or warning), -// the kv_cache state will be returned to its original state -// (for non-recurrent models) or cleaned (for recurrent models) -// -// - lctx: llama context -// - inp_batch: batch to evaluate -// -// return 0 on success -// return positive int on warning -// return negative int on error -// -static int llama_decode_impl( - llama_context & lctx, - llama_batch inp_batch) { - - lctx.is_encoding = false; - - if (inp_batch.n_tokens == 0) { - LLAMA_LOG_ERROR("%s: n_tokens == 0\n", __func__); - return -1; - } - - // temporarily allocate memory for the input batch if needed - llama_batch_allocr batch_allocr(inp_batch, inp_batch.pos ? -1 : lctx.kv_self.max_pos() + 1); - const llama_batch & batch = batch_allocr.batch; - - const auto & model = lctx.model; - const auto & vocab = model.vocab; - const auto & hparams = model.hparams; - const auto & cparams = lctx.cparams; - - if (lctx.t_compute_start_us == 0) { - lctx.t_compute_start_us = ggml_time_us(); - } - auto & kv_self = lctx.kv_self; - llama_kv_slot_restorer kv_slot_restorer(kv_self); - - const int64_t n_embd = hparams.n_embd; - const int64_t n_vocab = vocab.n_tokens(); - - uint32_t n_outputs = 0; - uint32_t n_outputs_prev = 0; - - { - const int ret = llama_prepare_sbatch(lctx, batch, n_outputs); - if (ret != 0) { - return ret; - } - } - - while (lctx.sbatch.n_tokens > 0) { - llama_ubatch ubatch; - { - const int ret = llama_prepare_ubatch(lctx, kv_slot_restorer, ubatch, n_outputs, batch.n_tokens); - if (ret != 0) { - return ret; - } - } - - const int n_threads = ubatch.n_tokens == 1 ? cparams.n_threads : cparams.n_threads_batch; - ggml_threadpool_t threadpool = ubatch.n_tokens == 1 ? lctx.threadpool : lctx.threadpool_batch; - - GGML_ASSERT(n_threads > 0); - - //printf("kv_self.n = %5d, kv_self.used = %5d, kv_self.head = %5d\n", kv_self.n, kv_self.used, kv_self.head); - - ggml_backend_sched_reset(lctx.sched.get()); - ggml_backend_sched_set_eval_callback(lctx.sched.get(), lctx.cparams.cb_eval, lctx.cparams.cb_eval_user_data); - - ggml_cgraph * gf = llama_build_graph(lctx, ubatch, false); - - // the output is always the last tensor in the graph - struct ggml_tensor * res = ggml_graph_node(gf, -1); - struct ggml_tensor * embd = ggml_graph_node(gf, -2); - - if (lctx.n_outputs == 0) { - // no output - res = nullptr; - embd = nullptr; - } else if (cparams.embeddings) { - res = nullptr; // do not extract logits for embedding case - embd = nullptr; - for (int i = ggml_graph_n_nodes(gf) - 1; i >= 0; --i) { - if (strcmp(ggml_graph_node(gf, i)->name, "result_embd_pooled") == 0) { - embd = ggml_graph_node(gf, i); - break; - } - } - GGML_ASSERT(embd != nullptr && "missing embeddings tensor"); - } else { - embd = nullptr; // do not extract embeddings when not needed - GGML_ASSERT(strcmp(res->name, "result_output") == 0 && "missing result_output tensor"); - } - - // LLAMA_LOG_INFO("graph build time: %.3f ms (%d nodes, %d leafs)\n", (ggml_time_us() - t_start_us)/1000.0, gf->n_nodes, gf->n_leafs); - - ggml_backend_sched_alloc_graph(lctx.sched.get(), gf); - - llama_set_inputs(lctx, ubatch); - - const auto compute_status = llama_graph_compute(lctx, gf, n_threads, threadpool); - if (compute_status != GGML_STATUS_SUCCESS) { - kv_slot_restorer.restore(kv_self); - switch (compute_status) { - case GGML_STATUS_ABORTED: - return 2; - case GGML_STATUS_ALLOC_FAILED: - return -2; - case GGML_STATUS_FAILED: - default: - return -3; - } - } - - // update the kv ring buffer - { - kv_self.head += ubatch.n_tokens; - - // Ensure kv cache head points to a valid index. - if (kv_self.head >= kv_self.size) { - kv_self.head = 0; - } - } - - // plot the computation graph in dot format (for debugging purposes) - //if (n_past%100 == 0) { - // ggml_graph_dump_dot(gf, NULL, "llama.dot"); - //} - - // extract logits - if (res) { - ggml_backend_t backend_res = ggml_backend_sched_get_tensor_backend(lctx.sched.get(), res); - GGML_ASSERT(backend_res != nullptr); - GGML_ASSERT(lctx.logits != nullptr); - - float * logits_out = lctx.logits + n_outputs_prev*n_vocab; - const int32_t n_outputs_new = lctx.n_outputs; - - if (n_outputs_new) { - GGML_ASSERT( n_outputs_prev + n_outputs_new <= n_outputs); - GGML_ASSERT((n_outputs_prev + n_outputs_new)*n_vocab <= (int64_t) lctx.logits_size); - ggml_backend_tensor_get_async(backend_res, res, logits_out, 0, n_outputs_new*n_vocab*sizeof(float)); - } - } - - // extract embeddings - if (embd) { - ggml_backend_t backend_embd = ggml_backend_sched_get_tensor_backend(lctx.sched.get(), embd); - GGML_ASSERT(backend_embd != nullptr); - - switch (cparams.pooling_type) { - case LLAMA_POOLING_TYPE_NONE: - { - // extract token embeddings - GGML_ASSERT(lctx.embd != nullptr); - float * embd_out = lctx.embd + n_outputs_prev*n_embd; - const int32_t n_outputs_new = lctx.n_outputs; - - if (n_outputs_new) { - GGML_ASSERT( n_outputs_prev + n_outputs_new <= n_outputs); - GGML_ASSERT((n_outputs_prev + n_outputs_new)*n_embd <= (int64_t) lctx.embd_size); - ggml_backend_tensor_get_async(backend_embd, embd, embd_out, 0, n_outputs_new*n_embd*sizeof(float)); - } - } break; - case LLAMA_POOLING_TYPE_MEAN: - case LLAMA_POOLING_TYPE_CLS: - case LLAMA_POOLING_TYPE_LAST: - { - // extract sequence embeddings (cleared before processing each batch) - auto & embd_seq_out = lctx.embd_seq; - - for (uint32_t s = 0; s < ubatch.n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; - if (embd_seq_out.find(seq_id) != embd_seq_out.end()) { - continue; - } - embd_seq_out[seq_id].resize(n_embd); - ggml_backend_tensor_get_async(backend_embd, embd, embd_seq_out[seq_id].data(), (n_embd*seq_id)*sizeof(float), n_embd*sizeof(float)); - } - } break; - case LLAMA_POOLING_TYPE_RANK: - { - // extract the rerank score - a single float per sequence - auto & embd_seq_out = lctx.embd_seq; - - for (uint32_t s = 0; s < ubatch.n_seqs; ++s) { - const llama_seq_id seq_id = ubatch.seq_id[s][0]; - if (embd_seq_out.find(seq_id) != embd_seq_out.end()) { - continue; - } - embd_seq_out[seq_id].resize(1); - ggml_backend_tensor_get_async(backend_embd, embd, embd_seq_out[seq_id].data(), (seq_id)*sizeof(float), sizeof(float)); - } - } break; - case LLAMA_POOLING_TYPE_UNSPECIFIED: - { - GGML_ABORT("unknown pooling type"); - } - } - } - n_outputs_prev += lctx.n_outputs; - } - - // set output mappings - { - bool sorted_output = true; - - GGML_ASSERT(lctx.sbatch.out_ids.size() == n_outputs); - - for (size_t i = 0; i < n_outputs; ++i) { - size_t out_id = lctx.sbatch.out_ids[i]; - lctx.output_ids[out_id] = i; - if (out_id != i) { - sorted_output = false; - } - } - - if (sorted_output) { - lctx.sbatch.out_ids.clear(); - } - } - - // set to total number of outputs in the batch, for use in llama_get_logits_ith - lctx.n_outputs = n_outputs; - - // wait for the computation to finish (automatically done when obtaining the model output) - //llama_synchronize(&lctx); - - // decide if we need to defrag the kv cache - if (cparams.causal_attn && cparams.defrag_thold > 0.0f) { - // - do not defrag small contexts (i.e. < 2048 tokens) - // - count the padding towards the number of used tokens - const float fragmentation = kv_self.n >= 2048 ? std::max(0.0f, 1.0f - float(kv_self.used + llama_kv_cache_get_padding(cparams))/float(kv_self.n)) : 0.0f; - - // queue defragmentation for next llama_kv_cache_update - if (fragmentation > cparams.defrag_thold) { - LLAMA_LOG_DEBUG("%s: fragmentation: %.2f - requesting defrag\n", __func__, fragmentation); - - llama_kv_cache_defrag(kv_self); - } - } - - // Reset state for the next token before backend sync, to allow the CPU activities in the reset to - // overlap with device computation. - ggml_backend_sched_reset(lctx.sched.get()); - - return 0; -} - -// encode a batch of tokens by evaluating the encoder part of the transformer -// -// - lctx: llama context -// - batch: batch to evaluate -// -// return 0 on success -// return positive int on warning -// return negative int on error -// -static int llama_encode_impl( - llama_context & lctx, - llama_batch inp_batch) { - - lctx.is_encoding = true; - - if (inp_batch.n_tokens == 0) { - LLAMA_LOG_ERROR("%s: n_tokens == 0\n", __func__); - return -1; - } - - // temporary allocate memory for the input batch if needed - llama_batch_allocr batch_allocr(inp_batch, inp_batch.pos ? -1 : lctx.kv_self.max_pos() + 1); - - const llama_batch & batch = batch_allocr.batch; - const uint32_t n_tokens = batch.n_tokens; - - const auto & model = lctx.model; - const auto & hparams = model.hparams; - const auto & cparams = lctx.cparams; - - GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT - - if (batch.token) { - for (uint32_t i = 0; i < n_tokens; ++i) { - if (batch.token[i] < 0 || (uint32_t) batch.token[i] >= model.vocab.n_tokens()) { - LLAMA_LOG_ERROR("%s: invalid token[%d] = %d\n", __func__, i, batch.token[i]); - return -1; - } - } - } - - // micro-batching is not possible for non-causal encoding, so we process the batch in a single shot - GGML_ASSERT(cparams.n_ubatch >= n_tokens && "encoder requires n_ubatch >= n_tokens"); - - if (lctx.t_compute_start_us == 0) { - lctx.t_compute_start_us = ggml_time_us(); - } - - lctx.n_queued_tokens += n_tokens; - - const int64_t n_embd = hparams.n_embd; - - lctx.sbatch.from_batch(batch, n_embd, /* simple_split */ true, /* logits_all */ true); - - const llama_ubatch ubatch = lctx.sbatch.split_simple(n_tokens); - - // reserve output buffer - if (llama_output_reserve(lctx, n_tokens) < n_tokens) { - LLAMA_LOG_ERROR("%s: could not reserve space for batch with %u outputs\n", __func__, n_tokens); - return -2; - }; - - for (uint32_t i = 0; i < n_tokens; ++i) { - lctx.output_ids[i] = i; - } - - lctx.inp_embd_enc = NULL; - lctx.n_outputs = n_tokens; - - int n_threads = n_tokens == 1 ? cparams.n_threads : cparams.n_threads_batch; - ggml_threadpool_t threadpool = n_tokens == 1 ? lctx.threadpool : lctx.threadpool_batch; - - GGML_ASSERT(n_threads > 0); - - ggml_backend_sched_reset(lctx.sched.get()); - ggml_backend_sched_set_eval_callback(lctx.sched.get(), lctx.cparams.cb_eval, lctx.cparams.cb_eval_user_data); - - ggml_cgraph * gf = llama_build_graph(lctx, ubatch, false); - - // the output embeddings after the final encoder normalization - struct ggml_tensor * embd = nullptr; - - // there are two cases here - if (llama_model_has_decoder(&lctx.model)) { - // first case is an encoder-decoder T5 model where embeddings are passed to decoder - embd = ggml_graph_node(gf, -1); - GGML_ASSERT(strcmp(embd->name, "result_norm") == 0 && "missing result_output tensor"); - } else { - // second case is an encoder-only T5 model - if (cparams.embeddings) { - // only output embeddings if required - embd = ggml_graph_node(gf, -1); - if (strcmp(embd->name, "result_embd_pooled") != 0) { - embd = ggml_graph_node(gf, -2); - } - GGML_ASSERT(strcmp(embd->name, "result_embd_pooled") == 0 && "missing embeddings tensor"); - } - } - - ggml_backend_sched_alloc_graph(lctx.sched.get(), gf); - - llama_set_inputs(lctx, ubatch); - - const auto compute_status = llama_graph_compute(lctx, gf, n_threads, threadpool); - switch (compute_status) { - case GGML_STATUS_SUCCESS: - break; - case GGML_STATUS_ABORTED: - return 2; - case GGML_STATUS_ALLOC_FAILED: - return -2; - case GGML_STATUS_FAILED: - default: - return -3; - } - - // extract embeddings - if (embd) { - ggml_backend_t backend_embd = ggml_backend_sched_get_tensor_backend(lctx.sched.get(), embd); - GGML_ASSERT(backend_embd != nullptr); - - if (llama_model_has_decoder(&lctx.model)) { - lctx.embd_enc.resize(n_tokens*n_embd); - float * embd_out = lctx.embd_enc.data(); - - ggml_backend_tensor_get_async(backend_embd, embd, embd_out, 0, n_tokens*n_embd*sizeof(float)); - GGML_ASSERT(!ubatch.equal_seqs); // TODO: handle equal splits - - // remember the sequence ids used during the encoding - needed for cross attention later - lctx.seq_ids_enc.resize(n_tokens); - for (uint32_t i = 0; i < n_tokens; i++) { - for (int s = 0; s < ubatch.n_seq_id[i]; s++) { - llama_seq_id seq_id = ubatch.seq_id[i][s]; - lctx.seq_ids_enc[i].insert(seq_id); - } - } - } else { - GGML_ASSERT(lctx.embd != nullptr); - - switch (cparams.pooling_type) { - case LLAMA_POOLING_TYPE_NONE: - { - // extract token embeddings - GGML_ASSERT(lctx.embd != nullptr); - float * embd_out = lctx.embd; - - GGML_ASSERT(n_tokens*n_embd <= (int64_t) lctx.embd_size); - ggml_backend_tensor_get_async(backend_embd, embd, embd_out, 0, n_tokens*n_embd*sizeof(float)); - } break; - case LLAMA_POOLING_TYPE_MEAN: - case LLAMA_POOLING_TYPE_CLS: - case LLAMA_POOLING_TYPE_LAST: - { - // extract sequence embeddings - auto & embd_seq_out = lctx.embd_seq; - embd_seq_out.clear(); - - GGML_ASSERT(!ubatch.equal_seqs); // TODO: handle equal splits - - for (uint32_t i = 0; i < n_tokens; i++) { - const llama_seq_id seq_id = ubatch.seq_id[i][0]; - if (embd_seq_out.find(seq_id) != embd_seq_out.end()) { - continue; - } - embd_seq_out[seq_id].resize(n_embd); - ggml_backend_tensor_get_async(backend_embd, embd, embd_seq_out[seq_id].data(), (n_embd*seq_id)*sizeof(float), n_embd*sizeof(float)); - } - } break; - case LLAMA_POOLING_TYPE_RANK: - { - // TODO: this likely should be the same logic as in llama_decoder_internal, but better to - // wait for an encoder model that requires this pooling type in order to test it - // https://github.com/ggerganov/llama.cpp/pull/9510 - GGML_ABORT("RANK pooling not implemented yet"); - } - case LLAMA_POOLING_TYPE_UNSPECIFIED: - { - GGML_ABORT("unknown pooling type"); - } - } - } - } - - // Reset state for the next token before backend sync, to allow the CPU activities in the reset to - // overlap with device computation. - ggml_backend_sched_reset(lctx.sched.get()); - - return 0; -} - -// find holes from the beginning of the KV cache and fill them by moving data from the end of the cache -static void llama_kv_cache_defrag_impl(struct llama_context & lctx) { - auto & kv_self = lctx.kv_self; - - const auto & hparams = lctx.model.hparams; - - const uint32_t n_layer = hparams.n_layer; - - const uint32_t n_kv = llama_kv_cache_cell_max(kv_self); - const uint32_t n_used = kv_self.used; - - assert(n_used <= n_kv); - - //const int64_t t_start = ggml_time_us(); - - // number of cells moved - uint32_t n_moves = 0; - - // each move requires 6*n_layer tensors (see build_defrag) - // - source view, destination view, copy operation - // - x2 for keys and values - //const uint32_t max_moves = model.max_nodes()/(6*n_layer); - // TODO: tmp fix https://github.com/ggerganov/llama.cpp/issues/6685#issuecomment-2057579516 - const uint32_t max_moves = (lctx.model.max_nodes() - 2*n_layer)/(6*n_layer); - - // determine which KV cells to move where - // - // cell i moves to ids[i] - // - // if ids[i] == i || ids[i] == n_kv, then cell i is not moved - // - std::vector ids(n_kv, n_kv); - - for (uint32_t i0 = 0; i0 < n_used; ++i0) { - const auto & cell0 = kv_self.cells[i0]; - - if (!cell0.is_empty()) { - ids[i0] = i0; - - continue; - } - - // found a hole - fill it with data from the end of the cache - - uint32_t nh = 1; - - // determine the size of the hole - while (i0 + nh < n_used && kv_self.cells[i0 + nh].is_empty()) { - nh++; - } - - uint32_t nf = 0; - uint32_t is = n_kv - 1; - - // starting from the end, find nh non-empty cells - for (; is > i0; --is) { - const auto & cell1 = kv_self.cells[is]; - - if (cell1.is_empty() || ids[is] != n_kv) { - continue; - } - - // non-empty cell which is not yet moved - nf++; - - if (nf == nh) { - break; - } - } - - // this can only happen if `n_used` is not accurate, which would be a bug - GGML_ASSERT(nf == nh && "KV defrag bug: nf != nh"); - - nf = 0; - - uint32_t i1 = is; - - // are we moving a continuous block of memory? - bool cont = false; - - // should we stop searching for the next move? - bool stop = false; - - // go back and move the nf cells to the hole - for (; i1 < n_kv; ++i1) { - auto & cell1 = kv_self.cells[i1]; - - if (cell1.is_empty() || ids[i1] != n_kv) { - if (n_moves == max_moves) { - stop = true; - break; - } - - cont = false; - continue; - } - - // this cell goes to (i0 + nf) - ids[i1] = i0 + nf; - - // move the cell meta data - kv_self.cells[i0 + nf] = cell1; - - // clear the old cell and move the head there - cell1 = llama_kv_cell(); - kv_self.head = n_used; - - if (!cont) { - n_moves++; - cont = true; - } - - nf++; - - if (nf == nh) { - break; - } - } - - if (stop || n_moves == max_moves) { - break; - } - - //LLAMA_LOG_INFO("(tmp log) KV defrag: move [%u, %u) to [%u, %u)\n", is, i1 + 1, i0, i0 + nh); - - i0 += nh - 1; - } - - if (n_moves == 0) { - return; - } - - //LLAMA_LOG_INFO("(tmp log) KV defrag cell moves: %u\n", n_moves); - - //LLAMA_LOG_INFO("expected gf nodes: %u\n", 6*n_moves*n_layer); - -#if 0 - // CPU defrag - // - // TODO: optimizations are possible: - // - multiple threads - // - avoid copying to the host memory when already there - // - // likely not worth the effort, as we have ggml_graph based defrag - // - - const uint32_t n_embd_k_gqa = hparams.n_embd_k_gqa(); - const uint32_t n_embd_v_gqa = hparams.n_embd_v_gqa(); - - const uint32_t kv_size = kv_self.size; - - std::vector buf_k; - std::vector buf_v; - - for (uint32_t il = 0; il < n_layer; ++il) { - const size_t k_size_row = ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa); - const size_t k_size = ggml_row_size(kv_self.k_l[il]->type, n_embd_k_gqa*kv_size); - - const size_t v_size_el = ggml_type_size(kv_self.v_l[il]->type); - const size_t v_size = ggml_row_size (kv_self.v_l[il]->type, n_embd_v_gqa*kv_size); - - buf_k.resize(k_size); - buf_v.resize(v_size); - - ggml_backend_tensor_get(kv_self.k_l[il], buf_k.data(), 0, buf_k.size()); - ggml_backend_tensor_get(kv_self.v_l[il], buf_v.data(), 0, buf_v.size()); - - // batch move [i, i+nm) to [id, id+nm) - // note: cells can move only to a lower index - for (uint32_t i = 0; i < n_kv; ++i) { - const uint32_t id = ids[i]; - - if (i == id || id == n_kv) { - continue; - } - - uint32_t nm = 1; - - while (i + nm < n_kv && ids[i + nm] == id + nm) { - nm++; - } - - // move keys - { - const int64_t os = i*k_size_row; - const int64_t od = id*k_size_row; - - memcpy(buf_k.data() + od, buf_k.data() + os, nm*k_size_row); - } - - // move values (note: they are transposed) - { - const int64_t os = i; - const int64_t od = id; - - for (uint32_t j = 0; j < n_embd_v_gqa; ++j) { - memcpy(buf_v.data() + (od + j*kv_size)*v_size_el, buf_v.data() + (os + j*kv_size)*v_size_el, nm*v_size_el); - } - } - - i += nm - 1; - } - - ggml_backend_tensor_set(kv_self.k_l[il], buf_k.data(), 0, buf_k.size()); - ggml_backend_tensor_set(kv_self.v_l[il], buf_v.data(), 0, buf_v.size()); - } -#else - // ggml_graph defrag - - ggml_backend_sched_reset(lctx.sched.get()); - - ggml_cgraph * gf = llama_build_graph_defrag(lctx, ids); - - llama_graph_compute(lctx, gf, lctx.cparams.n_threads, lctx.threadpool); -#endif - - //const int64_t t_end = ggml_time_us(); - - //LLAMA_LOG_INFO("(tmp log) KV defrag time: %.3f ms\n", (t_end - t_start)/1000.0); -} - -static void llama_kv_cache_update_impl(struct llama_context & lctx) { - bool need_reserve = false; - - if (lctx.kv_self.has_shift) { - if (!llama_kv_cache_can_shift(&lctx)) { - GGML_ABORT("The current context does not support K-shift"); - } - - // apply K-shift if needed - if (lctx.model.hparams.rope_type != LLAMA_ROPE_TYPE_NONE) { - ggml_backend_sched_reset(lctx.sched.get()); - - ggml_cgraph * gf = llama_build_graph_k_shift(lctx); - - ggml_backend_sched_alloc_graph(lctx.sched.get(), gf); - - llama_set_k_shift(lctx); - - llama_graph_compute(lctx, gf, lctx.cparams.n_threads, lctx.threadpool); - - need_reserve = true; - } - - { - auto & kv_self = lctx.kv_self; - - kv_self.has_shift = false; - - for (uint32_t i = 0; i < kv_self.size; ++i) { - kv_self.cells[i].delta = 0; - } - } - } - - // defragment the KV cache if needed - if (lctx.kv_self.do_defrag) { - llama_kv_cache_defrag_impl(lctx); - - need_reserve = true; - - lctx.kv_self.do_defrag = false; - } - - // reserve a worst case graph again - if (need_reserve) { - // TODO: extract to a function - // build worst-case graph - uint32_t n_seqs = 1; // TODO: worst-case number of sequences - uint32_t n_tokens = std::min(lctx.cparams.n_ctx, lctx.cparams.n_ubatch); - llama_token token = lctx.model.vocab.token_bos(); // not actually used by llama_build_graph, but required to choose between token and embedding inputs graph - llama_ubatch ubatch = { true, n_tokens, n_tokens / n_seqs, n_seqs, &token, nullptr, nullptr, nullptr, nullptr, nullptr}; - ggml_cgraph * gf = llama_build_graph(lctx, ubatch, true); - - // initialize scheduler with the worst-case graph - ggml_backend_sched_reset(lctx.sched.get()); - if (!ggml_backend_sched_reserve(lctx.sched.get(), gf)) { - LLAMA_LOG_ERROR("%s: failed to allocate compute buffers\n", __func__); - } - } -} - -int32_t llama_set_adapter_lora( - struct llama_context * ctx, - struct llama_adapter_lora * adapter, - float scale) { - ctx->lora[adapter] = scale; - return 0; -} - -int32_t llama_rm_adapter_lora( - struct llama_context * ctx, - struct llama_adapter_lora * adapter) { - auto pos = ctx->lora.find(adapter); - if (pos != ctx->lora.end()) { - ctx->lora.erase(pos); - return 0; - } - - return -1; -} - -void llama_clear_adapter_lora(struct llama_context * ctx) { - ctx->lora.clear(); -} - -int32_t llama_apply_adapter_cvec( - struct llama_context * ctx, - const float * data, - size_t len, - int32_t n_embd, - int32_t il_start, - int32_t il_end) { - return ctx->cvec.apply(ctx->model, data, len, n_embd, il_start, il_end); -} - // // interface implementation // -struct llama_context_params llama_context_default_params() { - struct llama_context_params result = { - /*.n_ctx =*/ 512, - /*.n_batch =*/ 2048, - /*.n_ubatch =*/ 512, - /*.n_seq_max =*/ 1, - /*.n_threads =*/ GGML_DEFAULT_N_THREADS, // TODO: better default - /*.n_threads_batch =*/ GGML_DEFAULT_N_THREADS, - /*.rope_scaling_type =*/ LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED, - /*.pooling_type =*/ LLAMA_POOLING_TYPE_UNSPECIFIED, - /*.attention_type =*/ LLAMA_ATTENTION_TYPE_UNSPECIFIED, - /*.rope_freq_base =*/ 0.0f, - /*.rope_freq_scale =*/ 0.0f, - /*.yarn_ext_factor =*/ -1.0f, - /*.yarn_attn_factor =*/ 1.0f, - /*.yarn_beta_fast =*/ 32.0f, - /*.yarn_beta_slow =*/ 1.0f, - /*.yarn_orig_ctx =*/ 0, - /*.defrag_thold =*/ -1.0f, - /*.cb_eval =*/ nullptr, - /*.cb_eval_user_data =*/ nullptr, - /*.type_k =*/ GGML_TYPE_F16, - /*.type_v =*/ GGML_TYPE_F16, - /*.logits_all =*/ false, - /*.embeddings =*/ false, - /*.offload_kqv =*/ true, - /*.flash_attn =*/ false, - /*.no_perf =*/ true, - /*.abort_callback =*/ nullptr, - /*.abort_callback_data =*/ nullptr, - }; - - return result; -} - struct llama_sampler_chain_params llama_sampler_chain_default_params() { struct llama_sampler_chain_params result = { /*.no_perf =*/ true, @@ -9571,6 +82,57 @@ int64_t llama_time_us(void) { return ggml_time_us(); } +// Returns 0 on success, -1 on error, and -2 on cancellation via llama_progress_callback +static int llama_model_load(const std::string & fname, std::vector & splits, llama_model & model, llama_model_params & params) { + // loading time will be recalculated after the first eval, so + // we take page faults deferred by mmap() into consideration + model.t_load_us = 0; + time_meas tm(model.t_load_us); + + model.t_start_us = tm.t_start_us; + + try { + llama_model_loader ml(fname, splits, params.use_mmap, params.check_tensors, params.kv_overrides); + + ml.print_info(); + + model.hparams.vocab_only = params.vocab_only; + + try { + model.load_arch(ml); + } catch(const std::exception & e) { + throw std::runtime_error("error loading model architecture: " + std::string(e.what())); + } + try { + model.load_hparams(ml); + } catch(const std::exception & e) { + throw std::runtime_error("error loading model hyperparameters: " + std::string(e.what())); + } + try { + model.load_vocab(ml); + } catch(const std::exception & e) { + throw std::runtime_error("error loading model vocabulary: " + std::string(e.what())); + } + + model.load_stats(ml); + model.print_info(); + + if (params.vocab_only) { + LLAMA_LOG_INFO("%s: vocab only - skipping tensors\n", __func__); + return 0; + } + + if (!model.load_tensors(ml)) { + return -2; + } + } catch (const std::exception & err) { + LLAMA_LOG_ERROR("%s: error loading model: %s\n", __func__, err.what()); + return -1; + } + + return 0; +} + static struct llama_model * llama_model_load_from_file_impl( const std::string & path_model, std::vector & splits, @@ -9691,460 +253,6 @@ struct llama_model * llama_model_load_from_splits( return llama_model_load_from_file_impl(splits.front(), splits, params); } -struct llama_context * llama_init_from_model( - struct llama_model * model, - struct llama_context_params params) { - - if (!model) { - LLAMA_LOG_ERROR("%s: model cannot be NULL\n", __func__); - return nullptr; - } - - if (params.n_batch == 0 && params.n_ubatch == 0) { - LLAMA_LOG_ERROR("%s: n_batch and n_ubatch cannot both be zero\n", __func__); - return nullptr; - } - - if (params.n_ctx == 0 && model->hparams.n_ctx_train == 0) { - LLAMA_LOG_ERROR("%s: n_ctx and model->hparams.n_ctx_train cannot both be zero\n", __func__); - return nullptr; - } - - if (params.flash_attn && model->arch == LLM_ARCH_GROK) { - LLAMA_LOG_WARN("%s: flash_attn is not compatible with Grok - forcing off\n", __func__); - params.flash_attn = false; - } - - if (params.flash_attn && model->hparams.n_embd_head_k != model->hparams.n_embd_head_v) { - LLAMA_LOG_WARN("%s: flash_attn requires n_embd_head_k == n_embd_head_v - forcing off\n", __func__); - params.flash_attn = false; - } - - if (ggml_is_quantized(params.type_v) && !params.flash_attn) { - LLAMA_LOG_ERROR("%s: V cache quantization requires flash_attn\n", __func__); - return nullptr; - } - - llama_context * ctx = new llama_context(*model); - - const auto & hparams = model->hparams; - auto & cparams = ctx->cparams; - - cparams.n_seq_max = std::max(1u, params.n_seq_max); - cparams.n_threads = params.n_threads; - cparams.n_threads_batch = params.n_threads_batch; - cparams.yarn_ext_factor = params.yarn_ext_factor; - cparams.yarn_attn_factor = params.yarn_attn_factor; - cparams.yarn_beta_fast = params.yarn_beta_fast; - cparams.yarn_beta_slow = params.yarn_beta_slow; - cparams.defrag_thold = params.defrag_thold; - cparams.embeddings = params.embeddings; - cparams.offload_kqv = params.offload_kqv; - cparams.flash_attn = params.flash_attn; - cparams.no_perf = params.no_perf; - cparams.pooling_type = params.pooling_type; - - cparams.n_ctx = params.n_ctx == 0 ? hparams.n_ctx_train : params.n_ctx; - cparams.rope_freq_base = params.rope_freq_base == 0.0f ? hparams.rope_freq_base_train : params.rope_freq_base; - cparams.rope_freq_scale = params.rope_freq_scale == 0.0f ? hparams.rope_freq_scale_train : params.rope_freq_scale; - - // this is necessary due to kv_self.n being padded later during inference - cparams.n_ctx = GGML_PAD(cparams.n_ctx, llama_kv_cache_get_padding(cparams)); - - // with causal attention, the batch size is limited by the context size - cparams.n_batch = hparams.causal_attn ? std::min(cparams.n_ctx, params.n_batch) : params.n_batch; - - // the batch has to be at least GGML_KQ_MASK_PAD because we will be padding the KQ_mask - // this is required by GPU kernels in order to avoid out-of-bounds accesses (e.g. ggml_flash_attn_ext) - // ref: https://github.com/ggerganov/llama.cpp/pull/5021 - if (cparams.n_batch < GGML_KQ_MASK_PAD) { - LLAMA_LOG_WARN("%s: n_batch is less than GGML_KQ_MASK_PAD - increasing to %d\n", __func__, GGML_KQ_MASK_PAD); - cparams.n_batch = GGML_KQ_MASK_PAD; - } - - cparams.n_ubatch = std::min(cparams.n_batch, params.n_ubatch == 0 ? params.n_batch : params.n_ubatch); - - cparams.n_ctx_orig_yarn = params.yarn_orig_ctx != 0 ? params.yarn_orig_ctx : - hparams.n_ctx_orig_yarn != 0 ? hparams.n_ctx_orig_yarn : - hparams.n_ctx_train; - - cparams.cb_eval = params.cb_eval; - cparams.cb_eval_user_data = params.cb_eval_user_data; - - auto rope_scaling_type = params.rope_scaling_type; - if (rope_scaling_type == LLAMA_ROPE_SCALING_TYPE_UNSPECIFIED) { - rope_scaling_type = hparams.rope_scaling_type_train; - } - - if (rope_scaling_type == LLAMA_ROPE_SCALING_TYPE_NONE) { - cparams.rope_freq_scale = 1.0f; // never scale if scaling type is none - } - - if (cparams.yarn_ext_factor < 0.0f) { // negative indicates 'not set' - cparams.yarn_ext_factor = rope_scaling_type == LLAMA_ROPE_SCALING_TYPE_YARN ? 1.0f : 0.0f; - } - - cparams.yarn_attn_factor *= hparams.rope_attn_factor; - - if (cparams.pooling_type == LLAMA_POOLING_TYPE_UNSPECIFIED) { - if (hparams.pooling_type == LLAMA_POOLING_TYPE_UNSPECIFIED) { - cparams.pooling_type = LLAMA_POOLING_TYPE_NONE; - } else { - cparams.pooling_type = hparams.pooling_type; - } - } - - if (params.attention_type == LLAMA_ATTENTION_TYPE_UNSPECIFIED) { - cparams.causal_attn = hparams.causal_attn; - } else { - cparams.causal_attn = params.attention_type == LLAMA_ATTENTION_TYPE_CAUSAL; - } - - const uint32_t n_ctx_per_seq = cparams.n_ctx / cparams.n_seq_max; - - LLAMA_LOG_INFO("%s: n_seq_max = %u\n", __func__, cparams.n_seq_max); - LLAMA_LOG_INFO("%s: n_ctx = %u\n", __func__, cparams.n_ctx); - LLAMA_LOG_INFO("%s: n_ctx_per_seq = %u\n", __func__, n_ctx_per_seq); - LLAMA_LOG_INFO("%s: n_batch = %u\n", __func__, cparams.n_batch); - LLAMA_LOG_INFO("%s: n_ubatch = %u\n", __func__, cparams.n_ubatch); - LLAMA_LOG_INFO("%s: flash_attn = %d\n", __func__, cparams.flash_attn); - LLAMA_LOG_INFO("%s: freq_base = %.1f\n", __func__, cparams.rope_freq_base); - LLAMA_LOG_INFO("%s: freq_scale = %g\n", __func__, cparams.rope_freq_scale); - - if (n_ctx_per_seq < hparams.n_ctx_train) { - LLAMA_LOG_WARN("%s: n_ctx_per_seq (%u) < n_ctx_train (%u) -- the full capacity of the model will not be utilized\n", - __func__, n_ctx_per_seq, hparams.n_ctx_train); - } - - if (n_ctx_per_seq > hparams.n_ctx_train) { - LLAMA_LOG_WARN("%s: n_ctx_pre_seq (%u) > n_ctx_train (%u) -- possible training context overflow\n", - __func__, n_ctx_per_seq, hparams.n_ctx_train); - } - - ctx->logits_all = params.logits_all; - - // build worst-case graph for encoder if a model contains encoder - ctx->is_encoding = llama_model_has_encoder(model); - - uint32_t kv_size = cparams.n_ctx; - ggml_type type_k = params.type_k; - ggml_type type_v = params.type_v; - - // Mamba only needs a constant number of KV cache cells per sequence - if (llama_model_is_recurrent(model)) { - // Mamba needs at least as many KV cells as there are sequences kept at any time - kv_size = std::max((uint32_t) 1, params.n_seq_max); - // it's probably best to keep as much precision as possible for the states - type_k = GGML_TYPE_F32; // required by ggml_ssm_conv for Mamba's conv_states - type_v = GGML_TYPE_F32; // required by ggml_ssm_scan for Mamba's ssm_states - } - - GGML_ASSERT(hparams.n_embd_head_k % ggml_blck_size(type_k) == 0); - GGML_ASSERT(hparams.n_embd_head_v % ggml_blck_size(type_v) == 0); - - if (!hparams.vocab_only) { - // GPU backends - for (auto * dev : model->devices) { - ggml_backend_t backend = ggml_backend_dev_init(dev, nullptr); - if (backend == nullptr) { - LLAMA_LOG_ERROR("%s: failed to initialize %s backend\n", __func__, ggml_backend_dev_name(dev)); - llama_free(ctx); - return nullptr; - } - ctx->backends.emplace_back(backend); - } - - // add ACCEL backends (such as BLAS) - for (size_t i = 0; i < ggml_backend_dev_count(); ++i) { - ggml_backend_dev_t dev = ggml_backend_dev_get(i); - if (ggml_backend_dev_type(dev) == GGML_BACKEND_DEVICE_TYPE_ACCEL) { - ggml_backend_t backend = ggml_backend_dev_init(dev, nullptr); - if (backend == nullptr) { - LLAMA_LOG_ERROR("%s: failed to initialize %s backend\n", __func__, ggml_backend_dev_name(dev)); - llama_free(ctx); - return nullptr; - } - ctx->backends.emplace_back(backend); - } - } - - // add CPU backend - ctx->backend_cpu = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr); - if (ctx->backend_cpu == nullptr) { - LLAMA_LOG_ERROR("%s: failed to initialize CPU backend\n", __func__); - llama_free(ctx); - return nullptr; - } - ctx->backends.emplace_back(ctx->backend_cpu); - - // create a list of the set_n_threads functions in the backends - for (auto & backend : ctx->backends) { - ggml_backend_dev_t dev = ggml_backend_get_device(backend.get()); - ggml_backend_reg_t reg = dev ? ggml_backend_dev_backend_reg(dev) : nullptr; - if (reg) { - auto ggml_backend_set_n_threads_fn = (ggml_backend_set_n_threads_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_set_n_threads"); - if (ggml_backend_set_n_threads_fn) { - ctx->set_n_threads_fns.emplace_back(backend.get(), ggml_backend_set_n_threads_fn); - } - } - } - - llama_set_abort_callback(ctx, params.abort_callback, params.abort_callback_data); - - if (!llama_kv_cache_init(ctx->kv_self, ctx->model, ctx->cparams, type_k, type_v, kv_size, cparams.offload_kqv)) { - LLAMA_LOG_ERROR("%s: llama_kv_cache_init() failed for self-attention cache\n", __func__); - llama_free(ctx); - return nullptr; - } - - { - size_t memory_size_k = 0; - size_t memory_size_v = 0; - - for (auto & k : ctx->kv_self.k_l) { - memory_size_k += ggml_nbytes(k); - } - - for (auto & v : ctx->kv_self.v_l) { - memory_size_v += ggml_nbytes(v); - } - - LLAMA_LOG_INFO("%s: KV self size = %7.2f MiB, K (%s): %7.2f MiB, V (%s): %7.2f MiB\n", __func__, - (float)(memory_size_k + memory_size_v) / (1024.0f * 1024.0f), - ggml_type_name(type_k), (float)memory_size_k / (1024.0f * 1024.0f), - ggml_type_name(type_v), (float)memory_size_v / (1024.0f * 1024.0f)); - } - - // graph outputs buffer - { - // resized during inference when a batch uses more outputs - if (llama_output_reserve(*ctx, params.n_seq_max) < params.n_seq_max) { - LLAMA_LOG_ERROR("%s: failed to reserve initial output buffer\n", __func__); - llama_free(ctx); - return nullptr; - } - - LLAMA_LOG_INFO("%s: %10s output buffer size = %8.2f MiB\n", __func__, - ggml_backend_buffer_name(ctx->buf_output.get()), - ggml_backend_buffer_get_size(ctx->buf_output.get()) / 1024.0 / 1024.0); - } - - // scheduler and compute buffers - { - // buffer types used for the compute buffer of each backend - std::vector backend_buft; - std::vector backend_ptrs; - for (auto & backend : ctx->backends) { - auto * buft = ggml_backend_get_default_buffer_type(backend.get()); - auto backend_type = ggml_backend_dev_type(ggml_backend_get_device(backend.get())); - if (backend_type == GGML_BACKEND_DEVICE_TYPE_CPU && !model->devices.empty()) { - // use the host buffer of the first device CPU for faster transfer of the intermediate state - auto * dev = model->devices[0]; - auto * host_buft = ggml_backend_dev_host_buffer_type(dev); - if (host_buft) { - buft = host_buft; - } - } - backend_buft.push_back(buft); - backend_ptrs.push_back(backend.get()); - } - - const size_t max_nodes = model->max_nodes(); - - // buffer used to store the computation graph and the tensor meta data - ctx->buf_compute_meta.resize(ggml_tensor_overhead()*max_nodes + ggml_graph_overhead_custom(max_nodes, false)); - - // TODO: move these checks to ggml_backend_sched - // enabling pipeline parallelism in the scheduler increases memory usage, so it is only done when necessary - bool pipeline_parallel = - model->n_devices() > 1 && - model->params.n_gpu_layers > (int)model->hparams.n_layer && - model->params.split_mode == LLAMA_SPLIT_MODE_LAYER && - params.offload_kqv; - - // pipeline parallelism requires support for async compute and events in all devices - if (pipeline_parallel) { - for (auto & backend : ctx->backends) { - auto dev_type = ggml_backend_dev_type(ggml_backend_get_device(backend.get())); - if (dev_type == GGML_BACKEND_DEVICE_TYPE_CPU) { - // ignore CPU backend - continue; - } - auto * dev = ggml_backend_get_device(backend.get()); - ggml_backend_dev_props props; - ggml_backend_dev_get_props(dev, &props); - if (!props.caps.async || !props.caps.events) { - // device does not support async compute or events - pipeline_parallel = false; - break; - } - } - } - - ctx->sched.reset(ggml_backend_sched_new(backend_ptrs.data(), backend_buft.data(), backend_ptrs.size(), max_nodes, pipeline_parallel)); - - if (pipeline_parallel) { - LLAMA_LOG_INFO("%s: pipeline parallelism enabled (n_copies=%d)\n", __func__, ggml_backend_sched_get_n_copies(ctx->sched.get())); - } - - // initialize scheduler with the worst-case graph - uint32_t n_seqs = 1; // TODO: worst-case number of sequences - uint32_t n_tokens = std::min(cparams.n_ctx, cparams.n_ubatch); - llama_token token = ctx->model.vocab.token_bos(); // not actually used by llama_build_graph, but required to choose between token and embedding inputs graph - - llama_ubatch ubatch_pp = { true, n_tokens, n_tokens / n_seqs, n_seqs, &token, nullptr, nullptr, nullptr, nullptr, nullptr}; - ggml_cgraph * gf_pp = llama_build_graph(*ctx, ubatch_pp, true); - - // reserve pp graph first so that buffers are only allocated once - ggml_backend_sched_reserve(ctx->sched.get(), gf_pp); - int n_splits_pp = ggml_backend_sched_get_n_splits(ctx->sched.get()); - int n_nodes_pp = ggml_graph_n_nodes(gf_pp); - - // reserve with tg graph to get the number of splits and nodes - llama_ubatch ubatch_tg = { true, 1, 1, n_seqs, &token, nullptr, nullptr, nullptr, nullptr, nullptr}; - ggml_cgraph * gf_tg = llama_build_graph(*ctx, ubatch_tg, true); - ggml_backend_sched_reserve(ctx->sched.get(), gf_tg); - int n_splits_tg = ggml_backend_sched_get_n_splits(ctx->sched.get()); - int n_nodes_tg = ggml_graph_n_nodes(gf_tg); - - // reserve again with pp graph to avoid ggml-alloc reallocations during inference - gf_pp = llama_build_graph(*ctx, ubatch_pp, true); - if (!ggml_backend_sched_reserve(ctx->sched.get(), gf_pp)) { - LLAMA_LOG_ERROR("%s: failed to allocate compute buffers\n", __func__); - llama_free(ctx); - return nullptr; - } - - for (size_t i = 0; i < backend_ptrs.size(); ++i) { - ggml_backend_t backend = backend_ptrs[i]; - ggml_backend_buffer_type_t buft = backend_buft[i]; - size_t size = ggml_backend_sched_get_buffer_size(ctx->sched.get(), backend); - if (size > 1) { - LLAMA_LOG_INFO("%s: %10s compute buffer size = %8.2f MiB\n", __func__, - ggml_backend_buft_name(buft), - size / 1024.0 / 1024.0); - } - } - - if (n_nodes_pp == n_nodes_tg) { - LLAMA_LOG_INFO("%s: graph nodes = %d\n", __func__, n_nodes_pp); - } else { - LLAMA_LOG_INFO("%s: graph nodes = %d (with bs=%d), %d (with bs=1)\n", __func__, n_nodes_pp, n_tokens, n_nodes_tg); - } - if (n_splits_pp == n_splits_tg) { - LLAMA_LOG_INFO("%s: graph splits = %d\n", __func__, n_splits_pp); - } else { - LLAMA_LOG_INFO("%s: graph splits = %d (with bs=%d), %d (with bs=1)\n", __func__, n_splits_pp, n_tokens, n_splits_tg); - } - } - } - - return ctx; -} - -struct llama_context * llama_new_context_with_model( - struct llama_model * model, - struct llama_context_params params) { - return llama_init_from_model(model, params); -} - -// -// kv cache -// - -// TODO: tmp bridges below until `struct llama_kv_cache` is exposed through the public API - -struct llama_kv_cache_view llama_kv_cache_view_init(const struct llama_context * ctx, int32_t n_seq_max) { - return llama_kv_cache_view_init(ctx->kv_self, n_seq_max); -} - -void llama_kv_cache_view_update(const struct llama_context * ctx, struct llama_kv_cache_view * view) { - llama_kv_cache_view_update(view, ctx->kv_self); -} - -int32_t llama_get_kv_cache_token_count(const struct llama_context * ctx) { - return llama_get_kv_cache_token_count(ctx->kv_self); -} - -int32_t llama_get_kv_cache_used_cells(const struct llama_context * ctx) { - return llama_get_kv_cache_used_cells(ctx->kv_self); -} - -void llama_kv_cache_clear(struct llama_context * ctx) { - llama_kv_cache_clear(ctx->kv_self); -} - -bool llama_kv_cache_seq_rm(struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, llama_pos p1) { - return llama_kv_cache_seq_rm(ctx->kv_self, seq_id, p0, p1); -} - -void llama_kv_cache_seq_cp(struct llama_context * ctx, llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) { - if (seq_id_src == seq_id_dst) { - return; - } - llama_kv_cache_seq_cp(ctx->kv_self, seq_id_src, seq_id_dst, p0, p1); -} - -void llama_kv_cache_seq_keep(struct llama_context * ctx, llama_seq_id seq_id) { - llama_kv_cache_seq_keep(ctx->kv_self, seq_id); -} - -void llama_kv_cache_seq_add(struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta) { - if (delta == 0) { - return; - } - - llama_kv_cache_seq_add(ctx->kv_self, seq_id, p0, p1, delta); -} - -void llama_kv_cache_seq_div(struct llama_context * ctx, llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) { - if (d == 1) { - return; - } - - llama_kv_cache_seq_div(ctx->kv_self, seq_id, p0, p1, d); -} - -llama_pos llama_kv_cache_seq_pos_max(struct llama_context * ctx, llama_seq_id seq_id) { - return llama_kv_cache_seq_pos_max(ctx->kv_self, seq_id); -} - -void llama_kv_cache_defrag(struct llama_context * ctx) { - llama_kv_cache_defrag(ctx->kv_self); -} - -void llama_kv_cache_update(struct llama_context * ctx) { - llama_kv_cache_update_impl(*ctx); -} - -bool llama_kv_cache_can_shift(struct llama_context * ctx) { - return llama_kv_cache_can_shift(ctx->kv_self); -} - -/// - -int32_t llama_encode( - struct llama_context * ctx, - struct llama_batch batch) { - const int ret = llama_encode_impl(*ctx, batch); - if (ret != 0) { - LLAMA_LOG_ERROR("%s: failed to encode, ret = %d\n", __func__, ret); - } - - return ret; -} - -int32_t llama_decode( - struct llama_context * ctx, - struct llama_batch batch) { - const int ret = llama_decode_impl(*ctx, batch); - if (ret != 0) { - LLAMA_LOG_ERROR("%s: failed to decode, ret = %d\n", __func__, ret); - } - - return ret; -} - // // chat templates // @@ -10212,7 +320,6 @@ const char * llama_print_system_info(void) { static std::string s; s.clear(); // Clear the string, since it's static, otherwise it will accumulate data from previous calls. - for (size_t i = 0; i < ggml_backend_reg_count(); i++) { auto * reg = ggml_backend_reg_get(i); auto * get_features_fn = (ggml_backend_get_features_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_get_features"); @@ -10231,43 +338,3 @@ const char * llama_print_system_info(void) { return s.c_str(); } - -// -// perf -// - -struct llama_perf_context_data llama_perf_context(const struct llama_context * ctx) { - struct llama_perf_context_data data = {}; - - if (ctx == nullptr) { - return data; - } - - data.t_start_ms = 1e-3 * ctx->t_start_us; - data.t_load_ms = 1e-3 * ctx->t_load_us; - data.t_p_eval_ms = 1e-3 * ctx->t_p_eval_us; - data.t_eval_ms = 1e-3 * ctx->t_eval_us; - data.n_p_eval = std::max(1, ctx->n_p_eval); - data.n_eval = std::max(1, ctx->n_eval); - - return data; -} - -void llama_perf_context_print(const struct llama_context * ctx) { - const auto data = llama_perf_context(ctx); - - const double t_end_ms = 1e-3 * ggml_time_us(); - - LLAMA_LOG_INFO("%s: load time = %10.2f ms\n", __func__, data.t_load_ms); - LLAMA_LOG_INFO("%s: prompt eval time = %10.2f ms / %5d tokens (%8.2f ms per token, %8.2f tokens per second)\n", - __func__, data.t_p_eval_ms, data.n_p_eval, data.t_p_eval_ms / data.n_p_eval, 1e3 / data.t_p_eval_ms * data.n_p_eval); - LLAMA_LOG_INFO("%s: eval time = %10.2f ms / %5d runs (%8.2f ms per token, %8.2f tokens per second)\n", - __func__, data.t_eval_ms, data.n_eval, data.t_eval_ms / data.n_eval, 1e3 / data.t_eval_ms * data.n_eval); - LLAMA_LOG_INFO("%s: total time = %10.2f ms / %5d tokens\n", __func__, (t_end_ms - data.t_start_ms), (data.n_p_eval + data.n_eval)); -} - -void llama_perf_context_reset(struct llama_context * ctx) { - ctx->t_start_us = ggml_time_us(); - ctx->t_eval_us = ctx->n_eval = 0; - ctx->t_p_eval_us = ctx->n_p_eval = 0; -} From be7c3034108473beda214fd1d7c98fd6a7a3bdf5 Mon Sep 17 00:00:00 2001 From: Xuan-Son Nguyen Date: Thu, 13 Mar 2025 12:34:54 +0100 Subject: [PATCH 87/87] arg : no n_predict = -2 for examples except for main and infill (#12364) --- common/arg.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/arg.cpp b/common/arg.cpp index 8531f0871..fe6a1eece 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -764,7 +764,11 @@ common_params_context common_params_parser_init(common_params & params, llama_ex ).set_env("LLAMA_ARG_CTX_SIZE")); add_opt(common_arg( {"-n", "--predict", "--n-predict"}, "N", - string_format("number of tokens to predict (default: %d, -1 = infinity, -2 = until context filled)", params.n_predict), + string_format( + ex == LLAMA_EXAMPLE_MAIN || ex == LLAMA_EXAMPLE_INFILL + ? "number of tokens to predict (default: %d, -1 = infinity, -2 = until context filled)" + : "number of tokens to predict (default: %d, -1 = infinity)", + params.n_predict), [](common_params & params, int value) { params.n_predict = value; }

kw-m0bp;<{M1v|gMB`xnoF>^`agk9v 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 delta 1215818 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%0AfjRWs_RB*31m3glM}FigqKb%4xYr_Y{u7 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 z%0A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 C=41v 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

y& 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�m5rDC#!!OP9N$-%qs1@ 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%0D{c zTO)on%(3^upPKR1>j3}Dp>?v!we=fYr2OQ}7gzo-?J`DAUT9mM zu$nCi(3n|kk+>(BUIkDr`U_~*L|9TCi4EgO{CzJ`ZMaJ!0!ftMgzM{n^pT2bRo5UE z3tW*Ti7P;^yFjxp^%^?@ezO-k1V}Q9knSzADvb?sw%go6MmtJ5KzGZn%i6zG;oK#g zmLBoZ4v8`+!VaJSr0Ix{;kpPM@v#p5^sNm^_sx?ZZ32Gui51DN<$dE;=Fy*A`){w` z^7;?XM6<0$SO(McC5NKEsN|q5cf$S$A9i;ZHkZQ@* z5;tsA6a~T!NFqSmQTt`E@E#~6L8y|>+N{!$Boi#HVdDkn6%7Oh@&K|BK#~ZSMgo;9 zYce3^(g$i#a+h-=n&o3Yx0=VFv z>Cc5!AX#(+LDAt=+w5lzE!EpdDG;Ys2MKQ=%@U9#DnjGHf)S3q6IURAb<$n-s4kiWL7@mmZb3miuq#7g%EMNF1U^Aqs@%2(;)IMia=?<{iZboc zQ*;k|iBUjV)M{lV0O2y|=@^BQaST;4tKwhzm5X9&3Ey0B4I%NhB@fqLMjC|Z;7uTd z#nK_rnnoHTxEwiENLXHo5J*tOr6$qoug?5VQ2Z>y3&8o%nF(GTIuqLBUv2rL7m6g5 zzu5eL;`s!9Yf}p={ytaz#_?N2t@``gFCLTMyh^^k$`|Y2p-uivT~Va>;` zOrKR>hI-K}@?t4h6o}Y6PCOt9U_qL+elah9R14Bfm;drBEVLI~dk9L+f{Q8$^`e;q zt$$;=4L2ytG3Sg-P0$40jc6(n%g(g3E;fOgzJqqOM=)EO~(MNwF z9r%|(aNu7CRUyH}Iyn0x6_yG?93Q>$SLeZ_rkgW(72ta4JTl3Cb)ND!hktX>E;Yh` z7OYO+tnT~xCjC>lzk2BCDS!LTzk8dj)}H+7u}NE`1?yKgf-gV+e%7D;U6Ma~@~D5R zwp|%jZUPZl|F?K%|HM;*P@uz$oFWJc0eDhj?~9@#K0NyPFJBjd1$SQfzP`{TxHcZD z^FjlO<*v=oXO_|c3P}blKoD7?fC9mP07wOkra(k{V96zT%LTY35-0)#y7^DL==D}e{%^r7yw9xD8Hx>-QkjA53mTZNMs4%3OFXNiYCSuCJiPDq+i{g zfMY+Pr~Uuo(!XBDFHax!@fTk|*!zPA>&xGV-Z-=^Eo)mj!?zERZXr z!-6VA@r$RU-qCRX*6pAc3P}WiE8qR)E2~3Ti)mCD5W)X`S|`ru}G%Z=d|_ zcaJz9ar=kQR9Uok`{lGiACp=;bo2k9W4<2F z^3NX2<@a;yZ=L@6PV$e(W$k})3{~{6S^|s1hY=wN1aWI0iX8ajQ9GA^K!zxA;2vm) zH*r}Mw?PsImP8dn<3JB7V4=ORfxZOjA8Z}{+<}b^*N)Hp;`Hmq9606M#BDaTWMHA1h0 z?k^u6y5VP^cloDhtbcn)0WSI1Z~7NU?n*cXKWn!Xu}IG1!Gmaj8AXsPpyKhPHufs#@ujrv2>&A;pD{{m1z|UTlpgm#%Q7=G1AG!d7>h&?*9xCAIy%QNO zxO3dW4HOL$7j)Dn6*^p3Ym;{D4_vGt?0x-&C&m^!bLb}P@NHLIJ9rHo`TO6v=uhwS z5{2xE|zwyL@ z``?~u*9aR}4*2S&Jd(e?CHmFnKiu%sKmGOaJ>cTPA$nlZt0F+vk=qcVznma_^(M;g zqL2U~K@jnhST+bQk|>tYRKz3@mqGL1;(_N4vYz1{& zH3J^}yC6}2sCB}XP%JN&YC&FsOJGW2UTU&+^qK#z{r`b~xLAj#fj_z01V22W$=IYp z4WP?$+$Jnq3X0(H)#-Ng9k@vpRn-a)f4z`?v2BUp{uUrnK{=GgfQZ9I z{{GgY5hU={SpU)nNYH=s;dY!jm5VVRlh5I33sNC}{qKG2pM0->d;gz$@VnRF{SM^v z>(`UN`svU`!MDFU@<%vo(f=d2BP5Dqs*5$U#BGYf^3&@>FFpLXivvL;pvJSB3Dc`$ zRX{F5wAip}-beoqFj@dhE&~)OVCfZQlP(Zl4DkGFOkzI(fdDKWsyZeV$#G^PNyUHX(ZfeMt{i_YkUelCW zTKMDp|9%ddF0MOkl3R$d$RQ|QO+uddtv6MFp9+O`9DymxF(zt}HAQHMOWhL&TC79k z!wwb)KA<3x0ze|5r=OZw= zfAt&3eiBY$ZQq`u{P$kwf6n(jdCmXu)5p8`vk!~_{wUr>^K|MuNRCa1woSG!XFys>&IFj>;>NFI2nzB2!LP)FZDQo(yfpB z`t23|iy!t^gOI;I*dJ}7{^_s(_zrfVnv$0o$uo^Fp*&o>S@nVBCFN3Ni!{1Eev#Y& zIdvXu0s}6-b(MFVyY2Z6OaO`le3w+~S-2~C&!rancGuvVlfhbvz>D|);IsV2`aeEB`aNez)UP)Ff2@E1@&vznTr9Lh z$CH0z1zi5$_3@(*tR?aQRqGC;g>b(laA z1%kF|FbI)`Hk3(4|1V$W$jLr{KoW$S-(iVTL2PyxY7oRXT>QV)CUNS2w59mcfdHXjG*LsaAX;7L6iPO)cyb)M~T{ ze#GBFU*3G}u6Vm!6x01G2B9DjpmGC4+oY#b{oqx5U?ccgM_v1W04+Jr2hMq&dp~$R zt_RU7z0$tdDE#9g=FvZA@=5*Y?<3xSysrPymcM7OPGS8$i_$miPn`dk{xbOQKDn3t z)WIJOD#-sIY46t6D6@SJe;_Y{8ryie>I4N8NkJfzJA+yfqNu0^`Sky>Ac^Ux``LT{ z-q+D%*h+$-4(l*~*Ict=y+2_&OZ_`0`4elS(>4{XG;>08O>~YR z%u@g+dmuA^z_*N{tZx^BT?$G0?|Gn@_C+!47bL9^$}u#fE*hxVW(RH}g=D$IvTh7#})_tCu=-K}d`bJ)zHVb)1`V@BB8` zvMOE=Inc20j($wUr+V_)9OpxxbehMqxQ>RsdCWca6;wN+mybKIt68b}LhNm^XtWY9 z>YA3eAf||a=0+wAV|A1A%xMEw-G$UhhcudnEWHU>BncGZ18r`_wsu*J<1J;(-yRm_ ztfhF?7J-j!SzkSMmPWRH_NZa~orxIn11@N#V(R3No};p$%Qq4V zms%B(a=KzR_uw%>e##awzruKOz?f^r`l66@x+dCHOi%Bmap;ii3>YwCG{@Ro&M;nt zejdhuv?YANsp|)CXIB(+{oR`gVm02^aQ6!R$gl@eLOOlr#>Epyd{iqJp0Ae#3dE9e zugnn-A;aIpynT;&nYE~ z7eyPeRoy)PpD->GZ3_yGyp{M*ItzE}YS#s%K;>f9@}M%FK`_?k5)w108$-w^(1>z*t{9;3FKL;i^G5k#K**#q{N)36jFuhWFs{9qrYASS<(AbniJlQ(cl zEECMh6D{3PxA7sC4TJ67mC((&*5hOHagB3Ql9kdQDXbiSL6>=PnBTeF z6|0QsfS7`^KA%J7m?)WTybd`}H5zS~k#&_>E64Ywdb#BOFyCT*zi=d{TdbX_h&lGz z+sPwl<}xBvo=wS@<(jRZ2`HJY49DK{*7hEU=0ZTSJeXF`z zNjvU=G0VaC*u%W{#vfvTB5`M6eNhvr357NzSU=WEv!UKnNcj3*fH48LIiaQqm`>3S zJ^^rgVGu8yp&fjsXb1Z=RcAaRzdB(9Bi1wQ!-3O!zAyhdkCljZBKE}v?2CWe!2?!M zTpjY3gPomGV)$!JxKE6l^IeRQM@$T-vM<&|s|PpPB{WuB32NAXhhVH-+&9a^zH}KY zYqXD?G%v2(dNhF;@dRpbT$iZ_-YNyw;k&7bBv!p zG4Fs0?x(;Gd~c$EPPN!!EH7ZIA?l0j=zEw^*}>+1W8e~SCc(rM*XqUdE76;~8F04BW-`grg4kLTTNBr` zeDd93{K6R47(mi&yho7M&9Jx7kI@(VFeg)j^F_3x?&9iybBGi4jwdm4gqvgjbp_82 z`O>fl-eCSkqsnGO{uS%<9On>2AGn|6zR&z4R&t&TA9CHnFBpF0Z5;EY*Au_L)3~id z59)C6A0Qx-*czJoUDlIVe#!Gtzq&!f=>%TH?fb;z|QHM#Vu(|IMkxTLr!O-o@p zr(josqub?W%J_i8Y$tcxeSwc00)zFe>T;3T6b$mDPks=`Y{ck}SisNNIEcIA^Pkm1 zmJvOxmv;KVi7bBdnO#k`maEw0RbcD`WBTGXvyX0nJ$2PqQI58Oq~qM%#jk~y{*XHx z#iW(4OCXntTzef);Jpp0-d_B|JyTkY169U}ZLPB{VyA#&uP}Bbv6_QfT)gan(EU&g zAzR%%yGzJ9g?sHFb)19zo?ODijC>iG;y#LKJ?tX^C;sA4!#Uw<#~S<*Q~QZ=-7{|W zd2OG6y!ZJd@A8xb@@m?p+!mj11)A<>lIxkiM`3xZeZFCWc@0OqD9dp(*e#ib8^By5iXMUTV?~@a@vCpqyH67MN zZDm1qiyR&f#&B-cN|K^nbQqT?3S0OlWkiGShA(QH306E3%`Y(z_u_$nAV`^C2F%fj z^?Kd(a&C<8L-0YZ@g^G{(5fMn#7bbj0<_8~+$-&jy!*-tU|F=WxZEs>as$NKBPB3@ z$OoNs9xpCloI4)!y9_$uKJ6s!lNjxeKRKbzC|R+4;0x%RTdFw~nd!0wbNco@cqKm7ic@VFA#cfC z=NGb1I~Uqi#`bnzDvw^p3%|BU_hAs)#Xe-8JL88x*cy1h?8v=Pyd zi*ky1rErN|9C_r*$`|CbB$z+$X9K_J$Q$Iic9LT}b*Qua;1?%bGK|d$r!IctgMq(! zw8y6!aVFsL%C+*IYkTJb{|?b_3^k4Et0Iz#q-la)cRp!bY3qa$$EQR_QSV@XpVlJW zntNZ@)jY|N=&}jvydqUoLOQ=6;vFIvL;kIOLwB>C)UuJW(*#u-6P>?!FWJC}pp95J3Vj`U%_mB;V-4+m)6 zXIGF+sXXP7r}c3i)lK3O?SW~3JHO2D12B(1wTh)8^pcxZSk=9+C1s_JgeMulehi8( z6+VcB!psP)|0K<`N9uU7tuHB!JyFUHw*_O+e!6ZNd#0r;C!Ne+;6rSILRV-8lZ&}Y zuj1bNtZN#`XAd4Jur9XCYi*WJ9&E=ts+~+y8ra|pWx2?Q+KC}QPS0?E8|3xLL(DeT z>ms7gZON$?gtfh&F*@+?$6C=L7CdlPjr-*9We{42saQ(ASDvguuz04#jdE${WJCO| z&0vcXQ{2Y;M+&z7;)YAw*^U{7SQuxF8*ZC#KZfEd)eEt2DZ|snr&76gmP3un@W@Z% zw)N@a_7S-yh@l8O+dprA`HGq5PT7_-Q-8!A_lLR&SxoLUxA2w%wS*0QO9^s&2Y)>F z+8q6_DVzg`!V@s15;5iTTH1&ed!r3MV#o(xQgy<}uA=3`)GzDAO-#;96LKwcQDJ`? z##!2B#t3&SH(qZXqWNd2)0mmIb+r;6AO}416wNy@Vnei_i$2ePd6_q^s&movyI~(0 zv&br$g;f!8?cY4bdEn|i%fKQZJ)UR!+b_9`xH-lplgV-tfxA46gTQeJdnph8=`aq( z**F~P3?|23x6?R8h*Ncgt<8?yt<$p~$8yXi$JiJ6n_o7uu(EbLnbWcf8EN-ibB;Ys z%ox|(LM1JqleArb!jkWyBT?AZxxa_Tjn%z`)R)_O4!B2m`oZtg*zJp~FC9*o%{ySN z#+WFf`G#oDwasI$o+YK9jOo0Rv3(Jxs=4LAd{~B8*71hEuEpdMo(uYE$ji{z1p|L= zdA1LJcm%^{k|j|@KhMfMH-iTNIoHb|JO zH=cFwPS&qMY827Tu9geZw*iVYF+Z-xBpS(_iG!Nrc15X)HJz^coO0-X6mw1=Pq$3u5Jn4 zU+O%6)`Zfu^Ln_}M)@J~|Di3Eo-(4RDIss1m-UO=nRy6y@C)&ldotmI#nYUEswm+h z?0G_Y-jSY{L^~nt8lrTuU{rhj(js@B5~Cu2+1$I-SyC-SE%5w8o6`N!=EMDu&EGxx zrpD&crGKB^v97oUbC)vtz-ZZ~RDW^F(+@Czv-`P~iwt_#*k*H@r&{AYEe707pU+eA zGfx(^K-BhUd=GuUOkJOB-=WXw&=dMU&C4+MAc;$gCAEzUC7%cH z%f|6!!#LhNZsFdo%{PUqf1l*OOYAf6v&)74=U8E$6He~5SHPx5DEzFwa&F$l85c&)(`f|bwz%EmFj$*FPmn`Yk=>`da|FAnRb6+{qO<%RagF6 zK{52J{x*-}{yO7+9Px@`=tcF+z(ej&nD-IeJn>IQ4S?U)%W+@thnV5e`*ZB?)Iar_ z&T(0+9$a!63f+7v81r}D?W%d1KSc3VK!W3fd||8|>k;>`dBAy{#HBjmoRSNFDg|7p z6yh2i81iGx@g27tV)K>X!xb;(l5ZVKHS$6vgE)7=n%8;Rw4gS-6Nj#1)Bzc7MKrq&CuU4 zUL_%Y7KvHgi(#$52l&V_&nYR&KVe^{5!s~hKo#)Q8FSJ3oJ zcFxjWniVV4rHrQmEuHFU#}}o1J*@+iGfInJZfTYr&xq9KjT-*$Q}__2?3i_efwA+N zC>oErYlL{?gF<^8p*@a&4}9=L3^ww6$7ehA%MNkX7fFtI$x)BtC-+l(`Fi3EbU%FH z19x$>Q?L0_bjY7YOp!CzIp0e%TS#2jaq2N$_@t`e!ku3VkWX$5sb>u0*m;-~SIjnV zp_zVj>_=L<-a}_S{{dFKZa+LC z*sQ6mb60KkrMB2tSiB08`XnwgNe=a6$mbN&G^o@r*vce-(1y4a-esu;RQid5iMgFF zm%t0rLCCC3xK&ScFu@#BH{8M}*+UdunOk9}p-2cEbHX?=ChXHRyqaE8n7ss4rwo$x ziPnYYiOh#b+F;AI*kS3{#}c$Vv`z z(Qh&8s0DC;!l)1X6!)2NpWU)adFM>-9TI}6UpVATV(YzYPPRvq*z|6%UX@Xc&?v!{ zawC@0H%g1h2lqCluuZvhV^TihCD?oq2`4qCL9E6e>#e@KmS0w&K6`LMG&d&*Kwp-+o zgH{U$)7mv{LCn+xoj!>Ek}@p?Gkir%x(Vtcgi3F?*6(32pMx?_!jcnWa>|*Md+RJ% zXNtIQvF1TwTQvcs=svfkY&gboF==npga50?=S9+Wm z-%)j^T-z)~T(nr5!kisCiG-q%&fx{N2%#=ePOV`>^7nUWT z&Acn-v`dW!j{TdGIr*!k(>HFV>#t_cV0VeR7vN?uCf|%YT!Vd0F^PgHFs3C!3&7Rrkj_{~7=4zzZI1@JXNRIvUsiVQn94`I{Ysbm1Cj?sd6;Ph!3y zRxxTFm&UpXR|4xi3sI>(@6CkbSQ1T{GrL4BDUZ|{HD(@CC9waGlu!pRS>#$P7_D30 zVc*wO2(6+8xKl7TWaX4n>V%+kms2RC?9r283DwT4XHegQ%SiAL^z>fnR4f2FkL^>i zCq-OZO>MhmxaJ}C{k=K#k#XvO=%6{^-4%>Hh~N1p>{Mg>@4fBSf#-r_`FoGc7)OuX zC6acr@o99=VK(p#iOv}{`N&UiT286+eBh~&i7g&L%Y*^)N7Cn@`&`Esd!k)MOy|1D zI~X~)*o!&;t%vf|gFf`*9(&LQDfx%kqmTyTP0EAG^%AhAW{y28Ddtyyh^{fDXamvU z0qW_sIfFr`X-7;^N}69r0ApX}FVm@0v^^A zSUNNK{>9Ca?D!}9N?dtPjN+mkc+z4$2!-rM}Bf5yf@av)LDdU+s2fRNO{jpQ4xUPeeX~Dc88$!J{Xt`AIj((P zV(nRtJt2pFAld)MG3ulKsMiF)>+F2PJSN2*8#zLOra&R9JrQ#kVx8h1qExL9dnWQO zRhD7l(QwL_^@8Dlele0vEKsOs$e9$QMip{^atqeqf-YQm{&g|=Xiy*PjFUC;gZQ_+ zeJW>WvPFKDc|fitMZF!=w_+)-O&{J<@bM%YuSI>U`*aDf?4)m1l&UPUQxDvL)8;`*HTGvrc3Ki#P1aHh3$Ek_-HFgDguPVaF~nlW2>3tPk! z)2kodBYmjhdQZf*N53zsbC0p)!>i(UWdVc8F@)#5iJ@BRl>KIukA~xkO>qZcr zha8Fqw2T?n`_28ue&DPHQ_@Yz0q+^KPIxb?-RiLpKzR&Wmuc&TgC@b^;ueAeZ4}xt znj1Fs-|n%0M?|@l&e%|w&?zk^H+#&5AzLS754>D*%TW(a5FHq>Im1a5v2@8d>d9!f zv)V)ZOTls(qm4xFCZEen;hfW*%@Lpa(NVc>P)DU1_4?rVe)7NcZ6F@!S0_${-69uYQ*w?*h9+n`D>0Wxhp%Nb=((7jk3Idr=^=^9?iq0Vy~9`un8eHa+SY=^#6ooCWa#fh7-Kg2wPJsGhd+4Gl(6%Z{oJ@O!A!qJW& z?LD1;THT7Oc-%@UO2b{@z^{ab(S!OtOdv7=SN>O*}*Xto?0?P}C zk?YYC0y9OiEL62}Sr!4BC;EN61B;wG8421>S6kGfEQ%m&6JlF(GxB+{2Wo)+5}R^H z&>kz7+|`tfe9i*x@i*#53G9bg*TiD|3+?fL3AY+~Egkx_{H!*V4?gm^o{x42e)I)@ zU!zA3#1T*3PuW>d*`d$Fk;JHn`K7aW_ZI!Q?{bpLL@jB>--%5Vp?T}=&1c-NLt;A5 z)gzCSC%e73GWT@g@zz;Pq$Jj$Z(M>YLb0E|ENsK5ZmB?CS*$;EV!od!j|yO5*7nQDZ6B~_hPdq+2MMvrB{9W+DTjhpymklu3GFiH=6;bD!4N}QE&MuF#HK!= z4w>onlbNkcfqGvBa$mE5%t`0D=|ASAi8!_90c)^k_x#Ku7OPJMvCNl<2a@S$8#|Wn zY^#m zDKYkKX{}F&zCM4xFCR(`xZFr!Y5ccNb`*VZO!@wT3I|jYMIni8_bt zuWlDd)N-Fe@Gm ze+x|(+d2AWjI^MW6gzkZoNeq!+xu1VQ_mU3Zy39NsBiC2{^4cpG5gI19&6!4eQoTa z%1?7V+)Ecny{(tCx&P67I`C*uJ;hkGe)BGP)ro5mY@-Xy1b zc0~u>F72iq^|e#Udb9WIOQv4PT-VM%ep4!-HzKWc=2s@b=D~q~=Z!qwT|4r0g+_ke zeBMv#*k>z`dII-i`47CU8*4GqKk$j6Z?Hed-v3ey-WJ#XUcW>MYH1zfta!$ljcL|_ z3rqe$AdQ69kBM#x*cl^cniD;uut8j{`4|?tRGL`+zO_VE+R7I%E;fa znT*#WB6U2}lG7c3@sj*8+1WYK1>x>p$;vWjMpBL(AzQnQBuyv@_P$5o1!}M3EodbXM!23Daq@UiK+!Ngim%#DE z?_}sp{n33pYL3z0FwmubJ#jxv$9=VWqe!y~mxeN{C(FHmv1~b?=epUflALRh2`q~j zAM#6PC1KlX#`baUnhY_CTeW+8A&GhqoEc*+?sG+-%uTwWa^V|8lD+Nj6NuC$dEJ^B zjrHb^m_ZxpHP>~{O}Zy=^PP6=;=NJ+7Y#Y)_hb)u9*Vc;1xw$l#y$l>R>lx|xy~1)=CmWv>#882kw>wAoZMkr);bUw;tjf(`?_;Sy@vFp z|9iyt4tm%>wV2`h!6u@%;LywbddeZkF(BjGIQH1(uj6=n%Z+}z z?d!aBHl%MVznT#eN1K2-gle@ThJX9oEchx{{QK9ZqIM(V=7q(O(4E~12v)qCQ4-67 zXr57j+qO?hC!;GrO}g2fmyuGXU9Z#jS!f*-XL?C=`xe=TLY#BDxX!}>SwN=0y~*5{ z`ciJ&S0A)_PW6z_xs%B|JXq2JAwxcwv}gSTzmLy|@l5I13ngEPJ#q5(zv-+WbHM(m zmtfSGb6Xc2pC!7_mb~P;Mt!}Wm+GFDX?$PFK+CL`e_Dmi=vB^15+>TPxDF^OGWP|h z%t^n5b$!<5zT5NE>r_m&WXy1v>2^g;9g)7hNtV_HGxI35`!JDx(A!w(!gu3Y zQm6JN5>7>uW~sE*ZUr5)Qt}uD?9_r<`6#GLf6&j+n2!-*F+^0?HbYF!ugxUBc`5B}SLzsku3>n!Mx9)Q*m83;c2 zfAYh}-h)vux{rR>QaHp;XZxi*a)Spwh5d-j7S|_D#W6M}3*_@I^C#cRXioi2NM`q> zw~vu-cE$GcB1-sHRVr0Wg8aX^f_nz>ET^4pLOMfCRD|sF#qFqg3pF9>ZxwdyPX_QXWe*+&rCrhkz4bi508hNF^bM#L2to@*|+Mn%- z-+FIwPkozNN|R2@p%L7`;4{D@vwfl>ksVjd)Td&JC z-K)Ygh7&ENplR=R>Qj_ld!l-iHVwEQaFTA|@tcvaMn07L!-v($K^ytNGd`~&f1mMs zj=deDAG{yxNN2jphxqKTyyQ_gV7+8z{6xT3ELNq|&67&n$1u^KK53V(mVviSy~sKO z$^;MY7R0m*PGHR~a`_b%NxJdr)FH+eYxJpcu>m`BgC1>NKnxMenn1}tQJI>Px^a`@ zo*UGRnSGL~^}*b5S~jUy>J_)se|0hx7P^HWw^yO5Un${>QKLsZugzFj4kr@_wm?4( z418{3Mm~4Mia`&CkDMRO=WsobT>g{JC}JW5p0t(K!wZk22N%3K#Fz}caaZr27R=5T z+9p02u}w3+#=yW90lf2wg8GKTdX|f#T{)lkv)+Rl{i&-e_rLUDI>c_SB3g$mP9-Ifuu_xSj@+Du zkyLj)2`edl6se7;bHOe7_nynjoqT9dqSq21}tFbazylElj6dFRg{N!ElA2jiZ!+PncRApXTffu3h$a2ff+C(xljbq7 zH3O|ZsMZg$u?${Ie~Erw3^Au>LJxf(F-l|d%c=Fc)T4$6VDdTbctXH1-)VDhrc#!g zEH%#*ZMQPE$b(9eGl#Z;YF|P;yI`b<$TGk2yQzz~7gYJ>Vuk(Z_9w4>wAjDA1d4rQ zsS&36i{4v)uEEbvvGZ@7?IAy%spv8Nw+gA<1~d$ zP3YyDH{XBCRYnLY;em_y#iXr2l+E*OyN*e@E9X_Ik|91pezm-VhZ*Q${qTESKmOq? zv9o&UC30DC{r~i$rz4jOCw{CZw-y4Fhjf6jUh#&TiorS{%(0ncV&i+D6o)VL|x7EWfS1Z=m`*~^=-Y3^PV)XAO0a~6c#_RG79 zxa{j%I^#J~-sB>Kb&B}P&A`{}2LFWG{D*wDc=;!{`M}wIIq^7-d0_X)88E{*ObK6c z69lkre-+kno_9QR8I;0I6|t?6X}PC{f5008c*S1YA{NOkA~u(zF77$zyXln3Iz_G8 zD7i9oLU_nby8vC>XZwQFt$u=CN*SrkfP)Wa8d0!}4*hl$T)#71zaGFR=Cyt|4Tt`K zV_(k+qf`5nE$e1ArU(0cgBy+yGmvst7JCvY8R6| z;_Dw42AtA0hklT8f1yo1*@7|dI@6o|;fhpfzi|(KRlKKN>yc{Ok!A6M^;QNgqf3>_ ze{SkF?;r$G5&6)>>w%KEjii3Bd|^_7+Gs47U{lE*9=oU;ZPFEs2Ym<9yc@wfdE^6M zfoYM)=;7z4yUJKX`^H01{SMTgrFO z{j^nJ;tj7iylSzK>Crgf4gD%CocP9n$GBn+hx14Ftv>Xt^k+TeXe+bPW*&GD<9K%y z@Kn_tarv&j5BK@k^Bx+NWokGg8{3bGe(ZFf7!6!1|0Yw9OB>bEmOEii19d4(zKBqqwdS%nV6h$ zBk9v??aQR7gqc2I{wp-du^+L_wRz@u%q23wvp{I4UnrRGu&GP(jdd35k>OllfBjh1MMrJQ zXmvPWlPo66`oB>3;U0Ci_C_D#*3q7wIAk(8ju)I__aW!?|pM2~!vvmP?6 zdHvBph}YhEqhk3PmokD3IRq*a0pC?aSh~wIEt$U-WO2g~seA9?BLHVt!};~qZKTKyy6 zKh(a{KY07&xmEw*svmU$D&&wh#auLrxP&Lr`4^sDzcFnV!89PYe+XDCTx$7yfaE@^ z@l1rkwT16l6$m|O+J)|tze=n*_8hqtHEcc?wDVQ!H;=?|DA^Z^tn)U!isr(koas6c zS7J`gY`*|5LoiFfZ(62RO^t0s)QmGqaGF1de0DFA*%Jrs@kQGw$G*mGO06a_xGC0i zo-^tUx~Wlj#;@p$f0r|D@bh?hf54INg+Uy#cs=G@Xa3_q^{}G{X?BnLJ(_<9zSWi zdBnqOvTXNP434FrD8;o;>YeD;TLaa56@cn--_EHV|5xZbRn(@W2$Wbu4kF1D!`_ESpT;z|%pp0@Qj z>L`a>;6eFmU6axlau>|~7w9(f>uKVOm$fkK=NvhtHn|@7eoo==xarg~PDIQ(Tukn6 z_G=)U{til#c-i_rz{^;~tm_uH0!t{^5 zr3Wtiz=h^U{Akr@|M2_6S*?eDRLAf6ANnwdST$otW+x1$y(w6k_M}W3(W^D;^m4%G z%P6tp4Rp%|$wQY&mr_5MNh7g#3O44ssmYCgzL-OL$89n3tMn_0fq|XQ$#Cx6#g zFZyb}f1sYRp&2}Q^^;2uJ6SmJ_;~CikIydJCE1@HP;$?>dy73SHGWUJMbhA zy42G7?ac0DTtB;X8XH1}91k&hYXV0~IDdFpps4mvt`EDLIj{XLF2_n-D$+u{`8opEB) ztB;sdm*fU($v^Qz)4ScQi6A9m;s~y%e_=?_N8veM=`!BKi_(&;Y)YPqxtB|4?A?O9 zl`PXQ-#Rh8?rwx>)}+kv08UB>zsczAh3lNotklC<^poX8Sz&Py%1m8OP3St9vgC}@)^RnSt00|_u!|>1Z>e}Die>X+HZTMurLj?A(_0@)za{g*&Pwa;4CFT!#6W_-E z6K~U{+sz;NBu{g)48&4ryYBu%G_%#Td?I2ZbJcB?yR_?F*SPMBeVBHi#GSRpD&D_( zEB&}8*V;4Y=_Q_l_iJY2ihj!_FR%MR%3g1qN^9SB>gy!E^Eb_lOV`%_e@I_L`uOSJ zsm80S%V3eet>{Y=JWt=_{#^y%`eU7Z=b^BzQ(eAHI(q+KmcwBR8k61!lMM=dhfsra;+i2P67pD4MdUG#l!(qe}e-44m4*Q0~zcL z2<`2FN^&=utYI?+sXYcHC6^j5VTJk;a)$4}L0q=ATf48Z?yn`GYxr zzQVv7nijbAzW`=*X>mL>1Xj()_Y(%|90Cx?OeY4%Z&;6EH0g6#nME+Ud!58qZ^qyM z^9z@NB;Vj_7+7^d03T=vsDh@U-}sUz0EHTs|MdFx6hNw@JM)PLcrzFz*mWHOmtEGCzWNi>-~Pnz%EPJ-*%`=o!H1l!r$cfXqi z%h~I5znb`q+0%1(@X%Sy3Iz$CW@*iM8kte2}@Wh3%s1FfG^OnMrrH_P3ZhrkwOZ608NxIbrfgZc zUL~{xeaYfgB=S{a13_}R;fMRBre)*%)bKtAsW8JhS1;VO@TONT;Qh>SKX@~4Pi?fr zd%#srKFuoIt=(Io{sxr3np+Tl-U11S_fpp~f37ykEj$hHCpTffF&f;tWjxw`K??b9 zw_dwq-2(quW%afNqE~LVUL~Y%$(l*WUxynIAtgeF!2Ok|WeA?WBzX(PR)2t$j@-xu z?;%XM0XIC1DfF#bhuq6+X<9J&S~t$jrqw*sPPQGs-vZ5fwrwGOmkG6$D^pc8z|Yez ze?j;g;QmhJxqwZc`Rf&p)-tQHi*~sRfdpM!ww$a_bC+CM()X68>Z8Ra$|IwzD@$o_ zX%bP{V#x3Hp?^v!1rbt}i`oa?LklmMx4U!FkLZ5E)G(LWY=s({xu|D1h#{2y21z>&>l`&5&tl+bS>9GH$6YLq* z9i2?CDBs9ltb>YwwlHg3Eor zSPy-sS0N|3R&e}u^BzdqZ1WB1f1u*q7DRdWGp=9ISJaO8kh}5sxc={0e2dTjh<51D zwbN6}YTS1ka;ymA+;C!6D_n<>L1drz5zZ}Z0WMn1rPFc!io`;zfyP;!52p}SM6@u) zJr&7e4@r}UMebsbgfR*CscwdGO{Ei9Sh<}5^U=!o!|jJTS>bqzr2TA3f6=y@XF-2u zUD|h0rXS%3)?vumc)e*`t;g$q-;sE@UW6fc$Lmhp>SDO=ReeXvaQ!(9xj$T|ZHwc4 zoc|WqCb^7r*~3>0;t~A^?%R;sEv}j4z7#Jc%!JuW`pd#SA8bsxfzOaC(-Kk*V|oiO zIj$F~O!xt$DBDtI^=C_=e}xbh!7T@f4Rn;k|g-5X<#9Kuqt`)kT)A=#;)SF8eZF5Xkqs8zrH@A)4AK;1kpFJ*~E&KOofo=dP-zTS;M7ZSn85e}BFwfv>oaJb8t&MZVP^ zTmcU(b<~Fpv1!$yUyWCx;u2Eh-YV{!^kJ3ygWsez`sT=!PO;6C$jw7=2mk%IHHN;q zKgKaJ%U!)~A!GR})~gV>zT%tVXMsL#W#Q#7W1lE9#2i)R=1a4Yw-9LO!9umNv_5=} z6|Ubk`>VaZe}e7!Ip&tsXxsTm3n|)bj4SBh)(oNRa*T6GEpLJ0cZ{9fUX`ogK2M3Z zXcmS5;sfr{w&1=aNp8a9eC{o-o4fPZw9ssIg-B+;jc@U@Mdh4c*+tdkTD78&XbWnG zer231*Mf-iu!0%Jn)v&lYdE&)4t>_~wWL~El4Snqf0yckkdj}i?Qw1W`#x7+vInz} z%@qB9xPi&)z2E_(4vixhjsp7g%jl|`Ak-sF$+W-J`G9+UStjl!S+6L}R>`kU0Z-As>b|%0s{Q9{wR`FR z@!FX7e|Fw~1^7I}era%Q{@e3>SyHR7mZ6O&;xLBe{yWb5m1`M|=y9F2@X3N+nFWO} zxvzfyKKfFlclzV(9{<1gFxs7e-7CZXkn%mq6KVmvDF^uz!+!by#eE+gdUNaFCb%lFMRgQiQT{O@E<(;H$Hsor`7B4u_OD@ZD?7ApK$>Dp~=|~ z>(QH6`->-8?!o5IoYMUZOKO_H{*65zTK>WoKeS{2YBRu3-SvK0KfFG_)fhk}S@yw~ z+%J9=bOv%iv#k{P=Yn~||Q;z@4Z*0{{e}D3dwXDjo zBT#0zYd#rfdq(qLH)hFb>e4>z;f$>bEfZGu^Zl&F8h^Zek>H#vBgvj$V;sZDf%XS0 zw#n+GY%Pl6Ue=E>3zl3p{-1J;U`LM+CrG@GV})n^dfu5ASS5_mBm&0>&dmmv#0a+V z|IM4nhKyJ~-r$y5d62d=f0l_skS?f^sUCl;#yoLJ4@)9J@HtN;`%kIhDaTpN6C33@ z$FY?X{=9#eKkvEix&LSh+5HQ`&whZP_?*9g3iFa5URn0{ik_PJ-8b-?|8Zsi%lq+$P8eskt{{JWaPTu(f0-C~}VWyWUMj(O=!Y_Y?06`0IC zM{<7h-IEUwwtLR!$j`pKpFFcaRsa8J_k8vN{7bvo)2{R2C4osEzq24b?NpDeJhIr0 zd9}~`>N(#WSx-Mxe~fFf)l+}`(D8cirDE5o-SBwAvr|k`ve0vHNpd{&q)haueXacE z)BI^?ead;yKAV7H3r2vRJj6&Pqgns1UhSdJf8-;U%;#W@C!am{)o>8w{FD=zgkh(L zU;nu$@g+0q@#LvrzIfqj|9s-&$P5cT^+)ByhxgR;ecFvJe|G;%Zm;l>&;E3-RxEGkE@}Wm&qJse*d1?%!KIP&+{Vp@C^G7~E z{g*xcC_VK4e~Vsm4C6liCPBY?_5Y+t<+GqQK6*1g{HMo*|Iy1o{ruP$_2>cg&=LN~ z$$Oqpj~&X)U;6iBe?N5n(gQ#Fi20@SN1vqfmmX1n^iltz^I(tPe*Jgt>i@3ZU;PMv z_nKA7B=&O4`cWD2!Uj4HQ zCLB+we|hg`$an^E=|^{np)$L@LS*&l&0 ze9D*%gFo^xpY>oKdd6$enRE#6D^6?Pmu}Ucn4{@p`%#5?L8k50E-yXUk9ITgBNdQ+Y z>hH13+@@=ZzEpLYBuK6#Zeed%Ojk`z$4;zoOc4TCEbJdC(ya-C@t#yo49woK^`}lq zf56#5TvMs4SV?*65hFz0l0Xn6$zL-`cts!fj)U`?lr|B4?218rD71VimY)Cil%RIS z23z$+0bu*HN&=+~|Egc%nI4Ckp_*8P-r~Tx9y-##`m)0>eY)k}agc4HWkBJ_du4yM zXB@HA@*z@94EoUQf0Mu;LM!@h+ZBXVf2tzW>YrR*Xv@Z~yr}ZOfi-*OdRK|MGwSw_+T&|GkLQ{Qvlq>g(?M zhZ?*2=f6AgusZot7ytJ2Zr!df|HtrD()~U;^17_He~=LLZ|jo&V_&-eoW)!Ge~;%S zc#K7X{96*QIf4Dx45B6dpNq2`fHBO^`Z5!8CBtxZ@gFae|BD&*3{#ee9F%>^vx3Zx zlIoh7%eWz@FeV?DJNujvmYG1|%bZJ&i`A+;>As3D%J_1oX z!X!tAUf4VH^~96JF#JlV$_9Wcf2!}C56=2S$6J312`yu1a2d@)z=^b3TgTQcWS;^{ zzS4wiybrDgOCIz4huS{{pE=J-+*5ruj5rQ3epf;aTsE2;OaDD~a|E7vVt8QX7L!Cy zb28zX-*Yoz>nsAn8>uNY^FfrwkN#+c zMT{-=9dYmB0^coJd{e7b8g0oOgW6nn)lI`dfCwPcCbN8jQQv0p%7BA;xn&DoqHN{E ziV!L=cG2fuv>5oM-yIPtfn=aTk2nmLs5cbAn6}c`g7iI0qaame_v_lumUq0eVp667 zefUj($bo**bf2|H89@-+f0nwi-n&%d^StnytaypQz=&^v&Y*f_bqY=5sxi3t?Q?XDDrvyjWtx7EcRO6fj#2E(eNz{wm+XG> zY~OhMwQX&Wqqxc@3Nm!NnU+^VSY3WQKylz>#npb5!F(fCoYt6w1;!X%<4}nGZ>Qs?8t6Z z#xSB?QT!@px&1jnf4>HRpm^C5!M{>Y8;rD!c%WGp@`ms0pq|UA-t(d#Oc{n_B75zJ z{fxBm^gP`(VU%kp}**!OnPRzEe-~ zU4S}~=-N%|Bldm|1@X;ebbI%?lRImPd0+Uue<|=gpv!oGf5nbghmV49>J7x7g(is_ zR)_C*-*+?U5fVaT#+aK|I)6m}V?y@IxlQy1{rSL5=Vh_oY#kQ4=pfl`fOywia=Rdq z5Ma4Ck={yWJ0&K<j8*xj*gG&cyU&O?g4Ew#) zNRGG_!j8k1G{0ue@U)&NaE#chQ#M~WR8eO#bi@Nf6G}_?sBfM}ZGzBQvY7~rM(Z*r zlo!|}Ax-haOPAFA4kQ)X*PRnHHo$&moE!K_{54(z)zm-lmks?69)C;LijGnCt)rVw zv5-E_aJsG+&b=_AL|NI(A_r2hv82M`i~x~SMR);Zxk_T_EIyo2mY=EhH{q%qDGDsc z2rGgRgkA>+*%01oW2nTt8}D$A`&w7jTN_wCu4i?7RlD=5f+1^f-dW$(O9AojRP@5K zHG2&fpgN}b#ukhJet*&+3Ov^eZ&Pm+R;*LL)YA}4gjGLO4)-0FdYvkve1ljsblu~f zoF_;Qc4KNHeM*cz>5b$`W_%bvd+#BKyt=PXA2 zs2V~lVPpdW`cX0Y6Z!&eGCEYRyC?PUstxUTplbRG)r24DxQ!%`0;+Gv|H@vmBNd5s~|#s-7&2Ei=cI|)h8Wdd+6Oo)zNmpD0<0Nm~sz7b6_DSSpi zMmnbS6GV`u;@t`ngue>aRr*X`t+30I_o*x5*50@=mb&1mWT2%`H!e&OF@JK7*FD=_ z!eY}D`jIr2msOUA;1`{CH0Ju~-KH-&B(2cXa|3>C8&?b0(hq&KBm@&Wn#3U5{(8h5 zpZ-$snU!_3Q3=M$iPKw0?9rLX$ux$EKgPnLTm5ah-@IeT{Is zTGSc|(eyd{eh81TIBvP`DuHV@=rzZk(75LuQku_cEn;zXKwfq_7slOg)p5x!BXnQ= zji{n*Mg>u}yyU&yW`vx}sF>7Ft%Sy6L9L zhZw7ExK$SX#PD4OMeFb%QfFx0s8LsIdgM3 zzR-&hu-6!2$3CzvM7;NJ$pbXwylF@7ma*LQLmYFju{dn`>S|QODUpK099?*>+4k62 z8yCZfwF!iWn=kloF6xN-mvJvQ#l@ASY?)vzbvY|Z5~uh~&!ObqaHVUnvR`#`3ifS_ zh9MQm=;WI#w||8s(sfzn!8az6>-_!$LQHQN z|GFxN9f7l~PSZLg`cZYqvvgR~tp+0XBW<>NYTMe7BIQuKe8%7bo7PkJQP~`V@w_C< zX*z4xolS22vBT`T^=2fmuy1>1GnR``Kcw(rQ(uu;I!^1-(PR!YSbcV3-oObZfc&zM zA<5U^Vt+=wq%axRo%U30-!PXr@99yz(%x@l!h=ZlcB;shr1z0})e3D4Rn9XrRIEpWV8lf^1JR&43>B2e6{-udPj^<~3b8(XDlOj??}Behh8 zE`0}DyPoIa*x;@R^H(D$Yb+W>%wrleW1|k46MtsZYD~B{(j7IO#*j4jLYJqcSLLK5ot^+w<1wKVD*2i5uooirK)*w6Og#;hKTa)tgZ2ED=_a^# zi8T-kdZdo2HK}zTZYVKkZi~^zGP(V-kaQ}&Q9QQho3wimrw%u8rzrI!Yu*kE z7k?*SNJNg?aJfoVwLUCs)y<*w8s0kL@LO78l643+M(>2xq&dd@PX^O*>l9s$)i4a> zS<^9&=2A41L5T2G$^LHD#msm{qG+Gd>hAyj#>JkXO>`Agj-g z!hQuty@naL&eWpU6rhe$)M2n9M}P1+5MKnA)|KV}N}Z(>qgLYHx?EO~DM;c(vry?% zPf#|F^G=OGV;EbeXpBD3qoQC&cYjYq*EYdfmm=V`alOHLnSgb=UiKU6C@mmubwpHSX=@%vmP~f`=yb7B;4^NQrvwXRY>TI`S~=v12g-jDLeuX}?_t zP!S!?Bo%s<7I|{ZvZQ)7?INGTbUbj5{<5$+I$wd9u&EJq2dP1Kw^=?bZD&ZNL9vz0 z@fq?Lmz7Fv<2N6{q-bB9#JBtBAbSFcXf zl)#U+I;h?oezu%2;iAezmV2cef@)_j1x(XO z0jl3uh@z16!9Hu#N@{-**jJ>>yjwhI1jT~SA@RJ)T2pT){EQvnyPMl?k%v&p1pt?b z=|_Y`iDwi%;G!UT%75o7c0(%@Utf#6+!?}iaGJ)7-s(FxYc;S9@M>uyfZpPp^g-A8 zu;Yje5pEY{JCWEsr;|%MNebf9Nr}-ON2Ns!3C}Wi2){TkT*r|Za@Jr8NMDyokKYn( z=SQ$PBKNxSNB|9Tk6wani0QP}mCvQ}B0!-W(v$1NV?_;lc7M<1o89#?*+c!!UA_SD z{cuxq93Mb(z#|(^$ShNeOBCO-_-1UPMaSiY0{OSc=KvmpU+4cvf*+Ho#N57;29|Gb7?w5gJ_GLnDpLA5*Lu>k5e%d? zd7a8GR!1!XXvSgSmsG(^v{>XMH1gKYGzT$7);7G>b%MuuO7EB02@fWJ+|THr$CNoXXPtGXheLq|l|^fm1PY%!395N| zSu6!NrLO|udTfZEzKR^LjaWHK6Lw*1MDngVoNhtQq26_FWaJ5BtRM zTqj!(Xx-Zxvt;wEYC~Rt(z@l@I_Rocbv+C}6^82IYI*BGmi9($PUlC6)Cxoz!jO02 zsGGEe!Bad14zj8OSpOCGeYFFBpB2CR-8P-qr7KaH=$=xO<3f}baYC*4_lD*)hLSM! zwk~uGEwyA-*>w!o4nH~7+qXWc9x>`vUl~AwC)UVLR3*~qUgdJ&NPuNIn#|3G=f769 z8fJ%G3ELmQ&lhr**k78v2&{<7s`P6Vv2iw}=vw2uspUN}?y$h?!z`751b-_rh9Div zd4V|9H!&ix5^Vt20~=r6gX40|>mxIf<}p`0kzIS_pkmd#Fk)lg=;&TpiFdkobbpnp zGmH;6bkU;C+l1@OoEUu9Gr*UkCEImx9>*YLy^Jrd0(IJ>{n+Bx^quLZs0(B~w^FqU z&c0@0_SfS)@;HcQ)vf1$qzPkzBE7TTq*cFS%*k`!sdKbX$|}M3nL|JR1>1$R5uEht z`+O%o98y;;@`RBAJ!nx7k~rJL`YI-rd*W5iw##pz{Ho`7(I4fx2K*ONP#|koNN z;?M#hb|X2WFUuvqJ~q2nSYEc?a~4hF6))X>!1&ob!jY$^r<_w8ORRga8j#m>A2%J=RDP>rPOHT<3vUv{^8FMg(P0+ z&)@~8j^gw45rmi5ximGhbR0E(s!?dc&1ke03^2$s3J9E*vGQY59J#MWg6fj@5fnT5 zOq_tNE{p}L!<55+3zN)x&c*jh_9kTl7#yVm9PFcBTGrPd3>ZvJsI7SDw0R-oooJ-P zLLhxDyxUF&<#%Dn)qDJUyDZB}J34~9^wQ0&p29(d>y$x{c7t8`q4BmN?jwz{S(zM) zGw>IE*EO;pCUJHtcXo*VjpY!ozf|iZL<60Ln{5k_Dh(}vf)$dDH~dz)7)lyxHvAS6 zvzE$*owG)l*+NIlYlti}fZgUU2^a4CtPq1xV)E+6W7q7nKvg=AAfF&E_M4>eXBA2^ zlP+hO-uM}HtnX%YDfaZ2)RcFT*bO--JIM~$fR4>QzP@GsDf$4q+Xm@C5Jy3mvc#b2 zV!Ecs!9py5vhZVY-y8o$uhg+wWK`?nLCmSy9OnvrUfX8&1D;487;H^H)2{5v^veoQ z`$}jSBat@Tbi8Q3I`ty(HC}Q3*ryx;khViGpeiS=et(NB$6WiH_6SOfl2NW`!ycGN z`Po8MIxw4=tAk%C7{RG3-aZfPnm2DznkP%9lMi5h~&QLE;z|riVDALSV1$T7cw|40pP)JLC1Jj8?mozEwmfZ^* zL3!>NuH>X9@w5(-dM~UaRLsgG2BwOD#XB|+y5d((&T&fI3|LKgV^Z0aI(glV{C!`Y zeXeB1Sr%D<(A#8WjR#>I1HWgff(=!_V3)Wt1}0da%PJjMh4;P{9JkD6dteyCxgV5& zQOgnRto8UXcKRB&}LEZp7=uTUYePE(7UPqgWt>frb zp4{E4Uur5@E;y%3ZQ%XZeKf624TQU1^5yr6nC6Rkg; zz)sa$VP#*<_Draz!f2+o}?Nti+g}@X6Ayn1;gKJHlcjN7Q0C7 ztC>g^&8j^m@RQI`h9B`#`m75Vn0bLc0d%UjK!}*qz3CTo=(~)_E~gMD~=Ritjz5l*%dhd2jGnWC$IP~-yDO-+;?9g0=n1xy#ce@Jqiy)s`Y`?U7gRF=uo!qKuD-)2MDqsKZ!>wAlc!n{N+d%Dl z`w8N|zUGBFHIR5NIDswVY|V)h7Wt}RT)h0s#uO?;zYe{OB9bXc%uXc|&yJFFu&vEP zu^+Y`!p8-sRR(^KWxBb4x86%b8P&j0zj4pf+K|V*1^VrtO`HZ zMRVQ@6TLEKKB$cwPA$Kv1tDID;R_qVPCwZu)F#h$qjBsARPrKn z!;pl_p#cC#TtBItNbr^rTwWL1xa>Ek#wNkgv&dP2?q2l}10Sn@Io@pm&xr1&h-=&3 zJbUdn$uw%e%9~jWRUVt}h~L+zpf?IFF@Wk z_2pr>yBr9!a@&qU4mBUj$aHXNXdB|;?4Ni|LED(gJN3{n*+TTX(7Tr_PLh7B}H9xNx{|Y1|-93~i*%v*3p;IBo(qty-Yi=&{TzL?^ zx@BEH&{e>ysxLQ?;ODB#!OTH-F(|61d;q-~1?$_4#4+~_+V*}yT;IJYy6AmNnQ=9Z zpcH4YtOUGN3g#Ui@baK!Q0m4t!0Oze%?y$T@6CW~r`X|cnj&00g5+?iY1)J=hKhlT z0q09li}h@O?2J~7#nkl<>cR%ljVeV>wz#TbV9E1YbM{4$oa;~JOCASv`o=?rSU84z z1E9nlJL#p7P)nHqMj$%-M1WGM-Zh~vS{!Y@yPkL$(V*40Pm{z~{lq~s$BlU*^B8p- z*et*ue$`L2=PRJ1ev=Zig7|f-@ni_dAf6e#P$L+BxI{#o`FfTgpl5fTGp9u1h@ZR% z3ySCH7_L8|3&r0)IK3n{547rFbofvNsKpo}zZKs$9gYdRJ-u2nzHmAZ>c|^_1qW5En|A86>XUstslHi2t`Ij(-zS&W}5iedhf^gu6lx~ zq2hOcN@?S!QMC(edAP*nEtltTk9w%T!{DYU92V;WHfod}Kdx$FxRJwYkXn@p8;8~m zPCW;r(4I@Pzrs5jn^@6cJ)R0MgugpNp%nI=m3C%1;k)+l^4ltXP;L8wKq*^)v_7GD z`FqAzB-l)Qt?ddH1|5qnG`xsRp0kCA@aE#7URf|eK%@bt4g9E1Y7UDOk$VKav24JX zca(?n`vjnKxqC43t@K)8(-f7PHz)u7?kcZCC1NCbw`97GaltHY04UdD0!_vBw2JiV zKrpe-7z*YsA2OpDIhVX(5?n&&o@O)x>vW7n_BS~nbWj()!&cWXp!sGU<@E)=XbVasnYRrX>>{jLme_ZCYPoY z{C}6D%p#V)I*ia2yq^p zo3QqV)nkUcxlfml8j#O`-X<((H|ArF-K>)oUoTM1?=_A3`yh_S+X(|~@S0&Gpnqz_ zOk~Bq#GwO(lF#L+kTTE$DN!I}|RiHB0s?Sef20De!!K%xr{j3Ch~5!r;L z0DqKv>ohXXm%9s3vd`cvVIQigWq;z7ejI)Vj6wE-sP6kEq}O+P^TMPuFL1`wcJRYS za4Jx@DsoRD-PU5~O(OtcoUtWYU+q{95U5{1=w=?W_+M2CiD>h?n4;^~8WWRJYxWh* zA*f7M-7IvIO$+SC4)2wj5e5oE@T$%@I<87qoQm`4l$&prgx|TJ7pEGsxqrNh_c#$# zI#k<;t93AZ^Fa9k<#d}nf+G6_yu)_gcCI6JTQou~4y0+$5jE#wAmnD5#zez%5V`ie zMJ3L_h1)Di-~;h8NC%r$K(h(griDRkXE2fS8v1Eha^I)3W)jVPs`em}KTeM5oF zYu-SDg8HlYnpio2{)y9Pbbs>0ni~TOLTg#=p&f=~d4;PUWKRBp-Y_^V)=UB)Tq{(< zDkf?Q?F=V_f>o`Lz6g<>$I?z#`-&C{HoxP0kv^{xXy5s$EYp>|@Dz6DIyAm#?~A7mssO_OxUcU-W~&vR=VwLM&40by=G&QSz^yMq z1l9W;Xg+ll(cVbF6}JWaf(#SOyM>Uc;Eb|h1jwR>SRN6g*-QC}F;k!Yyo&OS-PS(p zT%n2M29w}Dp*^k-vf3hf9+`O|*M4dC8&94wbYDfEA$3N1buS(8Iv2z8>As{7ns~>` zl@lVixsr#^R4dg0PJd^cG`Og`Ex`DudjvCXP7Vg|I6X}^TE9-d$GsTiW9X%rzG!Ld zziBh`-bP^S{r0{=+bcgR;eFPKPKIuYMXT>SKzs3X4JhxZcZ_v^m!>gp0$>xuB>Dtk zsd^hR%50$HZ49<(a_(Aj&|5iOPeG!A?z7HeP!~jq5yVN=g)C?fm*(MulZ|Al~ zz4ea?PY2t}2!EMcHpvzD_04WlvI3GQk|}eh?45<5AXVEcc!O(9z-;u1lpiE6a<7Ngk@%mCAevT zQTd9x$G3_z_x+|SKTX4t4$~e%81tCV^TZU9wq9hv65fI;%^;(AY_}7=OrHfsL3xyh zd;0i_Kl*{&8~a)S?%_ct!n&V)LpwX`D&qxwDt)Ku%|_;UR}h2icWTMr>tewEkl!8J zq)naLXnzhQ8ZUhT+134712jaWT*p5!SM*wAvU+et*SM=#tx6!NVR3t}ysP!J)te4O77b_Ve0WO@7axC0I#SEkPBUPLLyBQDtv%^oi6H1~bCmkufxhx=mBDEsA{$ zP345CcNy?@77Mi0I2u|C>DASty+jx&2K<6o)qijmv6{TUuOkd6x6!}0Q@fS5=vS)< zwO)Vl42X7-AV;YxSR5Kf9*-RAi3V9T0iYx#K$Pj%9Ghh?%peW*kbL=p@EO|G3wb1Q zUn}p0^cP%vHXnLzu5tb&8)x)O)EGB@f5OQ=U#w>S+<~$=9 zGDMVx94>Q5kQX=0GGMgQASECavPyxs_mW3}+7w zh-_^ngwP?3k9#h*+ghzX={a&svSA)F@%4mHcxfjV#S?N1DB;@W98&Gr>^$uPyiSI9 z0E~5Gl<*RW-*>gYqrUB5+^8C%XMZ4&=C2WGl{^ExP8F}l3{hMghB02RbiedGr+<^= zgQ@35)Bq3GlPtG*-TV9@y`l^47qy|vK%6|!?rpY)J_yN$5;dFEt~ZBFX<^3TBoJPQ zbz1IjOI+=~1ulh!f$Wu*eK}JHPQH151R9ZJ&}ekXZp1HSKoVF|Q^GlXD}Mv(X5Ydw zu(DM{b8`>D%Y##Q;UU+(Y+pNeTE7KP{%gkTIp7JnzF z;6|-)Y^}y}8*x4)(3g&8M}Gm9Y#C3-KM2TJ1a9qbgR8( zd@|?GqmgPeY{g+D-Yga;`l8>4<%MW>(4m<$o)>}Bv}eQF^JBUMK7X$yXPx0;@ERvZ z`^GAZ^MZvNYjk5}FcI(d#=Q1(o>+CWwb}esGb2Vvp-W?%6(ECKJUVx6PsGYL;@^_T zv+ul9UUsfH^l>h&*r?Dt4;GL#4Wd+29N2WeVjvs%cC+?LP7EJBLd^W~|o6=f|Q4n*rOdq4E@btSX8ZF!~HBbU5<~hI9g?Dmn$z?7+de*-mi%Etjs$ z+J|*yoK8zTU$0SNDr!wIKJ2nRr|ljyB3<}()_aE#!M3^JvZj(xIPD;|s z9QpBMPJhPpi5bsK6o%7_?dNv*Ngwwvw7ZdF&UDh#h$WmvC?iJHm0q*UawEmfaa20j znhB$D+*=RZ?Olt4B$5BW=z5QxX~8ft_FlZRutZKva?Y6@Ifo|0)mz^`GiQ!udqYbt zntt9^FAz{wChm)hA_hY*RQ_z<;Yu93=6<=#3V*((XOG+g>Ix%4V|Q{JNlN#GuVWNha{8*FwDFkR*FKMVGN7yUk+3cK*TU6dDCHugRJm}#pE?wBbbH<^h3Fyh{OB}fS#Tp+1GsUn`P4=rBRP)j-6Zw#jYb3O4_0B zL0?Tc=aYQ(kKh2a!5?s8o|O7@J!_qFIS*Aao8{JMRW$O)wFm>x@_+Xtg<16S zRD3`ASml*Dx|_8P%ql%X|G`M0bA>%kMmv%95B3i8P-<(CXnnG&DXe&q9RBWf?*zoo zhuS*`>BS2cg&MA!nkUk8%b%_ZcUhPnA$XW)46JXlppvg$H5CM_IRhV~AhG^KmSZD}Ukxc2{VMm5~c` zexZxF_v%LDoLUn80zzx}Q-dk#mZBFzZH(6NXGU|pn9>$VY=7=Y3CU=4bLgyWn%u_~ zO`=Bw@(s@^TqQUhqVlrR=#<9*D#Oj6zx5kGe-2>qwu8xJ)LBKoc@x-tQav4DjU2;Q zzG=RsVu_Rq0VhS;fqz?Ogxfi>%7++{0dORH#QcIHGy_?RDxY%azSOUty{O`r2E0ji zpxHnmzo}}_7fsNV;yxWs|B9i+lvN=haH5pSD!$*#r9E_qy?<6qOK~vuHm;l&?dGp7 z_*xK=yVJ9st2#KPY6w_+8+EzEAMA~~BpYme$G>RF(2#gI# z(3L7-rBc~#6p}HR|CR&%!}kBj|NLM7C(Qr$E7`Tvq29Dl>=4Uy%Oc%%-)n135aD*q1J zPo`ck<(;GE-|Q6))7W2~cL=^zZlM{eLT+{x-Tg-i;Fe)k6tgw@B# z9zehI7Ju}M2EiWvAqMv50{wrqp-A1GM8%1pkmA(E=R~h{F z1_U=|sYS3T0@igP8P;5GScwfOjVx=jncC-pEA~Lcm60&3-;v%F{8Ls!iSXwMTdx;= z8B?*<=oTw)p7wJu+2HtzeYlp>g+&G?Na{45w11>4wwS2FxzcuD#NcO2SKM{9;K@)# zwg+oyUz=w2F2(^>%UK2^6+0u91mRz2Ck3@5rr!{#`X;_G;hF&x0ao|qM+gD_ZxpX+eo@xeX31arn zihmVH>v4mKzKzK&b9VQKvgvIU#DN?F&&9LZAqq>c>K2aQ8%YHt?E#lk@9zi~u$Pkn z=9)1gQ)n$`b%lH6aVx$1fY=*b+f5Bo?o0@*S4zI&6dRIC_{wvwW=hM-M7$m+79X%q zYjk#(up|h7CO9JRVJ591f}pLH)2YsK1Ak5Nxp($|(ovmv1xDJ0v|KGuck(8Qv)0uU z8M;jJ)#OZybW3DN6EQj21B*E~#_!I?2AL&qgH|_BHHzsEdE&C02{1p9T!heM(w-NI z@KhP?%@gi@Le})2^z%D%E%kIUJdKm%)a%iD?`JGwZl4SH1AlbTmCh98$-HI1FMs`s zC1A=lp_gaQM`9*x*(boV6SBcqAdO%o{(Fa?Ttt+<-cDl_t{u0Qq)A*z>~JbP{Oxc~ zr0U!jD=9_jx|x3A%Y@Js!oK4**{Hx_s3QZD(_w1q_(T#`85!qK&|`>FSoY;7B`eI9 zwSa;f{1*wk8}#TXBU?YndS@Z(TYtC}HZF!mp?=0b1nTB1=%$Y6$nU=5hRfjsdoqYk z;6}R8oo0te5H4)mi)uWZ2$XGMvWKtmbpSQTxIRsn)04)o3^wZ{nCDG1pDcI)@7e0JKFc5126vMc2B zcS9x6H3F@oDR7_~g4o07)7T3Wr!qSwDyO$zxt5ylSNX|37bW|hBQ?#X2R@CAd*87w zlhG6iM`ad)$woC>j<3=6k$*0s9Ih;RQPTi7&{Zu{Pbqsa!Xq2WwxgG1jwf>ZX*%4y zmtWFI!kds^C4?C2QWohS@ZY}~b`FTzSShlQgN`h8?|i+vK`D_VeGRi{m%|KBc3Aju z1Xj|qKD>}&u|k4N`06%|@z*({)AjRtZgKNKml&+S5Cu&~{)!AK(uyT>p5! zwh-7Q5f{o#dLbZYarKSMgZz>UA93F;)ndPfAVX9XJ(yxJbI~uQFYTVVVyVOY&v^k0 z?Pub}cPvvIiAV8?T7NzSr?Ds$*u_#z|FR1CRwDvmB2%z+RByEigc1J4E&#*Mk{vQO zBPerWD~ISm>IsZO;3UO8FfJkaj&x8uxe)Ga8Aw!t=tnH=b}&SLYP|PJVo{>f|a2#(z}KB4zMK_}0R^3W_y> zT#X^7SNgSr#BWiFF&O{jhNWu z*7J#Fr~soIR@5Nt9)OmYn1o|KUc8IRHMitc)M|*s1=a$|EX&1$`8p>^Lm`0^i!JJ-$!FJ2Y`@(N7t+Fgq)3v$C-y@ZE zE^?dh^mm=7EIKQipw=8TPnjJD>1izgBZO_g4(vydgWxP06MASaY#N8HR-ZzrU)9yc zEujBHYJc0FNhIr+00NT;S;1 zXioDe$W<(a$HmLdFrz))KOTtJ(XlOHWo0utC-R)f99Zu6G|loZNWF&2t)G&hHC zq9N1XNCAt`BA>N7$$_Fypehl<%9sVpUPG7l+EtHB(>|XA0iH@A4{LZqV>MLxWGKPJ za(}8{J(-qTotYC|`%rUp6edsSJQ$w1~aGW@}?jZ^z%TRj-E zcCipL;bk|r7&_PSI!%;zjMIC=vBU@hEq|Pa@5H^J31{!9BeDswxpx#Xr~8AGFa;Ro znTB6~_pPl+DY`zKIRrmDwHBF&6_wBnV{Og7ooqr{!-x5eC-Cg|?h665RH1NKvsuwBtu>@32si&$bgIH(Oc*uD9;x_^Qr7WFKlYk$eW zBD6nPKcpcf{)FSFoi|EikY{oRQxJupqnqJ$q&*M`^4#bZg|_;vn|u>L>0$bckow`^ zxjAe$C>p`Tgr50n7a~{PCQI%Tv|vNSrlbwoUxw=UH;;RYIjWU|An1F;rrpuBdNZHuZ~cAFiE29tbgTfjxfS5a|#iA^n#SUd$m7{%n`yj{-R@h6In~n zu0jHR7W^b6%Umy;nO!Cwr6X(WiZ&fN2+(C&ZKgEF?W-b1nvLD}IbVlblYK-yrMh7< zq}RwZZsPXQ|M-ctoNJ^U>=9T)P-6FL2J(p$#6clW97Ka1s#(KVCacw8>VKLyPPZhp+{<-4A~#XOoe446cR0Cd5fsvSK~ zj>Gu7@AY?kd3KYi*uBCP_Iplx1zN(L3ps8Ko!peq%9%USUlZh(?dH(Ufm+{>T~Ktx z21yV?OfhF#25H>hjT=^2=zq5=Rt8tHX@rLi%`Od=Wbx3H=E`OxD?y^hj>Y_aK zO}dh?w1JsobHK3^J4{e`8U$4w>mK_}Dy~HDM@awt{sn(@y0UslAUi|Zcv~WrE#IpQ zGc@`|ohp>=nJ}8{K6~AaVK)`)RoZOjoInzuf0OlZR{5cTxOj3 zU^WdmaH@s_kq~K5J^7-#v|JaHW?0)~(fCC9coWYNU%L?Fv447R`X{c|11CrKyuZLP z;~&x|MZk?LQ2T^j6~#{ibYtPW7Jufp6Ky+r5Y-0)jCGr%0DtFo8G_~1)}75b8z{(PI!2V38H*MIfSBh-Jx0v`$w1wwC3de_@h z1_#S>49zvUu2c!#hMldu6{hroZcz_?J}mvRf*$J_oNgl^ z41lq0mNQBcBMKE{O5-E_F3`*-MYPTNusawC!cBd<#$Zc)+Q-!+sAP+aDN5c4L2x5v zryaw{cz@{xXV*HtMzoamuy92=y%Jiy;zF!R^a~uzHiPF}y_IVVFG~3+_a!F+Nw=Mv zS@(oBk{@ppU#n!OD`d@h;w`xD-Aco!bFfD`o?9!D*>@!TqgO*Nc;XRRW5|e)Xe} zYkxkb>g-lUEJTg~tA<3Mg5!cMXVwIRc@sjiNMk0oVk?*_-_vK7)7mB92%|ZI%jK=M zUvWQf;*_m>hAebURC+j44))nkYQ65`<&i|GYh8Y2%g`=NX6)21IZ8V1RB3X2hTjAi z<=G^BM{3ju+in@kVd86L*#N6t zif^q(=`eem-#gw<%QKWoQhWj0xHX?b0IZ55riMOPMz(3@5=Im*$f2gY&bkNpD}O4L z)n!gsak)0%KA42DIs9FWyJt`9DEUQsiSPeN;OPk-m*3Ak!NN0f0jtPTp>WttxKnfq z4HppsZ^hpltM2Oz(6i2fRe{Nc@F*HU=26;a3u7|{1RqXyC=DY7f}&^Aszl&r>GoEy z7=~tAkHa3)QvuYIJS{-td@xLnr+;(Fk8cyJj$2T3P%0J(3H|nEGw!serKKpgn(#^) ztO0?Xp9pHN9luz8Zh-2#%edg;4=&?&QX?eTXI~8)+JZc!;O1VibM3u!;19FAb;^Sw zBF-rJ#&@~x@!e|M@rTC7Mun$h$SH38p`{kWo!=ylG<(0M^;xG6EHweVPJi5%MQmOf zBY29RK!WfE=r{RJVzKhXNuwjT7=cHQ&6X9Gg&hr)c`P1j>==OqD_o0TuT<(Q&4TgR zI|rTy!Efn@NFJ!dqj1Hw_%C?R!OJcTwv4BYgnU@46E=*uBRqY8enmWeAoHgeCUNfL zg$+O3?E0Oa2d8CTTe8>&r+;t?h5-P*L={>&cPe{oc%KLg3}&Z`T60T>cVe0uG0kl{ z6y@@jXwxncm==nORtM||!`MTij~Gdh`S}GNkZjq>O0Q*-21f`%j*gfm07AJF-y^x8 zAgKwNb?CrO&|UYXfdE{;SSQYmQ{6uCVhNUA!c9yim$X+`!_C}GY=4lC7IsTfL^zuV z!zBrW`i#XzQ^%$=cedQ{h6xnJIE-#)eG9zvR1a+Z{{0jw{=EX|9(NS???@{%IglRb z&OEbU^~jOgsCQ%KZF@J88eX1Slxl9v$jMjI1=TKNoa@g+I zoMBrfrRtz;1r{!IugfG?G?h<&);)_O16k9j9H7PqbhY3I2bxZdVL|r8(`ezHR@0&P zs$nItRg(#&hAUzNx>yiqW+L{kqdEx5NVx*J2`zV}T(}WU7=O{K_%yLZXjLRR^tpwO z*qFiYb#c2fUY%TrtWok%%puI5nUv{*h`DjdRD=lK_`pZeX8B6WWn5%s;yN$J4fENR zJhC_;9wCw84pg%8x>wYo?uC$<1H(^q(;ng z-vh;f88~k`z<)<>1Z`Q)Z;nZ}vD3q8ZBuYCA^KEmHVBUTJtrI}wcY|e9X4kzErffO z{;KW8(mC$|^;>z`V|cm|9OOoPpoO_(`b%VV=4FOSF}C1-`2wl72Q>HtTZY@hm#R;2ZGQ}?O~47S;-ZSS#0jYJfy-WT;rw2d)(rAi#)maF|P`E@ko%xJG66 zd;_k9c7M@vJ&T{F>?sGGRihM|uYo=%e-Ixe)sOEi-h&(aI{I=pnnRuU_B!h6&b2{j zAfcr1RS*UbfodS^B`mp_1xj`GfD_zg=nv*h@F&<>6hHCzz!2K8g{C)Teyl`WU25I3 zwEz5qvuD+h2}NT~9o~U!oNnWZwX_ew#d63kUw?Qw8r+m*9eRvPCxD>$ng}0qy+mFa z!i1@VO$k!JxT#p2OMWeesRbD&84jGe6(OS?*~?T-==`GI9uvabyEu3Uzb_+U%ie+0RJ46H{|x5lnZNoJ0aY&Ai*vnOfCx)9{`3 zuz!24m#_j|Q?=jNRjrL{H|WSz&3sdd%6zh#8!s9o>0}-lp4D45iHgdr9_>yvTkzY@HdG z%!1Cs?$if4C$XS%0~^9<#zE&RbQZRssu8`rQN()xGJ(=NiQz}i9rK*cffj+s&z;Uc zBI{X|{@|5zT{AoR?3X*(wER46$b7Wr(>pV<`rR40s-AMv42R`xP(YW#fg2`ee}DB( z=T%Sdg{u4#Hsqm1C!Bs=o5@lqqG!!cGW*i5-E>cXzeqsP^&1}@K5SD8={rQ^5J_|; zmwc2z2PkGrj|pub6op6c7M9^wz@81?HYEY8)apdcMF@Y*BZUd*Y2nKWWD_#FlmRuS zbdK(U6o*An%P^fUM5k4^5<#F6$A5(x=x4-(lcU5`Wxs6Bu6}Le!b&8HBe;s)rtO$? z8Ys}WmwAflg;1-^Oa#YKSBxh7FXe9Tqo}7^q(Nga!7a+xW=Yy!qrYkZhAek9x(c^foOh`cwSOsS6FV7P zwGC_xt8xVh^p#eEXX6avpcO0xL0?jLIIP!>)};w&MlW2GF$TbFz2!ec7G-ty4=bgU2LW99l-ql3n${$SCgAN`fbe@C~r*(>-hN=r6{fk#8s*zMBskD4yxkAReRlfDatAq6>;|l33mKa=2;;& z6Uhfe%1Ka4cX^eHr1LTA{bClP8kig;@xl`E+ar0NwQ)@;vJ+5rSbtq=GA~S6RHh;N zoZU7lVBA40Q#4B7WEyzk#c1L+|Acr^lvpmv>AV8DOje0CGF7FvVG%b4?ZLZ}0^EW)bI{R1Lai0V!w&Dr?%hhwYo4Y^e_3t|natu)kmP*bxpRgq zBzpKj_=CO-3)o%hfq#Z3>Sb^J@tuz3qiC@7`FNsFKo4ovE2vSBpG@JJ4`$@99DX!B z_T29A(_>>zIZ&_1jDyjZr~~IK_4X`G*Mt@(c-ni#4-Dq+6L^=@+=<7)1k+SUi5E~9 zF3@h|AZNQ#mwddPBf{?!)u%ar*JJQKOPMZ6zIh%nkZ>vF=R<;4ovd zJmGXWuQ6ol_%_zuhCXye-+;K68Ox=0^7byWYn22Tk@5hK00RxVPHcA?yy}qrXf~%% zC~=Jod5^Aq8-HRFj$s=*j?;sJ52X81@*StR$HP7^BHWcMYQKdHu4S$-r&fZ73a3OV zDN5L!oMl$5oNV2L>oQ^y`{6wGSYeBb6AHj%4|khSKEIw0t0|gbvVT%(jcsv?are!N z^NXxjNQ$GG{SB=%Ia(@!fd_s7zIJP~o$RM`LJU^yA z$3^t5p*-^h*8I)<$eT&1q^?=MTeR?1g zA^KXx(e@~4cbtM+wzqWXY1*L9=0Y9!D&YCgFy~-f!sh;wmJta?7Phu8g%KRkH3G3? zc_}~{<9~f4BAD{61duM~#BHI(vd6leURo6m&WjT zUIPl&iN36@l6nt{QKf~Sn`!)vq(y;k+Ax4*ysZQ(4P?}z3Q5$~L_*5xH*abis%(-Y zGJgnX&lv*7f>^fP4eRwJFYA854)c{`4Zd(@(oEDsQJ0S#xj}F^b+8@QHGJ`yU=HYM z*X)ahE)tMqIdE-7K2iQV?9kY zFQ;SKxSyIJXUKBLG%2b&%7?!DK^uKd{85akSvjK6HzcgeELDJ^qRQev?sSO%L|9L4Vq>G zc1GMoJ(ZOF5>6jRfXL&8!fUXu+Y_)^l!eNe_x(c#*Mz-Eq+*oOS}4FMGm?tFY*)D8 z`W?98axVY+BOO@l%V{&TZEHvjW`B}ww==1W1J*GvLVPNC)IvWdR;*0$sIKx1-m$%S9UnguU{e%F%#w6l)UvTjFJjaJsMX_t5{xXy66tF` zd5)Qxgv+AGiXDbh{2XMxOX5J$9Y-S5e*%7S2-2+pc@f*M_L9oJbTR`mi}X>M#~cY0 zR|)`UZA0l8>m&vz;5)?Hgnz7^1%0s7B~&nG$FahHQ;9)Y{>4fhP{(gE)F~s@zCeSE zJD{=(zU8eX!e{7DW;FC#!Df&0(rz`hW{&5zAg=iHK?arMNFKCP-Rs*L)N6Bi0BF|( zTRObxFv>9Qk|l=Pw00>;e6g{%gA+h@68xvqK+!qZMLYit&#Vo4k$()%6@uvp=rtl{ zlYZ_W)Tc|_W-2B(-;tR``P+hdG$uD9+w6@7J7|#8SFCdrTu64(#G3ZZ_4eiCIb9rx z;#N697}PjHN;KA-LmWi46M=af!i6{k&Tz{lzNsl&W;0TM(~x9n-*R_@uz+ zS!Ki##jg612MxCaQh(qIt64$fI$03*Y%BPYYv%Nr*y%CvXzp0lz733uWmHyu7zNz#lb;yARd*xw!zpXUx~6jTyp z;E2G-Y;~QT=M=BqRubw1AS1*^I*Y{WWBj(Y}!0D~gqmM8p@s zgyOpbU{G;$(RHnEFcrsg@d5h#1Fwt^JMx&pfiy5m0Dsw(u4`o>jn2*I=59$<;&Bz{ z#eB#0CK*(xNpR`?`czZ4hrZbCZ5Ro1jk=Msy967Od-I7dgSh$93|EzI&*+BFG_dhq zPvYQ6p}Et~2#qyg!R|Mp9`LF*4Gmre#Q^Z+{QSEc+J5-_V5RHx_zv#RrJXxC&JEP@ zdkAi>i+}h@hyXx4v$8Y8T-JN@k5(U~bodkB3dAT)Ap&>LbX_WJW(=#a(%VF(iQy7tiO{BtKbrksX#M?`4)Wp73{OgOg_WGHK9OLTw> z6b9Kn(1KNo`5l{=s(JegeHR$Imfs-}v6HJ|l4A4L*m`RUMGVolpaSR49b{5B+_WtD zHGiEuL_(A}jXwq@;ZoYP=pHL5?yBqw8)TU)xJuR;Rf<7)S7hniEo|njm>f6@K+HVv zccP74`B;Ru=9XU{U)b2TfJ**-en8P&G;})rYz9a1n9uz%@Z&xZZnI}X;RJYh76wUJ zp_cKj7&6t0$x9q3GIgRVKmPgV<_6p6lKNklqJv&AbJ8UiljyB$$6 zd;@&3Fy$UvD^cb?5tQ~}bu?VJtSMbE%m<#yV2Vl{-eme2L7Al*u)JX+&HcX6=YOF{ zgVv4xeg(Kpe@BHC00&XMNL)CZReIX#7a9Ud7~B)Ge!LNi_f2$Ub7yH(@LBJ;R$G6J zp%xGtme}33XB{}0^)nfTJ(DKk2d$PNr=r?6=2(dWUhf)?j6HIErNg@vjB)q zZn}0A;;kkPes?a@6eyey1OnpwFd&!R0*>YMqT+?qVi!fAEV|}o(l{;4yeKe?I6=zS(ia5V6Tw?rD`o~!1fjtTw2z(S;)s9k4}S>39V<;x zuglLNx&R;>R=Y>bdcs;bx7AOQq=*kS$&~08Smiwwtg>20Q2U$xfle1%pG4b4TnBlH z&ykXdj2fX(p$J@Z#ZN=kpNIx)gwI-)d!RIG7TM~G%=Z=61$=N1MrnbY#sOu6ZYoB1 z?ZQYKxL>ILB+u@Q@|~Xr^?#{6gk#Z-3iiE2!KkEH#g@7Jb~-NJZk+j!?-bq78(PMf~Ua6 zN<`8|cgqh$X%pS!$$u1I0_{+!mqkpwDQdpt$(55ibSIb4##EY2ei}D(Dh|Y{LYlfH z_e-%tvcM`h%K+$n^iQgvKF-;{1X81EAC2bt3Gl#BTV!uuu?u6(l75WbUqMQ9$qPvJ zX#|ak?bT7>N0*^C)yb4}i5m7_SA>XNDGJAc&+OhXyquKLGoS`{;- z-S|)a#TdLcSn|{Wc^%|8$mJ3O^u9)mv1zGCy=7V^qam8#96b@G*dlKpJL?|c)3k}L zSS0wIzv2^OWuIXHkEr47m)x#iQ|lcV)pI8ciCnOM_9)%-ug*TO&2Bakqzk-kgv&qp zi~)*7CkpL45q~#+GO1ZiQFZWJPLw~MFuPaYWadoP4||s63G@}k-S*BNjp4RAD)sJY&0K}-E5GF}q<;aB`)(9`Eb45#Y-xJ%MNUOh zX795%=-h^(evHB)%(=rnHx1Op?Lju=n(hGsYpo?rQRWD*kD^eSQSF{BHWY8zRo{Rm zD5W>=QlZ2A%7cFdm;5Dv2Fd(#00GKXDkB|fqlVqhQ*+lH-HOde*6<{D!Y9(j=j88Z z2Lo2R#(%BZlx|ey0OuCU@T%q&mX{tOvmfB3@o!mmm)Gn9$6u57iMm-Rg@`FU-9sg1 zw|_Ka<(9)c_vc&*c8)oD-}_4AmyIeQI>(t@AMKF{35KCjq5 z3Y0jPd+Gr1$zq;(Y}xTxTpV3vykn~Sbw{Y{Pk&myaPmX9CtiU0+%L+Lw-?@|c)nbsogP>J`~lig?#Dz$p#~}uTt>h&r9EqXQZ4H|3cuHUrN)m zLnog|I$v5cT_B_Km~ZISwf_0Y&H84FjGGdNc2B^n)>N+g)6e`;xxa`u_-q9g)t#07Ei+z}@#@v~fM7T<%f={1{P0hfkI1g`?#Q@JU){CmDh5Q%pN zTcWNOO9pWg+aiIfzpla@(^a>2!_w(EiSJkd#1pHEWs(?&ioH<4m186FH{(zVZ6WB(BXO}NZ99AdFFt4jxjI>X?TQjES4XH=yoYq zGX(k$9yYl}tVvLIxh1?Qek_K`RDaW~oU|x2)8kyksE4y?+~{Znvu)g`=(Tex9Do^` z^Rm2dnDPxne7=}~gRlJF*!oSQJh|I|%RYkHxSA`HLI$~Ls~AEDdEKL1!jt$ZYyAWe z3!2t+wI+U{M z6iz+=v&GCZ47YS;)5bSN(GFuXK=Xg4Ize&<*~ZnG6Z=n;@xOxTEQSoPqlTX7xSU7= zUq_zg$u}cfVwG@$C9~EF(SHRFh(jRMarrW6a)SzD4H#r8ryy%k3**QOV~Ym5N0K&3 zWBKF7RI}sTRgl9WrC4COd*#q&5DyRh4Otux}&X+f_O_jNVJ zupOM%GlOmSd`U0PMqhMaN`Wu8?I9TD$O$wzrvgPfmS*@U^MX zEOPFT?jsp=_pvnEU&DXXxZ4ZXY6@jmFP`g;@z_N6^4gio&1%6+*FT(Id7;F7!1W)- zwkH03Hwup7ZGH5%*ZJdej8>O?xw#zC@N%r}`%QQTh9h*xU;N9RsAa3Q9&S3q>r7t7 za63b{#d3V#BgbifRWxahoPKXPrDgRxa7b1y|B&6o;vRm@gLQw>^Rh!(qi(nxuF7pW ztHk(=wDZTI-M20|fRzlRwcqbvt3{`G+l0{HUT??c(GO12IkUlQVQ2T*7LRs@ckgvt zqwIdc%k%!3TwfzJw&vurZQl$0g@axDw3&yP@Dje1hj1Z?`FxB_u*R*-v+rK#ux_s( zvzJjPq;zL=+8%$N+`Bz%-_2(?>wGcuvIrzL&C6rUM7o{I!5U|Dg~$;VPmb0^)T(q z%Tf$iYma-yF{@uAK0PeR%r{DxzcvdmYJH8S>(0@z>G*#N?eP<W!SyYbUHa4 z(}6&D*{cU~@mv=E$$|g{i&t7&gS0y{{ikJ~v-aj>4PW-PcYhXX`%sk8Zq~nL3=Zok z#+EJoEdqbb!134swVU8;hQ-0iLc24lM@eh2aNAoqCnjQp1-)IIY%R}wv3+o4rKkJp zYtMUMx%*6$XqENVIxgg8{&F@q z`F(iZ-M4rlb8A2!@pQJH1O=Ven`DUq=E*R)f!lwVq>oHBfnMx*W9N!G^K)$a#p|nE z9pvg9IL7WWwM&yv7Z3BEA?rc$?8$oeI zaYld4)6&9z2ixFGsbx&VYth^FzJj$iqNHc%k^NPd?rXQ1-JjdT^tfJGt@E_Fxv3TI z?&F!0B^~QxO=xcex$Shk>U_BM?18xQlU$*)CC;JWJ8Y-0noeI|hd}7Rf7jz-W*b2m zA+|UM?Wh-=Ps4>1ba;x>Nk4xa7SlXVFJ^!DI=E1Fp6t#=D>P&@^9PFw`*N&Tu~e;5 zcavVESnaIA-zm|1GCYEvBwX1_01Scm9MGN+OQ|{+@F}v5Z!}B%G5>9{n zTWjA6t%y4Igg>k3B%i01uy$K#k2Wa`Za3JO2Uq0#y1%1`?qWNdSP46;vTcO@1?`8k z%c||1Rk>1fU-#Gevh<~0AKl%H)5+p=d#t0pOz3Mmc&a?^&IY94noHz8++f2m*RXBj zwo!Wdn2raN=*tSKubE8-yCA+;oxOi|mQ{E(`t{E3b$9ME+s&U}Nwyx$wy*x#I&9|2 z&D?b+eb&C;<9s=D_+aKP%#pCicyzJ*(e!e8jokUQXQp*B?GNTJ-^j+V^EFyz^CGc4 z(`3)A`|RK3<@92>-6wrPr-O5NCRcOK`eJUbcGOFRbbxjQS5)=4MfJ* zX>u8NWxnd#&hFfOf=Tw*b-CF;_P7Id)brBoSq>A^aHg(IkEavuL0w(=c-N^gJ3s1n zlw0;DKAQGs=`20$2fK$j_xy8QGv|vKM{jVp^Mg~;ydSJrv6$pVHjT?XFl3Om7i@Og zZ3k35it@|+nx2NOT8v-$f|P$=cz`_JoTrzXt#<74SnRS8pT~J`_2q_1wOZ^ZViEGV zlfAla$ZtM3o%04mwb_2+veK1 zVA(k*6?(3FFQ*4-Ya#QvUU$NxcOC4@#~@w|cIB{GRC8lqq~h6~i@bkl;^CTamlikH za&lfA)5A&~Gd4;uujyAOwDv3{M%k64K5`e#wa(MW?m0LGDw=FBE3)VJi8t$BU2E>q zffMJm^=0~E<$OE6m)BgBUD8>!b9d-(AHi}y%zIYuE>miDcCYnTh5M1s$Z`z#eXr}Z zrLkRgLbv5i7Mp50&3k_bdtzUx*L_+1ajnMlVI`)s_HHnk+`TMijNtp%Kn7jn9wvZ$ zUbmAhp2>Y__o|J5&&g%ZHnaBE;a=GtnEG)frsbD@=J;9vqvnjqT zyQ@`sy9T#Wt3B~%BHyqSsv*%w%{mD5rVvilnb*R`w;8bM~q4BZ;BWDh}aK%Yp zOL12>;T3J*;7F5#v=UGq{52WK*RA#)K| z<5@NA;Mwwpd*#BvU9C>)jIU*qqu0E1-dOqOa9z{K!)@KfD+_0Hwsud^rCQkRe7ltE zXYKcFujPlv^I;_^dam7I>(9eoYv`P_`)=3rR<3oM9jBzbBvH>;F2f#I*H?ZYJM(&N z?7e^0z~4pe^_&h{mtA$6t+`!?hwFNpe7W=E>Z{x==8xEtr{~=`&E2G9FK3c`@pgOm zT%p!(v{_ePG(NkE9=hRimiGsYw0owtd|jt$bZd#{^lQ|m-eNQ>+}`PW#k1LA&2Gc> zdNp%=?>HY%OZSxam*;%B9HX7JeyqCDZJ~eSi;35kn??Qp;&Q*FPii{d`E@cpJRgCd zE+$>HKex<&NDSF-Wsi7yUiL1huGn<9h>q`ZetvZ8JegHlwymB^XTe%)qdcQUU_9=b zREzoP<|R(MG)`Y%U+!kO@628x#_PNI)Z3>QiVc?Qn~RLu&YLZso9a=Wy2H)Qo^^kd zUT?A7J2Re-g}KW|^nv@gM`B!Mkrk&&MlVia9Nap2GB=yH27|9*-?q=UybN}`-DCY_ zcD@E*ai`aNK4oEyTCJ9Q+YE=p{(8ILKc9!&m(y-v@8TL=JJxM^?O0E7HBXcI!x(I* zx8N4-p0lT65meM09u$1XPoY!Pn`D1oPWOCqV*%SP=C@bcrB~`L*=|Fxp=VEWHgYJd zFO&^dly$!-YngQ7U$X9Se0pty?V$813*Qag&<$|th4N*urMzp|ZJo3auUxV({#6he7NzY|iM!p`_4t=LVh_@P zUyb>0dioYC)ZAJHfa2ztPME&9tNB$musHw+qyTtDUo=QwG~o5|Bx)|%yuB-H*iZn8 z9&ZNA?E<3U2w->L2$2NLvobW(1S1t&EQ`-hmYlp$^t=Nn-hnO6G+CICSV+YOr;g9g zOZ2>FZh}-MsIMuJoFEmOU{Hn3m{JvgVUTfv0(CP*j6g>CE)%PL;5HHzArW3`pGBZ1 zbj?hC|Iox8f04jj2yT**Qdp_eu;_Cuc`;3XzFG3H>p)(TG6GLZU{0)=>QK z--GMO0wIWeC4CUg0?F|tGcbrXMUqnJ^WGFFMv@W8`gf4jYSu$~?V0qJdOd4EFTI|` zDl!1Qo+NueTipFT-)Akn4TnhYd&eV5kH32pLX ziTH~z-=8N3q+;6)|NR_g{6F4*lQ;VWVRT@cp-RQed+k%2$_yiBB08QizqA$|6`4z< z^vA6%I)WmH>vbxeG$y`zK&u%l;G;%#Q`CpBOnIwAm?o_h_|L1F%VJhDjKnx zY5TAB-spWZ)A+>?N!JU-*~xf@WIU%ed;5%pzrFxS#mDd0n$^c|^uDM3^t-pL=N%#g z*6Y{(Vqgl3PG5?-DRP@-%*K8+M|c!8_W-3Miy(jITcV)t9W${qle3^&s#E$Icveus z{lU19iHXD(6Ns?G&+Y>Os#7jmYEWv9cND~qWn`SExsO#&;SM%INkEigwL@-Ve(F=8 z+sSeqPpVkhf^v?jFDUg{2m#koQo*y`DhP-P2O7fy&=KI;i|6;5U*`ZXc7u?;?M=rD zlq`SDO2?3-%U?RS$IH)tytG~N7wdUxGXIH}S#s8~qR9&%JD*9`d&i?#|7?cRC~Efg z(8Q*WhhrTxPmYS`CTi@s_Ff5E7{@C~$6qw#`9vH~6A@z!R5_}T2thek6xk`?PctvdK# zJ0hIVYb-R0k#xNZ5U4n1{z%%m&!F9(ikDhUtNs%SHU$L;Oh6AwvQPf9N~H*d>_&fI z@k_@FQ}6S49R9?25A(Crp#*`6gy7VvV*;t#gJJFJ9i&+UQfPr=eIA+DM}Ww=-YufB}_`jF3JHxbEcBXvWnSWJRb-WJDv8c z{9r376NCjf$$3d;3(~4q#Z=5HPoNeD zyiyqknVlg&*rFsLJHwqa@DLdLy!Ru81c4M3WaOWK4j{}nRB&6rzfklDJEr3`*YEEF zd%r*V+zeY`H z5S1X94a&gJly7Y$Ojrs;t2iTqo@_Mo9H2+yj}k{xk7YU90<~;qU|Sl_|K(?Gj0{gB zSr9O8_e)|)=K`1ky73iKw03`AiQ&~$+u|oaM04hU@>R_nd->p~j>agnfFcJNv#b6D zB+Zdu%KXAGu8bX)Zjfj8z)G>mMZB}++Rx#We^=N?X@7?&B4@w{rQG#%C0>u(raZFP_BWgYQKj1N>gXcri3VaGwX#amS8vpcO;*&o< z>z42LB&eWU)7YVk`l#w`w-BwrGG>FMl%QfmKp>DwQw=p&;!YXlQr8{pmtGRj%AWRl zqFDCE*zdJ<6{iS1@g*fh3Rr(i-^^Egq6S`*wjRPWg#BvSf*=jXNoF}(vkI3(`{N~sw6^AMQx-|FH9+j`-1w) z(F2M|eT^u(bOJ++?U&4vB`64HQW@`T^{$r~Y!3~8VS6C$9+V2E+7GK@ru`5?abh)l z*KUo!{HbxO#y7t)it&3c8s|lZlZ}YR;@+Y8hh}M>n<5@ES#ql?5H>n$b?Riq_FG%4 zicCpoAcTovY%NH9ws8D(WlWLIFTQbvv@94k2h}gt=XT3P_F$&UQvW)sf2{ISL z#s@)vys$r-Dv3d?93-iQjOL>4eN*{Mw+jToQ^4*aub3?G+wS56tA5VveZEbMWk2;e zZSa*oTULM8s?U9{{oQ#*=LX*?W|@IlgN#CilL8@b!g=07J~u&5)>y?Z0?sMou29lK z+UGJc?*bi#@HJ5x54}TTQK`>63XrxH{eKpJosh6jSS1)lM6gKIr5uHHu#;y8)*$pb zF7-J+G~StNyi<*=2Jh7Ind-C4;J5Z^@Fky{gm-^z*cZRC{cXP*kN#qO726v>rWjEQ zVPU>)G78bcKY)xEC_V1I@HUQfer71Pu!x1o`U57D2@9h=_5oQ^Mz9bOQdIK}rd25$ zQ?J#J1O-Jq)AQ00K{SO|oRKo(h$sk7`2>gZ?i`P^ zpjMe3%A+uHF5Gg-+b3vhbEpJ*e6Fib!_}_ z5r1Ql<`pVov2n~@R3g+}t*EqII~O+7+>g*a5T_h2nOnv>USLqCHb&7ASCCTiV6BCS zKs4uOUd?nY5;`A<5c%bb$lJ4hr)MgG{Kk_KYzYrdGvZs)oz!_|0wce8@YfbU_4?Ze zKb(kD$0sKgC#Q))O)h)aoI?9xV(9NT@hOdVh;+_zZA`8a4~SqUNM2e&n13yo25%3x ze|!;0JQDCZA$si!AH#jCP2y4in7nLJdPt=hD{eDv?EFmH(-iz5P0ybQen4N^E`Xu!g57;F#ey~bCz858`pzSKVXB5VoI%D;O>NfH zY_kkhpgBH-gxAz(=)Yh$2uB#f3VA*de~^N-%MpdXAfUcq7o&y`G)eoY>%*h~qT>l< z9V?{{$cEpvP|Y>h`aX{;Uc&#aZfr4vn6SPvBdFm2fQ@4`Q;edVb|`R+VAiT3MhK?F zdr8#rM~Xcrf*~ZE{51x%Pb_IIHEy<={o|gNMC$!(>dK6!wq&|SFyD5PbXh>(fBxU; zr?!kxC`=ElV!~#focYW{!t@|grd0#-L5;9r7DjYpL+?b8F*7Cq=I@&LJJY9_KM}DzU^v3e>FAjRe^>1CO?OeyOMEgJDsYs(>NgCgq~P=nR6;n671ESx7FCq6i0xM>D9oyxg!5CZ;Sz!?l7r%t4GXd$F(0q2Q0{ zR!->%L8>@BhnM_u5ByyCnt%{XIFAAyzmd4dA?Zwr;4-C3d9qI-?<3e41ii$~$-Zk$3$^c z_e9%I(72)cwL7<^{bC}u-Tm<2y+8cKoQ2>0vro)^pT%zt?EmF3wh2lF_6U2QgFkBO zhLx@ZJ~hPq<4LP8w4Fr;uQ-EC`E5Ja-mXS_XzGXN^S1sQC*SpMadon|__euzW*wR{ zB3-=>s@I|V|79KUiyu0XWdbv}{ILboBRs_5Zhp@D*=4_W(C|KwcB?>FrSlnm^Pi&O zeZJ3pL4Ek)BAXukA?cdcI}Um&6&kZRQdIoC7YHwWKhBLQ=)Vo2O3o*8Gxu4oowiLe^c87Zb9 zX*Z0@#8PwuRU(jL7z=uu)L+TsmutfNim`@+g3QX|Q5FOV!oU%cIYN>`bpxZ=SnUCC zDg=Rap^r_CD^RJ=!N>X>>PYj!|A+NaU+@1Q6*H{gOD)l}dO!cSty;0)!zsLZF!3MH zCO56&bNH9-b`MW~uPI5XP0X!@B}H%iE6-F(d}`Jf+teqmal#g$c&PUMl!CN=eL&aB z4L_(kZVMZS)-_T{{|u7)cGSm!t4X{4{Ogn7_So0<_-f+&f7_olS@O4E{AX-Ad~_}k zX!e2rk9`oPv`pD|`XXY@^C^GYaB0oQ^T{lg4pGwH_5fidc>B1ElRrMrBeL&H;x{$C z^}Ei^IQx!0kZ`>3y&w%+?fr1@m)~~}K7WU0>e4k)_JFSLWDd$DRaClRbn#PmMnKVA znyCraGOI=%zaI9IlhH3HUz1sVPvV1b+o;U!@OVc-#69@nA#hQHhZGz&9PL3lVHF_K_8hliP|MvM$kFb98 zBp!}+ooF-pZA<^~A@6;!V$pHrgWBH=>+vnLg`p*VSlDV$EAErg4o6)*VCLFs@O77^f@oPmAUtg<#Tf- zg+)R0wmHJ7U=HYxtI==U=5ody+lf+vmA3*RETR$wiZTQv(-urk?fFgDpN+p2jlU@% zs^O8mv~PZRq@Lz!`GNfhCQNov{r1p);!gEXPXZdfK$aZLP}@dx-WIB&HGfO3yLlC7 za*_)w#Z{zbfP{{z^f86Ph7Ou8-#Pxpea;{*^NCvVfNnXe`=9v3#JY~oNj+jnnv-oX zl2{6xKx~4b1gXH!S?2uuo+V?fY!J2!g4#{~Cw6-v*-_hxuX*hk4LwA$I+Zx8x9{XLQ=H`>bbHQ^Gt2$qD0fMYEO^sMfEca z-5b@tihkyY^I|4_14Y~Q-i`{^*?Lrc|4hX2p_;JnYC(m#P#I0J8U@qi$RwxOm{ww? z^Y0I)%fv2t@j3Vko97GL^teR=rLnwVsR;xJ} zKclTJqZNorYxEpezvoE>_@Hgy!Yba`-*{%$zQPr>Jzw?nJO3qrytP^%&i5sH|M9(f zQ*VAaxTUUd4x(-_ynmz!ld_ehO!vMTEW?#Fk!b3bwEc|FNd90!fv4vRkwPu}y&8ZN zNNWmJY}0D)?OM|9Ow@Lx?GTl^&TQf;Qw^R*-+Gc?z9(6FDgTQH<|Z^fw1c)!-Jh6% z=y*~r33$`FC@7rF83?sRLH`cbBm-Hlj(#zL2m9c}*zC61oqwPNSzd`v(O`iHwYx5) zoMFT-bL(NUtd{ebM`m zb-lk{MP2&cmsPWjDswVd$;5xMJ^I)5QvzKWL%A55Gk)RAr%r(m}qVe47-HGZ>@>@y{)$CW_AtZv~-n2jx} z7;lB%B#MwP*kd+aFj<5%MdeW$@7IbEtDZxH!|DZd+9tk!ZL@z`QH}4-{zZEK?gSbg zMEK4*4d1JCy3Q&3-}}rDKN#>ETVoTk@0``dr->A2M}IXsmN)-ZH(J7SWA!n}5k;c! zo1&O8Sx$)9fgj|$Zm>}fZ7Ky>b!P*R)c5mvifMmlR*Y-xgGF9YTG&WDEK&oCgf+_* zw?K|;5R{^!lh0s8u%H<0-zV07rY5aYXn3h6AR@N)BFYJ*-;7b>9GzPCZ-KCcZQLqedi5J-maqQSZ$ar4o;4;9_mrEd|HW4&goVvB5o z;r?tyNb25B;-KYy^t>4qR3hGaMRVFtq1WZkzF6GvAt<<*1Sox6+cM zx6XiEWgIm7iwD<@gpN5zHqs46ORQG>5 znoEit%v~hB0wn8tf}xd&Eu8Tj<_yP1jzAPPDp=De+$-tm8qEJpJG8$TcJ}Ry*88Iy z_ZmG__1y>fv7I-snih1-dB4#%z4l}b(OUdyo67Z%wn^$aj|g?a-e?`etkE$T9e*d~ zZ{8ihdkIW^_XD(TL|Tkr9$cZP^=oQ`N?#a+;SOT|pc z$JsOG=&f;3D-$J_Wk$Ez97YrBU5Jifi%|%fut*poFX*3Vvc%Zbzazp8ha0RdyxJ{3 zbr~}e^BJx-A}EI>jjaNStyxoy!$y+f0|cOXUb1PAC7U#SywXj7J&#~`4bQ8h%=yK% z{=ZludFL!&96vg!1~=+@0V3M=WD=rabboV*?Cz?l=?~zr6JBRSx7B|SZUKMSJ!E%U z#Uu2NCtDp;_ZokaMxUv06HmB~U$6HWXq#e-kKKP_e0=`%oPT5g{NI_P=)h6~QzRxR z?Q#&(B1&ADQYOfV=^n6~8Co;9W2*3}C{p{4t?v`W8Hl`qHJww*%4vFh=otmAPv#*b zNHS*oBWrdrKJj^Ry~=N1U~yNwL8GJh+b@PqY0rU_;7b&19sNAIpcz(3>*(oA=v=IA z?HhA^^gYS1hT_A!eEM-e+Lxc%qeJrkzfMl(q0u(I`&qsqCW=32-Sl3YnGwA|hAF#* zh+(%Gf)DQjf1!}dL$ADtWI@jPIL5&AT*?a9bWNlKGZ`<@`y6wY{_Rl#y9~;~OiFDB zCJ_leDf702lAx5DAWAgv2-B4DX!^@OpwKmH3Z{^yxJ`M=oIpMF`B z)Bg6uh<-2rglzPpX2=uRBS>vdmv#G-SL;q2@ zX*XrQ?)^5sh6XojUd3@=kZ61V|KaPVnHA-mtFdsDmuyb9fW8LnAAesB_Ls+m4{uPu zMkbYp;rzQ!9rt9r9bqKxwWj`TjsN|^N1};)CVS_&Z*Aq-!+r9@i~nGm7}2M5-Bk3B zll2m0F?am3O;n)=NK3bh1c7I{?G+6CgB;G6hJ_Eoe}j&QOgwrx(wN!)vg}k8O;paU zHx>)fa~QVo;=5-qu;rgotwIj8P1x3U>ilLPCdix5(j)q41@>I)w9t)93g2<}R|D|o zZP+_Ty>&eQ84J3|k1wCv$fgFIKq!J_;o!rHBk{@cfeJBL9SSAZ{W{xMu3Z}@i0uhU zN~S?>e{L4#zwrzW+hb{Q*cNZydR=($IiL@}ul?}ww{A{8Gu937uX*h6UfVxf+CQ_r zi*8O&&=Dq&_{p6oLlJ2HTH2sulcb}bTlF_gY`JG#YBReeVFgI%J`6Eskr_;o;^0$E zjM5Nwd?85anfp&2Rjy4jT3D)}M0`bFZ?r%`f6kEb&meV;-P{@)wc9b;3dj54_v(Yc z^h{g#J-eLzn+yLFuj@6wHR_)`0s8o-mwJdgA}u0F*^27;3GC{=wJ_Bbq~=ZfTu76^ z=w!=+V#pm(+ySFn@fX+#%$MosOL`E-56(KU8VR-5cDH7*rJ#r<5(HVaM>4`l|LGSJ zf9<7B_4*9WOSHjufi&}M0_nM#n(A4r#xFkl<=+3`_}^Hj4Tpa@{_i{qE4elWW!{Om zeW|%GoiqFQ57$pIF6QVZgyz;z%HIC;Q$MP}5+i2@>^iA}`#Js5A{=ij=OFt7T+|NM z)1q%KskMFghnqZN>3qJ;Q7zwn7AD2_e>~%F9MJ#%Xe;<{-C_ToDf+4JCur!lX~}i&aGU6DQO2agsX1 zc5w<;`>ZvQI?qKjVwu;eD7?w}xI<}VzIB~3${-3cP;Rw{UG^v)t14Ohq0k{Ns3{`! zv;G}LwbWI#o`?Nje-qp0pI)(!e;FSwm!7xQx|p{P^_$)D~wxZ5vQK+)pZr=a2)f0A?pV$@}p zAgE~vQLuHL@wVdz4`KOdALJ+A|LEC&e6r`&Km5+(&y2>LAO6haDchn(Cj#G}as=xD zBA2LS=VZwoi_%%n4Ik>_iu`CoajAKJ>Pdq%=PmVlGdkS&2{)1ng7FrK+|)B21oNch zC5#Bovof3dX%z>F1wwVMe|2LY=$$`C`u^pC*6}-UotyLK@&E8s|L6(X{EsgE4~La> zLDUE0Cl>WfqIK~|B^*gRFQu_DQDNQ&eN*#)#3;}Xn1xd#(K>Q{Zk8X}@Eoo|u+Ykc z=BAnBM-HT3`qr@(P)XZ?xdhhe*aS4ssbe7g_}d4gC)sDd@FyOAe|RXQWQ=AnHYMrk zXhVOAfLg3FCZGgGhw^TrcxfXwHI+a}nlXmB8%oY>B(Au@?Sh%OLonnE6BkZ%eYHdz zIC4}gT~9~gYFrs4Ykfb(&-{3*Yq57+`|0J7q-%c9Nc@YV-rO@5#Y1av|Py-?kU z(LK#lO^6a|qGDgqe+46uHVtw`LE*b#9#K>vKM9*TF%dhO%p|p1n9cJ?0wcaaQreA< z%NGC=e?eNHo7V3k26l75PC5Vc{NM9Xe`lx-^YFv}EcnYE(W4|ph}x=CA7f_Nb=J27 z*xRW}nQ}%`NvE_{Eu!@Q#)Q3KN~$C#x=-fC*wVTMty9!>f0^dXn>os6e&pB3^uFo& z_d|@P(xgJqDy|Fy0Za6p4l%Voaoywc5V)GdK}aOQ4j5_dh&|f^Xsg|lpZ6J2{XYMk z!v}Xay~lbzS&E3Tj1!cOY%E8XM>vI{untY06gC*SZ`Pb@9_mjWtK-H0w>ow``d_#Y zK>C($u1L}NL2WbtJ^GJ+`a9PA?eo8NwN2gdqp9~^tH*!iF0{TG$;h(((E-bb<3Keu zy?u=GC}Q!XgX35tl@R8aTGJhvAcwboj1S5If5V9{7iOgrk|r9jQ8-(B!mV-f55K>d8iM|<#dr%H3j zL%n(seb+?f6O<(vknG?9H}9&i^CA^0KD&ZpRttgz%ZaTp0*){UOOFgSy?Pb%Jv4JC ze+=nMGlY)KpE%s;EZIWOb=VE=D1LS6|KN@PMTgZ<&CJ67Tc@t?WUKpeR2Qc|nk#%l z-x}pcV>Q(?R_!Ngjo=?%NP{4^9+WY6obuZV>6f`mH(cS{e18Ht@W+7_CDvNQkAOs#t1c{)oQgw zPilVh9Q{deDVE03_$RtNv~Jj?IDiX(XffIY(P_UBaNr=kn2>cvViBOV{5iJd_=oQS z2pxE}X%%~hSrva=)Wi=~iorFG(**wyxcmq0J*p`gLW zmAFN*pffHiO3;?IJXdN2ic1xp+qqpv3!;8HK?qMH6p4RawT9s=mVt%hPN9=q+@el! z4L&Ja5dK4{EdWx$EMb7g#cT3WLA&q$vmV|*zJ$MWC49aODh2*&ED*ny!SS!LKg#__ zcSf4!caQent10{6zjo8?gFLd&+$L|L2~SfaDM69 zL?Z1sxCDP9ve$@iCMg?#5zE&6bG#Hbkq5F0q^~`z|0zb`$G(Hj!k=Sb;@`0^jEIf#@0goX2!MZUADA06{>caa$3N;DSNGM+8K1l$ zs)y{b@n-yu|C7*t*Gh^*`p!S>ZGRufh4@7M<};GuB61)I5^e<&_~>%bzVUL{Z;UN1 z23L@db?X-HGgiRh;_^>pTL}jCeSYgo|M>3xwNC$GU;LFTiT$E0{i zc!&-(U-lF4;O!#50sC-^RK=INKgCQKO6ZelepSc^~fg>a%1mOi20gv|0b^PmFMMcUZ_r8B}aINhY#qSBd z2K9pkgb}WgvwgNvorMFr83>DhAOQZ>%kGm8?h`M+_9%|%vwya$Zyeh#&ujJO9ngRR4*0{@6Evb1m_|aN|bOY$%szaT?2B5A&&*b}?=$E7r0#^f$534`EkI}P& z0;*V-cSi=D!4&}!sGRY-gwAYmWA&kP72JOEvp}_V7BMUw5!#^vPcLW3&sy85%1=%f zx%w5WYr#sv?G1lQSrcnY80z1AYXGo7=|GVGO};h3|Ht{(q|(Qiy_5x4kWJRcq1!{5 z`v*RWpFGn10)-K}3tB3We(|%8xo8YN>)2;pgi_t&6rvN)+&+aj@`T-bQ7VO8DRbnr zRV&NqAAP5|AR7Vo`96%%cuU}GFM0e8zkl+$IzRd8VmW_YViXJc=X}8^j#dEKC{=t; z{yAST1Qz-x{K*$5(ZEvvJqN!1)4%zkFMs5NR`=j9 zeh@!+Ab$OqG-$y;ra|ibchlyd)2sv?$a?tv;9sIRX=U<)oCgN?pP`%iALUZn;(wll zbH@LN@^gPy|0=)A|9`6A|A$ZY1L%?MdnKAbWdI@;=@Vwa1$^g#GpJ)=IF1N-oVOS7 z2EKyk{RjjW4&YnwEM^RN92#i7j#z+fv_J%$T7K)bMY#iELFEyZ^-{S5$f9!htIScT zJb%ld=fCX{B|!ewfX6u!;WObtEA;}13-?~Y8LWRjxBv~sZ*uVhb5w6TMhe6QdJ7DZ zT+~aQMfEO6TNj3Qfk z9EJYw1C`i~uE1}=lmj^YFU z?fAobZuu=AXbE20^oom(XHM9C-)2#l5E9FGzaaklI07_+fB>Y(Ki76(21FKIOL#!Rh%cnv z&>fWQZ3Ruvt&6ULspm+?3c#u4?~8Q>e>C9x#kvE!EkzC_3M4V?8wrf|$ruoE5Ig^* zy%M!oawM?)ziY1pbctqJtiT<^Fs#82I!4{F5<6oUX&)Gj@v-4{cwzJn(=qCWCHwh~ z9Zf9WSpwSw%+y)j-fhev+1=iCO47^A0kNn6{-6AzSWQI-APg%p@<8b^CEzFA zS&kxfB2HQyvCR}6P=Q!hBVQ$v$F0C2csDY|IPw-vgt3wdKkWtO$bX+RKF{$W5X%pp z>$^~n;ORsXK<$;E_Q120Hf}LH)CM@la4Ms)OC$zxY6cAFXf1z0RO1mq{qrm*Excf4 z9s{nQ=iy0@v(f>QweW)3%pd@9*CmN0CL<7rC~TV%Kqr#IB=TT8!h~0FHPJI5>Kqgm z9SCY9wu%m9hk)@2^2Ql}qTouVc&H7r)H5LIKQsl~SSGq4$E{M1phU2e8MUcgznnawLC}CTU0`wytKy4kX zQGm&>vGa}#+_r@ajA2A9Dww5H9~X|>7S1y{W#bmWnOvL!F21J=h^z%f+yb|L8bLcM z-+o%o(V`%LHJTTJSTBwQlVkueJ|b!P>8GaaiprOecLRUrrDO{FHu&MMar_5!!O%HS zx*oRxZ$xzFN8ofZ2gSNJD@Ah3k^AxjfHR7;h(``&sBe*n#udg%cwfL4G;!emfrI(4 z+w>L{wFAEG{GJPdS3R?G1#bZnm_|T-=D&h#JCAa1y65 z#(^`95M?dU6ibEU79KaX56__M&E%pCI1c{$@S&mu=ZAk>o#PfkQtu-W8$~Y#AX%Dn zmrR=v9)D7L27FzZ+(?-GKkB4SMD_kpeW2?C5Lz>gbior^G_E2yLSaDX=pa5*18wCO zrE>fYK!`s4u!T;fqm;g8iRkC_FHKSUCeDDP)j~4@vHDXP@h@Av?7 z|DSo6LH#d~9QrHoY}~@PXx=#>uDQ>cjsh&B2!HXRS&j}`wM{g({0P8dM7GZ0%fF(x zfYAY*8@llbmBy)|I06dIDO35(A*GD(JT>}Nz77$6R2+Cnp#zERX zV-g{HiQYJkFds)p2(|6FNZhu9Dj4((B)Tr}-}-(W9p_uWZ7Xy?^|`JK(zhNTM<@T( z%YXH@a`01s({(}p)N|vA=={g{k02>M!i|*;%p(vBw0@v@t8+_(c;=6JDc+$Tie;m4 z^a3uzN5<$Gm~_r4M+oZ=O&M^H5x;OosSg0=)mSNEJB=I|fevhq5ddhzAku-S;7aLc zz(Vxk(VV(NPLVi78$yC5MDdVLt7)+=1b-YiFZDKNN{8AK#?b*K>Yq|?EARm7U!&^+ zr*No$&Nw>8r(X586>^{YyRHl3w;s_q{?u#Sw!-aG|I~Fs`PL))wx4>vUP@aBFh&_( zwxx`95XT%uYZHtG>$CQvxi@mu3$3LFw=McMFFKN6yny7F{F#^kg3pwrKq(tq%YVz# z-9R~l6CX2ZP9ixCok)iu7Q4?_#hh7LaQuvqQU8et9ZGToZ2@k&7~X4zju5(GxkT<* ze_%J1V2vIAv+yRjlxFtrxB21qANU~rC;hM%;LZP{pWk`_Q~c-SSg>n@8hrn)SO=wE zLwQ75=msQ{?podEjk}qZB33n$X(JFCXHY2M2%*TKaqY(ufM|rD^;Y<-iNW`o(OG~q z0NvT9uCA#@;Q(7V=zZf~pYg!#Zl6}G9JMLMewir@&>TEnKpiby`-4Y>_&4GIp}akU=8K25z!u4N zVHiPxyw=TEy*&wS|- zZT_SF%nNLddE}9dhkxP^4Zrj6k8wXr3(uL{AAB-`iPtuxv^g*i?h~y&DLDzyK1JeKgiyKaB$Zk(;h(AUQ3e zee@si*E4A8I?&Mm!AJWVfgQ&Z0Jk2eQ3U83ey@dbEQO!@3cCKeZ+zi5bnSfMKi9z* z{&O9F;Xl{;IDdXrIR<)ntRoi`2lA-@k+D?Aw3%g`>Xx|H8cy z582%KTW-hz?cZ39fdD<5dx-CrVH5-ezkTN@dS+f6G)}UC_QSv63$!Qpf58(!@bEW$ zjM_hI+i%%Xe0UolM&Tm|s1Huwyf}z&k7FV3g0=vxgOGzLNhUvgjgQBVdw1$Y0SEk!}X9 zSy7-2BdEF&7;PZezxR$F4v?;DLpl%SV&2^s@PEgeM{+9w1vhTxCnxxbRJKEqaex&- z+5b`QQ2xK4vg!<@{8fZ1fZJXx027ktUv*mvbZuxqdPr9nS`b$*T0d*CJ|X{vMDSJ( zNJIf#(n`lDynj>yj$*zDn3 zuS1kya&hDo!!pcRKF|OBT9Bi2G=Ly*h)mi?@B2p?B5iR0yPiWtTYlH`$T$E&K)%1V z{VofD`y?^_qbveJf!6P`^mp|pxKr@@yL}7r4o`mr$ODN5Ie;f1E9l6Q2MUfV(95|J z#0z*LOpH%{LV(T@not~=f%Miq8fhp1DFFEbpFqk%hU@{N0pd?N09gqe^sl4#g!WtJ zD1_R7$9n~o$LUY+Ezx^*1RpzaMsSXU-Xnknozp1c;Od}y0feY5mf*5LACCKXkaGcv}a(UqXk3!RV*G9pU@I58;DU z=)8cASS}I11%P+dzrukydS43A`>9{_EJ}Z{BD!11p2HhJbN=VX{X3qY{(taFe((ww zG!8AgKLZKT8H^u#{gn0c+rAAT3FI6U$PZEa*avX*{t=MO%}9>r5Y`>%g!5}j-NrO#*lj_5!6(Cs&$DF9j@zI1=S zeD@UmxF3Ip1q3MW3yHwby7qq|@%V!x zg&wW}X8;wQgTci>Mftb57FmynU#2>a{h3D!FcyHLJQe6HU^K5R2U+VzU?V#_PoXU( z1SmBXfFh#5yC5W5;FVBE$oLMlQ2zsTERCoj{ti$c_^^Z*gk*%`7{n1FTL1~=0^}^9 z7@%?ZD=<+GT|Neu03qNrbl86z>F^0KSqL2gof!ksnaaTFA-4zyaB#?@^XGI0j0<-} zF0T{d2uOx=>Vw7cfm}qVr@#3{bJ z73iub=-?BE<}*1G6(qtXKXzkwr1(Ipo`8UR>io2c3#YF?gpBN>_J4o-UvB+yPpAL- zU#4NcPTTYPU;f+w^}pZx$MnD5(){{={#@PbZu>Va^{SPm`rGaJ?^!xtY3hG1@Uvu;Un4N! z7#4t!(*+36A2+=AKQe!g!aD$E=_pZo&v_^)+`9|N5kR)urT^izhLN%t*6a!Hx2BY-8`uU1GYS)Go0drhQ6#8x)M+G*;DC&|K+! zYiZ|HV~@Q#zPjc_O&fJvD>sG7$-4WmgmZ2ZOR(W<E@?brEc)W^>G`(ignU*=`>?^?!Ewzk+$d!zVyDPc6{O)| z&Wb621)=e@RgrCX`k8s#3u_#&YQqyf3s8GnUR+9yT_2{AoNfhv+ijCP?3Vh-IQ}W7 z&%+jwvR0GxX1#wfT=AOIvpLFVnjx><(U3dWaron79CPYSb!>S!U!!|J-eV_}4(Vfj zE=MO04BF_`LttyuKvxA}yyG*z#)scncBeSGgXEa+_NU7WViaBgX{Ux9yEfT%U}w|;)F7;(0C;!HM? z+eJCOJ*41ty`D#MeID1f8hO%-jMKK>%=`@NUegsp9KmuKNzt~it{IFrq9zU$+5nw zp!S?&EOmcEzyg}$6ZC!mc5V&_{QU6X8x|ye1NPkYfxO#rIa?xk)N$@no<@2px$z~60oRE>Y_U9YnGeqb2MI6Rs5;^6VSKw)Ka zk}_J%js~?hN97^v(~I(@D|V3$`>juY)ZMy0DRA)G@O|hmJO4I?p?qad zaO8g{so_bYEprUK@FuKqvArpNS_tYyIGTXDfkK;;<2=Do;L*aVJ$V&+W4T$Lrij;B z0Xd!!4{A9z@79QP9A*LYepSA2_{?*Ig+K}qGj~a!7+W~XJ7dD%f-U3+cywwU7OSfMz+3dOSEeO7-}QqzJwR_Zery>wRznPsKbXT+&eL7wF# zsr~5WHWqPED7qLAyIBs(?s`&1=v;p_srqr`YPHN394fIAv5F;tCP;-%YM+d9uHhv< zzO>_58ZUouIpA{E>$n>IAy~X;n7!O#YVoJEAMdSKrB5rsMafoL@K*a^yi|nh08D@I zqbD%#tlSR414eJ@I7JJCH@zHQ%3V+_+a0PrpYF0v4Zw1Hk0`o@JC!<{Z}VCsXblbCbtJO!;%D_8jN-eBeI?97|eJyi80E2N|U9OSU=J&s=2^}HpLnF3v< zy2R3rEWC^p#zDzq_zOCku6^kAX{`rkQQf4~tuSl9f=Gqf#Sz zJd~$knm)@)o9x>@^?5YdJ%zKqkazU!25!>`_R`236dI!fj_O(mJ zT;*ya*9WQVNSaf*qQ*P@#MQ@_Ev*kGf1v|HZJ-2KhT6HEqoBUt%;^b*=X$%o25k!i zjCd|&Rtl`*Ucp90gZC`L@VUPW;jYZ?**SB-R?; z$x~#;QgC&bAw5c=orW^C@6;cjEx*!u?r!e#=&3SmYvnd?})1oeVf05o-;;|~d zrd*Y>jT6NvAD3fODI}bY7*vw2e^lv^A5L^vbwa5To#nXU^?BNuEadJT{(dmrBQhWU z>t3}%)|pM^t@qLpqt}|ewX4%m7}-D|@nZ9glQm*Y3zz5I9WL+ZxzJ4IGP$!UJkRNR zJra{ubA6+9%dL{+EVBlXh0*HyX-+efHC(ZjNyy_C)nvasjwKPz3Vk^%e_W`K(~;LN z=X?H674e{Grx&+qBT$01+ZRC>=0{2|kf8^Slb#pje6)$a;JtMyrp&|+Ub%xtyzo~! z8>2ZjtKj$yFL!ub(mprh3b^w046`U*qK=>MTr7+Z)*F#457XmGZ$~x~ig|K?u7g@Uq>tkNF3G7Xi+xju)#xyomRq+m| zX@w+5YTld?%p(+l?%$5++yDKXBLm^+kS zhTZfE1yL!wW`cG-BLBRSz3&Ots1YOn!DI}UOPE5cdLL9uM3cA5k$njq@P6xe_kFDuyo^zVVRit7Rq9E z%c4~kqLR}uAlv;*1m+%l)|}vk<%TQQYrW2K9X@^9*Y+sx=^82vFZ4oF0tc?v!nd*@ zTtzBUg0dPedew3VP}e@?-lY>QoG0E&Eqggoub2hg=yh#+$>G9#3U@kW-Ae_lPuy-R zkQZXRsz&53f7AO^oE*nk)Yry6MO#;%A?NAIDKYxIWb4x|VC!a}v%_Q04-Jy6McyF7 z_V&8wUT3sn)Ge3SBh^oplD7TxL29Ro>z+*>vk}e*V@q_c@m>S>1WHO=lP)NuByDgv zR$JVeC3YR~ZK!y{J7i=Af4IDs#)s5WxVj&w)g?zJ6w(=h zauA_3xvMlhVnQ(G;w6>P4{as1gA~`i+u1n_oS!eX_qbss)eWJXjv)3Y%3^BRMw8R{ zZKiQko4IX&l=Q7OdKF+!HeUEczpSY&Y%6i23mv=rWYl`sQ0kv;7;Rc!t>;nQ#$|#q zlP=|8e;OtE(r?};?!qKP429^C!bvN_qrPP90MWxh-N8c%7RVsS0M z8$;{^aRlaFyxXc4upRE)PrY|FN-x&v*Pds$I4NjmKS2rH=fdyn!wl$5pozfD)om&C zER^{Ruge?uSjANo#rZv0w^vF+FQdeg5A*)4Cp#g1a$bpKZ5Pt!<_wqmM&n}S&X%xY zO&{UZifZ6_%Uj|OHu)Y;m+!I<8GlYD!8O<5CPZBlkJ)(b%usfz>X@HeB@g#!do9wg z*X)^C64yGgi|Eh7RVUdL<{nARCAgN%`yOzI%(1Q87Gj%G%hy?E3gNW5bw?Z9z|iN! zDM&ZYpQq4zE{Do9QkE5%{#`^klLfR_?N>FhNX>*n)B091z1FAC2fX=O$bZ8kuw(pw z>!}>Plp|rQ5&ft*@~%~&BJ`aP2@`(?EsrfVyO*tf7wY(ChiUTgdHcMs?`Wb0zHsv% zKGe77@|k|K6h;wkx}gkeoQ&L!H{z^!rNaf-^DsRGaWv!WUAi=fy}E_&yl~5j1qOx^5n~f%)^IvzU?mV-Cc_FXb z&WSpolZOt&tjmhuAAf71hK<=zB3o{8G`Wt)vbyT{SCclo$2D&NIdbuFeXVz)j*i>` z9?rVlP0$1fTVo?&Jx*3}h?Jq2R%&VNAZq1f#of%5_3()6`bTE4uVZWEZ~lZNTwi%p zxUTfRzIi>4lTIhulO>J7w--{lDBiWm%*=8o{UU3o_Q)dX(0?sA7idY!>0o@<)q~zz z@vYBdkg#AR4PECpRwkR)iPY*zg>!%4tKAS`7cWnN<=dQinVYaq%fy_wm$ zpLJalabw1kaDDl!@H9-CP0a-sae40Js8QX66lHE6Q8met9e+N*>dgs_6J>eaId!Q^ z7cW4IN|Q7Un;Nrrm+iW|X417)_rx#6D?hwky9=*Lxqk${W}O&!T6wEtmTWg^Yo|<~ zZO2Go7bfQJQ9w`UWW3DJ%7JtTS3h9x`n#_KtzWWZ`pTuOsv1)=b_E2 zZnmVKhOA13IqvS_>WexL$C8)LTZ}(~Atu^r2}_fH1Q+M_+HS-;Z5xvhm!#P%>qHT4 zv9Wfn4S(BI5f*;giu`oQ_)%DChV(06T2%d1_Q66v3yBGNc3m6369N4`^1faPcegZ}ud%Y}`NRbZD0&!*t6fA3ZDx9~=N+v96tDLuGwhRCSZ!w^j?Y}YQ_8k}%vg6^t= z>T2&w((A`vo%794js{hoGW;CR?P3W=V;mFF&h&ACWOsMu!+F4cPf5-9d|ILQZitoO zFSwf)Oej$g%`Zjk z5*R|`arDjNiYu=mAW1z+`({(l5%jm~GzqRiEMvG$<;bg?daC_8GUFi)tNc{Ns>8a6 zscNi7xwFSi(n`-Grq&bA{3Xa#*MiOY4ai+7mu77s! zmixF%o+8NWE`2`+`gpDB{V`n$K_-f@G6oW-i~y**Q*o-*b-WFAG{jEX;{vxX1R>}^`T!HYh*ET04`!8;Bpu*83xK8bdO!B#8KF|x;vD- zfM*y#@@3(xa#j*5djJ|kYbWO-;x|XU+=EG-1C56VTdX+4zRTUK%7nD>n1)ETrG}DRB}nQgL})uGi;u3Hi5lt1C;aF@2yqAskkhH}|7uromn4Fx8-@ z+ty$B0vX@^r;Nv&5wO8_U)FSx9#YI?1Su?r z7`EaS&L0#4X99(NUROEidwH93OG;Lv$LeL=Md8A4j@dj_@otgzoFv`M!+(O>5?ot^ zJ;Rku(o!pUOc__wi5?C8Of~J}@H8$_w9kZC>wQ-Sv~VtaFCmNOHo^l3Prej*+T6Vt zrb^Rme{XTn*6MWi6n{P(hhDq0XVIj|dLega?C#mSlc}ywvMZIU*sR`o;*ek7)&@_j zc-_~S9 zth%M;lfEsu*N{Qr`e&^uuh=X{i%v2({q5Bm40c~imcvtdSyc=C@6j*X(x8{Z!d+?yH~&YY}K}>%;TyHoJ$H za_E)x&R!00R!j3iCWk$*a<$TUyCZ^lcw6_bEVe8G)#|6GVu&?g(pQR_?S>WhHq4`X z^ENpZOR8oklAi4PB7bBBE-%=X84KcQD6cM12E|ecL4JGKSgV+Io`k?#0*1FwubiSn zYn3|ea#I1`0J9*DK6UI#|5j;Uo!z|A*}8$7$o9^7M)f8uI@+OZ+THEh9&eYEPLn$E zrgimvN*RiMUkfO*a@9_LPBe#;=k){E+?|{KXgn^vnev6jx_{Ts7A>>AT#|K%i&mxP z7=&+3Gqn4lXS0hF2mIYdW`;kt-MonON>9q|Fh--qveZjYwhP@#!Qw~H_eC-BIeT-VHM{CW2@b)VJ7E=(X=-ye`!H48+pseRYo2b8r&VX2D0OOuL^b{#nR8#km5DrDLHgf-VQ$IdrJmJ1lN%h*ftldx!Gl+HroXzi|CdUeifj z+(J-s(On76Utb#Iyu;pp<|oQfoN}u({J__6x2S(=6s@1oJz&-T&Bs*_~7QD*VGC%*(b@7QBCJ1-$Eu5Xh*y&pLA`ikzCguo9f zf75*rGL^$;U4VC&qU2ZYV%>aF#lczD7b!ELaTt$N2}FCYmMIPKXE)(Rc@P?##?4Z8 zM}JdJn!obQe2$KRph|CVApPSdeUmYro;N+Hx)P>bb$8DXLcSW=F_Z-AoQ&OT(B*@@ z#w~_TtLudiv8fOIGgzA-YA*#wnvX3!e-*>j5!;+vNvzCyksvw4w26i6DLj>P@)nUV zOo@%#wvpx|y*I}E!l zHWVgq$DkvnV=EuP%#0&`i|N9SR?>#A_ubr1PbO~GMs&-aoRUJLlQUBiRm!ZVf4h55 zoc--g*J~wM2jvFG`J0}y#_4-g(j4G~9Y=J}tCAPk3Zhm{mUMHJ5 zCys;;q+GdNz*Rc0my3CQX8k?5yw!ypDF4t+K}rj$Dv_3`cQp2PUm3xR0hv8uaPf+r zvl%DsFFe7Y25d6RBpsuFW3lG@SOiJw0 zIbwYpVXlxKW|;~|d0w9P<4sTL!R#<&zSGkXsJngTId&R-F*|q%C+m_&e{mQGXN*s+ z`c`OtCLi}^lB$<+F&B5L4&*$!htsLow@qloTTG4~d-gGZ%xR1|oN<%Ki;QrLXuCf0 z>PY!#4SzidH&^3o)Z@o4&b_}S^s!S;X(YbLRCgLfx46@5o^NlyuhSJXXZbD*ZpL_* zOM#6wDKXa3DF9|}H0eH*f1I{@?N0jewra&{c~9oN6>ifwc9e8|&zu+--nUp;{i{FH zvr%Z9-1WKmbVn@0-jZ7Liual^HQP3JdqlN)EU%}$w;56f1wq%R#X4_$a5-8Jr@j++ z7KT(R9{pJB77S={CEs@kJr7uicPnn#7a-XuWjhf7~40s7%1i@atqc zf+wVk+v&37IlM*qd&Hj`wM&6XKOFM`%ZSkd`(TNS47XuAUEJeqC%-oi>>=uw;OVR6Z=EC)#*WLVs#`~H62qOl z(G@d32q=EgYGKtiHQYIman8=8a!yAvIKQY|@U#44k`HoUf0<0O`Pvg={P5PWK^pri(n@eSPpT8*L{Ml?%bM|1y$GAsdsDvQ5)F>?k&qOPO!f=bwPXe` z_7V$e;}C1Obe}EC7Pwv^ohRT@_pG0l5X7R$` z`%K&>!kSu^y&ZX1yxFm}dY8M%T^Mqz#gmkpkF)UP({Ku1R;{l2LKDoDDR4rKWn0$| zo-$*(QQ_>RFgh$@vs~Slttuq%ybgS-E*k7BBmdAe7~J8@m}=n z3AT?*f2k?2f;CF)oV{uMCR3x!NbhdS=my_0s#PmpShwV}+jPrj&>3@7P5U_3e|j!xQ0Q;%5FF&0dDzbdaD^m14$^48 zIJ%opb62a>LsrXqCY@&LCU7Mt$81$fw$6Tj!U=6J*h6-D^{yuG+QYgjBg1mkg>hqZ zFT!z2`(%U!HgnX?w;xfm&oei<=c|!bI9^d>X~6QD`ck!F>N$0294hK)_ED(T91B-F ze|qR9hR1aC5Xb$IXi9x$;yEh*Z??``XL}gP&iCTZkOAdXY@wWUR;QeEdZnvhe80mQ zuvfBg-q zIs7z;4dEdC1widLX`IbJaILAL9p7Y1ee>?WN zv3J{`H1gE+#jGmH2217b{30%U-qYwv;lq8!t3C;`uL?D!c0ui{)PpvDVaC0rK-=bQ zo2aQBH|lfZk={u5+ns^NJ8JuGT)=;G_oL};@?F@JJ*C~&yP-7)Ozb_$_N-@02itZ$WBtkiJuN9I zg$i3>TbB`HB^CM&ub~fBJsrHvl6erKH_5Xft$dHptR+!R`LidMG4Eok1lYpXQV^NG zP;GhzMC@zvbjj_fse(dyxcctNtAyr38pgLmDSlG-92Ve`v}RYMxz^ z0DmA|hzR2=*>FfaBw%ot{6YfV()ySuM?LUa92L$*s=B;ax!=fK13)UTZH2usghjOQ ziH;7BS<^tu?|GyHoS;nO8|~J~IV0mV2FW0X<>u1muB9ZQKaaYYg;5Lbi*Fl@y)Ry z(raJ4;Tk?`k_c+Ap2!c?yliyY2DQf*irq_-X7%RSXZ_3>*ed+?_(>cjjuT}89z=oV z3-5#!@kG5>~0@V6c=oVo0q3u`qZSsZ1tcZJQpq?6_SO=`1>hy} zr}{D|wJITp&v==&@eNjXZv?qa%u2)my)UwHV4l=xf!i;As8OfnAVz`<^o~CPb`>@^NvK6H}2h zgbnQ|Ts9p+p;ll7#kz35I-zGAj7|~V1RmUxxHVVAOSWa$qn2u&PX~?gJvajajt>PJ z?X7LzBi9-yP_2Jbhvq1377w10>ZsbrlJnC2z!1D3g*8IAi5DqF=Q0IFDH*H#_K8i& zHianrb}Y4sf12#MWZv{Ows3R>Uuk+fUM&y%*iw)4Zo@(pAyL=W0!V+i72ftaAXps} z#{u4Mg-Az}=8raKrk0Wzt~B9eg7n=`Wd+mkD3=UVJZ3k~AvgC!v4Nn-+Pm&^K!Em_ ztw#7NFzSV{bsrE|ylCp*I7Fe@1N02mbuMA9C@%&&f2`@hCFuVg8++3QNo#^Iva4Pp z6>6j-;2&}ZD4cVoPv?3YRavd&Q)j?k!F&6H$hqb_XMatU@+(yw#p4hLmNvS~&m|NQO=)`or%lh#o1KGNoji*ZwD`heFl_-ZrBZD32}&vZ&OEp7+!VYo~# zf3`Rr2t)b`phdmT+9?A-yBVe>c^7~?!P;#>m_>d*3w;&`oZzgYjw5iA`2J|%#dBp> zD-gP|&H(Qp3@5Fs!KyfUkDBg$0)mTwB~6Lrfi?>xadZ7n3D6s<|5yC$ zT6YQ56kn?S@5YXTfe5qC*bGt5BhMnD`MNAu942!Cog17>Fly{LNW~gReP^ssx9gT+ z4r41!%mP2iJyFu!L){wHZutwXe|mISB7+`joxVk0loy%PuN1Gm|Ikge;v24en@rW* z`s1JxQLb-5Eu+@BS{dFJXw%L@TFHV&<~TDWk?SlL6ZUE4e;Gut8bxdH zP$l+X{ugV(b=RLo>okKf4- zW!jAx_T=z@0luhAADn@#sOE(;sB@Dj(Xu~w5eNK|*u7r8f#ukk9rhaa#f)nKAO>*| z1@#w!AczTaG2G#7}wOFuOL; zj7~U)WM4SSwqQKje_*MA+~8}VqqZQ{8@F}oD&7)9(8`}e+W)wX`1vagTt8sbyCb9 z7p-LY>(C7vrQ7N}u}xykKb1@UIG^D^f>&L!UrU~0*hq&R z8^w|u4WtcNW3IW$KS8dz-Kc$e7X<>MmB=|{|H1HAhLM|2%4Tulkdx{NlQwagpO5b+^r2Zkf5vqLBj&(zH_dqc`3|`~x=4iMO#uU; z1^5FI4sDr)Ol-#wy2f8Indo&x>&Ybu(A5F+=Av0n%IO+nDXviY#Cu}aniZCWg&_|Z zUtat15k{GDQY#liy8$F98Xlh=3)mz0n{7#@#d#3h*$LYX6tc&}=rakHLDrobAY3PyzisJ!t@&F+OL9 z>ZApMcB8s*_+R zZ~VQ+Qyn`*9>XvAZLdUzA|+Z2)R)co!$+lgc=ELz7N?qbnMx2EF`)mt6oCiZz>PK4 zp(7f(gt$Ygjus_VvUJh0%Eihfe-Jyg7Mv-8v99@+?qE(k3~a$TG$KGBMa&^CkEvGC zEKyPgU~dm`I7UH9GQrAG=L2zxjz8{hw)fO*a7Ub9TFdrK{=lZ*tv1m#wK+=WXXw&X z#5@i#gU}(eJ`2>)DzDcpTh@e{=n4*W$~)e%Lo#^AbL`VkMb=^qHkezze?7?fmg5B1 z=ebntq%`l@Q1Zku_W9C!8^XqPrjdK%3tf%XoaV{MT@E$!RYjGwinGA&GqRKh+OJ4t7q%v}u7c!ayI|cS@fBVe{2^6VrmsE7{Embrt4hO|-_H1LN zW$oJflSltNvY93@KOvbS84nz8)t;qM`?Bn7>$u+GxY{EFR;Yv&e{_cVkN@~Dk^DdT z`hWZH|KtA^wg2CmcK3g4+WDgSKbm&<`Tv92|4Yqo2QT$!FtGolT#A282DWi?OYIQz zO#WQFxM%nW`ThfGIS!zUn4F*~^oMFNxxa`1bFrw=W+`5$LMqR{&yl~G_P_U-k#rWvG)8zX#f0aHtYW^J^@^3%?%%&tZ zMp@&BvTyo#e!TTZMPmMiqO0T6Xi{bF=JiB{Y*wKO?=x!Y*LI{Ex#E*_wX58vs_|Q@ zFX_g?d!yW#4C%AQZ(Ul_yewDtay z_lB-hxx6Ey-F(9~y@)#&@BvD*&!{v9?9vlGV~zI5>8gCh>r`DJukI6e#8)LyeV^uK zJZD`9e~UzAA_goJK`GJ_1}WU*t~~cWyOwPI$`j4>)LtW(7YqVy#5SaoWyg`+{h~`b zAL-Z!(p)xY4LdG3C$QGGg(Kky*KiZy2;bj`dy3GzUcx4LA;T7e$xln3g7haKcd8b} z$QRqU+?Hj@+Qh{QNe(PdO;jU8pMs-5Lf{9)eT@8sIr?=h3@gL;Vm77`}SS zL0-EFZ2~f+h{_+)lqd;rDH&IOFqJf`-K(#z+mH3YpW#4Y5ubG2(Vy}`D>fOb9)`(a zBanemTbP}ysiZ)Y)7y4hHIiX=h}&nCohxs63+(Nn)A8}4#lJC|ou9%8mg{@&bTm(( ze@Bc%4|SNbDi}*C&486VjZVQ0!p14rdv{pcXaQVx(bkzj;}s&P1P>p2lfHTt46hH% zM87X71=tZoPZvprT2w7CvS$|HB=uK#FD=T9uIwr_HiqPee@NXk4R{2D%=vg{2p-2T4gFR@hW&7W{<=v={f+uSEW6 zOrvWDP_8;Zl=Xf{L)=j?Jpi@Nf4jC!o`%vc+g_7owO^>3rnG0U8Q^erQuTA4L!5P9 z`Q~0-9s40>YXaz86EaEBg=dinT{(DH3`>p&S|$lB%`I`1=_O8#YqN$bANiPM@412) zVE}nQrwfbaMo*g+f)I{43e(>NllU~Ma-A5!Lc0Am^x-9|*qv>Nv8`rhe{6<&9KIGQ z&r;{Q0in}yC2~mC=M80rR~?-F$T67-ws@>Ox9dlTV@HnyFFP8W$rlbn!Dwijw1$pmI0aZn@tQU z1%RL7<jve@sxee?{u*ojqcH*=-65e_XuKN-Cq!8tZW zyC#e2dRBql=Ao1u_;y)x*C8#8WZ6oF!GN)8XsbWAsM#Jwvsra0!~aR}hZJ5=LA)2s zk{+Y_Q*#ZnDo$x$f2Hcfu9)yZoUAwiMIuD8jTvKjB;)aht0O8r(|j>rs7(wzO-DMB z^2X`;;B@v>1lR9uTx%ML`!uhXg;ckhQ&qyU;45?NU6_T?)e%sM`mi^qur69$k4?j% zdZ}Jt0)Zp)pqKv%TxrCv@s&>uBv#R9#4_kfcff=XM`npBl$)C?iCMx4nj zTt&}{b4>WPWOV$sl3$aCL;{-Eahynk?+eB&qjWS{1$uEC!Y%W(V56Vh{&IvV9LK^b zmG8gS4*Kg#e+PFnh=5CEHEOpl!l+01W;t}9r}263yq=DK(y6b<2B>x zDP9sAy7vuIvYzRY;1;N#?oLim>I`W=8bi*s{_rCOAU@>tB7uO^_G^``Y$KCTX@t%L zyE-HJ!AFBf(vKf7{H!MIy>WRhxSA$NE4Y5$cO|x}e+^ssHr<+G`KPJwFCqxlCSeaZN}il ziICRt8h0xll2Hs(dGliGMV;}o&?Z`)6Y&mB-P_s+C!fiKV3fH)5!*7~vMor$%ZFZr$STVSw z6>xjq^No{NWVc#FMbRJ`WexXoEsZwQqgJ~e(pNx3-1l+ufu7z^vy}A>sJlixvx27& zGSG)bc`Tvl?g6*2DzxqZhD z=&U~c8l3PrNtuOfR5V9-`6zUn)jWu!>w9YHTbGm2h%~PYA@rl2l)>sVquV#`!30!! zx>qzy>ke6|BNj}Ai$*zp`FUj7@lx7PmgT91 zEzw*L)poELtRpdRk-fkh6rOrC0UYlnn{-Dgo>T&oDyl?g)PbV{ON_>gS8CDda~hZt zp#3N+Kl=-&#kCxS#~7-EIY%lvf~5}ie|apfx`_%y3LS&*#?>Tk9*#I%Z=PyWmrN8n zFioBQS^RF8@*&p8OEL~frJoV+gZ#3o6&dW4H~UaBdDjX0X*Uq;1IDJrG7bNw^v=GE zvz*kWYstCGzVoEn9M}8t2oGM`CLD9&2TSaRnOu;YmQXiF}Qk5I!X*K@T{ZCfOIZkdnyjw?xO4f3whzAm7>_ z!@$#71!Q7R1-PL*Z{$kFWP(6_Il8jpW@%^Uh&Q6Kwhiz^5msLd3#Xr9GrYF?0TlaY z39H^2ZpiIY!_Aa)HFN_XYY9jQTY>2Cy;Q8?onn{l#*8`D;H_vq)h5=odHgfKJRNn{ zpMXYrJmS!%+1M*f5HrVY^ZVOc-Ta9PEbiPk)Pqe6=U<<#`?_jPED! z)%rsWotq&s@oLU1XB>$fmnoSzTIMmjri+4tX*55{g?`Wq=75O@Xn{eOuy@uFY-3*W zWa0zB>H5gF$&GZ{@|fE5Ondi+^qP~{1slVZItnN76z{{## zbPTWOt^RIrAG`h-_BpQ0OFFSm4NzE1vKAf!I{2pP_0U4MC8WP#n|)1GcN zzWjBFY!N!CFBbkyVvI>`jYDnM9E-p78!*iY&$d-hoxC*_p>kE}JBAP>#+%8q#-c7$ z;H*LT&RU3WB@db)P1lm9datVfB)U(jG4@5-gun6b&Id~Z#&bsGA#*7pjrxlVZv~wx z^BqEBw8BKzxmp-!tbeKS_md~0ZrW?sgk)LOX%-MTH+~}?!=;KNdM4Bcaffjf*(VPF zGB(}D7U9_`+AoHqOT64ODw4(s#lD)Ul6AiH1loD>=Z2+bP2qj>DxzsO$-SvV*^o_^ zf-;p|EK@((MZq@L4I4pYz2=wN6I?J9+q#vds7=R4_eg@_8h^fwE4o|)MMdYCpCJ4u z`o=6Y{PxV!J*uh?3OLH`$Elw~QN+sEJHzkB&4CMS-|~_g;#D^(wCeoCqT_`g#aqLm zOXGmJNQ8+d0~?YT@3xsO(Yy|zvfg^b@h)J+IH@!e^P4B%#SylvaIrl-B!583s-@^B%C?qgXww(XmP>ZA zz|wJ@GrFU#AuUu@hb$ifg$pnRJE(FMpfO#(fWF7uk;Fy0134CB2s%AVNqjYc`!PQv zPWUIc>;qJ0^$~%tX&xO>Nie7vpp&HetfQXHBAAw%OC77<>-}lHGm4V}t_Fhu;6HRe z>LcR&h<_H7HCF+xCb;2gGo;=pmU_Z{Q$mox1D0B$*6DftoumAy&2l}?1lfu(%p@eZ z%~r_D+k(op5ykEAN5S=aj0qdX-%|UKH7N@7N7AP-q8+?V*2zV{7HNwM05BGgxig-7 z^vFV{Y)bv`A^vr^U0O6*3Htg(3UajU=~+U5)qfUU&PZH(-aPYx1ZaVYl^u0u2Ye~h zF#Y7YlR6>0a+KGGDPUOh;29(VU3G)I_6&ZKlB|T)U}ZxUF2=U4P*k}S7)_DbjaA>* zYBPizaitNIr8$n*rb|`dJW%B6`#x97X9eCCb(=I#u7RKuhZ1Q6ocKsYI?&}?JL>90 z?|)TU4kwVF{tPd9!t88A@@mA_c82BClX}PXV-$vWyV@|Sr=VDWaeWYAWOzar1C%Zr zEmp1WBsuP`%rNKb?H;}&b}944rS2ag*tV_Ss_sp6z5X6qHKQ%n_EHh*9r zo_e=f9CHEt-XFCvKs5R-V~RsLmhIu{HooFKl*`#{*%vd7>8kmNu&;-3-+)@W%)boq zvYLQ=`0A!So^r1`&sdVEbh8XNFY~J@*->nCq~!^O{t?)S^GWL}RbyKAUfFXbS(keT z4-K*sA#Lv}PIsf1a8b0SH>10cdVc_6nZ(E7wTn3Z5@tRo<7pn3VPvb;sc9eT&di66 zKF5U-f7=8b-Y7X96-i*lUZTGVLwJ9$;FG7|8x@%YqpX=~m(svy39V`YH0mnD?@N7& z@{e1KgB4u&G$;z@uaw`-zvAx$6G=e1sZWoaZ3cju{>J>#r4?1elU z$f%3?kV1c3ZMqRZ7~@@OsDEs0*NsdJ#}Bu&(Csq8EeNwZk3cKSJtry^p4Zln6OR^C zjfkPtZmAz)-l(7IV6J`pc{GhSU-VT97CJTv$jLot44>?aQ!n{qPUvY~c~cHn5a8pz zLqFO-lW`=nva0+UYixkJMJ@G8DDUvUG)T_pd*t-ExTI;9xR1(b8h?&6!GEco%{0n$ z%w?HArNn(tKJc6;4H9+ARgFYWBp3otG1J8WmqHS#Ba)x%8!Xkfz`|%y^~$s(s2ljU z$%h#9vg(9AHgHg;XnZ(L?~l^b&_Yq=NmQ8|d5pNy2-t3M3mhFs#=0(5i29wk&in8Pk-5q5U><))`DYYtgB;EVPI2hDCWQ!)$fxx}LV(0N=!?ZO;OlQ~f3e@>yy2l5!fOHL41Mxxu1;ImGM(ZD!7}?jz5z z6muLf>N52|3qKcS7$QU&JgSv6FsAQd7NnlGIK;Y`Tol~T%zxa2=~`;3UFaL-ykelR za;%cpO0N#cwT)I!s^}vtH)WU^1U*bMS#v2_^ym5Sm#g4Msf6F|uOg)2A$EmLQr7>6)B?`w{ciYBRDoiR+2p<>#fn;MZ0LBRD5) zsq6c)X)mfmGt+zJjUV)1a^c{y!s#dUBrz32Nunegjm(WN65d_GE{jd5K8PIm@9N=;(sqXfk2t76rP@O&$4KrrHDT5 z>!2so(i~^}8lY(vP3<*uo!6vHcOiv?Dtvk?d+|P82ZW^(i@>)%nkX*KMjigCC|@XJ zUxKPx-vMV7iQo4YDOPBht+5VAqLoG>)<*#&4bF5W&@_Y}S5O7^{)YPvP1$l3v41i! zn&s!j=zkUo9qe^MuFQB2)`sRPf)L0#rD7QgV^&+5f|LVSngR8h3D*79ZnH!?6O&cGFo zo=~DxzK^;&0|a5LvU53rROv7~=<5mB@p=OM4S!T>Ke^%_!MEZRp-^&$EVL9Y6}~0( zAsDGNDY-($`+WcG{8ZP^#L@cxuKGmC3S?|BbT+_56F6jI(QpG5w{PPft%UVX`!B=# z>&wCA7FK#_G|2D6#*1f$+!9NALS2urasGClJ-vT0-6?eSu&4988EZc=Gdk9lbdZ*B zkbj*)S5h`;nE1HlQSe1-qZMCAuOMiKKU6R6h@-D0b4{H{BiqkfEn73B(&D+&yi~*MTlDSOu0ZzdxiWW2LMt;+g z>m`72ntM}brr}e6ENXnWgCm*Ru6rY;gnzip02;ID*8H$_XuaSmdy)W+7$xQWI;ho~tKe2Cd!!nlPA(X|Bb~NT~w9 zHWz$_Y8tDvBKWBe>2=`j9KHhW9P^aC$~=#t)UeiFCiPHh(Z9 zTntRDOvJIO>?72uA=xDPsZ3(?xnMvZ_X(}SqMDcIQ=m5(T?##vrtg73OQReXM<^g- zzjFjHe6xJpatAD?aBBMjDva4fYb7T=m;}I?tYjV2iBL;;-QMJqP=)N`Xr*3&N;*1! znGu;Fh1n8cD9mXue#v32(DvMZxPQpNid(-gxk)kZsar1BYXFs$;TVUhTPWWMD8p?Q z_l(XQ4xtsfREj=F4iMkJN6WR#knYtU@2yf#tSL;*G!MU-n7Quc3O&I)e#?c%W6vFh2Y!}(7KTuiQZ>E>xLV9zk`Y-d{=rOU}&#Y`P z$j3=>Lv&YC#0t6Ry%6_ET>DW`?9HJ=QPjbb#*TqWESwP7svXNkTq=)Xb&z(>Og}Y^ zo*&`1&QWu&5AiS$DDsX;(}*~cO5 zPI}E8Zhy3%EyS!#IHg$8P3iQD9%a$aO0;wc#yeQ=?*=^J>6%s z%sz4-zW|(JJuQd9IMdI3WW4dwkl=WpjL*BZj}#crg6SpuvR!XaeSgFCnhu{BvX!1w z1GEHAS@3ALHnez>g;|`Pe|jRc9@-ULP&>6V(wan4NIWebWH@b`jl24f4+XB#VM+0X zKGID5B0QE6@StCCo!qcNQS@sHS0ql?{Nkio8-5C7roiMZ+7Wj${4*7`v&6>>@!M*> zr%l%8e;!A3YugF3K*a(QaF43_H!OaA zX*EvV>+THvJz?WIa-L`GYyLVkpd@Uz%^Twbofl^}LvYp^;{1@WBg~lr<(LJTMu};)jq?y~Gk%}!9H5ljRX1bm z^H&(=k3Q<;E*8aaf0C^{sPg5L<|Ay--yfw8ny$_Pw0fC~-eM_k+bDbj4d_!gpA8AV z>>9qUy7i8#^M9l$tv;Hm?q^>Ge@s4S`%1y%RnVk$XA`aO3y5QNWoU>d5+GBmfwmKd zyy>shuzs^ zeo4H9if)y)a`n8+bTZUk&AjRtHVB!wNLlb<`mT4q?tkA$UK1gy8+qnoh~WU$Nb57rZ+b_Dv95kw+17A1vrNlWHr;I}m5+@q%s1|w z7L?`%otE&tI04o zaH07t)|SYr>1l?WEw7#{Qm~_6ekbx${mvq}UAwi=f$&C43>CImAtUuq_^7XG#O;T4 zI}SQpDFjX*Rtz&3K~$Ur-Uh&3@Ub~5|p5H}* zzMMoE=9yAj>4zyl5FfNeU}Enrms?G*sdBTtss$ctKY}mG@#~r$mTMx&^L>U|`i}Q% z_~ERj8nS|_VmO79zN>G&!GmjUdTtUQfQ zC4Z;#!R1TGR}PA5eMW&srAICky)RBrjbFT4?arlXnG<<# z0CHK`dh>?OPjFgmn=T%`jycuj2KDVK-tO~3X6)AnOg^~}^jj_8bIx&W%E|2`Y}Xm4 zm2>4I&t#CCfQv@@+QkpHViEU1V(?nL|O@BVj z#ahL6LnCD|a0ieV;W2#N4-0e$s}MD^rqL0{D^AbsZoOH1I|Da~FMZ#f9*3ITzE#17 z^=SK?Z=P5HwR6mliW$L$s;mt`{13Z-6n*8#QXzl%^xaCppZi~iKh}koIQ;epjzGB~ zqMa4p-|*oK6*_3)m4zMlwdHg1c7H@(^gCoeir^sL4Tx$@mhj0mt1O1bTPblpN6DBt z-@1H#I*nY{=^_ScVj+1S)?{5yph0~72SUV_IAztdbEIShu!n++iM>%(e@TyWM5N!AtU4NmucGBqkOSuQi|}(Z18q_F#Wc&6OUMgn#bjq+--i zON|%*0^5PwsSr-MjH}q?sB?^b&z_&H#pd)kLwtiKuKelrZMm!H21sF|D(u|*m@HM^ zu_#IGWp2zo)?EM}=q~~BMKGEISl>jS9<+q`2`o=1+Soz0+6JQorq?a^MEUo2v(XPt z^%$fBAXu0_F3}%pJT05!uYdGTG1sHb>+X7sy7VW5>kcCFii(K25_#woHb{MZzoN~H zo+xo|3J9s+&o{?_1`PsJ_dD-qJ6YbSTi=3!2eB`I@fxy;pM|Mzc>xx1j6(moc&xlD zjh+3-L8L1s%R1Z9dj6BJH|tiFSHgvVkQbn$;$wcUs(rG;Zq)&M@CEri-_$C{?4nFc?xhO7ZZ}yMt z_5D&kV^e;6>o9F6Mt?@;mLTi-YkvbRw@Y*N^^Yp#nr5HX_u9CPH*atiA`rbJBUeGTtP@k31dkUnxb5s^{ zv6PRBl{@Omnr>t@+DA$=Vp_!MQAX5tJA{*&mQrlcP`t@$~;FKp&S(Nw2Y7T++UiZ zlv!B*F3HMR$PzvO)FWzp?CSG>=3k*4I4&*dtW5bg_i zE@9#IMSnAqC+j&{xpMtZ(}~t}$VUFDluwa;&?D=)TFi*P*qKLq)L)zI&|Q(esPo5y z-wbEsW{yKA+`B~=Cz@pSx!q;o{R(@cxdf%dqF$MN?iYHV%%on~N~?pkDZa04vtKFo zHf!gTVn&b0)%5zpoB4Wo@TSIYyNk9fYE*N!4S(Nyw?_SUD^IXJ^_emG-1hoHZSmuJ z)M@;ApQrCtshul#nQdp&W&2d8crVU*aRxqXjXg>jb2ZHQr&-2qUL*7TjlGt|C<}6uUro z1AkSP@l5Q?g2s-M@6z+63ZvFs*4yufmRWOx0Z zciY9nd|s;KXI{J=us^oE-%fb$e{K0$MSuD7xm!Fs^ZU3ySD*b&6_fUC-ZsnC_pL6$ zOCPRQ?Pf*J9dK+fQwn&Ti>L|$j%xN~##+agFss^7SLsqQ!@V*uPUd8`ve$4?oEN!O zleLx^%I0ft&u!*e)4=Mdi)nmv=ieO3!6x0@C4GIrNcAIIbmVaQ5ZCFp2RSTzqkqk& z=$RhlqqU9dG+4om!@XViavA8WXX}=0d-xFc`Yn096#1EcUrM zo03V7&)3;3%Cj-sspkEear&VrT7Tv0eDgl#@5Saby)AGE=YByabNyglylU-uv6OjJ z;%u|;&d3jow|Gc)S=}zf({!l(^_+z=TYRB=9WDo5@vX4xz8mq};B0#Lr0hEBqy@XN z!}ERAL0mvyY>LZG%(u}cJ$HGTYUSefj4#Jb?NLPE=T*Fay0_i7=$_F{zkkhK#n@o? z-gSwGx_R$4%VTz|_xgPQD5;_G^~v6+c9Y&`xpn9F<%5vLfmXYlbm9uL&(7Z1$I&*w z9Llsz%JZ3+_G=Btbv!@fhCe2?{+--EfiIWI=c->Oxv^a9D1EjUWA$kcdS%e7;_toV zRl(cGXC5JCH=i>-jYB(G7k}C|&=*s6ajKVSSD5bfSWCI17ls`i5X(hlZ>H&q7}J%< zTVG9afn8g(eaCf^nJ5ZHHS}z5u56ed&$l>)KvMMvXEj_Wnq7ar*RhXr=%75{c>S77 z`l78BgTD_1zb};L7I!jr3FWoO?IYjn0`;_+N=D)45I(V)kI^8SfXR6zkW6k#SxZ`IpTGy%;PVH4Tu_jk| z8W>S+da1ASHx2E$M5oy-&7Iz(`6(YBq6e8_E!xjT?qAnuDrLn?m-^nFqn-2uBa}K)aOv$zFD3iVozM1Iic_2icZz0#eE8n( zlODF$V=yJj1#Q|qS60=*T07g`kFrB~a1wKu&eFp*lvmT~V)pb_;)!ODsK@u)Io^M7 zH)&V8a-Ihl?flgBMSHk#gOp^FZsrqh<=yAa^thAVhZX8&8-J#^r(S&~0QYt?$wTF! z&U$#JmrT!J+x{`3aKa`207BQvx0`iII8i3|d3r^QxGTFAbGCtbylFzZX4_AA**uXK z$YMQzDBBq%llQ@U>x<`89P|C+weHVnWlp~5Qr_-PE4@+sx#C6bmn-{ebC{R&^X}_9 zmz`5t&(|dQXn&t+wmoOvF@B!Ng?alb3#PGVt-4f=Sid{y)w$?O3l1rpiAQI8zNwg! zb&y%%`^MqqMs>ZL_2s;Im$roN(lNOnr0FGZrNwu$-E2zRlGbzSvU*Em({0{#{rf=Q z@xxok;Q{VH|Hh9}8GyZ?&tWOJj|wF?V$R)P$aDZ{|zeD*)9Y_DHfdMXZ)F2pu%PgGwi+i!8c8>q>= zpl}WImEDR`GQ1{Ji`p?Fwu^$x#5l0sylB8Em3@VtV2JGCqW9Za)w$PpcQc?zrBf&8Dl}Yqs8pmrr+n+S~2od+B{k>L<>Hz2A4MZf3FJzL$ID zdf8vUESY(&KJRn6-)4``6&;STntO*i+NW~qY)^CJv$0kv)!d!FXUAisALR|CGof;E zqkreqS2O+1=c=yOvHbuyIy>`pf-pLkx_mS%zBxp=E_69Pk;lw zDc9#a1~1JEjpR>OrMjD~>m(3YIXt{&CLQx$o#*X+p7&c>?eM0ww@SE!9n>^)7q-T4 zb6)|AAj*v4qwtV zq0%&jwY-&1r_KGKQeQ`=r@ePTf!lY#W=NSm+H^X99)>aSkLP833BoJ4ZgknFX8GP6 zv3iod_k220%l92`Z|86R=vA~f677DJ-VI*h@FZOiNrW}`1qPc!(*CpQVIm#&5iWdzq4|>p!z)xIo9?2=SW#`^!aj+OQPDo=7;fn zA6>I#txazBIxhB~_KAr*4}-0oF2a8Hb(e?fhP!^KSNBIYGoNvH+IDNw?$P}8N~(jg zm-nk;#_wCU+U-5pYc6HitFB+A+9r@+w%Z?4FPHy)nwo zZg1W*b*@_K=2$JRvgGeRLOWb%!M>TPdA8W*GJ){4^YnNYJ)SS^W^7lEc?%zr!i+f~ zzEfR_B|~pM@0L9MZkyn0K#0P$FJ8v7m~HgnYv{L9I$VuaZ$9SlZ&OHB^NLR! zzAn!0d{NuqB9C{aBKBFs?@4bRp2*W?^QE$jvlS0j%@!!1Nn2}I(C;^)`AT<{#-I6} zk-S%r)BA{1UK>mD$^6aU2^->fhkT0wl6)0D!B)7YAYC{x&wng$Z9UL5xn+9L^ovwrnd~J6g#nnk z{}g09b8geu{h4B;xD~E-xaP%V+6Yx|gS`U2y*sPIkQ-PPzQ3OBwbN;RePcOnE+{KC z{kk=9FvTWVK7TP}KYBFt(|i%`4V7qfvyRP0_p$Au5PUy`!-I_@x^M7~~EK`RrETeC>VxrCt#htU= z$yhp-$LQ`ASi59mNbBcSOz5+?7f-M8=ND{=Grg+$yt~xT&M_v>yQ_r>xdw}1mR$7e zl*IM9o4+2*^tjk|vE~@^GS$b3*Bd0g!1fdp3kjr&{d&Fs(G`ZpFI{lWjukz&gYfrJH zXbL0#@)q5+hrXu@OZ44|czOAam%G{0$~U+T^|z^J9zH-UFRspgJ>&ImW?HA)>7fL zKI}FRZdpgIg(hFT<;|=s>qTlM-0w2x)J^GUuR4@@SV}3~Tu;X(VV~x;&=>x7HR;&8 zuT$;iMHSS=;pX2vx;xSPCq0!BzOC!|Zhv7%dAmzb4of39o0k1dg8CV_@;8i+ei7I! z6yMjgXT4eSu=_5N6zID_5A?bVhj`{SKx9Gc{_tqSWNy_W2 z+fSor{#c%0pJkRVPp?&zwuziH1^dntR?l_3+PlZC;mUjN+|o-??Zl;|YH{!V#eXz1 z&NR~G*Nm$QvQugsH~(|`F0Y}8o#TC{o!z(NZDtSKNIbH%vU;<>`#pUnNB{kL)a*6W zrm0lhtKj$vx5=uW8@0VHh(0~_`=f}?s!6r&8s6vm%#yf#+)X2UVmaxd-TL*sG9B|y zyjgF!pGUh+RxR^4(rLML-d*g2xi_2U={J9G&3StW-nDj5=wTx* zs&{Kn!4I;S`Nej4U~?76!wkTf8usQMH+{sR-n*pM?hmWPw(fa*IgGpJQPz_~oL%mh zdc{m@dcVDvGBb|*oh2X3GS#`UO>vUNaM|5IMe_78@?gEY3phOSWcG-5X@B;TiA{*0+Cj!AHAo zufZq0CyG$3x|98rQdo=ga_f`|x-WBZ*B>vPxykKhhMUc5Y2LK8)&~o@*X~P>REhES z_`WWj%Qtd538qVlD{E;D3x8z-(di5N=3M&tzMbuMujeCtsuRhdv-xDd){Jcbm|K^9 z(w~D!QLSG&4Y z`U=b0`L?*P`O@}bA=?2hSRwZ0@r^geE6)6rRBqz0W1m;Wc2bjYoqtfE?`P=L-92~| zXMdKV6d=2`(Nf->ou#yLk0+`I>wYV<2Z#Pt9o89s#jWk^)#UwIklnerqh+_&=fPc7 zoLeMk911Z2YYulS+)z|b*XnZR2&;a%q&ws-K*a4%JNXD2AQxAPYzc0EJ`~&6}#_JqR&_F z_HKVX21>84rTN9GSI4$@s>d>Z<*psX5BV6+B8#LRC(H6^U4KpE9Jq3JqBQjQB`T7I zZVSI8kE;1po7?w&z{d5q#@nv;-A#Gl%-)}X$h+jyly+7=uit}OZHnZaKhm>iKd-+3 z2xWVHb-I)PdMqk&e7l{Ao&AQb5S0A>9pICD1Nm;kpZRPoWepyS`_1S4>{juvS|8!d9 zOX(Cv)2GXQf0qR9tqN%;)YH3s?yX7xo>-^D3ZH8~PZqQJd%t#R7 zqCigTGd*PU=We%B?-7B;^09xd;8Pwx-a1%box@jKb<$+FL1;XTZ#ILQNWH)mjqs;*x_)c5^d)GzP3>Syic`~7at zC|Io3^()!VrMZx2Yf0K{H|K7;f2X%?lla?1HC?Vx^*r-1%RJSoc;=K z=iY0rtlYvV#2b=%yLqU;{D~<^0yh6StLcA6HND?|Cp7_(;hp|CUPvGwP2I0sr+t~d z0DlM`hcIQvIC*KDv;=_ANQ<$cI^GzEN4`68fY=+xC87Q9hHi(Hex$7cAaody zEsfj`+9u<-#qD5TuDLGX$AM730MJ^#H>{uw4KZ64#yrO&}wSJ|3?hZ?c`^Y(l|K@0M^m?e)P%G>1F46Qajv# zG~7kF&y96|)Yl?%a{ztI#_?0zVR8~0CnW(OW{s1R=rAm5m{bKF&;-B*Bmmr&^d!uC z61v^x$~u?RL^{1XI1m7iKEw4gVb1_w1HDM!fxAJ1V7GilUhj4~%S_a{r59zISAXTQ zTg0XwZUR>$tx=Mt)#Yi37|M#Igu`tOTicbG-bwG|2#n$_AMOk5aLmyR>=~dO90Bwl z%B9YlpLMEi?qRp`A~ye7GdB>=O~f;kc69##{=2PfNH9$(4vt6*oan$C*A?>4aH(q| z*l7G^xe>v@VvMMYiClV}<=#%bHSp`bAW8ABrwB-3Lczc3QA zr2)}`xJVPoY{Xa?&){a=Yh;zX<2L-c&em=$ENbVrlQkq{ih+0rGmbarni}K!WfvpN z8V|`zV2j2EP7RH{4B$q7V}Ddf;Od$dR`5cH+ND^=a@#O#ii#)!2a4tv zA-T%6)-cFuaar!4zc3L zXZ`r9L6#MLD*ujm2>1~1gj=&{8-bK-sXK2aF8%F{}~)#Gz4-+dr|( ztMVD_V%G}e&7Rf=EumTj_r2K%GeHCtF?K>ur|)%O{MsN&9?8`V2Wlp%K&=bIY?Lt2Qt#b^dmd+Y+6do5!rN zF?T(fb@!w4nejlWX+SJwD=5AW@QuI?NCy?iD}gM4eQyDv!56v3xTg6VYk$|ze`0Ov z4)ObD4PRo613&Rx%YFD8??<`Je}7{6=!;HJxt&+VGmjgY7G#X1vWY>7HL>&TL@_CH z32NbpgIGt5>6oz%1vR8NlL=!QE+8OqG@V4YXiIg>*_8^4h+s$fsG-KVx{0Z#gBocf zyXabDYJpqgwl)c4#Kc6!fgEV9_0mhQfsa#4+1C>At#}iO@e*lwU^wN{L zCe%4l0miFs9Ej-C`@tuL7b*B3`Ot(0S&TY@|Kb}&ryllHf&e+3(P)BNHsI8m*XI?ze>5?qG_kt4)tGwJgo?L}V7MrF(le)MrN>UcjGhWp9?>we-YEq-zFMMl7_ z6O0pR4-(>5HpWLj?gI_)gXj;w`;BWqF$+9Fmx#Lq_QKL}@Ocf@Mi@m<))+nlYfw{3 zQ#B+6May@ziFefsOuw^lj&a1#}A zJiOK&aQG0Hq!$oYf7DkxBsaN>?;MIjUq&(N3n8A%o;KKJ-n-RLtoqGe@DTG+=iY`K z!tHYuX>SMkfTg$rywUX1+W6w-!d6{x*yQ;T)Pc?5_RsW2IYaoSJ{}O!a?}H_u|Xf2Xrw?3vIgli-hx`wX>O zCaC5%dH{$NaENXNO`$=+Up>9ZT!St&`HopT!Qi`S5ipD0$ksydn+A3oYuKKQ}GuMb#m#26kP-ap{zxEuF8#Fro$ z5O9C=+iV7Ef!DYO*aN13o%m?9M1yKP|KVtRKutYz2fsAreg(9*I|7}2UG2pu>K~NkreG_B$ibSmIP+zFf z1EiahDadG-(xkz*u-V`&(bGM`4}OR|&Fy~&9gQ*d2RE3%`umgP{P6=nIZ~C+|KPvh zvwyROSUA{l=j-wQ^8mpxlGF%6qXB2S-3MA6(&8W!Mv_dy?SNymJ#?thfp-jErYQtN zZ5G*~6+qyk^O)bfVvK`>UMemYR5NCl#VVmj;)Q*9jnCQqH|I!omYX`xuYdE5A0OQR;NUU8{*g!F z{^laTzVMGc`ok=$o1_X$luM*ym|Dx0?8kYk#>D76164A;yhyW;nwpt>U>??cdnb zHoyo0&iBQ|19M>b*aAN)nBSM#h%0wxgAj{j9A<~o)}@nB5ssYex6i)7h=G5Kc;N56 z(GIzN1))K~PrUB*0ekitI*MgZI`5ud7QWMx8g3)kpu7U^8o;TBG$kdn^0DzdXY%8DKsop8 z*TSk?6JllZgGWZ}y@!JUEFd2CON45Uc%*gz@Gs`btMCEGvB6dox>Rg8B06GC>#}5{ zgI?+>MU@6fFJ1zI!=!&s{^BeAgA@O*a~Rgq+5hi4@o*M?xHOF0L6zbVBkY=q!@p3*%2^eXw%^Nz_Sid z7QhBL!=!(327WRWjUg2LPuw2tCck=G_RA^$3zPhji}o9fqkph09Ga_LzbyL#LzAUAvbfw(M%YXZ*Hu{U+osrh<$(T3i z$)I1WiVHO6sbu=Y8N1U#R#qWM=O&E@uOkw>7jU|jKD;I!2^^-cbqn_SjUot{2}y&J z^Rfw7uZMpv+z>5tbJM}f1cIX=o=M%{3tb!e%E-T_11@@U{N`{1jY7b|e#`OP#$@of zgI`Pk^433jed$G`?jpC%w*SJ%Lma4nxsBw9`}@TnoD8~;-7#hjUn7?{yuO5UyiSGd zgb{R%UH2E>SXQCiWv1qb5G*5HzbsaG;mB{g8oPhgH4B>)DsGcj&>oWA9&5#xu=-3Z z)r({m?Zw6Sir96gkQuxgIHb2@ucJXWC^&k0kYBAjK1+YI}*?ObjAUCa94*#E1`eHq@<6zhNMci1iWDHPpv&?DDVbg_J&D<>q1Bw_6` zEY%GZ{0@mgDJO_zix*F))}C<$q5OIZ{Q~FJn`Lq}$QFv^8(g!{sOdWzpVl(;HUNHs z-4FN#J>44uGSmrXWTB-_~d zhkMV)__pD6KIY}a`DVk}{`JNG;5V$nEA*=u#U4c-BP5ZDx}#Z&>z$}bhKbn4L91SI zXXze_?cLqoz!e3i&SuHLo0f0^aaaIrGLp8b)lHMev@FC3*MwK%Ld~HtriV#_Z?-pg z+)pz2D*=PQDu?|LR{!j$pi{4;KY81*ud%-4_9LGVlKJmGV;FLFL3M~-06hK|Ey3v1%*alEt` zr(<3$2%^OL>H(Z#&ymJmLpmyCbD<6td@~rc!(5C8e{iX_u#x}aaoSPt*MDJux?rQ< z(^0n7JNFA^W{mdS#??&B*T!-6E6>avOQN zmRLV>8}DH_U;pS~h+jevd4Ii&uUygkmon%h2(LMQ33Gkp1O=@A*LuVC2PON(aDA5z zdXe?<`h!mRZ+-EP-38f}6nWxt@{is1@r)F7?(qS;W@zwHLmY%EMt+xIgOjiG8~+MH zJSN;60{2{66m1!iHbV^JG?2cE;@}qn)*`qX59xJT5Ao_B8`Wd!dVg_9&5+#38l0!m zz&`*Z4+s?vF&81+PlAhzh*)FTA@j#y4TsAa@rpI>PmsU+`%k@Yb(DvCo6ko~I_{T^ zuNn7K=ExJ41flxDyuOn75kk<;v2YQ=uFv!?gq^EFr*}wL1)OKqf8GC0s>MuWF^X(N zAQXT0;Av)!Zk-t7*ne!uQzyc4hkAs=2i(k$8mA*}{_DH`!7l%erde@)x zlg&MDKB1+$iM?nC%+He`-(D=_M8VZ-R?|Rxg*u3C+a+G0H6GE_^*+o!c)butX|V6e zZg+^4P2^sV_5M)Em!0%2yd9S@s?`3Ft=WOgnlr_@H|AM`+<)zEkh>w^Ip9Pqgyc8> z`NdhkIrYfl3_fMRz<+ge@o+YBJU`g$C+7e&K+L~v>W5!Lp{G4RZZ$}Ex_mM(qVVG z$qAq$P7&u+tNzgyW`ycH{Yit%o>3K^ARKe;rsOHuWhy`jmcq| zMl>Y7`v)&8vc;yt1x{EP%6&THUOc54VhREIo#``HVWA`GsiOY6-(ST)m>Ad_d%zz^ zt`!=XMuc1p+c-XBT-g9;EG+oIPmbp;V~z{jh`abNKPmrW-{C&XA6<=g$5j81{NN8q zIdUQYoV9;)fvfc}s>AecVNU9y2bZEI5L18A58A`S?c8)YiTaP9AL~S9y`bwRFCs~89Qb7Sh7I4!kN#n!zx!{`#Lkl!aR1dDYH}o~=Lh*j&GW7Ym=U=-v zUTr?&5+dAz`%3lpx5sJFYw?%2(T2D<wivxAYyPsYZcZj=xxX9n1nFd20eym~q$n2M2(9rOEpf{^`w}g`m0>YeqwixV) zaFwv%B}rckqlK+ak~4ZbyIYVuXmF7Rg`_)_}L%`xv)Iyv2U(;m3!E z`sl9){FBE3`H=e#J&AL#J8d_SFuC9un2He8Q&(E#Afgb_ok4p1U5WLw_QIGP?kGQ)9EbN}n8InPI5Ldg6WP zi+HfVeG&24htcQJpI(n&e~}DzO`T=Qh!d^go?J2njA4wMM|x=+sZ5SO42zGW5-b?$}o` z^stQmK~da?6>TG=`UcmTC5sYQ3NAD&iUnzPT;s6JN*w*<6Yh87L$#G=|CxU;ZGY-; z+2C7$W8=%5eCrLIp9|oGgk6k-vA=4lp^Xn)T}x7iX3X?K8=HgaJ9_oxhtELXz^M;D zY0UlO%8UM|$86*=#y-rSI@!Q4R@Se-g_ixPeGY%G#yG~w3As=~C15sPoA^|p+~2v~nJJf>P4!iHNi^?)~yW6-S$rVHFMH^6*QM_#WsIE{gG z*(&PT=v2oL@y-aKC5(PR=ss}SB+~L@1af2YxEbq>?8ScS6JKe~=wUdIR6sl64yVli z!IAxN?L7Xc_WPebd_xWRZ+=w9zg%l>pmxMuvrF8(oJb(d?{3`2rWJn*gr^n>sb2416QS6g4#({Z!opCLHRNvP>dgZsoJi_@2D<) z9JZ^$PQsxsc6Lz@1CHAFwr~eK8S;+#Ppv5*V&qSc&;N~g8?a)*etSSObL2PbPr3_0 z@ypmCppHGpR_UH}rn-L~X&k8HP=~u8GNB_D>l*hUBfAc3V%BKJD zztar}#$hMt2lj{V&)Hxu)64Podx;_+mIVtvGM?7n|a60$(wRqKXofI_7n z^r^M=1@l;qK{24bdVe{H;^ph$o*?jU1ifN(^*=VxjCH8afz=H*E_YzrMi<14>+JAj zcV}tM%nWh?l>g)}b{PkF;JLezTl%Li_P2KF{?^O#;@`M_zzM&#-5&NYgn>}MS3^Bs zmz&soA;|3-IF^6jM03KS95@XPPG44A@0@P4I}DREn5&zNYrBheh^I{oyS%bNEg)1T zn9=X2%)eTZse^rOhZu5F{_y^F2R zCcpjE|6Nm`T4jD4&eNcipI(ss*AM1btNd^LKIWOm&{y~u+yC;}|LQ}!4Yuh;?DD66 zHR^blDIVqvutT?G9SptG*hTS|jyOSZy8u&TM2CQ4obC{6 z*~=RFPvYzKF(mWs9yRXW3fFjuCz@8%!QVhgO0&&Vqhz&Ns;d|ZUt7wu?EiE^LZHeGJ_P+eVJbyZog z=*6zhQwZX6+!*w1Vtnvs^tV6k?{>BgG=p3pWcn|A6H}QFm0@;ZYiaW~ zSz++=qKO3wQz4Q{-H4fwwvBScQiZ5jVaXGZc|`tVYm>TWo(S?Pa@Zc7mpiVL5Rik< z`XBtnOSm)czYPXIF%t{~!@k4M`xC46Gn9W>0cj$^N`GYCVGRyN2atUTSrC@O@Gg3x z7%mj2jNox0D8LBc>hX9XjctA+`@H8e_=%bDFZ{$q+za3De)}B<*^}&kcuszbrqxpg zu}a{wHM|H|@{=b@{nkjCE7K$-ZS}(3@OSlla9CnBa>Q+e@D>sBkcye?V@9#gV={kQ z<{(BiE?0*5pj71Yo(*^oHsDoLy(3%r%emjj%IBKvRbT9OqQTC|A!9eGS>28A89ykS zjpS8PEJYIt?M%ZqSVvM2Ay9wM)pq2AY~h~xJ1V0f@Yk-GpyB-XnWq`&D`_~_e$Q`z z*zdl065r)}i7Pw@ThU+_vd}oNr0;(|&HXSugh^7Erhz=*ov#}E@xyRmMzVpH1|RIh zS7vfddHV||@>f31{a>*I+=lf}f9rG|f>mwscJn!C=-%u6xzY-R<5$eQNQf#b;H}V( zvc+${Z;x2IQOv400pXrsRmAQn{>v#@Z3OqJ(3bIF8G$w>Xp|mF|B=lg7u8 z0a9qS049vIXv%#q3>@FsFk)}hsm;Fr7I%m_l2JSCgB42?T3-f}wx=4R{?0L(^?%_#oyh_x7L^zM$t^{v94Yu2SErpC>1oPCL zE^2T|yP*|}GLl;T6VYJ|AshE1RyluR_{N_VnbP=!UXN1$Hx}Yg+zt0-r8FnK&&Ql& zA%0H=|n z0ZJs35#oE3#F?xva!w>TSr~fKL6D8WPq3-BHHb?aR-Y&um_A#a?E&!ob)u#E~U4Au}?%_i)V= zTrV|7WRwwen~Alb`wxFR6D_IHH1wW~foVrfEk$lCO)81#33cbTvY{ctmQi=~GI<>3 z0hp|n2ma>z(t+z2AOD*IKKh9V9Bl4<-KRdsd2I&1=Cb$?-d~}4G@L&f8}PhTZCq&C z4l>~h!Rlc!Hej`2SDcK7B8gh5M)~Hp7h>+i`0#jvsGwm=_zcc z*^osqs}D{_;71t95oodSyj6hGMmO9@v0BRnzaBY=THp`(i!(+fQ-H@65Ct09-ry3f z-VbF)RhLrD$ZCI6N{bDmj6iBtO6psD{3Gtq-B)-sobR~3aIkyLteop&{!bj^&zk+j zo%BEPh)HjyKR$60^RwQ7`%Qg+?KV#YqG+Ww*zh$5@>OR{0sI#&&-T*`{>@LDd`LRjL0psS3=a0%9un&1WOQ+GB|!#f=agX9;}bc6dB79x-(V zQqBAS_~I8Xko(s^Y?eOy!O(Dw z_#|M3pcUW-P9y=VAF7b33T|qvUw2k-5ya@=7e;?h(*|sR;{L%0wPaxAUMqwVAUe+M z_x390Xf)YsEtOEZKG~vR>WxyIjsilSGBSI{QxRg-SDK17!+tpQIW5o|KKOr`4tC6$ z$;g%ac?P|wNivjD?nmbS(A_U(uBRxhE6G!Uqvrof$)kE6wb`9%D{lVLQY^z`2 zh3})*|2+o)KkMr{*b%s|-5LCbA3ThkT=a|ZHk$!IlA(sk2$I4mtt5OeO-a@PK@-T# zr-(%c2N)3tb}EmL>_qfpgxme}o5Dibl{bID>ckBU!)&zmIJIw>+Z*`4?hkP-7S4h# znojE3Cn|nOm9XS|g$mABo55c9)r)zI6nM$Uw)U~{{NRVDjGp?s@s)9n#^+{*UdviV zY9F4oM1noz>myXgO8~0#GbmP_<72|HI|DyU8dx&6K+yoL_^!q7y9 z2?QaK^DXyN(I^_0FOza8BCLT?0Tf(wCr>BZaGU+duj2O{4@6p;4OofZ?@>!X_@I#$ zM65C(G$pxFGHyoz#xblq*)f9o9*ciCUV{<|sIbSGfQJ3uk+IZh9Xx!_S;=rNab)$o zzyH`g{^F0;JE9JlpFHZh4-9rtZc=vHwzZckVcj$L=k@7i$rfHyQ{N56DIZ;oW}#360d@ z`){QbAHTz}zf;23#V5Xs4eP?SCGrcya93`}!EYE>7~XT6^8|n2=X@rgxcpTAz^%v} zuglLDf5ENrvHyuvjb^QKdjgwiCXE8ag}Xv)1DNIMPI1FjUGj7Hn8}JIM+VS_B4(Ac zBTJALJNbWry?RQuE98K423vnVF1Q)S*Bj~{bTjLN|EgiS#&X75#Q;=^%+5q!2QEg1m^~Chw+a-a^T~a`0{_!|HYTt zTl}o9LKuyFu#gAxLu#X|3x(vi&^Sz6`MJ1}X{|_75n!(_G0>4Mf8xpnoz@~&v}1=o9f5DfN4%TV0r;VERc#hzeJ5O8FHQsc{F?nvEkfG|Dv;1*+4o)wVhT zt4qT1N>+lkhBQ2$KpWyCqe0&Qm-})2=@2(R;JSXr#(gkWKmLDsy$v3_at1rQ)u(b%cQi8U`GC|EcW6VEb6&nA%6gp_N}dPNRKs3%~6vzjR6e7jI!) zyv&rH?4nWNXx+?AjI?}jaU9t}sFCi@Jxp!tHgai}Jhu7=uVttlA1M##xvAMmTCh1_mVWe7~`r!D~^L3FSiQSFf^8p`~n4yavu8)21>>XwKR1s zjtDfijS@tfA^**6JgOueOp~tzlfi<=&)7MXD$hF8lLvot{}$J@`va%s{fgoIiM3Dv z63eChLyi~3v0stkVP8VxX$%>^)J;jgDs2i(*->U8Q6*+uPd*D&lcj7*Equ z5WNd^F*JnrNX5JyDvtQh-Jv55AoT4#nVvnI5iW*6^PqUrf_waZTXmh1~#XuyeL z9$PWkmp*@Zcl8%Ops|3@r^RDpIi4XU!GM`?|A-m-+B=|0Gz}~iH}(~LVQM$ND>F8n z_YjEVjSdGBeEa}kM%zii<3Z)+{d&saNSaEMvUHt{my>~$!1~PpTfjAd0m$d~#lb5SQt(Afiy8EAtrj~@&fN5qX@zK#yRG0SKi zP;P&>LQvKcdN1v9-Te5^C6mi-Jou9niOFBwfAUL5v4&V}x%|l+LB4rwKJDRgi3&n` ztt_*Zo=9el>2=h_(+O68!j!tj_h8%P__6_a*^$jR{(AC<9ZG*gKX$bK$2ay_N2LF;w+-jFKW%S#(U7Cs zRv~qLliP(3@HC~a-pDiwB)745v{2OxU7jH+EvK0n(o=_qJTNPcq^VCSK6g)!`^r{m zA27!KqNq&-jR^w1i>Vw4FEvdyyY+3(muIf4ypj)YMfSlT;w{z|^&*CNevi)Qx*C7q zZwJisV4KK(<5fOq5iBhbh6$y1olnREcS|-pY+Mq}W*UD!3 zssm;z;QQz-5%-YNiN>)S4e2e8U8R5GV-r}BlHV@G5lmo2uo_v~gN1-j+)XRTx{K_j z1(Y{3l9f_Ij-0Dlbg^Ni=iC9@$Y}hikusG_t_R$?$eD0Cj|Lophy5?UJ(}2GEc?fv z!_R9G$430hUGr;fKKSI%*!6?`=NsGb&EeGg9FOqBW5fUNISK{b2SR=AN^5^2wHA@6 zCD@R}GOSH#cu=J{jU4%AQCU^Z1k}Z<`7Os|8)2nEItTb6Jv9{Tdp@Zcfb7c6zeIY=hEBMU2P0TW2jFIi89(bn5!MQcqb)rN_Q$_VxcdpGA%au58dG}86x-qe4{FZ@I+gH{&E z)96H*%OM^+4;|GuRQ6owlV8MQQa#|X;jj4p{|t`;j#WaDd}1;k`pGY_X=H=SB7nf< zsrGXYCocE{PTYk7C%$PCv<9u08f_$PMf;!E_h()iI_wAVkJ$d4zE6GAEXjg&q&K@cjghI}2Sh$fA)9pcr7JR-jF z#XU}koM`<=kLUU127mA;ms$2^O(Mf;gPVfO5sWA?B#+pt!_X8}Bf{;uo%jZts4A`B zN;otW!P5w>aRsCP}z2WhVOy++%Bo0Pz_E5+eWcLvXH{i0nQWDYW^y^+3-nZrV9@PYph0pUteU`zWp8|fut%egAF`x!t8gzi`3eI4< zpfDV8{WmWlU`7m@fLlNze?Dlm2r&1jqX<$Fg2sM;((v*KUI0g?kNNW=pea-lgg|PL zB7EoleE_h=h{2Gh8gR7JXhgG)5YXYcj|AZW>tge4@JsEkF~Y0$g$B z>IHHOd4gM>m+o2N8Qu6WXVRtFoL~V`)od=XD42p_Ptc5K+8y4%r7#9XfQX_Ix4_*w z!o`1N$f9Hhb%Z-=M(}K;qS-_+uca&7Fj!d9jczJ}EIzBrcsw49<8d|~X=8CaK9AS^ z_%$90-Fz%hPEv@=@Z;!2>MI*#SMf{G(|1*Cz zKut`5AV`(a1?DapNTp)du=m0;Yi#st45fc$`wSaFkTsA6>FX0fpGTdYshynGfc7;Y zi3o1Tr+`ioHe*1h$&sDWvj$R=PR@xtZJ=w|-n1kI`9OP(oU@C}YPiu*1zsN;>Vtn9Q#;()C9eaf5qh#PDEI0TupWa&r<(>8J*okj z!?RdzB-x7HC7g!m(cFw;MnT;)l5FQM@F6P8{a#h}HOP-JDDoN*4b@;Dx~QnpULu0N zH)Bvtj1*#mtcOZLOwi~AMKvTjeE=Z>iHXbWP?#BmYJSHQx|;1xS&It7YG8kyR&@dv z*HpHt5ah%ECE!R7@*4a*adCrXi)9%$czbFO6g>u6FO?`#AdUikA7Xn?f`ZjD@5u8m2D8^AV>V!+Ym&_K9pAjA#os%H&F zO+NkH(CJ1*z)=~z-mIZ2+V6iKfTAgqzx^~!ljssdlH-#*i3i)zm%r-zpR5JT#K0UE zH{jNMoTVCQ8DXSknVk}qvKoJQ0nn?l6cp7MV&1pV<@1W7eQ;@@^Yh4ee%fIF`#Rl5 z=k>s+p5JQ$B;B=BM|K+s;aP(?tbZaHy+j)TA)q0aW6~*mBa@#stm=Q7670mNhF6B<)j_y>5cNcWu#(!87Hj6UtBTr%de>UhaL%ebbadF6}Dd|I|kOjB~IUM+*3utJ{i1P{`KU&=lLaIE9ff|{d*Px_- z+;jc~I>pVW4pM%8=ls8xoF(u7k;|dK^G=5wso?95LX_cQPHP#lFywq_Gae-%cQ&6} zsRkI;+|J;C_*Zcos3~A4aH1NKoMuR=LF8-7Cc_#cEHaZw1(|=Rckw{hF|CGi^@(6K z5UQ;L>`{~Yp?1TZgnYadw|>?rscR|+MmKF#9>10P4>N|nY0A>4ysB$TKjmH5B4;R1 zOjA}rt(eBQj+l<5!b)bxcZLmt5Br81Em+x)xmE z{mV^L#su^J(YmJAP_DaOi||l>F-=+dl=Jb8hH?XUE$V-U@|$VO>3uC5JedAy$MC~X4rfA+N-g6=XE z&Y05yt6?rhOTH$#oJKS>5kyKk%vFT#bc5<)eyr>d9;Bk`_(lWHp|RY1i>Mqp0c%31 z&Ia19ff|2SkN+yYjT>gipMKi|uYc+N;9vA((}4T>H~svS13Cy_om1XsmRNffDQ=aT zF-%PiDoL3vAvvGe7R>}93&s?buC{AQ%u;RKV|NVCvA6viV zd)5yv%EAV@f&ST-is1tm(bUR+cZE*SDm1Jh+!4Fi`D|!=kk?yU9-vRf25`AME@JDgS%$ay$s%;VZBs*Z2q(Uyc$$k zuUg_V9x2~3{H(v9d7r9{gl+u8CpA1JqqEo+!;AFU@Avb)l+ltt{;1=>YYlU`^Do!R zus#U684%NCN3~1v$dga zzV8H=-~H>l7NqK7KI8@*%Eyavon+J1>A;I7s9Y!9n4faqcJl!Zf7W&RdhwaF9Q0PM zXCuX-p80^Okxd&n`%lWdAx_Qam`z?PvjstHCk6Iq& zfH<_teKnNxjaGcPA6kAKD`t6(Pq5e-Y;5XXvcpq+Pbb;{W*7^aCdJ3 zo?M!L%!~|7<5BS3X5g4|0a5Dk{WDXtImZp`Ww$jzC4P{J7%+bc%`dG|#I>8COi`j2 zdSaxB=L%#80^~UTNj1JL{~mw5V>{`b8MxIyagdj({IoZt8AKa|^W5mEZP{tZY} zS_6_mT|ok94jO?2MOO}PJ@OgD459{Zyd@TchCjLCc_AgjN519vgdh4;ACd;$KusX# z@qmg2(QxlW%uvq%o4h``_}pU=F#EsrUYR?s|9CIAQzL(q(?=A&I31<@Ju>V8m7of6 z;(iTPhJfEIjN7q2ejhW`^Y-m2>Od`E&%ev0QC?5Y?;}2B>Wb3|AV&~4oGyVq1;*cR z^7deW4ezI1^XGitzmR`Vi1(YfN3-}R9LjIME`SAaDH4YF^R#cO1#W{<9_qQLDB^L< zKEGE*K8}ChFrJLlMPSmuwJ-dZ_xwI?KK-{Sy!be68ep9M2osXxIMRF2CXPQt;njyx)5YHUHiH-ka=G{}#{;v;>X~ zy!iY@L%SId#Y(wr#AN8r+qG|C1i1Jgz(4=2T{V9n$6=nLztg{l_Aqn>N#t?OH9!SN zz78}B2i`7)e8*>)zbXH}AI2^E%%etmyEX%#P*e`%^k3zZ0oPn{ey{j=C(YmL^?3XC zoUgTnx4+}h6V4Z!#sB~CSNW~K1a)|B!taNEYJ}ep^D?Xl#p3g5@pgI*YCh}zZ|}AK zRxf`Z@~Hh=J|6m`&=24KtM*~w{h0FcIt=SWhKT!jKmD3<`Xe8Yf$q~TN|Ez@PT=u$ zn4#*sUK)OHHt^=}i<*yoNO*rW&ZpmY!XNXDSG?aUm&=ENZU|CY@ZZgb(_5eU(SXpy?A`uf+0ya;G;=|#L3gzqz$@g>>tIOq+) zif_TrfN$V=&XGTe#9^NshPeJVQREM294Dy*lz=0i2fpI#&EWCA+-1k-2d}>Ch=A3A zz`rwMb3dxYxLjE9xUcQ-aW#>vmul}dH6i{L-KuB<^EB;0b;?7NjsnxOhHQdq#`P-VAs46N3aW+HL?bjAxvch zXpJP0ZJ;8O8kzF17u5{+Ft{AC0H&`U!}-mU5VGJni7!QC<<<<%g4coPZSIS2xh_%q zEiY`0{9_u2lk`j1Z#=35YFZvuS@nNZ#t z|1b{TY4^XohimPg9@+W74Q2JSD^LG%<&~75Uz$_K(&vAOg7Dw!NAe$k{p^1!{}$@> z=fkH*VXa#1>(It&1t1QW9?!JQ6Dq>L*QwA2fH6u!c1a{86a3Oy*NQxtqX5xp)G9Is=FIVmaX-#K`TXf8*8=FyZQ61kF zr`PA=e2d5gsk`v)YmKWvl&F8IY_&b_to6j`PlmbiB=;O&U)jwS#N$4E_Nr^T`PyCK z)B4d@bZy3xb-SsqWX4jxey_&k1W%fm5oK~7h1s1*k-s*WIadw0WRs)2^qkXvd|xDw z^}?9Gqnq+7kIVCXsvXv)b-Wp+Y02%f4Wr%p%_erZKQ9lHTS3p!V!eM{HaiEJYS->O6_hJE1Nd6E^BjbOa599rtcMU zq&BEG_cBsi5n`l^0leoUF zgGqRm0(5hw_htWp)5U*Arwco{{!zKzM#cr4@DK2u$l6e#lN z+dgJXNq@dd;c1?(!ei^C+o`|CX)#}=`1bjrR5y7_4|{1ZcaN)g-3i48zem%jzJ3Lx zQ<1FASJ{};k=8I zaq>QC)23Y#>TmG7-IyX9YvK8@3PP>hLL)8w!UA#g^foXTTcgD{G(I&GhPIDMzqJA* zFpA0S;>1f$BP)NO-QTOFf1HK$$2&B3&+X$hvEPf+bbTM6Ug@?a=U1aumvxN2;(T7H z{rDblCP}!M*01f$+|C~0th9W5c~7@5uRqzZje7SNi^x92llNFUkDjOXg7`0-^@|0u zXS3_gOAOcIyUcwR$J19;0Umkls*WlvqNFoPtSnSUN2Pzc-Cjj05?AjTd+mE65ZgfC z%dTc9p2+in;?>w!`Y|rsXn#&x^Cq9Q6@0BjtQ=xrwzE`2hq72$ z6$=&%2F+6Jj04d2Jhe4lBf+1y&! zv-M+|Wr<{6fl&)+`c27b4Y&W=-m2hE^xsbWt z-rt2a+)6Jg)CN^#BznQlm}Xcb@hY-4dZS zJY##2+^rN^YWUWyRp4CoD#eFaWkxG2Hg1bLII8wlpf@krjXLw`6yntVSp@j=_EHEb7NyB(gt?ak^N~ z(uaa@9c_IVC$rUdw3BhYHD`2Q=GJ+qy_%h$n=GqNXk;w*O|hO`F2NyAZntopT8l&E zXcte^w1;h`y|m4h$-NDF8J2l;<2 zOU#?#c-_KSPv%Rx+}jVi5*4l6PU81nH7wY)jdv?jw=1%ZkvZGUp_MN9cb8o5H@TVk zcWrT^7Fpj#f1Ye+#K_2_n<}H-MN@-G-mi|WGnvKLdbNCzYSLGSjW6bb=m@WD=1S@t zr~E^(zM5gmYJYl{C`A6t*g8%B5or?OqrIBcwPcx%vMKw?OrBmz z`Wh3rRdDVF)nT(8H{lbHN;2(=O+0zan~u4g*Hs&Y z{yvv;R`s;h%`RS=^=!5bp-d-ZSG;;Ke%z^Wo?ed$73BVU&ZM*cCS<+8>8*LW_4PcK z(J@#cd6K><4vbruVyZ=MJf7(7erDG4dO;ImG^h1raeeO(^x&vd=G+`Z6a6&hlhGu z7IV1m9)?Yv>uNcTpACIZ)dMp`(Vf3W-m_fM(Gl{jebwd5pYD})j~0JALdx}UTAB2+ zEYyi|4@_%fZ|d`Td!8k0c%O~+{)%JY&=D3&5$fnw8i5`=Op2h|f!ZLI;eWf{( zOt!0Q^ge2alKZzqzDR!#uP(~Pp1x{pcMIoczqh+GpJ;GOiv*RPGLr5zo6pd^J<=$+ z#ic`>!;0rQbQuSQUZCZQ?;jeVw+-JfmY3qZ7(91iWvLX2s-SN3n9p# zRJO5ma=hGZ1V{a%_~^MXVdt!dyPuS{ZqGLIj=LMPMajaAZLoD9`lzp1xYGrfum$qQiH zB%x=VQ0!g1#5Gv;($d3AOZP7=jbEbiJuHP>_u?e3?Yy0_ns5Ifc7eoK|Td_9yCvpDXA=Wg-{pXTCRxaFeldn*}(A?=<@ zMBvbrg-w49sx#KBci}M4V`Vi`Ji9oe;BnE&{TaEd*4VI9_?Q-9^xS9Ceb?@^%iK(9 z+D@5TzT0(g=5l%8-*z)&QNB<#Q6_;yXESTMpw7NoO%8X37*e#c?-V5ych*ib8Js}3 zWLBNTn>?}S_wFg5oqc$GUF0`~?a}k4#!Aj|8@qpS8(%J7Eks>IN8@%qJB0faENZvQ z#gpRCYWmVPDIJylb$s_PhtqidO569SytZC*4c6X#HlI41`{>pAi)YKWkKHtU=7(Es ztd_^xq)P7v z?bUy@(6cx~3fmr*r1Cay--KgZe{|tEn!W_gu+MmO)5dkGY~mo|^;^zOxQBRnR1f10=I>4pq_pA>Z_<%ju! zC}pvTb%<|Ed9~`*eU9-i9JSI)+PI`5JN_LTQTu-j+X*9RbyS{(A zqcqheJv(cFnWOJ@VZ0H`hhFyXYPWyxL)8>FZhZDrc0QZpd~tuXN~--_bhZMljY2uw zNsTYYb-CC^n`gn)KG~FFHhn&h!PeFH^Igz4`J7I|S1R~HJ@xj-4&P>`;m;o1Tm<92 zcUP8AeRfG5cM_kqAd@HK+X^f4?44($=Wb@wFKPtNX=kol`xcPnwO zPZrP`>*GZ8-)`cY7wJH!?K#L=Bd7Xhbm(%k=_Nn)RU4nR3-%jL+#IOBR(zDi_S&3# z`t3RfD-V{gaF`$n-Sh6)ZexE{eT~;q_tF+)d}DLRDRRTk-CeXeSk3Pbcbw$(?0CK97-p0%Y^87(dwb!evvEMx)hmCPy!~C^6h^aZ z{Y9g!(TLfv?QXIfP4z{Z-nZh0nZ|M|H+SQB-AogwOI_WYowvs;c^bP1sAKJvKC9?p z%!9k05pl9MZszDYw$#gGw^Poy(V^6X$U|B!)%u~(l7l#DEBAi)R@YQGM9ZCAsE0DD z=5)p~`=a0E+C1ik+O2=q;@$Z>G^5^E=NbQOAQnkH)yZF1;ac5bUTU|%1 zNf2pXPDkc#ayzca#e84ob|uht5!iKeLn^!qJ(kX=SQ`gUPLPp_j<3$i$X<<0F z>G*6RPRAk9uKwdKoO*QY{W5xwpIUl*U9L@V*A;EG463^{q3C~lJ~^)Xc)g!CyI`cv zj;xW^T{MyCOSlL2@kI{v^Tf1orF982*qpbyq6OpA+wP_(iI}o=>S+E@pF--7Z_Dd) z)2gfLihlSlY|G`&CH&o=RK zwAkrFa<#Wx96x_)X75sLU;P_OSmE|vFuiUy-zenwbuGTh6W;ko+L#lJcS0A#Z9XqA zekBF3<97G1>=QwmuNYDN@G4A93guFm25dIBR%S6N()DeYPxqU(UQCo-JSleZ!#p1r z9p1>>ylnQaSvuEwUsshj1|i=DNPFBX-22Dsy6pGHEuDYGntt1}L~{1?mln_W&#@NX zS4&5d4x8w%>GFK4BW;s(7~d_jXLP(|+5)PkdI&6=Zk;I#kE_$mkFs%=tOcg#`TBSh z9Z`XHt!GQYI_e73XT4%;ul|z8b8S*jQ*Rv?B0gqh!OFl$XBXX)r~!_8_obq*&t;XY zlhy4dj;eoTvG;=O$>=uNFE2Z-=u7v}T{>3Uvx~(}wVF>W98?Btrc@3NoBgw19lX^- zgHfGM(r!lX4}bnVc;?Bu9C}wh(C~gRPxr`1^cs@=tGafn&?t1-U&6Iw`8qk@&nvde zw`g>q9+q)&EDw9fR@JAU6yBLmbf>Ox9xk+Edb@vLH(Gn{Cu0Gx;**kP-74`TPnm4= zW*Qzw_dr{{rU4OZ|FYZ|%C@MM$7h2UBd0h_&Z`#C_Gmilada<h$H%qNPlLlV>k{j9toqqwH%Hz%41JnrTTz{w1i|7k)5Z60`f5k(r1g~3 zeRP&dORZwPG#<%)7qm|7xO5jk6CqyTr_6ATzzvUQskO?6!+f^;tv5N?+XEbK>f*4O z+2$w`{Hc04;8(vq?N7GkT;4l9UE0$~&yIi7gY8TYMH{FyxhT*slbfKTlD(Unqmo^s zMYOopzC-$q8Ot=7^OTPF^=^ASW+l`@Qa*Vnlk ztv%Yy+Gv)jqx+KH&e5w7`UtK^2Q=#vl@GNy|Bwq`?)_arYl@6F1~A9MVqf$*|~VfPCv}3w;nC7!I3VP-NQhan=sqI7ncdENuSzj z`f4Y6*@e~Y^dyFPRp)H_dhPbXta{~3$)5svC%5$P+c7(@<+nZ(A9bY`SNXWy`H%bI zB5$Ok5QQ}BZSP#hOBUtp<`Bl_rBi>4YBh1?s&8H$RimskwbDF})6>bTY02pK?lp-g{?uO?%pZ(b}6r1;QIva+l)VFK*N@tn$6PQx%%&twH2wEsNr}#WoY?u*<+#<>-PFGb`UU zUFV^jxAe7pPj7i{KHFoof#u$Oo0@QM!|VLq()Eb!ef4-!Pa3wLd(kI)1m=apYh2+l6&%S5$Hx0ccNu4*hW!3d`{m z?X)6#=J(#uN2VK%;?iv~UaYP8DBQMdYZIOKwbZ&v6SK^9XmV}EG+2esHi+sh%*(g; zo`JPlti9*;Jbyi{Mk)@k9h#YCzujh!z{O>LXeOTO%*%*0hPMTb>SH%*!~>D!oi)jp z`u3KspQDNOo?5Z_wmW}+p(W>g)ElmGlUA>ZcC{u4R60-cBuinfyjEd9n$6N>aJ?Xg zdLX*4@8Zs&0p?UP=giC0G3T85^uqTGk_@NJ4%8@e*AsnUxHGAlbJxV&7L;u4^QF;-s@w zp^z+F3^b$m=^?OJUgQsh!z4#e>h?5n28OgKOL+P8nOb zu{KqUMMYPEI2DUPS0p=fbPcoQd9&o#8(6yo{BijP()H z={#6dqkX3UnT~N$4Pfqw=@&aAnE>hL-^cj$wHh#g8qB|-KG~%SPiZ-gqfas7XqMf} zItB->-3cS3MX!l@{=7c&dVYZ(v+>`O`)LZ}lMqb!&pP}}H=G%pS7;4^H7Q=x_iYDD z&c?83*~x3e6Dxw?U4~8KfQd6mH_N==0OKz^O+Z3Y=YZPyT?PIe&C;?=@4Pbx`JT=% zU-LSDf?*+i3y zk}o<5N4dN%NtAn7^R3(nD_gL9>%75#N~d2M%zNhdL*?Z(1>FIZhu9L?_NYmJv0u8J zd*Sm@E7xl-sE>d6FKxLQgvq(X$no$%bn15k~F4$Z_Uk2XH zk&L8Y8nn-<6bQp-mISJ5t#pWos$V@^U=g_D>77Krmns-YPN-;DgJ=AV+F8(lH#&Y7 z)C1DyD*4)85o+_3`wxJ%+Dp8-W#O@#^^}SSQSo8DxT0_Bgm!9v-b-CReqVW1jgeDd z2k7mc^xaz?#uu(Daa}HPWa&F9>nKgs5E_ z`p6*;i6dtl;=o7m=;ECE?V2xt%;qC0@4Xlll|2US%3iFU+K>kvzK-uvSmm5^9*BZO z(^Ci!ndvlr=5}~kcUXHRjjv-iUItma9DHeb+tfzv5e*Pu%wT0@_jaVE zwkd{i7TM9O>6~;3dGF2l;d$iytE0JfO~J^~83A!Sa_`GLAF)zwP;MK4$OOSy0E)k5 zve&g)^79-pLMOMhU&*%vtSxO}q(LOd69vt%RADodLc)z98ucm0{Kj#Uv>n)B(>roitp9F(Gs4>k2($ylF< z_%N%0Y!WU*c)@_gU`Z%{8sB>H1H<_;<>y#I-_o28%H8tIYL@9T;aov5C*Xh+s9c(d zn!602+%HUz$U%WoerQWO<%awc(6_AkOIuY|g7i6w7kxXeHX%or9ogmw>X`YPl?=km1ol?USn`Wl?9Z$pU_%%y#AmC^t3&iJU2* zQiU2)`7@|c@XvgfP^l*J3ce9R<*%p@IM>rh*uBQty24U4(I`^yv(9_b?+sKO4)>>2 zQ}at|xY|291bwD{B$oNa1PCMpR(y>tQmi#+^WOEY<;dY_`oR^&8VhN5*Sq8WrB6vH z`z}eM&IooZUBXq@xZDB4V+;t8YFkKI{bxh@!#cMyaO2T`5WrFx2E?eIcdNnRLIkeq zsrfc}mcC7U7-zt-EGfsGI;yJw@P!l)=W;Dct^5j6XzOqZU38KwO$`PJ-P2;Z7t_S) z_(wm2{iw|^b$tE^nw8}S{PB+vyc~u_EU_Sqy&$X&BLgl)y<%vVb$+&1fxAbPtb2d7 zW2UEa+6{Pr-}L+ERITB|fv^8IS4=p`k=~pOPy;Nx;Lca(aH1`E}adBOkb!qwm{#U%C`cqxm@ogo;9d$M+QLpK4r0+=qdZX z{J888S8hvLuB$G9Tg%az1nb0Ut`qwk9puM}P>yc2*9UnAdOx!>ahMDPSJ8MZ`w?A# zSZOBH|5UK#Co1cI&)}0kU-Tz_zTtEe7P=k3BeUh27hM5ge}@DsY8g7@!(gcn_^C;B zD)g7$xsavKg1N?k4_>rHy&H(f<>7S`W#m-Mb@{>wo>IN&7Qo)uNTr3)oj zjKJEyFnhmY$W)9(8B2&5Gu4^)qcWO*I2LsQVfK{1EmioY1{I^{ZPh0GBQem1pKNK- zB8?h2bIegOt;Rs_g7?~pO-hv^F2wS*le2nY{kC00)KXZBYj(wU*z4`i!9Fn%D>y+~m#w+##-o@@;Ns@EDk=&KyQRz6dfdxJwipdx>~bD^>5J6m*5dLM z4BnTu(Q;($MciFb8Ix5v1OALnIUXnd)jxrOM#i$t15O0j4>Dfs{r<-M`JRd$PS9N! z+B(|NCpvGlaM7aH;EaQG<$%M?me4BtAhf($NWAqT3GYw8^f34iw2Qfa?3DIQmRcYM zLw6z)=Ulo}@Lo9fpy6iIk1$~kA%IvtXwi1>tRUOytOTcWwB@L7S4S^FrN zDR>@5M?FLt9@KRGMVq{nrjV*S$F`fIwlqOR9SvabMr|!qDn8S3^&%1&JeXFQ=(FH$+8&tSB;Ttqljbz<>q)ZHm4S=b6p75pL z*n;Zo_v|u?W_`~1T=J5{SAqEw#|lfo zQtFiTPT=O_xdTXlB4#$YYWGm+fFa&FJ5?+Eh+_MTVS7gA~LQkFGZX)#FOk%JO%OyFDiYzXl{j=`oKn zx*9wRDK3{Y0Md<`vNm9V;sHa%h? zXB=m3Y%EH%_tc7p=yLlx>{)kc2yspJ>C_ns5F5zypCFaVI_twezx%QF{KWP!bh+Vm z1dr$_Vt75(H*IFi^$?ss!&p;Iuad;h0k3H#o9Wn%MSspLQ$y@T;EqT`V{&bp;-D;X zPkzAsRkiDXg0IN+sUZ6Wa+lyPW*$XXkAq_fuR&@`pt{`Z$s5l2)8XQSnij5suumox z>65!$gJ|uv&cBGfmY8#xflD#_1CxkOQP4%Uld+R^B~ri%cnG9I2RoW2nz^b7e$pU( z+@LvjIlBrMO->bFxa#%_b>hB;T_Q9fQfs}&m)hKa;Lg1IyBc|wojuwbJNeXh5M&_9 zm=?qJAfHrMCN9s7#C2tTr!&1Pd1>^9lpcU)whFJ0T&L# z#&&UkvOON*N2E@9-gH4`0DEEnVkQByAQ);uI7nbJ$V=yFS%MRXaRJ6m{l zb)6*0E9F4EO*-zXM_1epJ#CV=k;@zULN}n3eiXr>oQ1cwwAOI;Y>%73{hJBQuN|Tv zro}=MF;d11hh=RM3bh;UZ}Q+V#g5eC?&`~Fw=9lVAKn-ZRA0P;d7ll@RAYg}&$VEG zMYt6PW2e{$0bUImV`h7kedd<&Zau0?1{=T3c@1(i9*c{?ZkKg$zhhs@Uz!{W##dN z`s4@TOklx4D*^P#o?7DpS+y_LZzA8x$lM)jWg?ngPJD|!{{0NsiARdW7^f4`Ay>l> z^40rZZ#`&TsOrr|(0`qxJNr_s;aJ+Aben4qbufpt*?<8$v6SIY*YYswXJ?9Cg~o@n ziYLgkW}7IVt9!p^rS}@l&7Lm0-r{;cQFk@b zI-T}+$Uej?kMVU%7<383_t=>=a2cc>3EUFrN-04K?28dnb_>j(bufs3qR3V|muW;! zWfP_5ex8uJO2sKc8h2f@zPwOL&vy_=9k%!{k-W})OJInu=)_OT)voU#EBv=64=3ev z8JOVa-p>I1c!ej=EKc7fmX0%1lee&c(18XBrgI~{`$%kIyf&09SQ}Ug^Z+kN`c~s? zg~%N}IkCV1_EHNwSTvM>A;XXUeDe3L9~J2v36+hKE}my=P$ zGMs7T%>Te;|FEzB^}qkm{|kft-z=E>Uo05^$2tBd3+4g$|3{{O$=bh{djIJ6=bw4> zk8@;eH?!1sG> z{WC)I|9%CDcbY?g!e&lFfnhlBZ~xCD%`luJ(YMK_5)74pdI02~VFdeEPIm2ygco~; zm<_`)t;PJ8te7XXJ+6uoZc6!Yh7$j`j+J9r{U)4j6pzGV7(Mu#Ck=l?XUPug;kh%^ z{F889{|?{z`;^2+C~G_@`zHU+@BKGw{9AN&xNA)+%@rLKA)&-PBcla#)m<{?4?|($WAJm7$nfXSa@~;8b0gc81oQh_DQa+Fo9DuU@xnxCfeNj=1tbBxE zV{?rBK5Ork2<@|{NkW8@qn|0(+dx`c|6RWk!PA8u#QUmDP681+m-sS@l2Nehv^z&nA(A2C=L*(seyHj z;utA^KKP9AFm%L;f0vRj;*CvUCe& ztFv_VGPPZ1@cWEu%6ml1!_G>@!l?jlvaJxlKs1wJu&NRO-yPLG5ySoVrQIU}Z0{px zhMzV+gQSU}R+fy>q2Uyc7SR$`ya}^w976GCZurB{xsft7a9lFL6B-1IFajf^pj;n#Hh%Qm%h8X34xQ;q*F;SNtO^aKT^VjS_V?~JX6hv9nYfL?SF6b|^%>Pi zEi-ggTHcN2Y-6QOrANzl8@vnoI$EwVWZ?5nfxh@`6bTQ4%?|R4_sehDI`~#I zsuR}E!UJlvvlDy<;i6wOlWpguKEL-lN*(h&;dl1L+t%?GQ|!%q(mm;n~2 z+zup&71Yv&vQuk&r9xIoFf7x5WH066<(3AUodMEh6%Mee2AF;0)tZyTEoe`y0Ox3xC;$MQgT%wPjM1%S(06&bpg_cbOc8+p(HY zu2OiD7|ZTkv)F`g%kq$bS1{*&_Ial`B_z@q1jU@Xqoa{0h^<_}`tj6R=Rqq)Myw_G zG@VT*^?teMuIO`UIYZ3r5f<0HWxs>WQ9W)2096ry{8bS-i#k0sgUY!&jqM^Ov8|c? z3;JLpDj@u>Wc9VQWL?mI5fyl1lwb+ODBJM{A6C(%AgY!f!->(6+Z+mfT)}a9bx2 za>Jr1ZIIr$b z@Y`Ha)0I&4YY6IyuPA$QiV$PQC3L;cQe4)n51c-rDNFX}2#VLk*z^NB_wD%&wl;xt z71Q8+-?hJ}Nk>|L3SB(jAEqYEf{ft5IAbp%c(kCZEO^#sHa%|IFLP5rf5yiBKm)I8 z_7BnRn%ncdc-y8f&YW2I8PWD?bBkt)l0Hd(=AoHwV#n+P^8MvDd^ekO{{z{1>m}MU zlFnSl=fzdOdnM81D^=H)OwtFv%ZS$sgA5GD5?9TvgzLb6+;XMN5d83{Vp*pL5anWU z7hZ)xSTbAWI=cJ@q!6#HPnf8yOx_4C5LZxn#&CqgFP}LZwVu{17v_v~P-{an9vTSv z-lGax(*n3SN7Zf-M&(8uzUFIR*e4Rill_&U!p73xw3o5e`Pw0Qm*7r~VURKS)Nj7 z@G!0>_WPa5#3Hw;6#P#!4W`(^9X$n>CXnU#;gqp|+84zOZmxG}xNyx6I?^uS4Y-q{ zGt-c%HST4K*iO31u))K36JJrqiLcD{(&33-`7%(9saXy1`3-;UAB?}=IK!}CPc7g2 zTh31Nc4|By`$$u3ivyU=N8^WV20ZoV?FrlW6HtB}?ebI}k`{-DZ6whc(`Jl=y zp3%{Np)VA~jYpI*t-|*;G&(6ToPN-rwi4%eODPc$KS`u*%UQ78{%R}PzPN;fFDKg( zU>l->8?dcAlmCqOtRZ4plOlQ%N~H@u)5;9Ix*vY?eX?#+X}@9kiNACWh&@h_ak)Bs zaP~4?C2pxsd>cFM zTM*Nx7egVd2MYTlv}PWnP3_e*)jeQ19Gs_CwY*eT+SMauH;y$@!Rm%Gj9wKYb&ln< zf1Fp}YMEQrLOe<+byZ^i3(y#GYdT-0f+w^81Fu^b}3-Ov!?O z7>O%qs9YAQ;#Ibqeq%RFOB`kts|VY_OkFDaX?zG`L+xjp&mwH+1bICxaaOWZA*L`K zAP@lL--9`E*yQFD4&)r)ishbB+4Y^2F!nkI4WdR|wziiEBHd zrjqRse$rZqB3Qk5!F!|BW$*U}Nn>b#IG@M0Q)*AbeTO5{xVmqQU58#)*(7HKTixd#P#(1<OIPEvhxz>fzE*XWwiVInk1IS z^5=NvCOxjmznnb>$D2FbgBayEkcq*Y;__}OG+>(^2l9QXHpr`*#In--PSxAriDG_q^R=gZo;Mb*@u1G zqNL#GjfZVZY;u2OODnYL(-IE7HLz^jhM|oCMj%jHEn4m0LD}^0SRAK+n@#!85+lg4 zx!QdD26CJM9#yxa`RYE!=U#24avoQu!(unkZiI!>&&Z3_+cLayQy2Y136@}x%wm0J zpZ5QH>AG{+(g=*Ht5N7TE9K0Lyfe}unr$S5)GzO$_sf`b zeqhO`zCHl>$DL?mzPGTM zQaWI_0lAR(nZz-%bcgw4TY-dh6rNMi*UrR(1{^51UslZF>?BBkV(C|8Hya9shuo#E zPZd#Ko#oiPK+$u;4DAI2gVz3g2Ch?v=BjGiS(T@fe*BC3;@$V}^mceFjn`EwRri>% z)u^8y-+4ijk2)oykd8mATx5jjnM^8r~I}pKUbyHcvj(yDXzlao(Hod*tO@t z*K^hW{qS!H1C=R%v#a9)Z#V(5YNzhQ)Ef)!=^OcJS@{eiX?{qw9d;-W-3DEP#Aza_ z+-G$3js2=i0zgt!4375dhOtYnb{kbS}u`XY79(rnN66WXN2e0G3dx zehy^O6<|Ilb0L{n>gbZ3v@bPYQC23~13#z_2Y^5!SXz^RC9uN{sF_>QcLNgkvvt zdRkZatB0zk>+`L&>uI}7v;)I1WUP8HD%U@P`I->mPv2x8BlvDzU==EQCH4&qQT z-K$zXkN&2A?swc-%A5ccXrN13t9z(mK+;m3VN+KjUB;ls5WzRSgePMYOBhA1ZJMd_ zg+eK#Oi5&YdFeJKGatAwAWK|-n+v^)D1YkKA1+a2vc_7$xJ~fVt`6M z=LmapwUs;RH}9)sf=dR;HqCGResMd>QO$FtGG0P|&eGp5_)dm&$yqBAWrK$`I~ zlPfLZkzR4ATU4-=x`iHb5*it+rn1!Q0}4JU9LfuM^v+S~(L3n&FpN4*>L>)NJ@reZ zSn)#i$dc75p$f#06S~%%=lR*EgU1C-g-)eoQtAc08H9#*f>%wuzIMGMm>uJ`q|=ev zvfc}SzaEupji}iW{cflS$H$a}dq8$)y}Z-Q(Dw{J+M|$HaHHfJ8byWXK;EiB3!Zmx zm-!P??S{UuI|ODiqzFiu)fYKKOX+ythu z`4Ta(Yo3cd5xphM{2DMsAw4PWCv8sK;zNsY;IyhUzeVi8t&xuxoQDNSv6bIM@~rHc znxE1`&~F@@p5YW`;dfC240ZADya-vP=L#HWKYrTQ#Vq#-UMl|iro^7luoUvQ3|G>B zPAS~BzE%HBGkutw)0O_2HLExLFa`Q5HG>%&TmFVIFlZL3ZRYR|ESqFF{2mxEvs1J3>pm z8?t?&Q8u2<;}Q9@@pst21P$7&gPO45-Hbk>juEvzO&jtT3XC}mY>|$i>JOwxz&>Ml z2KNGh%8){MDMff5QH0(Ne1(pG+uPN!12iOpnJ#Imc4m*<-=8CEvhQ2Ie;%jLsywmF z;)v0_$}@>)paatb3!{*+ol1zg`8u>zKFN`UM7xph4we|d-! zSJWJPYnj85k9`hIIH`;Hum3%4(KFC$aY#+1i^e>%0m($@j{V$KH;hVu0;6QtX~W`u zF^ziRq9;Yi4z$gM6nBS#bLRA^ot?_;sbobrdHL!x+Y&c&TaiWOauW_sRT}|7ZXC;; z#!T?8eG}e9#ii`H8N(9j)o*V}THQ_{7wQC~=P6nrajHS z^TeJt`)fZV_kMdpkQpR``zPl{aqRa{7z=cQx_*1Nb5Gc>W^F-?F1yz2+yi=Jz<{wY zFcIV@yf3RBBt+W0s;?I{`9Ohi{%~J{ydMd#I`)8o+r4i`LkKOaZHt2(7M7mi(ozx+ zrIpY_NLQcHWQBy|ffh8YJY4$NaCuddk0?{m zI8#nZ*MQ}cT|O{%mLI?yA&pUc7D;}yy&Dkxr-JMrraoJLC}_)|4^Gm41pS_!PJte@ zU86FqSj(e{pztL#Xc$C7WUdu5fjRZ0<__TEk0P?dmGW4DZmdH^Wf|l0c=Gtrn*vxV zU=KqV^WX~$I!gW#A9L5r>RpfuWl2Q!_a6>fwcSl|%O3p5p76PvC6);#5e2fJyK>nl zI%Pr+>WYSczaD=jrp%cF)b)u$Q2P)0V48r{Dr;i;Q{G(%L+M&7Oe<1>ul&9pWS&dD zw?};LCo(-0l6v^{7SsK-BM8;)+^4&#R9>r9hEpa85gphhrGep^n4nM(>v5deh-L;S`Cr^ie&HhwTK2~Xyki1sT%+KJUagGEF zTA3O-=Q*?A0T}-CnlR|}D`b2({;m9UiJ@BQRpNgq6Mo}tq7HysuA*KJPA1z_R3gei z{(7zojAc7OdQ9FweZ;u;a8tZUwW#|UjVpZwp<~e{>!1f$fOvN=rK}5sW~?(rltrjb zxBysxtH{p2Ak&oZ$Clqs3hH!V8GGj|d1|iZy&v<8rDukzvRD`=d6zKt1j^+ia+TkK zAAS7THV<4|Gxsy|t&9?tUN^m?ORESPG#clWj|<8Qox~Mk>(^b)K2*ch3VJ6s?0X8y z%qyerE_seLbIDEs-9l+Ku)oYrg6vJM?Q5ccs|l(J;mwj(YE_Ks!KY*!Q<0S!R|cU< z9LgiT+PTQH1S%U#4Hp(U_aw!$G;kIQD;)U>&U*qeW93e_GDbU|(Z`Gzm1kpy2~!!f0iEgQpp+^i-$xR|B_OGL zIBuj18Ho4Hdg97qv*kf&Gi3{^foQ;8hpSOGLHRw@?*0n=_mgaYKw{W9ma z<<7zZZpVHuccQ?J5Gk-Y^jWWVaCDzLSvjBahp3LNlwt)+*9^vfwCEU~wl z(ZzZ=2Z9KOd!&*Yc*6;yz*Xnx`7Q9OQA$L2w5r`rZKvlX#gMcW3hBRYDWZh3@zmU#+??AgE z2bWO+N2WUrpx|)LQQgA&T^+B7*(eDkOsNGc9RPq<%n@5-G6-s7^o}bD>{0&kW+}0I z7U=C2fyW$I`!7>~Tu^1yDAlNc<)5GB`eOwD8Xs3@;u#M(7~IjwGGc(=WrY%XP2uSavFt zq2~mB)+dGCZkLrNHOT9UU1ngx!^a_zsEDFgVE(YjAQ|eDC!}yzCWjV(dZAK;kG}z$ zV*CBJHDaevNHf`Bm-n!O1P-JX6sSh_OS>)LEhE)y|BHq%BU^D(4)548>o+X zR`4i#n^esgNO*G|Yk$6Tl){6%$~F?#5(A2YeHaN&5-8x#F0OXY8QFA34&yl41s!sf zQ;EiL!{?%SZIKJua^C%a*rvh3;y9`0tc2J=4x{i$U*;xghN6re9 zA41s;cY{+!U({B#VFJZ*eK3t)$?XU~XvTR-#8Jk!h3@sD0iCZyUlzF-QTrPyK5)Zy z3&T4HjW(b|f@ffVuB>cTooH<_&5xRPO?fj8H6qalfpo1Wv3G1Sjv@*0Xp#q)@eQ)s1)|yt(}r z!}RAj9$Y+iEN9wf6cJ6U3PY+ML7JqjJX{`?1dLqGZS}~1wKM#q&cT^Jr?kU*!@p;1 z>RSd~K;+N8q-NPgk|&aZGvKkj=8@mCT!$%Tgbn08h$&~x!+LezgEq{QKkbmX^c7)G z+fP4wg)W}2LJ!x6Xt)aU*DGlM0@Q7DjZfG-3L|`QWDe==%s_$qf|(3U}KD zV6pGlxU;?pMN0qL=OW@o=bAB_wos+$-!CF!TnN0cjjOu0e?j&Y(F0w-$N=oXagtQj z2g(U`%kUkE24B=@yQdA!%q24iVKbnCDoc4wsAmy%@)6#yL${ATpQC1f%5D?yp~E}i zXNL-Z$+K3|L|v6&44O>Jjv$T>O1Rpx+cf1q!FpUdMht$qSo6G1=K#-*>s8|Si(;iU z6WxO47|U3rSt^wFg?+(w5odN2y+)>@)j>A8Nr!HeUJ@Bw68QsREG;a?2Zxs4gDeES z58hm>HJk(%2FyEUV!BiI`)(Xo=oq{~beYV5n*$pLsDXE|!_6q~-#ET9LlV^j9!;L^ z*YD9eI7e$WPZaL#%A0$`oQN5XpD11Jw?O_e0#Fn0J`3EQHNV5TfqO42+#W4jHcZL_ z#hcj;Fe*KIf+)se=o4*=SITKm;UFb8{_-q@ZZen@BOF&wMNJ}zHMR(J{tjoKDF|?X z;o8CWbcRsAyY`Z^URgIZ00x8xYSgN65NC2WSHDcD*smQP{7Rt|6kMS_w38n!;pf37 z^wjq0H?-qBdQpMWkr(S+n?~hd%fZ?401!|yM7EG;0H0V4F=4h2a+tmWsqNBW?(>mfdK=u z{q?m9>+DtlPhp7`|6hTwRB*ere~W7p@9rdI{TQ`YgCJRWI4r ziI%tWp;wl-(zHvw)CpbgCUUfYt?%_=zAEsIueWb%yaq{&oKt9}N1K0~W9#nJplmmX z_p@*4vCI|4m)@UUbAQ}o6BityL!G>YH{7YHrDg=xI0Nny_FUCiC-_=Z2&79LVKxy=aW-CzX9cO zLkU$d8al@nId-ljLt2*@W-Ncy$#%l1Q z=OP~__Vu1RyJz1u)-Zd2cb+Uyit~ATxzWvWF}c1zpO1gg_j~Wr*{kZM7_t8R+8au>d0>3%O|PqydV{t@K=)p9$St;6a_<)DN3{N&FB4l{rp<#W{_;4#IP&FwJk#|u zyxIqP%IxhMC)HKm*Su*CWC03R&CFQt;xq|IBs|Iqa&T4TG{_H{%uwr#0=VN_NG%tJPVOr2wtDomJNRBbTB&li?#bbAS zFE&kjAJUnBld4Age(MX?0F%$wvl6DuC~n@`QL`exvGy^kj>+c#eEO3+`t{WRtGiTm=6$yvU><`?^eOfwIIIm@>5Ji2S)uv~VRr_>Cm3SVM;f$K?{ zkYc%Pjh*iL-UD8jM`cbQd>1aLWXr+1&$dA}88k_M$}d3DlK0R*jPF4(W6SRazz6uY zH2>)uPJun1%gc1ee><%)1L1hci#XiLXo1Fz2%K7!an}bAhBzlRkY#<(d#45lAA%yKcC>ZiuTjo`SLfP4Xx<;w$H0)L& zmbnRke{9f)dz8K}XqkB$Q+}kOx+RSsIeuN$|Z2hnysMh@-UgOFU!IJ>M93MI#B)!oV!v z!eC}Nas19B$Jk_IA;;R-;-m_8cO#Ftez13cja$5Z!;Bi!YS(v{gE6U62-(@hJUy|W zLs-V~hxoE=y&c!I6$KkGVgGBFyQJ+T$Tm0dR(~ex&*42#omL73(^828zFJADG#w5% z;=iZI-DiI`t##MFv(I5?xLJ2Ur1|l>R)*W+6HS83n$N_+aCoCSJS)JyE8yxtyuprt znrBUd0k5Z_=d_gG8g3n$NxE0NRjF0;(!DJtnLgC5j*N+WE6=MY^$*WoyC%jicQ?o0 z_T+G_5M$>RzIQKt{ha%Y$$ev|mV7;Qv)Z&am&&~*b|ZD3cUxcXQ|GGH>&$Ua6GW_v z+|K(|18zliUAB2R`=}Aj=yG;9Y-$dF?6&N^t!}P&lkhS}5`udvSzf}jO?|3e@@shI zd3igK6}tuQb?J89eL)_DSKemH+1%N~&bavVMbK<{H^5GbFOSewuE#;2y$<)q;dpFn zM%is&@k8)k=jwDxg2lmkgYEXSxLopo4#{n| zpBn1)>a)EG+4*z6l%eTPvYpgOlMfj*t9T%EU`Was(|}bT(kU!%L{(X8CM-4Y#kAT0 z?(4c5TrUK&o|KpYdN5&mMg!8$^i#q`IKP)bC5Sb>Za*dO#0t|{bQ1JfYUUeN-9M~$ zBM%3LSuECBcw4AX#Qk>orPC&Vh1i-&5xUsNd%C}>-EwZLK{SW2=_FlDrPNrrP>W6l z)}rwQD8e`X@P004=1K()wkMu4scfL^drX4}$?RC%gB|xV>k8j`g0cmFsYJ zt^;jel77<v?k8{uDTzxdvGrMSSo3NQp7)gln@`!tTb^XoUdc(c zUq9Y_o$W7edp^1MO%9G3rRsaVweG;2>KE?;536%-rYW=y=eRcc@nNM}VruF3?5*DE z@k7qf^K?>JlXcO51*%lMZHD}N!0hw{4OyI4=ae(5L$!4uwu3gILoU0g*A2^i`drBm zN@85z)9_tgod-It;8f-KU>>H&S{p7``j{A9aP>-fFA7xeNd0cHyg6Q;c^#B*=yCD{ z#&BF^^%WPBRh$oPJQQr1F75qx_P#F^**PG3Y{EHHSIx_RWpwGhx(oxD3@^6@&jM^1 z-hoy>v1%q?8!OqKSYno&+tFOZ>&d$un7|=*jRl8Xo z-2?JHvU8lZzNlPm1P0&wk36FDxsg|wtSS2IE42^i8T0zR@2%yw)cMXZo(!n>S{lGH zWcnMc%h|qv@#o9wLG}W-h>gM~+kKWgR%~aWQt6S-*N^hFywpx}}Xd4;f6kIkDXAis9Fu6OEDn!b;^TD;Ax*-qK=9NRaj6~}J4 zxZCh!x5vf1;=U7yd#kqg+j#5GlQ59HbN{^WXZ6LQq&H4%E?qIf=sK1M!ToG4qRlfuP!-VTyGnG-#)XgT2MxsjQmq zho;%ba@5oXT|KHLDY`^nO#4TGhIEr0C-nI;rgP`Cdq>%U-p`oslBIv2L0{q-^Di<| zq)U36=z(%e$WyIe`;U<=qBF_bb46!If0Fi#r={#Z22iEd^4YxQsf!sS?(Ft}UP>OM z1zt8gCf#AxE7|2@yv!+G*KyuT(sezbzFTj3xcl|Km~NfbecNxZR&-Ko9mE;}3P(`kHA((^ib z$6eRS=5qH~pvVnZeMYa+`stYJ`gGo#bGP1=dcTf5I$sv}R!jHn?J@Iq=U|ws$}#P> zC-r1&(x*9R8+qefw}`B74`2-|f214J>9KlmSLEYq`tCW=%b6tWw^D`vLId$?VykX_ z+1J<0C?-%2+uVj3YjZQB&h6C2=W4$H2)(i5<<$9ayO{3~JddG!&Uc?Pxic}i`ksAXr({7ZlyK=&8^ zM`3Ok;pX-1w$o)5)DpRGo}RornYV$xPn&?r1xfB3P|SgAA$Jbd>2(A2kh03G2Ef;m z3(Kug~dYRqwC+>+w2^@?1jb^qEbyf6QBxc59h(TU{ov zgAbbhJs!fxt3>zStb>ed!96;=TkltPDBR$78!hMflJg?V{ofcuf??f0qWnI+Z-TZ(np<$BBWqLnJE~BW-J~x<38w z;^fW9MCtC!$7Qdtf1a}y8!lV6TE|^kJsZ$G;o;=!P6*ZG<@A8{vx?Sb6G-dyLoHc` z)?@KJn(ZZdpl35znO`2ytL^JTH}dke&l2t0?OyX`-)!8*9^65hXT!ez)cd$|CkuJG zT_jzwE6&nweNgR3chr_2jlQv211~vl)#epchTSgqWt}9(f1dMTdpiQUqJ%D0!`H5SVp4 zz6R&l^VLT0x4v3zrSk@?dFRy^k#(Q_d&^IL?g-(8!1-a~x6|e6W-hJQ=Ht$!NmVb4 z;OfMce%)hGf8LuzRJvZ}pt!mpf_m@oVj~EX+DPKr#XW4#*(saP4W*O&ZL-^0J6}Iu zvQv9HtyaT~tawPw^GMQ+b(OH+LYqfA{Y4-W-nY_7h#Mv^1ou33S7a z)47|tWP76R_L&sQUayxQ-_;^O^neq7+y<@wFi+mWlfC&Ac_w+YvRR9N(Uzl zJ8yr1&QK|Kcn$6TO6`7|l0jCnOWE5cvrVtfnNCV~57cI`gC_H+anhp2=jRY&C`lU7 z`Tz6(fBbt-f&a0k!0Yw9qri{CvL1yJ4q2p-52?08kv0J6$#~(^9Crv9cLV?cD9w1c zpgi3u15a&VF#v+C*nR*W_BVJtZtb_U;{fOfv0{I%|Je~>+@k<`-}80z+tI48ABvN` z5YN`)^Ll$QlYDP_8~UmM(7jP!^RMF$0ON{(e{p|nT(KWC$6cUKy6RYS07x$`V!e;% zs!YSDY0XjqbZeA>Cf^nR;|hNOKsOz~58vrlsngXKiN*UtHtwUqGIKSYj1`Ya1^~XZ zahrslSm6)H75zeqYR47+w%F7_?5F^GU?=18&*C{cJm4@Ja7g<4N_)cWL^`)UIAQ=8 ze|(G2%fOui&;p$U`$c7f7)7LLXFjkMU$+wj*olE`%a2HM2KNG0s+&IBD>$fEK=Ds*8S z(*NgY?!@U8KN4MD0qPWKc#k)c48>vWe?Tv#4I_@Y-%cE>4GJYyG!=pIezHH1-Vf}V zUy|O)vly@}CWEcuGMkdY-WmZlAs2rmTLWaK-4hG4%rXXhXXJ4Vdr}zGwqQXDr;KI4 z%w|6NU;kE)KM&)(%Hu@|WAZs?~+x_p)oOcS*A!|%MWU*o7dp$=>$kokKPN-?611vkqGQ2g_IWg+KohZNf;h;=i_RG(uVvX&rVO?pNhL^JzZ%2yP3f7NcSXHeLkw~=gcvjxM#_R0rxd9#Vh0^1mrs} zWhUl+AbGYmx-@|uy*Wiz8bSJJi13e-+vcTojxE z-g#X04Vs~dV#@`$qdxOVbi*4GYA#_JiUH#~@MeIm0>8sj2jcUl2TBEk&ymyhI*iM; zKokm8Nn<(!-dpU5VpA{xOhLlIhJwxy%2sxJvcuwN_Q-zXuN{8vsZSMO&!$G7mNv^w zBcNL{2>Z>Zek8^y9_0BDRU4;+S}o0`xrPi99zghILZ3 z#?QFk9G;rrG0Uz_kzM_Wj=uV5tjM2v5dNQMTT-Uq@fy;Oug^NKORG&(xjG_y6Sjs_t&(j{V-WDpE;9#o8UPgT!6^fupSS{_!~hik zPyAQz{|Cm~W2GhhXeNkdfg>IOhXGLnNzrbxp3Ml)OboM~-JjfhZV+_uGgR?_0!MxX z*t>s}#htZ*f4Gh>X(ou8|9Ksh-AI>hF~}@?xSVd_PVnJy#W8n7>YC#F_s`V4=hze1 z*>K#0BSlLl!v0}!c_pqB`MNm4Jli=#`n4gR{luF%{;`*xuqT0Qc5mODF58a(ChW4v zW`Fy!KV;X@R!i-GY3lAksv8~Hn7}r7Aaiigcu#^Y3d;^qS|-b&vFdy3>(X*7oL_pSYn|bT81L<6q63eE^k?26#bUe%!9yU+ z%F*ADe@Ju82-7xzuKwl*g57z*YoI}~KJuX_fdJs%9WuoZVh_;AB8)3xuLr?{J^&W~ z{+zJalfJRA-z)35T6$Z>U*q|8ty5h;H71ThX67_PkF-tfihFDA2WM!GonqYKbdbCD`ON^ee26kjLbXZrqajK{Fgu6~$~eGfWXK~swg_L%RS zGE@QJ16Tp%#T%Vv5R~>4L_c;gfATl1_(K|Dntta=#8sU@og3{|d7Y)te13)*1oY}d zQSMVHDw#Lg%Khag4^+O)FJMOvSRV(-H3N>hAqMtEdV&m#`*Shw4jlb(HpXj|UG3f; z?`H(Gv;`K0Br$aIgH7q~FPadx!sU@$K!&FwP1hKxPkXRub{uz`!G4qLDYb))0M=ri zH+MhKVuvvwasD&|o0`C_aUWNP=_i0uAJ7;QCYndsG@RyD5H_`2oG*K8GPl`mqH>Io zLDg-ED;?Mfm39?YSxLkWg6Ju&sO5k=0GI=_O!}e0rQGBcQtxr}8-dj(aToGZ<~AEJA=r z3C$p>umf&g6yG>Pe=+U>i*-^yg1z3TzD^eJKfGw&xK7w`H9Yku<& zBK$#c*6({x{UQGIZ$EiOI`i}FYnwb3?>gF<{~Lb}Yocc>f46HwYUVJO($&-|OmG{^gQ!?&PuT_xKDtp-tfH z8mQ<(wYAiG6P^PKZX7~RbX}V2`Zxc#b^$rj`AJi#v0IOA5z-|Iqrzu zEaIz;C@@?=X=G9CL~>#i{9>@cXJ=sdGzJJ!ytPAKdY|ch9D87c^+r;_l_Czn0$>>+ zFEKV^e*jDS2}AoQpG#-IHZ5?IrN6d2+U++6C{FPchktV8ANw8i3dmFaU)<{J3t#+9 zLyre`elrP;^*F_Pr9;r|);x<1x;J+9+<*#yoG?yrRPms1IiHy)C%UoWJ{Y% zwwFCXNeHQy;1WQI*=yIN-0JB~FY=1O75I(UHx<2@uv8%I{bF!?95*sz0Euv(iFk9f zX(nQ0?J;t5M6NdG%vntGK?4z$FE<(aDA?SLcY9f_QQ)0#opd!y1hqz@PXl}wLlygNi{bL7ajO% z9aeQ@%KV~Z`{eX?PteOs>UKvkwLxKrf8d!y2ou-o)6~RSiTYDw2Ef6aU?a6OKo<@nZDgA@mK)mPm`_NO0;(2qDx#j?F=IXne{J($+&-Q8W8V00 zoyZ^TAODPz*S~BZ0xKz7%??kd8`)|Qsy?8$?&+)eadnJi4Li_LE0VP%DBH~Bf7pqt zd6(#`jUCXf#i|JRm2Kn`FWo)PM+0~us9Z4O1r$5fqU$(c7}#T;l14xHCwSlXCl>s{ z3cylFx()a>7__SxZ;-E>Q%-kg zfKXD=4PY1@skfQ}Y^(>UZ|mN&f1xe%ldX6@m$`#bwg1ZF0y~IHr;BqV#0eR)Bw?2I zTmnd?#p?A;QL6x`$U_T~^!GaYc%A0|x=xTVQ+>D$I?{3vo<0TVfJp7Q^YK!WVw7-! zt4w@9MneDSqoCQTaJO?UEjI^4oHVf@&Dw?U@*-a=~d#%1JRf4R_wVEoM=zvCkALj~6S0n-oSuxRz>d)142CT-#(50HB!Z?DxR(h35*4W*J53CZhaYU);w~#a zE_im5?g56eW$HGz100lZ{W^b~z@56(oeF!|sZ|~XcIa*vN8^FGf3DDnO2s&ef{itZ zafJUJ$0!^8F4-N-$AO5k*jErFV?Hgur0c?;Q2d{9%g!LrLZi#3cu>)pUxy?B9bE&S zS$3Zxr_Tx;7+C>gh&pUvDTnwT+nBZxru7L>wYDpMG?Fa4(-r~hPIX33ULH;MW#vTF z+!#nb0lr*?40j-ue|>Vj@4Jf4LTWBH;4_go%gw0!jIHO+Q@kH$|9(G_Q{g-tZN(Yr z4HVf8Cq;xQo7U0lRCRdrh75yeTH@(!GNc@(AH}t~3BZo6&}VuQamtsZhv-P}ImiSv zLtgx}sRqBi>?iN}8~gw0y1!a(3P)`D#_r#^KIT7f9|f?Af9Vd~){N3>s#4rhn&PZ9 zBYTY%8`ia01zNe#*xz;vwT(Qse-^P7SF26TPOSlOY6}~pwtuSH(2$)IqTXc5##l620t|88m`0&7kA8Wd zq!RQ1o+s=s5WFwOGvizLt1V{l>^{ByV$`2lQ~q+n-LJOEGSeC8)sKkKx&Mi^#czJ_ zj|MJc6}M9m;W^q>r3ZNK++b#RRj=oMxQ-oc1_8`af3|>N1#zdjxluoC1R!MT2I}*B z!cw0k@xk8)0m|boq&5a2fkCCYB&HbE?4Nl-_6@N6h8nB69n_yVU0m6fXZ>MQjrh;HE(w@Zzcncm^Z7F|1)ntIN-BdS-_@S&$BGl~U>##-BP_6#V#k2@gy^q}3DVdw z;_}8Z1pCKcYFl&!He51n8kmS47Cjp7WI&g&}WBiKkBo?504mYKwq13zH|G> zcSa4{0I4$ise{cY= z2W2c%F7StUSXY1%uI3$2ZyaYVnD`MuCA3rBi1=jw*zOUY^)vLz*OkBJ;=Nw zGci*Q0yA6h05PZOYP-|0u46;sy))uHMJ*6N9tOzpSDz1YV)t2Kci3`(!!EaZb72mP ze+>Yoy@pcy)s+%~KQ$Baq7>h^z|Z$ZyvYCJVd6jWH#qX+r zL*S=-lMJLg00b~XJC>zezXHz~qWD!ApT*6mF@&sopMi0TuH_`fq8;9b_b%p$b0q4P zcWH42aRYhGJ*0S(-86<*5U?F6Ntk_53eC82MPAy+M%;-`aCFe6cPajIrjF z-F%Q*kk28F9eB>wi4BZJRA&%9e_kD+e(&oVEYfSSA`%bM^Mxy*T=sqL?r ztvB&K1;_KWy4x_4!|*%a0-)WU7;kH=uVg>t{qrn(_QMxNuBu|lN4p+t<51@-a==2% z@SLgqLfZ=JU7LIG;O^7*66P4asNrZ_H6X{xi29mR6&iik(ZX6w?-m-ZfA&6h&FBxl z;QS>JawJ@rd67$H`0XDcIS6utq@hv}>5?%Jr%Etr! z9z~nUTw2})&c;y;O^Wwl%*9|Q>V0&q(^-GA7!xBjgce+s=rdxdt3cK=I zYoI}s9mwIMupyFV7409XBQ#j{vPlQ98#DzBstks>b*U}ty&*0bmR|DF4#7bWWYIq1 z;BOx3Nm2~eF^{Z7f8H;2r_A8;-}SEl^1Q3lXJ0!A$o5yC{N;P+YoxS$1M#^IR=^F? zeGpX$0*rP^qvL`xOjBj86RrbwaA*bV$aale?ynK)L#Em;$GYfe0?z}LYH%%40fB&rq;TlikvYNT9T?0-E zAE^fvs)JjkiG^#Vi@BgS0<6-5iXUNhFLZ#R4or_yo2G zV*}ViYs~>w+K8tIljq^L{$NQfX3ho97~soq?3`JnF3i7q-#@mN{iU4=TqLC}=H*xC z9`iN0Q|>2Jf6mtitqmuTH4?O0R1s6p?c4xWwa!79@-)JX-AtasE5K(dZd%xD2+P{y zYNe?j*1pbE-wD*pSM433w&#HAt7C11pJ;HP0+m$ZCszl2^8<(ex344pr`{9dziS~g z!P&rfj?B?7@)%z6Jv8~r-BTF>)>R?R{CEH_xLJm%e}@EuE~Yd!1FCY55(kv*gnIA* zRCz@Kh;awk8K~eUx;L29gOy+(gt8v6*aQ^62*=*Kqa#l-g%2d7?sE~ifcc0EkmOl1 z=KeqRE11U#>Ecr4efBWcRlo1Wuqif_w*%RBJLUiuqr>%dpfZ6_!3#(|h!h*^F!La7 zVqaf5e^MjEOs=>O(q$rQG=KnWqxIk%!;TC1ZNQEK_oet=h{+65BI@Kp4=^ZXB}}v(;I@N9>WIJTg`7Ju zv&f)Ld@we}>5H28ev&HEvn{QhQp__17|jjF4HLE^-Uw<6--6S_OyI^Aa{PDwC9#M2 ze;?iFtFZ@ULBxW)7y{!2C|-v>i7lSOUDCi}=xSqeu5NqPSm*Sz=4Z@AJOehM!oJ)V zJ^t_dhR|j7gJ~Q<1)IZW2EcKc1OOnhVp$+0crZ~fI|y9RLHx~ozWqBo7W&m!dmVjl z#D+gOr{vAHZXlqkzv<`?lYImzwDhuBA0#0wjn;kWN6 z`l&C!7)bx4+XSNa4_WrjL3?uZnEmbR>JpMn{q-?%0?5`i;CZ>>n&{JXbR>J=d7OmP zQ=Aygfg6H#gKtT$={n_Hx4-rLQ1C&Qiu>ySy>D1I==D+D@pFQry#VaE=vO!lf9ThL z)7?My*`NN!uT2Y|_}}Nai>Dw0-8v`MTFF0#5Ys4zdexQ&)J%~(06O>Vj$R-$PRXFb zt|v9Z@PE$#etL#tkC36YavMWlHq!6&9$WFe$M5sfFOL&7<&ym0&)eal(N7pK6@#gk z{7*Z~V4-Ig*v7m2B0Sw#yfC1)e}rlXK{oayXChuI+#;i141`|HW1Wt5E%2L5eldG0 zdUXY6{OOSxao`*0p)#9aOrGm0SFKE`h{gAzUXck2<7NYSV{|YD(N)X2?eAjyXen0@ zF}zmfQ*8G+-J>Rg;dc>!C}|ULCSp7iQTH0_Aszk?-}dxSWmsRn-`mAtQ(h-64~IdtW-yKl_c*@XH75-@1Xo-!JFLcX8}lG+nste%R4w z66I~+;}~w3c6Yieb;8c^fAy+{ukMtC3ZkCc>x(j5@bn3IO4(hmUBII#T)}N=+rNGi zXJY)meNg--FBo$HGU`~Oe^>DKhwMaL6YAGcSMQNcK;ix?E4##~b*%vsZ2;^>%oYlUwj-uk;y`zFodo>q@h31-k|Hgf8qG;aXU;w1$S_DxC3)O z^4&6;NTrqodMAK+lkZ8BLXU7WaOA)hdW6VT$9!+pL6R{y9>~{DqMuxOAg0dk(%~Xj zWMAD<=p%f71PZkQO^9B{VF)q=DBG-aC$)-1Cj-$F7DEum4;_$?ClmMq&&je*9aQZk zFOvGTsCiOee}#lD_SW+RXag-=xv)RD70NttlK-592?xDITzkde&{%-}tJ3H2G(Ko??DXFxsWye|a}wCqEiaJnA_lkF8Np`o+TZ zHtM}W_D?@~n`b+UKLjW(WZ2$w_VOZoI8b_YV0txaV`3`u9)7X8Z0cMyEpDA=07Ltt zffzJS!m(ul6S2=yMwlG2DDw!dGgcu4Tt|?TSkzg@#sxDJ^RJKje)F$BA;|yq0j4w9 zH*kNQe_svIEzi=zJ=ul~c8*KZiD~8lM$!6kXFq+71j7ax7Jy^Fve1FW{7ipyh!Ic6 z-i}`%5j@=p{Rj-KH49o`PA!xA1Ps~J?Bn0x2R*RNuEHRc2^#+SdBl4&Ljg0%58tu` z-a|_N=38UG>wfCwDRWHGlQOQeF)-3O9_x1ae}|`;K}-Pq_VxU%clnb;i~i!VZ`2rQ zY3FfFYT~Z@__hHp0<2j%AzL8kRvR6*;FcX7L^1@p4?DSZAh&eNeK)KcVL!!Z1wbH4 z3-E*gU!8R~#&0nPOha}ldVvog2c=g?X#jiha9M2N={*Fj_1w-6L~bXFJ%B=?U4#2i ze_zdi>WA)@nVM8l04|at4MZIAt^L#wH)!k+9c@u)A;JIPrcqW}eVRHnM%%I1O_scn zahr7)tBV831lPYzCTrZ|g2|Z5*bz8`HKcR1{uy7h<^R#)SXPMsydNLE`q3ez)eBKT zgywy5DsX{?{Bnv|2iG8sYoQ$(uESEre;;jo#OF0QXYdZ(^^XqqwY!d7{lOkaElTJ+ zLRVm8&F>nCH9AncdZBDuGPpXT?QXoUO8~`+Pt$8C^fU#Edyf7dP`d#K6`lCMcx`pt6JYG-q;R*j7*K_^ayYQc_Y|t5yx#INI(^u>S%UlPQHgkAo z_=ez^&C5lpfx_%t2jC6>p7xVJfBiLH5lNCML)6S0!6Rqf-hks+Uyelo3i9H;A$oMa zJo4Xtgg^BGKcc&F{a8SIl{QN!%rwMBFQi<%dgFoz)riT_scS2{JoIq}HAiYB25NF&~4v(J@RnUa#r_u#wK2H|;rub7rApu6qDmS8<@5aAocg18a2~`Locj$##4`Dp~*v1vA357sM?#~c%#Tty zYUVuEVV4a)%1}RFwYLR;e^Njp*x3kDjC3vb)H6QcsF8u>Ik|rp*KrLUbxfE8jLLGd z%`*rF6(%BY)Jti>y-?KOOb)m(di2bC5@sg@Q2l4U$n00+?9$&l>fgE`2>;y!@^{@1 zL~(9J#lQdy!e|xjMXiIakd^O^E#N1Mb;^xt|1W!Qw(GjCEQCeC|sq zs&B2nc?qn>>MdD~)dczXfF5(rwf5fY?0bTn1PGAvGDx#nDi(`miPeY&!D@++8SmJz z1y&KOdo1}Je?3nt8?Qpt-hd7qzVA9c&{=!;p>CT1gP>HmC+Jywm1CL2^E6& zjknu=P9NeY9^&g)Ue-iN{)4~7XSn>=pUgrwpYE%3ZQnZ}4#iR$GQPzZb~BEM2X?MQ zOHS0Thnj=pBZSBKot%b3W?|t=;Bm9zYDLj7o<2nZzu)lw&abi}&E@C3oDhE%2s|EG zfctHibI=exe`}Y!{OJ#s{@4+I`VoBnwFBcna{BAO0{IrA^TSO=5*S!!DK)*23UBk6 z7{m{+I1*y*+54))TE_1l;5C8u&eCgPGn;39wEuDG&-c%#6I ziudn)qei0+*M7w+zbGasL=9_2tX1gjdF(X^eFL&FQ1{}uJYYy3xbOQ`_80%AUojxx zcaj6e6QaA_@BL{JNdWl}I6D5z$NC!sCZqTHf8%$I>@R!^2$QC?ja2_Xt3F!y|bem;aCHh==Hn;O<)jR33MWPr( z`CgAFW{=oJTp=%Q1s8gnZWX9aQeoU!B}Td{^F1d~Kp1#?@c8chN!di9*0N zLaeamON0IBiAHP}k*V(e6mLZnc)aN&fBn(XWA{?B;%0S!Wa6Ze-8Q=X! zI%s~=|Af20{vPiB`VA-aEWX0qS6}+-Hxu`xcOrZGH#Qx`s{1nDE3#E=Ke3ay3e<(~ zv)=7)@i6-O^)(0&^QT{*_uDS|kN)YhEpzgnTlqU^?SJx1hYQG37W?}3tthls2%hc2 zf~)?^PM5ON5GVm2m)p}2iUHD>X4DW`f9{JaPgYUwT0jD*y#X|eW3xWz z&5{Q6(oCp zi^mUtSr^=q{wHBTOxfqk+UOprD!31tKX^V1h#nWs4^JZaZ+-hcU#x=W+h5fLe;CXU zzNZCZOU{9iBKdg#%#Tt7c18SogUJFuig)Hx4x)IOSq8>eK2nIG{1#6{za$gMx3-+u2n5BwNAioW_t!7E|EE8e20&)pRkVKgAyow<+IOH1`W}AM>f``@ z?;QSfPbBK}1^{hhfBq=29m<1ae*xspfpPMkA(5QX1$RZX)i}wahyKLre^(Ow8yWKU z`Vyi4++VU^<#YW>&I7*6j);yl4g`;BnmA9l*M(x zOaMi4Juqu3Kf?dj1V?3sPY{*P`He5XtOuKA+F^`J|o6=eaoF&gaYhM4xH*JU&m|d8be6lSt0- zc&k5zaW-lOe;)4HkQnTKm}mXM941?nB3FdJ&V~Pb{@@DWT1tdVa4X0D(yyd1)ngWob212CB|r(n6*PKnjj{`D1JO`VfVBeAe~+g!V!!<=Vr9|g z-oC7YXGHSO*Kz^^3)6qYiaXoL8iz6q@JjpMRlpk-=GS%tMB6XQ3Fzp1!ASu5TDBK8 zfDmONiR6R@fjt!yS6TrSS5s(XS>svGGlU59%UA=wCluvm{le$KRsZ$_>$jiIS^-3S zeyfoKSJ<*q#7@Nof7vfS*nvdW0P)4a#f3<)ao{(}1mt!C8yC?4cx|-;e);y56QEn$ ztW7NS?JqTRxv&64G|(-=Bw35C0>5n{zgvMb$AM$6KwzWTZ(~_>Rsr#{ZRQDhlgxX? z1gtg+tYQKg=Lyxy?gpGdQCsCy$_PgQ<_Sd8FP?Jh&Nk@Nf8kaIR|pYoEClSb0So8s z!2JH7fKu3jxw1}Q${LWZ9jdbYUV*c0I`G;FSe@sWg~!gN*S3+2H)Y_!)e?+o0{kfM z;%W)a@43?wAZZ#k;LVkVej)RLDieGWqc?^hSpXspR>WVKT~-Up5Smw^Y=Z=Fier@aZyKIMe@XZvgugsvbj4AQNvYay_IV_5a1wZn`@{_CqE9xFA2=rnB7Kq5cjuK#7 z1SqNw6cfwWR;AAqD^Ct?N0VhYw$L;az+3rJ%oD3m4lYCvZv4@f$bQpItnsVenkEZ4 z7Vbxre=R!}npaOM=UK*T>-^?gxQ zMme$IEu%FN@PF2AB)=>dX}@q({?G4zw{n;vq4C=UTtWA*vLkE2{H{B|R!9!f+*l$T zf8~&XDE{7+F=qvyxdQIGqx-yH^6P5=wJU-ze^e`98Bpefm8;O2!fLdJtcoq>t%!gH zY;Av@_FWHQ#o1U+X{T-(1;_)qJ6-Wq4hI ze~6?y9I(iIf4+k6c__C|^j7WNkkEb|h;s5hM;!xBb-@DL^U%DS z)xHAuu?pYw)?I(y18i;6b2hOsxj$ck+y+Zjrnc5iKT3glkJQS1)e=NV|v%YgkZm_?=z!jps8-l{F4CzZ7!IN47PMU^f6@)UT zu3!()x$-kt2>`xOEHbwuU2_H1U)m6FodBI#f53`L0tChDzUR_nA%i?yN4x$@w%Y%E zo$q8VL%>vZQGfSYj`>Hr8@$0unT56o&>CX^fS%dZ0I zB(#d&AHL^cgmgmkr+r!3Mqeflos+EcT`vwR{phVo&qluVf2cirYYD6VciJ`dY+zgN z#HFaNYZ{=?Uh6t&-;4#MPsscO>Cxn$^pVp9`q~;<1IeSi?>hjjh{_&BW#Omn>^rc2 z{a&H+uit;*B~*9 z^)3JWUjM)ssNDR(f6MI;{I}fwz<E30@lfKm59_l*?ke`nk}PW)GPHZ=ElxU3e^QziLl zjiNp@3%~G4A9jDkV@T)w6aLqlw)o%hS%vUp<6riU%l8@1vRa5H=_}Vam1bE4pF2PB z6E7p!>lgoT*lC(9{x|Fs(eD0+y?ycib(6`V1fparEC?_k-OZpgE4Hd-g<`OR-L`V=Pu)?o&|MWLdu_D=OEiN7 zuz#F+sm22qQxElPvw3d-WN@~T%4b1X{i-{je~5C4{?uEztm)6iS^+e5UFWd{y8ny-Tfpx= ze^8?P+VA3nDDf5$NR*G-06d25-T>t>LHD=kgZycqr1Q1VSdbp)+lM)R`v1BqwAlUU z-qrdEY5wCr_FLzHRKV)bx(v92`%AkH+=4UztXn`U`1H@Z2dqL+|Ex#<)Q-Uf`6K?W zlfVG?E8umItn3P;2Bav@wwQtka%P19f2e@1kzHR#smH&WHUR}72J`~?zwoGDp!~z08t0Ag|3bPaDLUb0;vC&o@)W@uh0G7Q}YvoFM){e<5?Er zjV!hSq6ZR-rBHihp}fH!2mt#8!nb`vuIS#%wm_1>!(uxi$cWAtkUWqee3A_8e}erW zycu9c

zV$WjLbv@A>>;th5BZ=xYo>+h%6K#%3izadEbquEgNQNvYR5am_`<})8d{+UBiJMiN zHSyjpe%LDc-)|H$K0nWKihK7eKEmyD`1gc{YY=$*Yk!W2r70ww(l8_79?kam`z4Kq zjOF}6E>Ou<_Kd$9o}+iMv{sJ~FR>bp3?e__ zrx}V>#(#SI43;uSe0jO?gik>_%ApEJq-)i7gQK;q|JZp_aLB@eJMLcG*Gx4ZPJmkW za7D8x_?aX3M%i9q64E3BB{VAcwIO%&6!wH!;!5SOd~$>askCjE?SUGGfCqmuv*G8; zK!lu8vqvg5dv?K}4@G+k9u;bqP{cdBRksX(ZoBs; zo@Ldi@lMi#{J*7ZoP>kB`4yZh({5Er$6}mC!I{@Sl%?Pwi(J!kWPWXm$Kxff6~A?u1m&RP&4baObrKn%*_g0Q)aGyU8QjW98Rr z?$qMiFjL1EUC6sH<8$^HF4@m63~-e-!#e#-+w4r z%r!3CS)M*p_2A~n-XkAf$JfHash}57B5f| zn$+zp#j}-p#kq9^_xIR)M(5 z@9^^=7C5(6#z{X*z@|`J&TVKme}7}OdtAe7&=34bcc-^TS{?JN3WohuQh$vz-Tj2~ zlG+(oS|W0uMGdd_2f`gyiUC+?LQ_uvwxpT+>Iq<%$z*D;?zd zP{?+0YOuu);~wIp=OPu2MEeWu`SRF1*YP)rSgYSM*YQbDHKvVH+1B-tJz&LEsT`pw zB%25Zcy!j;+gSV%YWHZNo2Fh_YZH2^xAlEv=+YCXMEn zg|@j*qtY?prPL2jD8agP8Nm0`^So?X6Y4e5XY(#)nOVH7{i>eI*h_OIzQ_oPzP_KSp1r(DN@b^fW=Dy zdLOla)$|MlGJbK3Ko)q(u#vb&%fVKIe`gLjWASYc)}+6|tFNV8hO)%BQg(Yqp^$}q zR&}x`;Zuxn`+vt|qgs1wLr1s>kG}gAqJiGO25JODb@KyRWiLtJ6bi%afTr6M(&2S6 zyb0*zk4%yGQ{T%ZT3bt_aCyXYPNW_QZlH*K*5-0LI~jAE4NY)1xN=%wJ3fLzOEDuL zqhZ54#3;+SKAg2~G-r+gRU?Ja`R{0#TdtY{Zd0>2r#v(S zrb?e$$CUCn6$NRMOx|+T^=MduQ!18j=N0~oY?I2~ZIrpQmYsbFi6nYQ-9$rr7zHkz zbzo5pX_4}g-i{@1fL*MB(4{!H{WbMKQ=`mm2LYAFPaZbrxYs!$=_UNG7JRV^rs)N6 zOJlgT7=Ni4{;E%DTKEenmiq{0qsxBK0*j;jYBYU(=eVI<5oz}*=3?4z+irh^%SrXG zF-oQRoUg^C_rduqK`&W;D_Z<%$oXRFFYNK~ZIVY+s+Ak`Y5eJ{{;UTSmlOouKo;zd zNexLvElEH23)@w&9E_a7(-dL^#UEQ&k+U(b1b+{dMVOXhX8f`XGjmQq`rp&+rX;%$ z;F4^$yQ)w;2Vo)iuW9A4aRA2cTWaN$!Z%Zq19M1?-h8;UCq!hTw2G_&tzuCc6Nvp4 z7nQdv5!Y0SM$lY@$@SuE>+-MwWE|o&&6Go$PqDOB(o>IQ)jC#YU@*xTvDo z`IYkp0Hpo4Ijgh>eI7BCz8fQI>_sf0Z^0a=y6q_vpKqdPly0z>ybh~KxEOc5=KI1L zC%E@|gF~e3!sRxwTFoR?0t&PjY1X|Fa(@likXx2>08~E9_vztWz0`{^ZUR@iKi?H{ zL!y-zxXD(Bs(v`-s6`mNI;O)FTwrb_ik+ev=z0fV6IEoE=y4+kz|9iHAijmeXr{9rg$uqwxr90WNrfA@#VSmW` zC51e{V_0u5+NrEQ=45tAk4UJKS^1b($XN&-x}Jb!I}hp@D$ofW8#apEj6-dDyuKg` zX%r`!GN^_kA2S*tcS}I%Fb1^I<-Ua-d``Mbea~n{{M4!f0P;yBFv71MA@_-0*wFrB zr<5=>z;DArGLq&)mdb!U#(+Jy1AotG2E>u2RnG+}hm6Vw;yL$&RK#Hako+TFEACX! za@}>Zo;%PNhKyT9o9I9|;cj$?cI1VA_*XxkC`~uBmJMkbnxaOUxlkLfYOykDd#d7z z2Am$pArLe9GS5sVNYWY;7j7w$uGz$c03x8)zO^O+?Y1slE3R9s@@OD95q~`$)4hN) zE=6l<@+JrhRAzK@S`5t3UJ;E67_FxztSv!=1QuXrj}Mh-UO zJPTihy&20F^9hIwCV*RcY=4^A)L;vRG~OGDhoP6bd~7U91&erhD&So@Q*# ztHWi|4B8z5DN9+J)UE+tvKjaKB0#j9@IZ2|cZ-31ST2L?EQrlZ52{P7RUV0IscdJkWy{ zLV2vz^4Y8p4>8;%BceU@O5Z&lq`O7uf>q}R)ksIh(SL&fo$!X@>xI$&!3V>97FL1t z;#Uxp(w7H676lMTeSdsTEO70yr?IWo{>nBDF4!kD`6fzP#E@Uk420Ql%(SwIKw%6# z!D^A>Q*I2M`Mb@)M7rWUeQl619u7>NbPnHU__%g*4sWqek^MWIw38;ZD;kkyKUd6# zv^-ktubs#chz&EHKjjAw{f}G$IS=|e`~?kSE|dh}#40=R6MvUDjxPs2>EFG-;gxoXlIasTdWEE6R&}@qer_hhXy{a-XPQ!P2O-k(gA3 zKqahMQl!v|9`2hD=7Kdqbm4E|F_1E2rRI~tc*l^&IA)ITJK%-Ni-*n3i9;A?ZB^Ha z93fls*L1+QE(-WK_UFu6a~iZy{5rV%6SJj@5mG(Rl%;!MA+zyQ#`tVZn_=Ke$5ri) zirRoq;wcPmAg_4{_0#kXSH{;EtulynKqCv68d)m(Lj*tx2LwFDfhO0z-TKH z@P1JbtxQ)jTukZ8!e>UQd0Z`tZ^sZy0f8I1_-bTNY|gMN0mSvFpOSEMB0^qwf~P(a zkbgGKK=g(4*ASGGB`$w=S|_0`)|)=?q*G%jGAku`TNP!Y%X28ZPoug=K}oB#n0In` zpYwp8wqDgNsZ-;-gZioReiwuKsa?v0T0KFSo|zxI1z!4{@fi2s14>&JFVUKPNOZ*1 zyqTs>(-OJ{X=?#xX%J%7=WrD&B)q9Ru=K+wjB-<1NFFYaGdmT8OO z9;oa%yeExQPiGI|$utzR^v~j@Cn*D0n&GBtz!_(A+x0_PRuZ!$?; z#jTD|3Ff962Z)EYeT4Ti#P1OU9`cO8oOiEeiPC2^^T=YDE<|48oFvT5fP9OjWgqwx z9=WT`pH^$Wmpg9MT2JVz+S5TV0e^K8GZN3}EI)XrI~Aww%C&@5ruQ7(o#>wO>G+;* z&|_4&j)3CoKS{`L<;VF^{!^ya> zr(3#8h7A1aW(J6+e#UPCeE-x#~*v9)u^te82u2)dEzX?5JC2X!kKS`zGO7FpQUf#~GD zfsek1(@R}|y3Mxrm?lT`dVg~4iN*?l%f9&%#TK_Eye(+!WRSQ*$__?#mCl=P1=s6{_Os^&kY1Y$WOrmcYk zwt|CMUNY1meGlsnN$o(~p1^l%fb6m-z~NYw1YA=Ef1!N_fP(AXgMZluU1B*@=stPD ztN%@JTLX9aktew7vRs0!)R1(>5*^1)J%@ll3r7m26{T-mLc&A2P!YeJ8)_dG_s{T*5 zNpYt**gkFDExx2r8XgqCqeauOmh?q`jnqu(A8}R`L1una#)rnZ`h98UHP+=C$(Md7 z69g2==GDLLX4>EHC{9D$8cLaU=Eizc9DNu0t-auMh2J!g*E!(A(6&B;wZ5^XcSTf%Zia#lXuWE*?c z(_vUCtO`m(kX(Qe^g6KQVv5fpTEZ|2Ua!53V%#yU8oVry8u3z1O-?8&utjT6wT|l~ z4h-IUQ%6eX?|%YAH|)=SWrIG>Ck6tObRA%|@W-9VrWGfe#7h-v<|;G)Wm9v zK4Gch#DCFmyJAa!c7;V2Rn6|AQP+KO*RD?9Uj!}Uf|FL6sqo}-&O5GpH5vI94Lwy` z_mknAkwZTQCjg$U5Z+^xz%v_I`ZI9z*;gb%s$}b;;(w^n=Cpcxm7!r1edI~u$AA$O zik#_Cz}-lqOY&lF6Oyi6Wu{<=0w@6Am24aPJQ`y+x%6A;oEt&AvI6Jo#(v>dTuYnL zUR!8w2&7w=Qo^VO&;*TDJA#B^>aE@pS5iGu?$h$efaC{Y#HBzt0N#Fz54c~-A4pZP zmHBIgXMdg;bpxIs#e4YB}%B$3*ucli?Bv47lJ_CMTB_ejK(rz5F}NSZLke|g}< z;tC1Ed*99E_qODPNXj$tGJD;v+PEoQ%1Q}F>dJp2HBMK z?#uW|`xOvbJl@$VvQFO~ODPY}=udZUAl|ZK=mUjuH4&zs_7rO%38bv0v@XdT?F;Lg zKYtT{UqKHDs{H3UIMxy`Fe!_z#(nS-ju8)HJVdh!F8kA$rX+rPfL9`<-mK$;RHaaY z6;aX#Z-HN0sP2=11&d@nnMJ89o30UWQ{7nT@PImx2Ml7 z3^nGIM?nI#^Ne>VHZ(y5&D*B!ny(p!?SK0<0Hr7T{Sx}^4iYWF-j(HN(w9`h$6wLr zKjOCZ;V9%A4?`?%dUEEzzZAIT@>Q_2(Jn22KhI9C+Q^Zp0*kyr>Mdh~(;*b=mujH7F`H5;7^}w#{(tl?d?Fik(fr>E2vk2koj>c z4(y}+Kmw1CN^1GkIgwxY*J&aNTs3{+dZK7VzCmKr@xoJLe<81LonCcBolc93^#Xz+ zysJ8TxkmJ#8W&EQbPhDsLM`_(8-KU)G*pwopOx9>X#vc2l7%E0 z5J#EJ=g`rQDEt1$Fp=ZN1oON$!~!&p2n40Dm1WX23H{xsg@CFyevoqgV^0Hf@P|I>9MdgOb|oI}1x8EQ3rnqFW>+9g0OFqw0fP@vXOj(SMPw;!SJ1 zb7EM<*?B;~H>wl3HWHu8c3q5;)59I=s{QfLDAD+P(AU&{$6Yiq3#?!MS<~xJC05mE zM265MiM24?hZxz<#wn-S6=r*cXAW@-~u-gNQ&sKhJWioYG#n5m55`oKdxq)fbLlFyo};sKnJ!3i6A8^N?bH% zKCm)8ZZlfb2b>7d8C__ykMg$Utp2lfZjsHs4Q!HJIwp-naNjwz5w>kz2QU^2tM3zn zxE}mRs=T^Tq#rFINU#GN12pFzUUgo4JNb{thKlLQNB1g|**kcgt?%D6#%+($Ihd%`iiwHmNtXJ!{HK5B`p0qJvK7UHX`r4K@?nkf}X+f?| za;MsDBoUNvj*w3BGm4MHcPDtQZF5~Wnt}7(pCrtK@d+N9@3}S0nV_=_AhpIj5>Gda zfDyr$U>}BA^!M5zHs<`-Yl=R;mls75oJG%vf>MzH#F@kDLBR{8(!@K(RT-Q*TrBHR ze6PR4%5W!FrGF(+m|k;yLD!|V?QShcK83b!F@o*w z;D^QZt1X5gHd%aFTimAc{G~2yhq0JapwE?WtbbtZPR(*aK65BiMg~{@fKrAPomzEb zZjA8r*O||ie|_Ib%rRpgHVJp`I@(RC0FAI5q{&yeB_1&d!pC%MjK4nm(w|*d)Hi_N z9=U{`uW(%EtMHq?klsRf0^`{A@ z<(K0%GmQwUf$>aJR}=UCL;cDg2J?r*$W0~5I**d6!}RSovJTs6y*Xu_WZ^oJsVzj4 zx{n=aqqb>Z_GhvyA6^Z)<0Uf7;h!FG?SE{*=kI)|N`1mLk!8yegV5^Ogh=2?MURa@ z)*f@y29`v(q^CiaG61A6Un1ZL%Oc*YRhjH*$C4hqa)sZ_HK*CSl(>tqq=z(e7s8S( z_3|2yE(sFf@gJJE8*0N8SHrJzjQ9&$-NyEBUsnv;Ge2A{?@u5Al;;4;iu51F=zq3_!*BbJ#O*_K9cZkoFKwK9MP@*Rmr#^zvA~BRy{)si z>`90je|^R9Fq$_qb})c(3Nd8&^uJ|LvY(@10%ws0djkI8`k;~?5%_jq{{yJFDciha zg<#Xk0X1Lqy&t26EbA*swC{k@P=Btq5i1uZ&iPP{3a?Z77c5hVqceWGpqEYqSdJ+p z6ck`xw{J^HVk58YLglBCZl+I_wt`yFBA%VDEG3E}Wjriw z)(2F$LkKr$_8TO8(66tfwMR)_AFf2}E-~3(<@94AfhI-Xbo-5!U9G3y&>i*}4rz`)I3*lchib`G>D;xZ`3uA@%fz^mgc75*~_S+j+X{&WKR0bN#J zdlkSL@-V++1Xg|t$a9&_Eq|l~_f=d$Fj4;#ldwxfpGI-Re$H;-?K8eCXJ3DXO=%K#Tp8b4BgjIqQ`AjS{!sG69{v`D>^ z>ZVub%A~ZSS{c!RCPwKKwfr^kK#{fM=?>$OARnM!q4<)S4LP<(;=xOOR}wjOfCVLYK9!j!F`rRfnv#CYd zRN^E4Tda%fg<4j|YiKH;CfDO4zc@jn{wQ;*L^Z7%vQxLT4uZ4{z#6NiwI7X@z zzyWKgIwAAUMP)sgQ)k=STnWYT21BmGW%&yijdgSPBoijzKv^jD)XCPMxLS5EO^xA!Zk|;oT9&cLMf>rnVjc%Al(I zfB=Lp%&nW0C_kxC==Y%vUSd9(axcSNBSta4tAKm;NvJ&EXck9Qh&V|D?Ay}ym6)+x zSy=J_)FH8UpX_Kk&-zc6&)jxq_*)FFc`H&-wMM0NZlYxABIGykZ&3gIWjgP^C|1XRW~$< zK2iboBY$QWZ&$<^Sl@gr0Rj*DD8zk#e5=B9STyJI*0kdlIICn=Tl;W$pG2{^joP)M zN0c1-E=;6-f8o_!*VR&q>^|zVJ#bcVJ?E^%w_OrjFauf?O)d~M#8drIE3BFf85aL! zPGFlaKhKDha6$Y$(8ef+tsNsRp7JRwuFFdWt-YW9&%yxWPRq{{w_aYuCNaHi4rHY&zy!gCkb1Ff?#|F zs(+(~GBz!QY){%=Y`fB(a1-e>y|x%yoEW7$pGrh;5Ao9?H3CRT=4%HzKCfT9xoHEy z1)R5HgtG^Xb4w|Q2B#DH*>@yw#A!)_ROblU+1yni==QkHw>2f2bsuzW!98E=XY9KJ zJ7*dmyQ6hq=V7`+$&O>0mO{E)T67r;+$(`%rL@lG0Z>)g{z`d#>y$G6A|E|2sF_;J zQqDqI_UC!{m1h4s`J~6V7fvSVLP%}W<#{QZv!jL8HLX5#qKL>Dyyk>A>K10w<-Xrl zr=~ewEgW8)u^uyhlL>-fS8>t#qx8a!XI$H$M9hHRI!n4?J*e~)6@RRG zATlFXrFM8*hF&x6%*Q6#v*{{e4)|Xp(2W04IC#tIdpy;P*)J7L&$||sT{JC3!66r$ zqpqkI*s;L?{OnPAfRr!E>_yD=VMiihy-G^oA;?JvpRb$VQ(V!4(NfL9$ zZB>8b50;X8%~9q{PPISNLjwCk-c|Scdp>AXKrfEkya9CHX8gHm*MIGDO^iDibi;i-eE?29R+Curkoa^^g1lw zAWeK@O+UYT>8hm$3AUByLUU15r>flfl!?yMU4K~2?X7!w&GFbtROuOm=vNa};D#vW zE|QVHR#CHVS$1n_^zLI(e z30xpBfUsd~%9tWAc_l9MT;n)danySd(^0a&W8?;aQ>luZ1Xt8wXkU{q7k^(Rl7tV<^Kr)>4LC)~zruc26K&f{8$pkEOW{cU{mz&EfCd!AI2OZk zV%)ei-@?jrPFpi&vaA%VL0EB{_-kFX#!n6#2GW>^vdgid+1(q4*XI+1Jhw)`%E8vT zu!r84qPV)y$h&)A+baa6c#O*(EtNV(yE4DDs$RRtWFm*6EWeiYk~{AENJq^1Q2(E5Cf_IWzlqKpnf7 zn++2tc$RA#Sf?FbGP(3?Shuh7MN>bd9z6@&F@LVmx#(B4Dvsd+iH*no@y7&8c-@X6 zQQ{feleCvYRW7Kd)ZES5?Qkap@GWHwx{9jnHDFApa@1DTlZ|$lvG>n;=FxvB;PJI zl7B0nUpmsCD~znX(SAyI>gE$Mrv-O@%)V@Cmq_4scnOWx=lb7NdLwv%H)mqRt)k$4 zIkt5C=+dy@_mmP4!+3zNNnm{uT5e(DkOR27{Dh{$t>Q#6OE#1U`_sv!3k_F@g+(9K zymrAXw?VG{Nk~(1@+gg1m!x+zI(x%8YNB_cd(R+wT7Dcg_kQM z?qC3XUc$cK}TaK7SAzK5nCY|#u!RBLk|ZqpGS*p zuG%WbO<41qM!~=Ka@vlg0hy#(b`&Xfn@U0R@rP#9fuz`V*FI>5LaypLn>dWi20_<- zm67Em1t%of7v(5fhs;162!A|~hnc&pcXlRpL|dh5P}q5!DzN5*sAnZGdo5h_HGh!yyTe29Q;b9Z)3#c`9_bHF3$qS-bJE5gob!1d3dw@8THJ=3Mh}Jvg%B$ zR?#t|p&V6WS)^z>wK}w%8Ozo9$S%5IlLL&Rp5!Ei(%Y99h-WaisegXdIGYb8Z>o(w z+1^-8z|ZeJ#V>?V7ebIv$jopT94Hy^B+RPD*P^+#Bpx_$0nId8|A)NGFmS7+k3eDfflFZ_kyQ7^UhknL_BCt|SS zHmof=6Hz@d?1;lRSZJI8oa>rqcT1Zn+S~&qgl8+5m6%z zVh+1?dhELsAc2KrWA^gF%4$ebqz`FqDx~*l2~jCO_>qH{H#V8ui-;{xP&Cse9V^`j zrd5&2v#I!|d4Kyaf(CvvqC+~?&rSoDd_k{*oeJ&m&sgF@prZx^#7|$>nl<4jVA6YP zbtK%jkl^s$C=K2r?p)`nN{H>(Pm2Ku-?g{UeUtb}?WOT6V>j{!K)#X%Jhya*?*Wcx zb)#!H(*RUR70Sv?ozu1z(#v_WfF>HhV_m8tOu|U?WPiO_c$F@_!v-tbugK+!uPyr$ zll1cw#0xq|`fBT3f|RpE#E-|Mw&Z5Xgd7Cbua8Rwk9u(z$A_sh&NB49SME&cun#-C z&Gd9PrV~_pTR;&c#ojuaIP9j!lVtmOU6iV$)3cH6Ugd@A09B=@M|5@OD*McK(|n~! zcH*wNoPXmp@0(mb=cQ$fx5?n9Z9-elE1i=(=!ShhYr}B81sNGB;`R~cPPyA?TNvb! zn>gz#fF8+H<`Cijd?6%+@b~yDnW2faxJs~vE-_mbt&IaB;d4CHBVwliT^u-2Kt=Zs5=V4!fZ}5YN znVm?0XM39$roqN;>}wL(#J;wEgZvE+v?k4BtDcqtZ-z4V(Y6UoE}BJY`u(tn`TPKu zdqjAs1s_x^9j`B2r1hk8+Mo2B$$)%BQCKSYFNFo?&<}m^JGRYPO||8EzR5-;$$GOI zGJm5&vcJ6H3K+Z}iSha>@Fj)Sw%_Gp&%8MBrjEvB;q9)iaPrphHm9gy7RwnIS z-~$u|bSfbKjr~+da0}C5Oy~5oO}ge6-+$tBbs%+6t5^zxXk0N)i4g{`gRsp6J?ZQt zl_%GM3RnMQ!EIX|3K_ydaRw=k*)2w)IhwK2*3GU&#uh!<4~HvJ8zwVY5CNlZKuoZ- zTk7p;QR!{eqYh4d$Q%_3(MuvWm7emKUvh)@5A_9DQ%~UHrGJ(q zXH;U9Cu{ewLdRi|9gYRpz-XPP$wXoIA{3D!*5xA_&&*8qM;`Nu-%hS*EGmN3g!!4c zSNQ}(O5GmdRV*7TE~!`4y|2wfe`>dM5U?rQx~f43+WkIkX=#!zb3>u%k`Arjc*`Nw zZ-Si*Y>_;Hl(9|g*iU@$%dw;!xkTtyBT!lc~ADF`89?EQf1Y;U-1qFRjWT01^ zxj(WC=_(ni#&&y4de94EL>$|66A^RC!4N$fgj%t#QumH6MPrq2P|LOL1vaX4bImJ$ zS{PI%QMSg^B2VVFg8pz4q-l!s3#Q+u4#Pvbqv-=5x~;tCGVaSIA1y=<%YSdcL8%~# zr(vD%Oypb}i5824oMkN#CYKWgb&;$D{I>5Vs`sr!-YI_Qr4TG7XgRY>agal1d3O=A zn3zRP*Hd|1!J7uJ+f|Dh2W}3oUm|Wo}Y5^qBy`UFs7Z=GtgdO4xU^B)bx%9 z3q0cXB_q?~J~%WsN2!tDxPNamKtbTnXE<#k&zwz35RPE=Y}V-lTh%EDEIFDo(rJ>`i`Q1WBA=Yqj{G9UHT@(0Pm4&TSe$A8cb20X;JnRQ%W z+gLIUHhfqaAo7rP05w3$zuNpwQk9A2)qlxzU%zK5$N-)aS61F2VRH21&lP_q%GBF4Bb2BmCh?yzh_7$2EiI8^&G%wbwSqK7S^Ubf z+GCy;Y3}A8$s!q)LsnkdwV^4hX$THYtg9FKd1cx`;!v>S1Vprl?+N8rWv5u7GyJ3y zA~QY+H;4y~(GB$qPwADUw{>RjtafM$W|}I7vu4B1z4y0ex}Y@TN^F0YRaFsk>lRq$ zM`b6;15SbpYs&;ulwh<&4aW*^NwdiRtTNvlY1}*yuUPt9No+vbUN5)IZdy+@_NmY^1E*m#&V*$^|!_COsR-SanBxCf|9&}!B=B1=o8AKy)c zhNuxwSO8-y*_V=~3etZzjT7rl<92ZY;RAG0SWWv7nJqxCQJX`C2MB2v zEzC>#83AlA?^OTxDTZNY&G+gwjOUv`+e9y5GP}zv3!?BkUThpNRR|P=O}@YYMwZLs z$j)y^GGREcRu=q@k8mDNRJIvU78mWqE1mYUj+We{N8qg~hX9X$0-U&f&dtZTx_9Ymx8($zPVdcO?$bB}k0#~SL@Qh23v z4asgKh+4ECYJEGNr#ZK@FQ!>yk>}O66n+?jTZiiCN2(of$8^#t^ja{xkOAeKpa(b! zhR2jn^v(|aM!J9fP&HRHsjO1Kx=PpIfye!vG9YmbV+900W3MT?hO4PNPzq@-pI~HF z-Dpl*g|ivIw~=z$(#&5iNAo5&h4!QKw3O;n%8oYKJYrq#OLuGA!aocJfUd9^cL82N;IOBd6igl_ZPE1(kp86cq8@of6x?HXBIW4NZDL zY~DzVm$J+nmy4;XyWM{``F$lNdV8>0aI&q5D&f21S^d_`K>C1~k1k(z4AWjO?=Q`4 zCUuh37I`G|bvWH2*eJdP+PA=A>n6-h;Bsy3GrQkN1G_mSdsa$8L&r;!pZRTH^0Vm6 zJ|bvi_UeDp+hcEs2(3jy(kZ3aDBl(MHa#%CQu;sD08(`5(^G!@`?P-CNXxj2$_Eas zEj5f)0#hw6OBj2p9EYxzYw)X-5k6ASVlj>6iN!JQYUYuSQd%|prOv)MC|U!jg1k-y zimgwE9u@f%b7nBX@`TBkz=)Cm9+F(1RR}&;GunSWrF_pvRV^rJt8rgItJyP9)>}-Y z>5To&62ZH=AB%yQKRAEOVRna+nE!+O+a!iF|Ef}B2JPux2~5LqUu|8i z+=~YD%h}D5?Yn+B<5o9kKDqU$N6c;Vj$+<5?(q*}PY-7b(d@~tHVMe?r;oFWZXce_ zj~0JNCfeN06(1~)-O3Ze{@1#FF8Nf_HB&9MN?JTCDBX3IJeMl7cb+xxC)>ZmbCFJN z`*Le2Nrr-IWC_*#nsP`%Chj2hPi?IpIlF%$O| zyGlW`?6sQa3d@fhUMf zuKfiOgP-r3=QYE*pNN+xqsm|V(*WahzPEEuQ~kj*AN6LFBXyT$=DVYcZH4^x^QfVgBgF_V%~><_#20wi{dbO!a0c6A~WC%hz+$^M1qMA zys`(-`$E@7>{x?6Jj#yv94?QkLZqm9VgcMf-igWSDZ$|hZd;hp?7C|20 z6h%9X%>Xs?U!ac+Fr0p2{$cIynpIVrF44boqOZEcjt~{U&bi7e3MjCU;zNJMJ4G!J z6&1CBUw@)-&b9Y`o__o7?sFp6jOA2NCzUyJPi(S|M3|N&6PHRYE zpC7+te}|p=5cF2Bdl?Vcj|}a;&FqU5ND|tYpzA zV@+H`v(E4`nXvn47V5*Ldpyphzqq*{v`WU;gJ=(U+dCdJCT%gSN6ppOn(<>k&|4Fy zhutT!rt*AhqFrxyvdCxdhV3=V*3EU}g`})CX%SMrK2?u<&t@6i_PKxI+VN|h#yX$o z&2DQI_sijx0#_Q-emIb zpXlgg4V%OqyW-0CJMBs>GO%8!+pr!Py;pTU?$0!F=g&rrY?#`~-Oa;AXnC{Cp%JHx zGdVp*0_FDW-Megi!G?dXu%F(&{b8#&-rYCG_FR0L%Sf}c{B@OwcYqCdG&oI$pTys9 zqkg7c_ow=9%-so($@2(9GJbz7h|OVT_Ft*Y9z7;c)OuYfi^Ib_UV78h>8PE#SKIzc z>%W6f^PXG&=k;>rf!+JkPqKBjlK^0!cgYYHiG_Oow8v?3kLG``_n<#Z$6iA6#}aPf zE+%N8!O^>)6KgSPqa2Ct8j0O?vEwrXH0Ed4b|x)@HY@~$%Ea>Y1zXf(+++5AalJA_ zNY`k%GE(ekgx9BLH`_}Ln%B1tk6y0Dt1yvBfP;_YU?D-hUeOMg>5UMMe6+2fyU}Dg zexJs-EDFka`ERbKToF`M80p=1Z6Jk%#2;u1&2eP72{_T($)zQjXOFLv?j?b;*xkC=_og`P}0)!8!+y`wQ54xT_NN|6Bu*32}?cNm<=L!$=3fsYz zEe==mG2S$8-*ENNG=FY;r~cr&jqz^fu2;L^N_!XWr`X>v)K=d@KWLApIrayy(XkTI`lQtbW_1v;x^b&I-d4tZQ5kb9l|xP5K1G&4cKZ!} zjL@)H)-Pc3!;cq>)#A3I8~Z6vj@|I#)2-@x;_UQvP@}t;?~SJa`LwUz=H%Y`^Zp>3 z#B}&^IG&{C)HbsH_1(W*{rh<|ehkL@)nps=cG+=_ zX7xRrZZB&Q1^qSZ2ggtR9%+l~AQ+z3lMUbXH}lzRGEIGZ+|H+Kf6#k;oYiFU$+olh z6z+fK=hYzFr0%{Bj^OzR1{8Fya8pq6`>0m0!(^z*rM-KMSK~Oomw4MOt3jqeqY?ku zFJph0pFZ@tC zSM$XC_vW*r>u0r-nc->0YHq&cYW{4O*LkEHMv*0x-POw`19rR2J^@>c!{})y!}|KN z-uj_*SK4y8K1asRNvf)E80A2;+F^muY&bZt{P)SYzP1Nc`#a(H_p(~VoAwjc<#~U& z&L(T$>*JF#N_yLu-(L3>49Blx{qR1vwOoxn1mt#&f|XZH9#a_CmtIqkwMWq-=v5;l z*T>1RfPLc4-lh2*OvpA9M8ua$-=lYVIM?yM&bInzIL_X)dh(j?C-kIG7N&jfxq1$C zc(EYMG_v6wz2NE}fZ4fxl%k+>TGW5@WA(B9_a*;~!aLMFTwXGF5+>Ku8EN+Z3_-bl zZr_{M>tDu;uwAaLC?>>X@9kon+_hx**&B<<-{FniuE7?=$JqDoo<7-b^2F(5SPw=4 z9zWA|{+P>tM=tG^2os#WCSn66PFRmpY|#|h?Rep`J0oq z%pNJ-tR@BBwXv-C#eE{Oo?)`m8D55UmKKahrkv8U-no;dw_qFU9BsXDDG63u?78=l zJ99fLHpjAQt}jZr)|=LsW6;>o-PzzL+uRpecd}l~Ph6ZIM4z_%@-WbckC_wf-m!^c zxxVwQGvYMmLg#xvUb?sA)W3f?$WM(B6&wIfw(fRuS52k?eAD0?htXCad=>M&m8Er(5I)IIpMW>wMo0wH{6-WBy$62 z9vz(H^uE1JxgrO_Pgh<4D&P_AKURV%+i_d#P4&F~XrS0%yDGS^fF*Dtq*q-Lt1xE=L#a$P>NJ(ou6Mp3TDQJ@3p2SL7OugW>98 zo{y`zI5nf{F$4k%S0{>i4^AgjoK|@4zZ(DiX_tA*h<>n6y~v7* zV=vgJj<4c#-E!-Aa87?{pTXq$grj+Od2wp=BRLP(huOkP=}lIBEz;LSkNo?#@7!dy zmEzRsJAB^+!fr0^v1OzUSLHsxID6kq13k?_@9j*Nk8G76i5aXnxiNzK;P^Pan>~_geBNgx(}27+56gYNiw@;>dC0>AycK4`u7269hx8 zF-Jk6ou7p>A8oHh;A7l(qT{2!L$l8uk6iOL$;S?DbLBl+kmNkf+d*+#-mS&MX2J3F zeEY@KPi4GZeAYU6bbX)R(+02e-Trc;RdYYB*l-zMM(KZUbqi-^5xIUctKZVW!^ktV zi@kZqIB!?G)9Ep`dYdOLHqquiT8|z3^jQ&S|J*$9sINPXIkGDbK5HhXzmMT2b6PR7yd6B)yY$X_W_TU9Mf7V-4{y6d$#$M@Yd)?mMk%g8P~ ze|%$)O?Q;XzLcieC-_f7T(_n z-X#&{dvx)1@{-?!*<>%V>Ij!+vv}3Os#Yo=rdaOziWSl-tdGF?puW zn7n&Qko3!}8YIDaI2`5Gap%|lcC-%6a}^`g&0K9z z7eCU+*598_`1FR^BYPl(??We{Ybe}8Kq*U z*}7=mv+Zf(x+`1X)5gVmLYl>M;ThGA^NPudOzv3XyZ0Kp9(n|KX_Vg3Li2Jp96W+W zWWIl^cE9_O7h$)Zb6UR0;Wm7vt$h^rvzRY+*YeV8pt$C zy=xSQUN4=b+OiqI%kqoV>SfJF^VxF~>*CNtN0#Zz~-(ssv>X8WUweY4y9&9;AQY)mHt&F4XRaC>{3T~^7ef9j8i6Vi)( zv5lV5dR*P2_rAZ9&{33Z41>SbB!r2MMY%JSZ2a}SKLUDmhKv~6B$zBQzs-Wy=TV0D=-J$NTX(p)jl+Ls zz(08Qevi+UIK~{R_0+NT!TqUa<79p<>?~+u6mN%ayc(eG`ZZ1a{h+;{Rs%i~2Ys}f zk1z1quNZ7vG_E%8EBW@*S0B(lgxI;D>$-S>^rLmY4Tyj1+X*+p80Bb9zx~q{3Ekpl zaz)p~iZZmI8;C5@rb3`)fQCe}6V!iuYDqCk1Bu!FnygU1rB<^JuBqj%#okDYbTzp; zEMczm_GJ={O&6`IB42uZn^)fcV|tT0Gg!-d^H9#}S#Q)_n6(`6qkq4An&)%1Uaic; z9wc=bKHl#VPt5_-dS!0r>(9WFvqpH~Do%%!U^6+oBJhP}RVQcuv7rAPxu<`ntg}gS zZ_j%tJmiDx#^g3h@I3m6st>E_^LiU;S~L!!+F3LDM4!_1;?d^4n(5IPjoQ6++&_CC zePcND+XkOeb35$ak#UA&Qay-XH0!IpjQO=3ok#b0aEl_-9-Ic=t^e*#pTT(i3L0aH zlEB{RRj+=XURAW%ou||G+3X|bH%llEgC>#E)8!}XE5My;{s1(Qh? z?l(uzBkR-f?eD5d7RG3?N!`iw!#<0OZQj=H9`E!;J`lrRl=|!8{3ZO=X8(?RySXFl zVShW^FyGL&`CJo?^I&JM7Y@vId!OoLZ|7Ax@h0O3%I7-Yo7^rvB}c@M*SJ-_{ICF2zW3BWzO|LWQA>CGG2z3DLzD)b<5$tjFD>&*fk`kOY5 zdr6vcpacgj3rnfvty_c+%R*hBq2v*}<}wRQZDMR6+RpPcO`y@pcd7!?qj9)gUhQZ& zydL`?^~rbv=kxh_eItKwxqPoRHq$5Lsa!0c&!WoT@ArE*vGkp18LR7v22MQLdskz1 z81ghCBxTk z+B3@Wvdt&&{aZiYF4Lp`95*wbS7CU;NM}@bg4y6vpN7-j>o|W8xBVL_^UY%QsCU(H zYTWbD{_t*hRj&_a=-bg_uaC;+{Mkm~ z_4(lb;9l#KCdk$gW0Kbs1D#hglGVL;o1};5dz1BVgHeB!+5>%Xjp%x6mFw3smkC>2 zn{bHHS+iO*m%8S@%uHKO3{%vUZ}DJT4IMIHtbKI9ZP9Z0F?AdF{lonD8BB&x8SZvs zueHpR?0*ySYtHqucg2-R&xoyp~xl1HUhiuWUJ-4+iCH=^dKBJ?mTA%@?CX zgi3AgTW5dq8hF+@DAOaXPVo`6En6?h`KY^sC)LvDyK1|y?VA_AwTRY{PdQ~@pw6$jUK(v z?e(6<;m8|34`%xw4ad6})sypj_U=2c-S)6wEYX|AlaWPcr(3mqXY@4F%jyUu@U9E< zyz*RU)99l6`>$R+DXSx%C-XyX`H+M9`x-r_L&1|7qRpPIZ5{cVcLJ{TV!Pj$;QzP( z>r{U}ue;ZO{V%dSo&L*z`|t1P<-Zvj5n_Pgph(f|98(!A^hV~IpG zU>{cOAj~xYFH>R#B$oF|HpaAGG%bLUe7ckh&W9TpXhQ8508FY*wwBu)y6xBW-5XT^ zo>X@(4eOAlqu<$$q37LAI{<53-1m%7c=)*TZGXXF#)RXv=y){248++^@bO6uR)sgr*$c{Fkx0r4Kj9}QE zkKW08aM|o%vswU5KI*LoGPUOIfo-|{-~h{c0RRr&pk}*4m%yE*0LH^s=PMmYK%;+d zHb7SZ43Gq1HEBthwj^ZD<;oi-=&FCL8rT!HJnBX8M=oqIDu_ASfyKdy!QEV5QCyTg z29&V8x|oojX`WuaHfh;88L~DRc@e)k4O=0RT4uo4W}R$Ik=Q7wHz!X<-Z>q5Z89R~ zbZFK|NU~HN)3PkNnUJ>Z9BWRa6GwkCb^gZ8(zPS$nSP(IMNKmBFk6C5@kdV97fF4@ zQxiBhA*)hb?o;5L8ny5c#01HRB1j2>*fVSD8AoCmLgG`BxC9Z$fWjT{fgOm{CPB4b z1i{1!(394yb=Uw|26cXx8Uk6_22TPkQiKBL04K=e@pg@f0YO~a4LO1&7OH>206`5y zrZ#ZKjfUY!u%*H6-q@cq6U`Ws)sv{_6ve_Zs>u%P$h>G6!i}~gYah5(tVDw9pe#+E z2ot4NH#~%HsVjJBDv@?zrErwk1t$g)!?K`nTijO9tvL_FphDywY2fhtXm%+=+Fmx^$b36^5jNymeV{rtK&!=ryvsb zT&cqg;Bq!(Uj-{prvc$k&?{zR~E1;eM#Ktl%F%*9oI5Etiv_QrS zBncCenXuMu#3@Gn@B$ti5G19;rSC|IkT$o(reKIu)5Q#dBn}AEbP(JkLt7xu>7vmL zf93aj_T08&mH;pDLsEo*a^A3yt5qu`c@VbDv9j3m$!v*$AdphM2aIGIKnO#A@mQ?U z5e2fsQa!FM`cHdhW@Ue10AGMCITpl+09*p4fz`)Z2IYEjJ~&v=$OY*jJH__-R8 zJMixPMqY644ceL+f+36t=XI1IqsX$W`i8LNXxkDD!2AA`yC103a2l<^lz^XybX5!t zTh0uYR}nE-Z`^nhA9;Cfeb@f9mO(-N4P;mf$KcFfT(2}L%y1`W)@l$shKLb? zMD1$37y(@vf}6mJi9mNiaBpq!k_KYED2Rs*Y64GBw<Q@Z=j?U8I;kNjvVxc!AY26THomYe;@m-^dai>sz=89O@#u~M zlWWJ!1+HQtSPhfymPy@)0Bp+P51v-SeSsxG2)qL~>F~6?zgOAl^$7)0cp7=Dzp0Mvi^F>Be?X_9~d`N_3zEo?*3 z*i_W;{9SX@Dr{Bj_RU30E}shLKoHdZ|F5?>{oC#T(c^#rF~=5A1GqU1&BG}emd9oJ z07r1k0AZs{54v+RazrAfhQ|#Y6=MVxgP>#?6)JxbjmH5Ny5-dL`}%?`78<=rj9pVeK`Ng{VvB%K{VR1*v#TC zmel)WEgk&9d=U?5ovuyE1}dJq_fWHusxeGDeVbDXpXs^(ni;?o20V392;p~~sX)B6 zfy;jdNLqqOjh|dzfXE_0kebUmLy~wqG-E_mM8yHF>6+lJgB7N7Nfr@L-9eJtqQHd5 zZvUzcJf2_>iTYnXrvY&>#u*C)$iR}!G?Dv8;Vi+$8Sq0GNN|LJ5DdBjoGyqY!qc26 zGCjk~2_mw>z?p|-tp2y*vNBDG36_P4^Rc&q%LRJ_0)PLP{>}wb0q?g_&jnZk0dKde z&;>{j0S~wH-vzD%0eiQi;{|>M0sXfj=mjGI0j{@2=>>-YfB$9e+uD-XxvqZ@2Q69^ z4`~ z2WY}mmlO>ZZJ@b+r(bu)3T7X#pvs7<_^vzwLktVKe0Z_RZJJss2pM`d8-prhT&O68 zjBZDJMote2e~jj1#mBk4^Q2TS4AdCPk~o5=nAj)MtV5+dko~FyL0Kj_5QP-)vI`GUjVtcG#zxQ& zsq>L3V#!#hwGa}-h-mK9nI(K=jYrT#RF#xI+lehLQhfo*s>Xw?6d<0Smyr7)$|X^3 zgEr4FLgNYRd58j50M4&@k9v+(xw~=Ua80YSf5SDMy4Z-F*tIU!aqI;bpz>2B3+M5( zCUE*n&BR<0$wLMhi{$*WVk-|YE^HS>S`2YfAhW^433JoAL+R)OBAnd`F}4MBy)#S0 z3T8yfm{uY{T&A~WzUD}%2=i7LyHM@dd>Ip1G<2W;C3pH9%EV+sz#xv>2 zMf)P<5Sr$~pt*YuoV7^!CslPyw)NIaxr01yQborYYbvGX+7yy_+uHUC<`nU4(n5du z-gqwP8o59ek0isKp~h$sa^Wu=Uy%El*)fFTH}Mitvy!a=UPXf*%a z?)>+oF=%KaLjrbo-VfxS$I^%JL_Qd5RRVj`fVLc}9RI zy!lwsofXV^yJe~5wvZSD1i@i1rjE6x$Mn?|4Izoh=$0I`Vm!mgbPw>711e=RooCed z;0+H*dhV$H9(6!|Vt2ORJ{+#oe?^o&6V{x_)^X0Y2g=`MC#n4pmpyMV#}g!_Lse9I zBH|?d$Zh$M!;+1O4VfM6*&c&`%$KR#HM4t!=8yRiiZ*Xbi2XvS3k!8 z?VnfTS`+`lts1>Nce;)T#e<$!FFjp2Y z=*V|u{j~s-A%^ttp2xe0EloP*{#bzlPe48d3=p~NKv~`Jnmgp-T8J&Z&iU?|E9~vu zUHt9iRloH@G~Z+H$g#4GhgG~o9$wCEU@bk#5Wb$qjE+_W^?8(do2${Jpfw}PEXYYI z22LDrTU-~L%7!xAoSaI*f9O{eQO8L%$44w|mPRR5pe9MgsAP=Z2}MEi=)gk)%qIyS zM7ZmSAds-o8LBym$kqGLmM~Fch3ki@)%YUrdDhh(@az!ur)61P*C*<+W1fsU{(D!$ z*!F9C&&74U3*@ZbceP77hGldYC=2Vx0hPRae#y?7jDC`1BJ$S)e+ou`IdngIBO)KW zP_Dw0J!mh*J?23vC^D&@9Hnx9AWbjNAqVv9%_!j~PMHk@CJG;f2#X!JK}9xl+Q`n? zQ6&hKBAaYSBA;Tu+Vsg@eSymH09xQgc8mMiF3`^0|M1%{_#Dwm?`4mtFz;dw)TZe7 zL>g&a?bQ$AXI+QAe~T|K3{J(Ik@lV3n|?;xPj+gLRImf2Edzmfbv77oo|ZH%U)b4t z$zcCX&g~0gw%|NHg7got(C2O!XTZtjBf;EbplbX)@+ufj+aXu0WUNXa+4&CleQ~iU zx!we^ydB6y$*S^fnqsAieRBdHj;U(^US&co#dYyKB`oK_)nE zPr6lq56_&=_xXQa|ss&r@22j#)$$v{6A#P>Q3&B7S(M%&4b%{RhvNa9$cgaWU=h31r_kp_*SIcd z-}x0cIKT30JDiKQZO5qdL0ochQ8yr$C2JJE&Qx8DRX`cg*r_FD_ zf-KSQb~-{OYE5}R_Df$Mvh3@*(KW>1e|DhvX)&+F?|+=9Ywf7dJs0;s&Le(L=e_R` zB2i9p5>>7)lo6yVbfKk2Yl-k=dM=nA zp|2ZTJg+!N`GPRj`?!k_&V8KbIhR&B)rey5fc15MmaywRz3ctvJ2AD6&Z!h$S_C`zrR7C` z=yuURbiC+aYkT=iT}wqxrb@c-WrhK%lThZX@s=e7_-TA7(N&YwMKvmRTW-^tjkCssZ!*2`BbhKgM#QaM!QQJ7mZ3eqL#=bbI`fYs%RDi#Xc&8A88 zkfyKmwHP^Gr5sYdjm;C*@0a^hwjw&!uA>UfeP+qo6!vuVPGlJ~AwBPshxG1sE{2>l zl7GD4jVhhzLLAU@NiG7OfALzBsN=r-_@}O4uZO7pfotvaB)tBt;^)2q z|C7$igI3zIIr*xk!PY$5VlQ4Wnk)Y^b6kuSuF)ai4YpQbZz1%EHFiL4Y=~wA`EsfZU6tG9^zr6b zbp9gBx3_s)`}XV3RV@Pl$3$?Ca}qn)P0k-N_WEp+OXJO7`I>+%LSZ^&D^r~F09ejw zdyhU)hjnVce?nRNAV+s4H81636m@<-9T^vktgx<2bi9^Cr#|O!vp40<4t^2g1$8@h z(BI9PmJ05;GS^(Q4>*OsRIYO>17}FP;a}Pa^CKT< zpXt$NXI~aevCQ1C!hxfYtRY3zl?Ka@4r+(d?M1t&jrSFSARxcb7Fnm zJ$L9|#GuB*lW}Zq8wvTZGQrO@evp`BM+Gm7 zno-F8?bW~T@5es2_MR6r^#m$v^&8~Bcy z7K+n_^b_Y)ZYL>f>xz#wVRJ_n94hljHxG}-v7r>P;5cv4ytyKnl3R?}otbM)NDk2e ze`VmFz|W(kbwTl$X~wBtMJztI0mwYI(Z@SmW|wE$81G`Npf0<5MDlAb*HGoNKi1jd zNoNCj7ei=YK=08@=M#`FhP0b*4RQQ_L@@OgQCgW_RJbk_1*7t5u>N{@;>2=YV4ut^ z-l=+h2?X~8ClBcP!)0fSI;vQ6aEDa3e*sZEh;qg-&r6a8i9~}MH!)F6Mxrs{;^(d` z+_9T8Hf&5Hi{;ejb_~sliS-o7#-~`v6OB2ke{zS& z(wXc;&?<}AB8q5Qt{Exkd}cW$Z{8V!_f)s(fT`g8vx7FXQ$dEtuF@(`<$O}DTnl_X&myMbzh zIhB;A)s)KiJ*lEks7lw{+Jm+6fAD0hhCxw~O4bT%XE;vJ2H!Zo57tryu!M-FaH2b5 zM|-g(vUn_%$Ywj_6};w=j7+*?5=0pz7l7^@;-DU)sF}!E0J7A1wA>gC;M2r98t&)?Q`#eJu6bP5b-kJNJuu!(DDF70n&hPW4@&97ErG zlZVKt+h~rwq?eq0h|`L9fA5F89>weIe>+*KJO?-$B1%(b z@y%oDTy1Hp?tNgC?#NiT#+G0i&m&xiDe73w@nNvGc#giuxV`bY54x6q!=n9+`>(i@ z0{Q=!o5nHXk}uI3P^a>mSJ)O^j7X#1w{CHHiKLf}Wth-iv?GZKiAsXqx%s5BaOq*W z3T5unlW_PY3Lq03e-7NWljsqlP_}B^ZP70M$IliJ$E=LOA!QYTT-eM+R>tvFHJ^zR zZhR3zWtA~l%BH)8gFsSHhcv132vECFL`ykTK7pFqEWe}mM+{PB&>&~2jIoX{9ON73 zsB0J#^Lb1lkJP!?XTZ6if(;cKFU`l<;{2W@pJ5+|Qc%ooe>(9+Xk7kvjzf9Fko9>L zo&UP#6%ZfzU0Y0q>xeRsuDY738i=jrFVuP+T5)=7lshv~VG&-wAD zSJ(Y5^!LdwJwJlZf$6)F5tceU5dp14wY^wc&)1Q885e==C^IHta$B(WQ${STl!M$z zEC5w0%c*K}e_pf$0?11#9M7Ind6IJiQB2{KFmW7MY4l8GGvsoAzfw+0=c{`VZS4AV zLQ_7(*JxvDzRj3L5dqW?Ec|_4WJF?OpvW>Ge8eqKDI$?`lF|Cu-AfVKX`Lux38k=Z zMTtDjk}7hw$WawXHPkM083~+-kWQQl!Ksp%`+s!Pf2bz1ke)&wiKP6z4?)Nchr;E3 zzWNU9T2+p+l2dK3?XEu8^Y2jS?}{_&^9$uQUUmP#W%czy%^T6{*TrahZP0IX@cnq! z@b#1C!FP$liel%zjLK7sBWp{|PCBrg=}y>N13 z`5I<|2XfV zvdJm0kf+|;nyz-%*`nU>Ei0^zBCf>LI@Ns6e=4!%GMS&?Ycf@0%PWyOigkLRTXPJF z{rm~?3Ay5>a83l;kW3yYMl}SKi1x6%tP2kjW4;Y!!S{X zHZ(zYLCwPg?Fc28A>w1Z`22y{2Zhf&!u&YmV>(^9{*JrFE4`hFE?sWB!_#nm&L=V& zfBxaG_xEIe7=xk@u%C>@Zg4+&D*K$;3=+hBzojJmu} zZ^mcS-ASn+zMhZcVE6SnwkHj8GoLfW5J@v6T6ak@e=9E_zt(H98d$qqs#YsyVgUN zsMoLSKC7=1;_17pIoT((Dc+Z0QaFz;RMfBZG76*JN(7?ju(euKcCigCoufdB!vnw8 ze`xxOI4wWUgcE>N7{58e*>p%61!K{)Av1SGZe12x(o%;)gZ^k~AyI?tGtuS7+3ZjK7vJEW>6bH#0PuIHFz@rY?t$ls@6 zji=ybwq(jy#=r#k=hu}j3*Yd$J>1f~Ts;vr5& zmy^7d-(2gC+q3=d_tRm&Zrnj}od>PYcF{ z3D4|p$*V*VM&t{X5h0S7S-JvxXy3KCVp)<{vLQLQPgLf_nU1_9 zkJhe|h7de}Et|WY-(wlWmOMlJf{U79{kg{hM!Wnk{KXy@Smk}JiugA4kI^5B2B7hj z(Lrm{b@c`OzOp4pjh~AvfB3GuL(x}~7W+5Lo6Ea%CUVc z2(N}Y?(?=9c}xl>IgmiGt(QNKU$>xtR;pm?%95sLOKigFR-m2O^ti-eNt5npxDUu; zWnkXbmFuyWj}j)iv%kmw8*F1N8sb^jDm$?hB-ps_h6od=Ylso@f9I&Ko^<8&*gtxK zbbXs{9IxA%|K{pk&w$1T`l!R!osZl(Su|3BTHdCAF30-!+_+)oT>+o_@_w3Ah+-F- zmf${xh8Fe*<+JvIB=yprP61!f0go->Xp(ZQ7-=v2R+t$9g_q}mq zO%b()ya+=-wD)Ax z3icjcR?NAGHwHX~ZFC?mRK%$YyP6HDU^3o~Y*ICzjk$-4r64}00*XXT%R?weE{H-f zi5deR(gx<(NyMSDbY5Tz_5qfR*b=;7_Hru5kio<@p2XEYVP15+8SIeXU`X(RjPQ4u znimKfHwD^Hf6Y2u!_v;)GEr>(6RThvtpYMyvs1n{K8rD=4WY8eywn@s1w&abiSaap z*37-cYP{-x5Lb!+Se z_ol)9TNi2WT&{8L5AGFWDz?9BCA$u5q0bOCD|wn#YH33>XQvMtvC$wW#mmAJm)Xhc ze|}m`+FmZoWu03>KH@IFah?Y|X8A7D1fIZJ5RO(&j48%MV_S zYP!n{f4(&XnnaXj{4ULhHQpmjv#q_edZysKr*(Z7U`?vS0RX(V^h3bniZAS+7kaE9 zJ|p7n2uaxtUYm*Wq6Em2j-kN&DJI~!+uR$BkW(w#*ugryGAWS_-Ji-Hy9P9VN z8FLqye>aR4|L$3UL>*V4tm6@;tg}xNe)1K7f2gjW6k!Z>&JVusfl*#!a7`jcf=nKt z7;q1E(gm4w>^Ww=-fQA|m`8bv33U@^xRU&3y)Hq;rQhIP;g&$c3-R6lNCYrDjmci36BU(s@$XTl#XKFtQ`axgyKA0KCJMf6SE8V?whS;bs zhv?D_MdxE-UKsbw&%5USYBQXq{LMpo z7e=OSB z^~lA3lv?YfdyTw_A|!E^5oleKxyRQX3+T>0yk77|M+_AqXPA*Dfl@$^C$Jf&tl=yNWwyG-BZ2Aodb(@$+yv&f1f9VkVY?V z$|^T$>T%WXc-1Vp?!FpPLXFdG4SCb|Z3`K1@o`5Bq`*8TW}+vqvh-*@EwlmVks zuDwfr35og&^5)eM7_&q{e_8`~l7f4e#tf6|YZ6}z-^_;(3d|;FXn4hzlVr4}r^cq$ zYp?_hb^T>Pqr}~r8&5VbpqpePuZKGD!O4q)cg;VV2 zK{lG$7x};vE}T1IaERPk<)4#Nod%aWVI5xg9vSqe^m5c|2Vl3ehxt*`n=EB4+JSES-lP@AKR&Ebp0t%f5+B|c`9B5%0}bLY`8SX z;ST%txnErlVK>-Nc$y)HQ;g1`L=MfK$AtT|iWnoMzt|S3L)hv2wVs!B7g19N33xdG z;oEObtQ*(+9A7N<%U`PUJnHp1uJLRCjJO}Ju`JG!_G9|E?HZf9Js&U%lZ!IPcOT6MJ?VV2u+#dO)z-wGek|>s8XI4Q0AUe+ zffK2l_b`p2YY(JPX^SQKYhaj(whg3wA4u4O`4{^pxzVwm@mooaIHlhLh`zIC1N~Q)2U!As76Z)Y~f`^w;$~i z_hXItb*;6K-Lz$Y%vtdRyDEO-;rg74MSK0TzkKaif6kv8#+^;0DsfVOJ4)whWJqks9cZC4hLr;BwY$~a{87-a4lMfFgi#yBdnEnmkk)R$UpXa;+0F|7^UuCK zZ}H4P;4xrhsKsVHWr7MT468hFMNQmfWO|7eIolK1LJ}98xcj+zN2|#jqIt)x8Pl^h zrB&@iQh#q^Vy; zeb-n2m|t>^4i4It-|KSS>v&#vKh}4LJgIlJnoP3QguIO=R4%p!#(29jb$8{8VQf+g z!6FfZEbdv=4!sI%{=;1%i@<&yg-K;rS!yO^Ie!|%w2jH7a?%XrFoijh6dQyDq~0-6 zI;|Qxr1HT7*|=$x5EY?bmzQnXSR~Ds^zpm)lhz9Tw6?FKU9NhC(G`<*)3ELLC+2G^ z)EH#fdh=lnk6*+bJ;&zAeOIG^9Q+-|hw+IogI`wsc->QCdk} zn}0-^5fPEgYA7j{3w~lAd5It!;OISQlfIj3+Uoq?U zwZ<8x#T0Wc9jC3Ve2E&$Q6F1!BGN*NRBZUjY^$e%`g)>_0NnsXe_&!1(HKO1 z;EdJY8Hlm7_T*x2d~XyJRmN0F^5UXc3*}kNTSYvs4yMxBSIPMlPi2PjjX} zvmLuQK3lXL#Oz`##KJ@#YAlkc{Dmh?NH+udX-hEMP7v6&qfYShGS3Ejy%B1 zo589R(dftfq4hKt7}V(u>(vL|_Pyw3am|-qePrjK_7QCOAUsDe4mrWBcJr*V-bvM% zRCr9$2N+b|!g zs<9^Mo%ELh%VfkLwJl>UJrE;3ZsP^>)#wBGHiHqpmqolSYGgD!&>T2a z9P@2_^)>R0Df+*tPqFd)dpxj3caP`B(|bSu5}f=y{?z$If%!ysy_fw|9Q%3$)+p|E zPjKY*?s|T-#>e4%M}PDiQxzdzr(09hL+EYVL~*QD{QK+oG7?|OzH)=ZtDOK@ZLKfV zW5IejKl@SE-#K54aq}juiP1ElsFguM;p=e*CVf&oW>65{+K=Ph+@LWG`Uu|g℘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�V#!RuU9H{42m4RcxNkm)S6tXz+2 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%0D4c&)?l1nUIpF#P{Q6wOmg{z8 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 z%0A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%0A5`PNz zQgM%Gn(&D+lH@ZLWzWfPU^enVyf$AdIXnA^PSRo+{GZri!7zD$7A9;rKKFL6C*|zU zDh@Ez#_j?nMu&Ls4_Z!_e3{ze z0U!;FHHL=ZYB=t zeAw13t2}lmODv~I4iptVpqI@|Fqyc20+a-;wZ4_e<>7W{U+Lp8-!pUxbblf(SdWd% ze1DlTFGGHo;t(^z5fXA{h6`nt$$^%k@1IAW9ZL%Wum~9{J!liqVJ_HFimD9X_yYlx-HQ( zfBX=NrfQK(zQ~KJ6Oap$$BP83xY9qv<*Am37n&x*u2tChf~O(4e*s|ErZ8L|x&e6m z>uaIATRmfX3ZckAcWB)4s92k z0khh}|JC7I?9A@MD-#-VcMjwXC4UP(NCqcL`}#NxRTm*Q_T_Ez3MVo{vzGrVJ*W^w zp(5hEdY zC~`#S-CcEg!RyN{e}8#@<$NJ}9+S;9+J85sqNgbgZQ_A1I1Fmq zhBXsu?)=OP$w#FjgEO434&LruK(v}<`X3+d;^lmli?}BRjK82c>nhel)Df=&o;F54 z7lyOkdpRfAF2UFiA=)&^E#8y`%TU=wC-k$V?!@OXwuGh?#*=Jb&jWHn34&t}tg~dy{ns=6Q+m-wRbKdy{9%(XHg^b^YsvE7h;m>ZrDQ zgaX`tWNo05>v{{>Q+Br`Cl)XEe8+YekgngMoGTaQ=zg~e_NksQbLeR{EvQJH3A%%0 zH$2Z@G$+4r*Ka(HGk~RjF>du5=2w6iE%I4G(+{L%<$uKv3e0OtdTPx9-KpBMg?_-s z0Ur3vi?T9=U#%dNKUv<+(ANJs{8WY!d-M74`Q9oLMc})}2V$QFWi6rQ#llNP9FAvF zJD^Ry5x(bOom|gh1EmQk;N8bHc};_>IqOxzzSQWvfkU=de;&a5F0sRp=zula+d2;( zM3bhiZhv*X3ZfYop0n1La6(VbOw#zBn~b+^6GYs&VjL8^A>r!z{5i4X1P$yR0O5N* z<~t25vBIe;DnatEg%djGv%E)Wg2j!+&l96K9tX>1{w2^7;3cUZ6Y=hngkz z{Vs=6`Hr<<@Lq>Into?1QBMql3^5S#(!T@Wx{{~x!O|h|w=oqyiRG8KNnr63P%m|= zB4)Xz-fIc-@6$n)FAj*DC#QTrd3k*66ih|tb6o0pc}mJ+l8m3kGypJ;b{9e;MVtPS z(tnPbr+%jxHkM3~+rFytwA9FXa$-6kexcDddzI38K&Jpf4Y0al^MbQPNSnQZHT#mDwWwQfjB_SZhXH( zc}R59)*Ke!78gFP_xNuh_do&>Fn{ItZ*Hnm)&)UpK1SiTHn(Pk1M*j?fW?hTY>i3u zPVV7dA{yVyT+DS3RTm38p) zsqjldOxEJQ@58yCHu}K<)ETk7(2(4PxVmO?f;-qb2c3`W8A`iA1spX55P#te>Be&F zL53Hv*BdK(yp&dWK&S?rn%1kH6SHh9pY6Bem_;3D(T#B=ek_-R{)7F{hQGjmO?M%m zs|yf@A?|Xk0CH&U-*#}fH}T75nkMX$+M#xAX-E``n9@bigGk>GsbES{Q0p~iSzu{| z=D~4-wjai_O59dr&J8vrwtpLtHU(6eXZv|4TdSN$LABq|bt*|>E=)rDPtSYL1BT5K zi@nXh`&V-Y;r3$X%D0K|(qaoxw)&2w3TV`dSIL;+DZxtRVzR3AUZfDfks{dZq(a~@ zPp0zrUJyO8ly67G9uvyiduzT+M!b&_hc8TQ>Z+Gs`B}=rQWZE^=YJk}Cp~ZAEQCD) z0Ipp^rBFTvMnrm(G^3%}4*h1H((4b6MSEMv2$A86BnH<#qpd3zy#CgK>FWN?AVDytvKJ*v3Z~TaBy3$0+7i$zknWmn_)neo=*KmOqUh({a)C}wv0|h@$k(*k^Bo~K<<$uoS2B-ZxMM*+T)o5yLlF3$V(Va#vOcS>OmoB^xuaQo5F+ zo+B0!NA!_iO+}6nDij|m-sA_?yzxuh82WVk(sbX#QH$h-f`5x-356u^Ly}7Gw-7AR zEFjs7-Y4sZorZ_ExGjH4-EbpnId1!U;6+^f^UQ6#XQ6-W5&}FjOk<;tIUj+=bul`O zQxv`tU?jKhvJ@Iin!(U-MSR|g8Os6<^8n=!MO;G#b81e@(n966Md%+Pp3``Z{=>lC zo+SE&ABM76kAL`52RTid_<44OwzUpg^@WeIZMn2zq*+O!%NQ)ff1AM@hZ8bZXS*^r zdhW{TJ`z12NfwM{_yfP~rB6Q7v8cxNc<@FJ1_^I0V}BrY*1=Zu$n!kaGTKhP%IjCv z;K-EBzPHB{m_zb6!5iN_10dHr`92mDflm(;E_S_XwPO=~Xgc|;Y*%Rs^njbUtEL=Y zo$z^}IwDKOVo;}Kl5@b{yXiRt9-?yX%DO8fW2p;|!$XSS5ANhp4RRwARA(9vV_7k0 zZD-NTrhmV+vfLSM##aczvjgNFK0SJG49yuHT}Y;oUa5HNh!^#nE=5dZ`_1&-81<-1 z9n1RopyDd)a7%RLF$KgPre=S7{iU#s%{WS~5i%Q{j6Cg>p~HWoY$Wi!iC5&kD)l)w z96b^qLfh#PTE0VjffuGkm{?akEwA`g$QIJ-lYf@9y`O2KnS-ji|E1GNd>Qs8OuBM? zaeBM>9xbDW5cC8qx6MY8n=>|8#xn*F1%`pW@&es@<306EPBsuQ!CxGsi zOMfE}<@nL%uA|WYGHU8VHVwkQ!r&Mn<n3z`}IL64x(R|s76j+Ca^OEK*_jVoXaQKh& zh0rVYQC2{%^}x&ZZWqybeF9D6n%`LO1%IBTT1mv`?nUOI65r>iEDmeZ@6jzp_RY`F z3tbz1Q}>Zt=gMkq@h9VCsb6QnRhA*!z2|tonDNg_eii3B5W_su7VTF#&KZb;Q^0{G zEt5Yi7sPj=iHEYa*E?JKUUh`9Yh7v50s9|tFhmFXM$`>`Uu!QWA++?YW%ShIynmU{ zCFNrX(`iA_C>Xkt3yR-KOM@WrQtvK|qTa;ABs*uTMRB&GKT5_^$GZA^J(ymMfXWW& zRp;Qri6_48@TVm2;uvi2fu;#|e*q3=3eJ%2z_`%Hyp1$osG|;g`j3dy?jle; z3azUW;RW(VcH@J59%u$_Yl|P^-+vvfMD&=&NIp4X-6>dFk|AkfcHHEXobi1wt&e_- z@?lbg_sfo!$3R1I!DVtQPP6rH*j1ebB+>y$#XIUiDM$z9D0YxZABSEVf^6XBnWMo> z+9E(t151RI>P~dwYxAo9APZ=CVvh8M(6rhTT2HqLGAOczZ}s;1;zIDU0Dm|fgn_rG zqwBYi-_X9>{qnhI*zuP2%??VtO&^lBe@ZublVOa_t(zP)I#%tCTG#IvERHDRumk$O zY_EdI8!oAEzFC1?S~)D)_fzcK?zNxZa!9evG(B6EKfjo)Rb*J{rn!hc_W%-5J~+Q}rg zkFL6Ud@jT4)ki^>06G|SUG&^REf5*^KSrdn zz)8s%R>bwZ5_mkK1vD5~+(pLgW~#l$xvo(w&v1{hhrT5Z_gz_$OmF4M49bfrwkQQg zQ^!3f-10F_q4;lbQh(B00qNX*ZX{LJSpmsjHSd^?)bXY~AAO*xkY_WX5uVDO*I!@vpl0#nETiD}FVubcRpnnDPdSNGpLg+3Y_t1f4BxzNYdu}0Vwh#XN>MO!$NfI7Z0ZI1;jG!{PD11XCrXIN?9Z;c zhKqD>K*NhRH(6MEf-cM47;q~Mb|^G(BJ7W!Q}?ae^7~oq(z)}fgOI0#yA3l1a$m6Z zCS|WM$WQ7LxEaM|Y#HkNA+k12kfh3&bBlH+rzdd0>c+)b_inf<+6%}>lw??J!_N^K zS*Tuu_kWVGvdDB*bhSiDm#OjHzb0qhIGA^fcaI>^BT@fj$=!P&s5u#%^ zrKbi07&`paV*zpHEb4!oqthvMlDB_Kgp~LLV;E3Jw=8hHrT=x z$ebb&T7x}zWnMN0NBUoWxB-eKmJNYYI7r8J(Q2n>`PYIixq@?J_!s(2@=B5iWeh0F zyOTIHM%2Y0XPL}6S!9aP0oDa-HKbXOj4kX7<*sy=iuGJjKss!7aK9AO1l!xkZ9QLl zxqn?k&w0oGv$<3T%X|kczr-FGiR&YalnSJW-t+ag+4*UrrF3gEPe#<(10rAA2$2!5 zEQViZt!gh8J%FBePV8DWb zgdWHTs!*Zu%q%U)E_oZ)I&r>!&us9H*7h2eSD%PQfH9(Y?~_%lCt!Eq@`U zj?+!c>cs3DKkQIjTo$3z{NKa7u$l9uYd4>iT~9pH%0|Q(381*@Ljtk8Z6v@koTT(c+4I$ zLQXJ1Nja)4a?OSb2!G}p(SfTZ@0C8;h=YcO7PXolIC({*`rYx9l6Z}ud-Ox>c8h6{qw*bi+)!vf2fcG@wSUexgrikNg-uJTlc2V43q=!z|@^+C|p`C=-+AK{q3V6vP{D1@A`_6UH02IhX#nk)D|j_ zW~8N}k;I{;#o<2u>}E4wK7VeyGBDwuZ_*+8rEw=;ZO0AU(Ub^81}4sSpe4aBjD2P2 z|G*HFbtEE>Qt(!W<(yV;iGag-RAm{sGyW}sRrFdp$@M_k*hq@%ZX3qGh z8ng;O`4~dGzjtm)t1bvc)~uCCmPeEHzR?~2Mk9izX{||;dlE|zynmmC%0h=62q4Bu zxBOX_~f!u~W9!nsR~^;oP71G4==1&wYBlsIYJQl}5RF6HTI&Rnyz+j+!er zB@0q^|G%U0zMVF2zkdfljnuTr#(a?o+|^4&?X|BEz`S1H!4ve!BWRbgaszsR!{>OG zpOe6L2mnml+pQ-pLiA{SE{26;S^SXK{;%Nt>TcUvZ2#K@)}OxO4kcc*^=d zfqiiunt64|JHlA1$h=tKcIb3;qgkbcq2XWLoAQYA$SCq9-Z!rizEm4lITw6c@K_-v zj-Y^(lIdND#_NK7)1RNf{T99D6fLI$qQ8Q}3{%fhNU6SpvLT>+c=b7l8%FMY=LDOT zC3D(J5-m-D2Y==#mvY#^6nd>;vlOp~Ko4R7M9u_o6|z_@i5gzo#0RM&to=xOQz%-8 z8^+ri`1=b5@^ihc&dVW3Qb{nVy}3g=(`RFjje*CvBc+8*;=qCD>{2@9jqfElCmr*% zIiEuP;ysH?3xJ()gyj2mPs)hTHOAeb9>4rh7&D4gsecSKHNg}mjgItwx}8j2yo>kJ z4}wBPTuE;}A_b2+qJ#Fx-0GgoccENvD+ht#T~29$u6 zTqu_L$qV)FqLC9~!F%zQ+|pF=^7X6wsX2!B*}TmRj;P9CbA0p%gk#fEtA;(};H z%O%%Y2V;n#k{J902#1(2l_jZjAetKsR-NJQU!z`Cso9htdWBzAZa&0jPCIY-dC?0T zXEae)Fb@*mvMTK>McWs?OzM&=`cm|Cz^*-lk$jyx>1UqhgZ6S4hF7n-27W#Ty1+|q z0Dqs9KuDMCmYXYByR>!cA)b@P_?qw0{($=T`_Zba#Kxzs+XI9?P9iQeOsU8Goc-w<`{e~f4 zsq+noFq`NdnL5E3PdwJ{A*F|f&~&$FNf@u@+Wx6m^i~9UMtGw#Uv$*TO>oX>wSV(y z$p;U&pVzwGXn*S3ZaLlNjh`AFcytIZ$o9mG+Jgl#`5HAg;ztvG z^=}Oi*jZo;uM{sPYb89I2QcvC4vj~b+TP*e`!x;~I5yHubzcF@me@N=t%?761qfrn zrlYSnrJP*i55bC#URtHE>!w_B*)QN4B!;GIDu%Y{&J;6%YMD}sndOFzRDS}`dW_U! z!=!wrNq&`#(hpahmX~3fMD_*y>(n?f`$LJdYh%G6_zsg9cNibW+C(}zu7gm$huF{S;njV}HjtOXv#zO=p^ML5On{%6!T{D?@Hb;phl(d3zgmCB+m~kwvCx&! z+F{6adZX*z|KaB=Jb!H;r}ZT!U{gL z+D$~(0#bq?hksb@oeWX>cZ7Ss;J5^H2_D)?S?YyjwR3Z8vRQBFP-0cZt784ac2jwM z;4a`XA`&cd!5hy!cv!U=a$aduk1#)e%jotz^L!MRDO7=9p7~g!Xy9BPfY759@p0yB z>R8?;co_ZPe7*Y~sj=vBdU zd+93^jHr&d;dRa0Vh#{&wbS91aD1gS`gJioyzKYU-G0lXCMJ7M8vP-3_DLSrtRqs2 zKkD+jUVmcd=Y#e&B)9WqAod%4p<>oNvzJL8qCBL((jFmb0*plj{Pu!6OV2xN6TMd< z+eT*vbf_Zg{gIr_BbKgLER9J#8AT^Oq9e_}#U7t8Tm!xV51=PA%xIW;({1%l08*MQ ztwU=wXnACH{FtagLV%!sh7hbdGy{C zW%HYn{ZpNh6SKq}M@eX5DX<4$x#Q{`rO@SmgOK=l|GLv|MnYp$0yoc-?wc>Jf2R|_ zgwh7_>aRa4Y`$!@Nz6yOSsqJ0XWh%Rm275Gz(pZ_d4B;@B3rPfv7QxOai}&T$d6ze z2!B33fqpZcn`)w~liOgPY5l@2+Am`ZPV?C-U{>sHT1Z9QGsW=h_HmsHZawDB$%0q^ z@uI^FG&?ytd9`k*86&9z(Vkti<*cu_?PTBsNinL#pdNU-&W1H0p-MpQIk}s~PIt@g zfLa2yXgQ_oG+Q&7DZ*70WrR<{#d1ETZh!y#ju`EB^`lc*T!W4QRua+XgO)mW45Z(h zrY<&W5VVccd_pCIXDSh~!?9`t_ry=lGAt1+zOI&-ni=qy**zd=LTlu*(Vxi&A(_c; zdC9gHz^?^?f*vy32kPf{)W{k{Hv6L~4{fUbcP6qg_(7j8znL>mW~R+Bi0LiRcYpU4 zGT8hPp0=ut@PlgKE0tavpKbC7s>fNNxGG=Le&pBUX9-Ic_iTh}s!lBLOp?mdD`R{D z(ejvds&W4y4>W5GaeU@d z#5pkR^PM#H+ZUA(1?TPGw4)?80e^9QfO>;-s%~kzh!YQyV?eK?Erawn`u-Qy>`?P4qjIY->AT=Pf>1p>4sn@WyX<^w~x8Si+_GZRn~7= z{?t}!8Laa9qAI4#lCSE>!A_*v=y#$&cVnycs8(u!dY(CaegI)%NUr({HdsBie$QYf zn4aQhn(M%kWI76p-+(6iioTQ-8_l*a1^^(-g3}}g!4;n=FpSDmm4WlS*W#e1Z#!~ziLkgyxIx=v=$n5yKMSOkb z(>Bo&N0x)Av0_n`zi1|zPfX!`p;y6kDgEV!ql zi`)UlgB*QAL&-(6+qj^zSKm{Q9a6+Bt^%5lue4BA<^>0|JTR6k$A93h&!EIYAU1FY zVQOwVnk96P!0;^?qM{lI+2+d0hzEBh8!1w*au@9R6N#K41Kkb0`~(j5cz#gq=nYw# z8M5?S;Wkl|V{n?gUGpE-dCcD>xt?F3p(pc!vZPbGUW#MF+XZlkJsI7IsB#Ln*nDlGZ4>Rn8 z@xkUXmy10FixIB=4ZdRYTVb6H;lA>*LP)f{wTyOub;{zP??B06h-R?98t}?r1xf^K z`l2qeC3zRxZquc7(eJvbU~pPfFnQlPX37ycsY(4t+APATc7NPr%0whV)%eq@DMwwn zPGoJrMMZD(D#%>mq<>A)xsh$i4^>9OK0DI_)0MuW00JqE;&9bXXw{&E15g$x5(UuE zj8pz1i3X%?;%>p_a?prp(xSM=>H9;XWs<&@RYM+0{2R&_*!HT>a^wdGKKa-s23^feoAw-rFn(n8$z2;c zK&8Lx4E1B4L`HE$kNqSd#UJp(8W=11LE91>bhL#>lYeA4^7~y?VpqNn9KfzuYY=)_ zt>VEyY);VB0LQeuIj~&7QS&3Vk+lj14iHDd%?^Olpuqt4L28_wpz@o!>McjbeiP{B zHjYRn25(2CVkYo}08nG$OJn?&8!Wxw%}A;uMfGxT>IZqys{!1M4WrCVp{eSZcspU( z+eEHUMSozD*r72dVS_4$m+Z&18#eevRyQT6lG306LDx7n{gZD%N%{y=fSvsF%Qod) z!&!pnpwJaD4HzP2B3c1!HjOHgF<9T58QaPC6OAVnj4$kb!1QgNXm04lw@Sd+bw$&u z+)2vxz`i$t^^8GN{g$P~LC{lx*E1Q9bAXyqlz)0lJRJ$41ie`GiCa_vQ0*PXk@XCF zBD&tVP%Wbn!F|mkqjnz{xklLG1qJyPWVCxf!V=C}7S>3w)-=JUA3d+7i@{G+SeE?F zJ3npH>Efpow_{>yiew?{EUgik^n}VNtgM=(-wYJpw*;ZN0T~p1NSOo^(Ll@Q6B@zK zNq-Rg@M_HKm~M4MxSUz-LTQIkjpHMXV`ooFz_=bv-=(GO%lios_+IcwGk*jue38>0 z5MFCjamSoz7GdYm>L&BJbC^S-W+=L8ul>S2a@DUK{2IX~prI%QasH$Xw0u{|CB&vm zfrF-bP3c|YKMU_FQf!EL4u5<*z_PSAdwITuCh<%MJgq({SNfiEh`1#S`DQ3H5sBK^%f~Y*h6Z9!cV5f!KYyT= zSqa_guDxOw^ExE4y^3+XCUN;{JwT_8AX%I3iwSi$2iFT(?$weQK8YL|tl8^URLNbQ z(1qKEagry(CSiEF3i2k1p(T>NN<5FKG$kUfkg$Qeyy9tHPxh6$C>{=kYk0llgaszn z*ophT!3Vp4H{VeL_!h|O|<^r3hQ#Sk+1HbXMZdk(;s8kwxz1BZ9m8dQBm}8G2v_k zHzxbn7}*Oe13U_zmz$N1UJJi|u1?A$IzGi{yYISp(ZVXejk%_T?oQjw&(Il}PTpLd zNZ`E1FaNoFJqxiOC4c&4dh*xZdgmSVr8YC@XpI87KftK(xR2imv4EVx>$Mi_);}PA+AyP`Q6>p6%^=x>n57Wq=gymRO4Q@6|V;4Q1^olJ~HN}qB+Okc=d&}ba?PR-e-#RfHRLM5Gn`^~Z zAF=Ki*eR8zYu%)Z_yT`gs3or&1HV$d7xrzCozUzTiMPR{afygkvCI+m04B<_E@=C<`ETiv54iq6GZ zGpxdG(%s4s`f5SY)|p267=~oIp=pSb8HM(B$B<>4bkgs{cX@=XwXCh( zmYWA9dKK6Ec7IoP<`H_2#XCM6^xboICS_*0_gbozdU}7{ExT1cF5Pq^*^k54R@>SB z<-hXfcs?DwygTnFW!;_J^VYlK^8P$6ozZ?YnH8jtrsV1wG0O`RjA)Q2@-ELz@_6`< z<$F`5=IbRgg47@|rmu3N;mR{-CIphnYCd+gR~CcG!cN?=dFG3Shq7Gu_xjA-&E9sn zKFi4I)=+;LZ=NQMFO_|Nzaw3~ji0$Co?~NEZto9WGfgXdNGqp0r`0)H*QfkxpJ#{Z z<9v>q*v7o0XYF<{suA2amlKayi^Ih(f_+9?d#XINgR!2B())sAaEP~?v!#J~{>n}B zemS3~&gEdcl?#fb7U}FV+LhMmF;=JgOo~EX3ABG_Sn_8&C)q2k(xoMF&+h;ObGU4pcbH(1jmE|jYYW|#>$k*^`o=z@r6}h8m8ImB{9o)ON%+D*e zI){IU_aO3q#T)^l- zXRp>O+wYz5LC$+ciG<*SVddO>?@M4J)6E zYojlnam@ryQTn{Bx%@z9c@o*@Wpl;#W;?-x?@pC~SLYNxHpl%XV??IXY`MHF-}`^p z%U4v^s-8c>l}5Jag+}>wHOV^avZcDTuBKqGP+XkX{`JcD>f*W8`O3SET%gZEcw994 zYyJYWxkug(e2#r}z1gT6S6A?E9Z%N&qoV6}38AY_J4e#5pfua67DaA0lQM|j#ieVM zOc{?}X}Un-PyiumAW>A3Q2d;KxaWAEohMM=jyP>(B zEw`^%BDLrHybJ#9xAoEX8HO}_Rr%sezoy9u(p3j@xDFo z@nU?~yV6c;kAA-YkV-4eGn z(LCOD>(>^GLf*ah$JKGQo6DL}Y3j}KisSQ4I>~>^qjlQ8SMR2M7}a|<0#jFP&+P8( z&dGJu$liDjTsIMt^Nz=dZ0Ucb+B3S##3!y6EHTM;0QM>@r z4DKU+!*?;1YU2fXj?9RRc_pEBZC+V@M)%CN!1JQQj2?j$s$1Y%d>MbMZ^Cg3fN@KTBx3}#v&;;KzYn!xJ<9xpnS(ij$+Zjp_epCEN(J}-)W zZH`Fo73I=eH`i%UTULJsZfS9|tb2A_7L993^1Vba*H&?}3%aG9(5L=h9Bfg)auq`A zX6+%=6S`xq+!2qS)Aw^QJ^rqTI(ok(do2`Y#efG!{J%bBb39s)ArBYeRecwY{5*eC zo)%LEtsoP)oqorPIKwFvG z{1ra*wY$Zuqr6VV3WV+r-}nCLanvUDqJK`m=P2I(pe54P90+pP{;%%MCzJA9)sQO^fkni?wE(h#(yCOVXN5)kv}j2d%rJ~tK@uF7lDG>SP! za#~-n3VpRK)xCRpCi+6{+y_8cKh*&S>Oscq2K1k|C*qU<-v`9M%%r<93)lIwzKmGr zURT6a>!z7_%gjI-*nue5 zt&8bzNfIiVw$Uc9A~4_AeW=J_bQ6#Hbk;1hPqdEyvIFCS~K1l#I9by5h-c zV*wH+=ed+4OPz;zdPC9R_U&}?NNw|N! zi1|HPvn-s}>UgTyXrd`gN!gOssXm;_?kFx|HTBNBP??{XzWl0>F%U-$1}T)wAMe{CA<~|I<4vH*MQm3Gb1tvyhsD{_e6$$`Fz$aIRs-$@ z@Hk$BM&0vjCY@^|PWJs>4c=v^yYRdx7k^R72N8++wlYUNKiE309qE+J%M1e+PGp(X ztDUt)j!oC5>8gv$!kVv%#JS}mo6ohpI%ak8K0i{j)el&lo}0I^OiER(HSNxUd_9dj zunV~Q#PV{ssh#<9x|M9-Dk6WaAT-%zscA$c1C`8nZ0_F5{qlG+>z!a;cJSHpVu`ym zZ${JAlrG|HwOeG1qPgLXvzSTB+3ccil{VqNK`gsOGyUMcvf~xi?=7tKZjSbjad0FV zR`Sw2J0^NQA6?eE>laKj^5b9uOe7D>B2AcYQ2BG-zrvQkHw*! zdjVuCQRqfpTs4lzBQ$Is^l6Uo!PC$Nc@#(adcjM`Er^>}sKkLnuFAov9K&9BV z-O);d7io5jXC)jn3O2^c*d$Tn%;Ufx+lTl4x|yAhCZo+Rh?irXUQH`KIgTpBm6E_! zWTvAT8M$M+Fog(nX)}MG(+y))*1X4ButlTI32f%lNztBIy*(Q!C-jQ^v7O6-*FPSt z*@)tZy0P!&X_(W|>7tyEsJ$RKw)5IL?R9XpqU(|h_SkNp^J@^aBBaaP82M#7uDx=e z06dkiX7fH@JteirftZF;IIACFwXuy#$-L{_EUI0sOb@E&uET%Ql<&uld_9=+WPEy? z_j)z+ifrpV;&&4-qZcnn(@EiHO4ZfMHC?yhDB17on6t(C;)!c=&l1BF%ksK*jKH3` zhpWFelU$@y6cro!zezOA7afa`G)jln}(Tc>s2>d zt}!VNOM4ZtbpI%#X#dDgnPh6_Vvde`eP0rOsk|VX-LgYK&mstO^Lom`GbqTsc>8t$ zEqj&n(PloYeY7aLYF#aMucfKZTt9Wi#HA?Ep4s9;@{@mDoadW`Nv-2F++V7z(`l!T z{D2$UmWl1{6cjvg7pzQQT4?y*Xu)N+eTJ{e^lhGGX}O;~1AjT6_-?$=7EAV8z^vW8 z?@D|RDoaiF9oAR(BfVtEm~W9^n)lc(5BKZny}ahT>!N$+J8kVJg@(qP7=>A6Kk9ap zrJa8R&;5Tk(VYuQNcq+;ba{#CM#-rcbX&FK_?q&1n=R&x@oi&6_L!b3M|n$)G~U+r zCX&MXRIt^pTGFD8rN#7p^HG<2@ovQK4{bU(_v>evZQ1pJ**ac2*BNxiBIC|cLX+_^ zy^K_Ua*63(t{$70mMy{q&6-2SW;>d`7k6W_erbO|9!sjHEH+X+1gxrQ-tR*CJr< zxjqw8N7Cf(o1sVn8XtVjUz?akbnmuiq+UuHItv9vs}Yf{({Xb; zzn@p@)h(6fUOmq565Zstdv=bmYiE3uv+ngC->3Pi41s1GoNJ*tOPB$Z)g8-Rh;%7D zCi?ZLZ8w#KkCN7^rKg#|O>b^O*NyGxqvQE9RqI+-FYJm74H>WwZY!p2Tc6LDBeH)A zl;%2qYR3ih?McKzF@2C{Xr1(%rYtvHO93p7ns@h4%IiLE+KF7Y#>_eT=mu10;k+i? zYC~KVaYoECX5d9)Ej44H&QVN&~_TEvUZ6 zW98thP6Yb<*Tp4#zLfFVPFv%38Owi5WuF-GE`m$s2(JZ4QE2dkm(w%kvd-%C49}?^ z=Flc<5bC(gI0sK3PO+dV?{=ggvdm%uo9j8eW*V54 zyJzaYJzN5p-b5>8)i1OSzXWWONe%95ZkzJDoW35DW=fU7_3gQD=*B#`?04BEd;~X3 z2{c@=>+Lf4Mp`GI^Ty3>uejsel2LQC-`XfSn9bt8!Lwu^U#e=U9`E~Ra(`J&Qnuw} zJt~)7bqkaeDOTW3>9&!~Nf>_zav4jf=9G%|!W{jv-OBHSG28O-xLGw+R_t^IH~#r# zzouDNZdDi2WPWtUul4M{A^vqnY|# zjukt(EH}^P0$O-7?gtP;`}MpOQSdlW%TzX#%`G`C&v}%SOxiZ#{=u#jIntL}D|g1z zB&*|deA`tTw{;0$%I%KoY8{bYCjg`6<}n?OcaOU@5BTJOX2C_@<}vhd*BYNY?Kay! z+*fpspWga1Tc|#lHco#*qQuj~4VO0i8%@^U*^Y11^pR}$ely+e&(m~uI2>8#8m!9P znQ`mv%04aT*>h&xyV^0r$wE22yr)=Xui0#=j9&C*B2idH`XoVhvIBZI7pu$^#S`T~ z2LO@T6F<+#3+$gaBby>}ORHjcGA(j)uz7NTd47mZd1WlgVU}#%V?OT~PS2SHTeAw(`W=BVo}iBeg8?{> z#{ek*+DGL-wo!k1Jbrgk`KmhZAkGNL!wG%SYUdXR4uF0cHuy+~T~Xk$3km@67J^|{ zlyZMz9Ng(9;Q$<}Vegae<^nIfggnP<0f7GO&+4i_yPymb9s(b|F2C%I(-|no&0@HM z{`mO4)#H4lGsJqyNk0sdk#in)JsEa60RUd#!!9L$y<30#vVTffR{_9g*l&dBJAGBA z>%(DvO99ZggWLo^yPOQWng9UL!+t6VKGS4!N_~Ia>xhS2FL4Dl(^uVI*Pda^05FvP zQenC7cQt{-E+zoL`LHXCP5O;ohD&(^5(7X16adf`cR0v89MJda%-)ofczkHyV21(V zNbS$p2-|-EumKhWBI@y%;DOd1Q`Ogi~z3^T@c*?SToxSLO@l(EMUCTl?j`x?F-bt$qw?`7+)k60)imR zG>}rP6_EiLhTu5cnQe1%1Gr%x{vXFcy_G8u)uoBS*#(LQxzGWhXNJE!8wFFWf>sQrvMM571u0Tb zVy|%$kzBgFfCy81Y@DDnF{m+Q1fdFUQ9$-q#}P$)I|-vJ@__|GgaE&Sgja(wc|0m3 zumpeT!QmD38oV8gtpqGklDp{-*J}`wxu9Q@GLoDwojL(ER8BtY&|iNU{rNs6?VK)? z$eUcg$9J^rkNNzg9Z58w_3w|hj?RYj^~dzKVVMhfW@sH9j)8A#z?OAp$4VkHLsMzz z2&dHi1ad4!8k2R^2P%-0bEwL(%2Njes^)*u%7r-z;AzFJ;_=$CG{Af_;;439p6*q^ zbqGWN#0Gn8qD4}Fu8cq?d;~~Dn6ipA5NnB+_wQd%oX{#BVf4OTRUan^=xiTQ9dn65 z;VEDPCq$%y%D4f>0s@gm8q3ru#=k#@?Ws}KGysAyl~=k-U<(+5<&2d;&_D&;2k(D$ ztj`Gie1_&nOfNvJ`5?vs0@REZt~Shm0+j-v!wl#WP$OV%CM(bHrFoX$ur$-Sx3KX=7g*yeDGTX@+i^rC>nnLiPO(# z&1jjb8caX$>(YsXXz_WE=DVtLbsk{lbk|eO8 zJKTb;#CMK^SI4+Tzv(TR5gC3E+Ha&&Io>F8sUJ4h0 zhJ&1=4FJWYs;e{R%eBg$+x*m?LlojG~-*7EGLmOpV>W-|w6 zXYwZfc?_qdKj;0dZPA}UHDG@p^`G(A8fBN^?>w9RzNbHDk)6$M`0QbAJx)sVb3IcK z(C_D@h6b~Qc0-=NnA{;c0(%ukstvMQMJhZk9`OgUEp&*EK7FfLXIF>=O!of@r( zp^!Wsu?@~EljfkX05RP{91TGcU}OzA+gj5x^b1NsKr|RIZ1P6yACG@*bfhrL$^;y% zs#FDfNK?pV6EKSPP95zzQ9;gAm}7`ovsFc;sQ^Q8Pc!XJIvrNn2H5r_iIU(kJz)M0 z{ftMQWFk>-RT%MjO-#UvFnQ&>K6ed2+gPAdA*(5APe+s2C1I&+b*VknkyGUwKyLM7 z^`H_bS|=umu>iC@gOGpkbp%?{HW~)9?FI@}TP1}#umLBO1mHb>5vZ{!0D{|?3DXe_ z4&5iGff3g$a8G;KrZ+;?KuGQ&7-D%!+w>dX-+2Dy-x=h1@u?xCa^HOMtsz$G%L&L? zVFZl~3gr?^qJ_mOhBzZoa(1Y%e+(64ks%k@PXJ{A@6-bfzb$_eMIXQV`e@$!K-SUT zFTpoge0&Z1uyFwASq$p^eJw)76b1zMy`q(<&ld36xPY;IXPuz4tst3X6bhoLK$)_w zw^+xnwH|hk!@%$q1MDKS@K`V$lVXM3Qa=l;77@lr;T`A#8jD;I(5 z)$KO>QphgmG6sMA!H+>&ID#WtG#JgSdAe#3SDl!EF&DDaTAojht-MLq{t}q#fsml0 zw};m6c;^@fz;COi#V20U&gNg+m)TTnW#okECyst&GW%ZFP!HFGy$X5&f3E*xa}vW( z&i#|CMW(L;tQlMfz^@iMpv1`g+Cgt7Co1GbBYxy-0(XB<@S_?w8e~lleHn6qH*U^V z1mzHOp;|?XfJhMxXo&p`(pjy8l%Gs4Lz_1nBq&kyG>0NHKu}+RFA5K2zSdF?a%Tit z6!#zl6wz7b_=(!e27Prw(931A<`0;y!6Y zz!>e%oAoH(ufVnEIsNxwpg(W-2fOt?n#PcCr$!N}2q^~@(ibS@%HWM@1T_YNQ77QD zA^v~HiUDrCkH6rr^Zmi^;3xNFQ=n#3P;&tg%)h z1hJ!nNWC#;_qcTDjbET<=mdZdPz8`36geXY-ww zHoxkfdd>?MeT9g|gNj1bO4ZiE`_Pr@^o)N$qf?+z{0p&&^(I9_k z7%}B;SMpQ^R)WE9G&?RUzzBk%jxdi@z%ar*+JnBfa9seFG9V({FE#>L#r_I@@*NDv zBL!`N6#-rJ@%lhN`R-d^hP>APa+?p%XtVb(&KUAsI{5LQxXJppxscx+m-fH^=EZOB z{=tyH^@M)-!o)#8x!`C0cP|o%g(H87i&13c z!qA6>D9iUPn8#|C8bXw&0GUU8FQq6UAB0|7>m zF=EBi$$m#n?V^zui`W;~uzS|bQ%3`&(0$2ghkQV%l?rzUE8c+STL2p}r1ya9AJG$K4SB ze_>Ea5UK6*bc2k$YgFGso0orxV_EY@dh#Z*rDi5X;-W+4sEHH-&il6HoU}Z^5Qk=v zA}ELr8LRA;Yz@)aDu!#oIn@)Vkt^t9EL z30eInLWEYw_gY@x5Fii;79b&)I&Kuhk3z^Xgdim*rwH<@BB&BtX=;B)uJ}5TZ57l6 z!svnh$Z>}_0rI$$5#d(cmlSxX*{7~W-#E#74D!Lv#ScE{u{`|;FNU0a)}~FnfwSdl z3*Wf)?W98@5w2t>qG$WCJ?$N(WKOWmHWLcv`Ok~4_;!QdIv z^N472I2uiw9ur2e=ArJ3=)yPzoSLBR=|IFl$f?m{sKL6=C)4p5pnY$r0YA~^FFXD5 z8J_8y&wjY;>|Z?e7vJLk@A(f08S>C4{|wx8@X0^=!k60;fen8q$;dA1EeWCx0!l)H zEXPdvTAn@imc0zYP3#kl;s`-jIi7SSAtb%649J*@X1ZoFid3%X@ZG$^lWgGGd}HL4 z1rdI_zPvGz-18D$ZPP^c$u6GMYl~;hWVJe+hifqq5rlrTg`8=a%Q~8J)l~=k#Zgpe z`Xqj17WFz5?(Kh;aVr8U0|5u*5rL_V2K@{;YC3Z|b}@?&FYCGFFaQ7Lm+8NG<@AFu zqEAldzx+`juzN{=V!uBYE}#-aA83U0s}E_YG5(+(S!ubTI3NZQ_0?Ciky$aM7W95O z*WQ8AC+14ZIDZmflp3$s22A^$W1ip~zyM7}h0abo$r#xN}nUJ)a{?u`#`G5fmp7JWRD-p?l5z*}%( z7PPOsf7_zhu>RDj?u*Mm`ET}HoBP+=K1S(BqwLt_lUsYAN)c=|PX!OKgXkpqQMiCGd z-s&6zfpyqMhAtG-$SVyoN*Jd$;8CAD0(ra;q-d%>p^@dT!To6f1-sYy1 z<~ti|I5+}su`E6%j@t4yQu!-quUtEu>#BnTp6GY;$FA$LUuD4d0SoftFLIE z{4>PKKeXNQKd{jcXBcWS2w5L*e_@-C-t9aHT(PIU}%;pb^;2;MjqyU;>J>>agk z5gA90Z4(`=IIoXx6t$RR+3>RiWsRff{H=dOP}@1RnpUK?&s89Z3X7^Rb)j1bH^C$) zBou)raC**VYp0#gxleT(YDg0tW^H{m{50F@Ahvj&?BcZf*rnglT|0uE0IC3o-Y&Y| z-;huKfeUH*lXp|~Kl#Q^F;IHd@)ROYGqY?T|KcA|FVf70iVp-XjUej><^BsN0SJF+ zyRpZ9ujk%hkKvR5?Rt#Ac-*&Mq!+XN=0uj3eGH7DI9q<209LC8N|i>fE{xY}PsmTm zG82I`pt-cgyfXAR{*UXO7JL!;brn^dSqvk{8&d_!od&W23i{FC8GL|Q3JV4-0HdDg zcu25;=ipBa=H#QpYs2*w_`{DCvDSYWg8|n}&0nu*o5c`l7Ko}?W1544ngAyG8ZY^u zpE&?r?OQ--!)ycK1|)qyBi1MdHTnl$Ec;mgH?ALQa;&w{5Z@kW?@ylm)tr8?=C@`H z@&B#a9}bJZ`0}G^4C?~bHsi?OE54u%mde%g$(pWte|sJQEQ*HQ3MfRZvUPvJ4A}NN zKu;Wc3U6KQmXWK^)P_07%=nn$gB{Et^-pT6w*x-0wn-5!v~4Z<tPyIw_Ru{=Q_WYtA~AD(|&$V%glI|E7! z%Ih=8v|tyV$n1GyM44A72d6oE8;dFTzYJQ0Tj(G>9^;XF>K}%S`FnE({ z--$~sCJ=3 z(;4k!edsNHa{&M0;+cQ`YyWT01PmN=ScgFKqd!{AAO0SiA3oJN!pL=2TNbJz5Ja1{ z$`OX?rpMEy-PnN-){tc?1kA#3WeYihdq8ahnj_#?v4RRC&Jhs&tW9ybZWV_VSKHQj zgE>Dyj*q&UN)C&BPyhl1hCPo5qQ)3f0y#zCtf(qb@HkZ<1Vn#BqUZP&562~^ksHM$ zz;NI1?v)DF6V|iGlT1J#fZHs@+0rQ*2Xy4_bZLM~R{Z6Y-EZIFi?Ov2SLyxlCr=F8 z>rd~13VbHLt#j5nKRgmp$$V#JZ$nM}^Z*}1)BTuhP*4nchNn(tSDewHV@H)S74poE zTdE=dVbQAcqOyo;PLElpU{u~OFih8gDMYpYZR z97Ames8(tg78309fYvFVDnzEo_+^L&0mf_yK>`Fp6qxd%=ZU$qBQ0N!ujxn?u9o+9 zWz^kp0D%?ueI5tg6%h9Nd?!wWKL4rnKl$?;kJ$)@WJ-T~jQua0n*YS-A8y!YKYDSj z0rJ7FpL{WMIK^K04C9U+wbN=HM^%djRso~E59pAwA#WmoQLbCE$>uCUKqNFw%CzOB zTk#SiUPC}_E$W99>QwFf&w?Pp3?582cSg*JN-N**r~*W#Lf(fk!3bpQc&$({HB;j) zO{wNv;go;55Q-!8BlgT9X+jFxP9IG`rSvD z`0=App8Vx-kY^v96{Np@X1=Kka`wwvJU;Zd&Vz3S;?d`L2vP&mjv+mtsc_Nqym~Yj zco}eYZ+{g-nePoBZwy?0XCV@>o{I7q$L=NXhICUUvB7%VR|9GVJ@mPYs zFIbPC9DzI@nK8FaF7DV8R(xtNx78v~G z&)@&(oV|a2vG<_&B-%$q|J7ta$C84)X>Y?`Py6y4S);%8eyB(Jp!0n6z3xdWXd_8Q zV#t3_$mH@Ch|EK6iV;gUhCe@gfK9PlKU5J}8s{G34g!J@Ew6OQBf~&_t|EK%ZfquT zk^~aB*Z{><1ZtvjW^Nfp=s2^GU_&10u_$2Vqg}E_>-D>yOTmYv^_&rjdVzxMidgMU z0fD4ze8?jUddn&JoFg(IOH_vMchtu;rcQqmA0cRZA4Y&j7CP42kVpk%!4}puhUwZ~Rja%8!kQ^?1UdK?7Ip=#Q596X)oA?C1SMZpiw0_P{^w z|Eb{xE&k#XpLI}y26?4HPEs|mRoIVGb7n%$ZQW-#!xy?E@X^S#Gj8PovU=UW&KQ5u zQ42~Svb_oGBNPgT054q5ECh&(RB+g%>jk$_U!!!;;g)fX%#SwN>mf#OuOHiMWo>GH zKX<`Zz?gb4I7Do&VVWMA6{pU?gg zTVJhn_T_aYY1t27LpeT)s#0Q9a8=VQ={%_ol!Ggjl&gg}2BL{sZ^N9sD(G_pK{N!q z)>hF4^qfz*fWgDoiQ!wf?<)Q@^tGb_K|%rgry|H)DR zttOB^{gq2R1?zYU7*P>tOy#^^yP%JOUiTkA%h3Y-o!>A7T=|}-@6Ue_Jbv{vZvTiI z?~6@_b#(f5?C*`|U|2_s%l}-*zj{m`|L^Vl!`r@fbI^C#&urI!^rjlnV>J0w16YJ{ z=SxPy*O*0v9URry{I?=Lb#}0KvP1l`$ysl22pN++odZask^ zfBFo(*EPZWFa7(I@A_FfND{64ch501erEZ48w~g!q`$qpKe6|n#Vp8xAO7@_{tG@E za%cMf;YNK9?t4gmJ|*w3CieL})hVw4iIhMVX(-370qVw^IM@g>w*_~U~##L%yz{&fS0A%;VGR`zKj6Tqrt&W==gvU1(Gn2-vCk#lXMU4@eR=Fjv0-=eIeIG=0xU*(4cCB~W1jwU zuD{}V$Y}#^`sTFWkH2voT7(^eAQAMW-tq0vp%2vknWJ&aEX1GQ z;@{uNF0&E%dq(2xd;Mqrt&8+rsn=Tn;m0kR0RH6@?+?Ck0J%7Ts#^K) z7@!3_u|Dx?s8u9f#adrCe)#Hf-RDKhN&k4#EiD003Amh=fJ?uA=SSJ#w|(tVTfZ^` z|A1Sp4fRXKZQdM+!5aug6>FRsppqerfaSKSJ~)4$ko>5X_u)_*SdYb^)~|v12NzM1 zu*;>(J+rT@D}e5ZZe1&(3>^|J#V2uHZJMZX=$H(|DhrDJt^GhWJG%|^6mS7c(oCqm`yYQ9M&9Z>u7)L2>Xe$hmHi-f)MI+3VIEmrz(P4XtZ-j z%_9PMW@#1C&L98Z7%Utu*H?^xa518BXzyo6{;8cSx zTlcXJa?;oIVXekns)E6;~N^x_}_Na}gqDv}7JWweEv(IqIr^ndlg83@Fj4IeA9cezZWXN&T-mEPBOjNfrQ|OYFN$Yn^;WDf;~+{&M1I0I$2fy_Zaw7m-Tr}0a$l`1e*aUaetO)W8uoWRdS^dz{O7$N?ytk{AHCv>dH=zPH6HkkvL>k7 z_wyM@mG`-NiX&a59t5nRAktAkf6-&RY2VwV7=l!#%-BN70ahz!KCD{Zr-3SD|F8Uq z5vMK&RbRU`uj9Jr*Jd=s4&d5L4;z11h>@R&o2P3v z?}Lhh+Ed0~KahZyg0%0~O(v;dW(UOS+j>WT&kg^X5oEtQ@{fH!@$zfeEY@K9>l>i^ zqfLG79&0dLe{1!y9>08x4|Bg?jUk(X7a&M5OMSNn@=0p}LTzNGN55HXMQMMZAZ^fj zFRA{Mq@e1}oN6aPVeV@_Da?h`s4zt>($*+W9eR0eLBD(&jOPxa3mrq)0$R7hC{k7*N}%It2C%u>UQ7w2@H(h8ZCUWtD*%PxUjmA1wjeWxN#D7&HK^`}!oM zXaC)wEHeOOI|!OyTT?%C1pN?Cn%i-@bRmI6U>bGl$vS^yVW5goMqKC&qL&T> ztaDYoRKQ!zaDW-VZ;R+%A!gVhLt0+-_ekj(#8(}13RtfrE1`zPP8Gv^#jEEbTVRzy z8|EvjAN=;!u7@1a=MCKFW+CH$-ZL`f>72lS;I`qlAKj+MvtM28d(RO2^3t8D_xe}0 zHvp?l(n8Ht@mha_N~H0M_VXFKpJEi%J%;J;DXAf-dkv9*zW3bcBEjDt+Gy&V5ybTW zVeVafTUDNZ!LKqpug+0sWa5w&=XrFbslEWs&2BKZ@tcv2lLq62BqV9@XukWX8ar{; zUVHzaa~n;hrDaTm`%+z9*I&6zMaE}CWw9-p=pGY3H*tTGX;fF1AY5@lO0@_(RdSWP z#twF`jr>Gp%f>o0_HqI><43g(yU(k;<2Vr&j-mCaiedt2Lmu??F~(!uYqYy0DChGb zPSiR1_O9SRre9se4HV-+RxT?4Z0j9ltsk}+jMq5%56E%Zd!WTJy0nd7*ilf&kM{g} zDkHijwO@brwv$UfrJY?7bty+(N326RDles4JVQCI_|hpHJ&BJ6@_{Hg`%zBv5Cavi zZaWdN>w-8!r;r22TvDP{<`_NrWFOJOfzR7FGA0w8w`((Rs2^cG#^%W7cYN*1&h4Qb z1ctvBgUwJyOkBjV4EB#9*Xg7eEF2;h7|ZBa<{5u%*PC`~I&z@q6ztxSlEdTeh{z~% zJBv{jk$|ek*Om{uk>OLcUiG$5WkDR(zQlDooPJD=ImeDsF=;d`^VG`Qk~GQj8t=ye-IcFnK_lRE5tI=^I*-Y%#i;@GEuJqv9tv z9H7lN&gj7Xp`EeophCprE=*vtHt$hOO*>%=)UN$JJV9eZ|hi9y}#`A#%y=GL`E-9g1 zmoHCFCz;7-kuBP2=v488;DV50w`C(tm|6^YK6Y68E~EhVy0pTIxX82JV+{S*9={^@g==#@d!zmoTYIvRm^H18|K8XDP5k3Y zzwqadtDe`Ls&G!@IZu2RyCH2b{*Vl^TO-18v00ZzMx_#76}7Z1Tq3=>4>BN{N5<|^ zI*G^YsiV<$+N9Gm=R{4Xd(wYwV9}iHDH;EsuZ6dN2}97CPo!o{3D3kbl#p>%j*I|0 zYtTlHHMUQ>_FzMWRC*M0`Wh@=Hu%i2e^&$FME?>nZsH#-oae{Ej>^w*H|KnoRrKX= z`r*U#hMd_`EMGd<%TXq0DyqKrn&J;cZuJDXPnCD&f^=d_ZPU8h5mkS$9Vvqa2udHf z_t}A~(QP6iWu2eCJ6N?btX^(GX08I85vgB;KE=F&C(te0UtIXG z9jaDW?#$kS%m%rvM84ssP(S_blQgzIc+&^1+8N$oYc| zt33)$?ocfm2kw#peY7>(p-!r!8P^I`m@EU~LOJ17<-Aaw6Nty4bDt=C4iX5s;Ye$L zJR0Q~qT{x@W~je7_`8GO*&FPZ>x#*Y+=CsH$G2ag+cy{OR7x+Yu}fo45~)TbMIXR( zfN@BM`0;BBCVqe1xrixSMWxaIZ{oc;=bgDu@)e(Yyo~uf+2uS^M&EwcAF=zzI96Pw z*KI!+lJldih_Qe1Ze7JsJm@|~s97BlYcGGTL#VXtV+Mz|h}Vg$WD!+d zWrtW7O{2{Gyx{x@#Cf1KNDbnBuHRhw`}`o?z%4Rk*L&R;s&nNfed zh!>6(kJ4+!2+K7AE|_d03IneMHC?h&Ft40^2KDWl^v-R3ux`9my57l0<|u_e{gua} zm?tu$&N_eKrOd|>kZ-#$`ViF&p1WVpVjX(j)oR+cWVLVCgtVNhrs0eH%}tbK(tdXP zg`8`ozt!jp#0rWCB8*GvnjtR54$ytluK^*?S*~v1KRM(Ck!%|5%jBc z-V?uWn9MwPO&V6`N>F?6lF5@OtzA&6DKDMdppt)ls&(whOfVi@%?M9f509(o+IPF+ z#b;vYRBA``B#X*U$P2nxIvAt98lCj-**zEPFLZwzPtpH*jnDTbyNK2P@7@c%+>xcy z^Pq}6NL2p&+B@@m!4kph|DpX66)u~^P)eRJ`2{^>Xmg&C(RfS}ku8%PWohYAxeH`V zL&$%hVHrI$$shUt*2#L2k~F&^eN~xwYj=xuv4KK@&WJ6qhc9Dy7rj6$d zf8(Xy#3TE{I>oAb(NSE%ho9tD5fPb3j^u>#hh#qYr%peeuG!0!Bz`y>>jzMu&w|vI zw=Z^1mH(QO`@8wkj#!d86guWHQcd@Vc(ooEnsw2=+ht)e5lasyn_Lx%FM*7%Mx$7Z z9NsKgD3?)?3N3$`tcjM~m5t{q?sLdDFjqE_wU6@E^w@GoP1=>kl~dW3n@k=FT6l*?TILvE@0K|0Jj6eclxz(=({_vp5cZi}(a_GKRgE0g(zJf9C;LQYz`m^=h?Jq7hX@yfcG zNzJEZl2Fyug4jDJ$rf2T>D|7#3-{uRNWLQpUpspLb_@JwR$JGODhj8wbLiWOR6Tb) z`{2m!fs`C$dX;yRWP^X~e{pmLzKwVd8PZpuMZd*^4tn+3CN|IKhL2VPW&N{kbB^=I zocQc#u3&L#TRz7rfBP(lJxAIOmU7S6P=iBLITyNhrVawjs+cM*Kx*9oi%{5We}Ky46D;z-@EQO+ zK*YZ)(3LExzgNF#r|bu&W-Jk#s1q(A-UQV4;wT!{R|@GV`5fIsZqauIG3F^?d??d} z@q?Z5F23{n@)O?4V3RezL!B>3nIFH;=1c4)v**U~amf3M=lPJwbeS8cc;gc5fccYd zGO^yP<|UkKA5`?=66Jx6M1PdDoF-~bpvZz+hWyA!sLzLc8156zX;Paxb3pW7mluI5 zsFx@e-U7x|2nx0j&+TZ|Wm766XN8y^N($DOlFO(IwD2)b{L$0Ik+u(d@xXLO2`El8 z3Gg{OjE)6qR4@i;F|SL!&&3{nv;!{2*Bs%vy&(?)b(E~S#0dFg4uAKzt=7E5(CYpa z&sd5vB<-gl^<&ucl^}@iW7`~qawIBSjgRM*Q$@EvEhc`_&bhKXLdYWS8WoqtEUcon zr=kdq?KOIJAU+WA8*dLgH?cbJy`IuzQ=#sSaX>gPw90P zt;G=@+_FfGyi;a(RDZft_iG=Dd)$W`jdDz3{M62ngEHoW&Avk0@roZ_J({KgK`Fh7U=$`@_DZaGOuLigYAJ;?T_U`s_KS z^$T?BF{pr$o;Q52_e{%Z+eMU0?opB>Pje`du8|x1Xv83j$bT^rB(V#wq6JrV=qR;u z;P*W{$cv=#C`;fe>SPYrqMJ!sxRk#Tl?e~5TcI^`*hFxtZK7MBR4@-rT!Ivgl!c=s z8ut@dKvA)hlgv_UiZKF+uQ40hurT}E#H+=`|4@h^GoFm=w<0)TWonwZ7_z)l95*wy0 ze&#R#X7i7K<_~=523_PF{E#)~XP#&7&p_GKk@-bFR)1l|t!-pZN_c>I1H9vJLS<>% z*&H!OptmQCtQ}w339Do`t^Fy1<{jglXjw10YBB!7!)Kv$7E^i;?5L$vi_VpT%<%gp zYaC*iLPe=lPi#`!9+!>hC-uUs@+XjvP0D!fn0QV#3)AA0O3or#pv{8@ps6RDM_v}Y zDQiNPm49}mbO2J9E-g|F+N2=;sZ$(%J!u+NtevA(QV1;u78Oa85f%8A;xkU_=hjwIWI-6n}H~yC?~I;qbbBAb|84eat{FYgxy> z@xL}}r$o$zA|stb+gh@it4|4&2`|^PDdZ2RSCBqiJBj_|D^4CDpP%#r!FuaC)HQ)4 zN1K`pm5Sh5F2(#%{_|X`wR33wM{-Sl5KC{E>&=rEvq67Az0zN!Ug;=!Mg2jPY6i;W zYk!WvbcY`}JB6W7r<0f1W#}WUhPmAYzMbTOd|-|io-5WBCspHW|8AbOFJ98Pv6d^E zOl~-_Hbn7vc^wfxoOS=Jqs!C`Qn?O2txUg(H<~HG!2O&k zl4HL!OWiPo>%UlXNki_LD8hEIr#>C`{gCqB7_k^h3O6&)1JLZGX|t zJXaUGWa+5f=neU3as_opIte}S0_D7`n2PXQZ@9=CK8n?a{QHM^@?oye@q-xq%ZD62 z+INBtfvlHG=JzHfYO>0*#<=J?=AUTeD_!0p7dOolg(Z{yVb*k zpG2NWYVK;2Pw~ZnLh137o%;AM`H#`9&Us@On5paw-(mWNv--_jW-Mv)3tl0oRTR*D zjgE=W8NKFAsSls1$B4+vC34~DsPtv#1tiNZc=n^o|G=|y{*H9Hr;s1~WPg%6X=Zsu zbuN)pmPWk1jb;vMHV)+U=>>ECjUQ|=8YyzCaJ(kI8S~oFu5emAX)x!^zcaq*$u527 zp(mNlthaN4S#ZKZ{FZ0miicpK*O;T^Dt}F=c=Pt;eO_g0P{Gnotd+;wj6&l%G`ex- zb{P2+C3?FLE4lWRyk&FkJAW!msOED}t>stkXVR;=mqP1yQQ^tvg+mijr98Cb`)soI zyvC!|r1IzD!L8~+9(o+vuxY5$#4~v>gI{}fS~rt(bdtxvawUFX%9Zk`taS1bqTYPU z?_y_pYT%dKHs-}1<8~a)Jt{K?a~`79O1X+0zbtZ(#wmf?CsOdRvVWLQjZZV;V6`3y z2b78!sX5VN6V_rwS@Fv9KEOOV(nTqe3qRFz?vZB6M18g)I3Pt-i;Oc+GpdE>>?aNb z%x94Sr#sh?-*kUKI&jnvJe~77`6b_c=fa(G*~A6y|2TJ1?n%GSQh-iDJ-dH>pF{Li@W|1f(b+Yp4fyMAf$r z?a(~+NOLcAy>e+I)Nz@_(vH2ZcscE#z)_RMTsFif6T!-;Sy27q?yZCp+X2lBqEL=$ zb9lT<`yp_@EED5*>K7dKg}Y)Rq1~mu;2?t1(m|3{OWst8%(t(EM_!^5kJ#2=e?j>>T0oJ(3hgh5 zIWpK^E^)5TdVlWoe_-r?Ls!`a=7E`;;Y|9GYi4}vXcwlBd;TE$Ogpr&TNGL>K~aWItXoiG?R8vI%mXY77mg6a zDk|cA^b&34>zp)^3vCqIb(tLMYo;vAN%E82)-0pCsee7hZcP0;CfOo6s##20xv{Q=I5L?CN2j zk2zhU9N-vyu`BNfzS!T>?BDUjnHE>@jk)Ds#DCdeV!;hK31;qbZy2m75@&}b?xYZ9 z6OwP+V8E^V<(nVc71gZ{sSrY|jOyaxCaQpC&b;eeM~+27dJFwLD@u4Wqmu<0C{6D&!m! z0B?vBD9$;YZY#D{Wd*pmg#pq#9ybbnsW8uX7R~FIxUyCe=CYaG_uNJM zCr`!7%(HCaS_c%JEWYt$x5obFf8{fr&g||BtNa`{`;BEh@B-pvJ~!1H4mSD^*MB0F zQ!mvqkwu8O_)*UvDNG(kXV2W;imx%Bt7~4FR2*cqaI4y<+73xN*-|aGPE{b@C}Bz{ zc+Tm&h7gF+Lo$Z)|NiHBVPwqX&uftOjZf<5Da|)xV%t7x>bS}`KKO+=s?zP{jp&+c zN~4X~t3Cc+4njd~(@r72slwmeyMMYR!|&xkV)noHGUk_mPY7P*lstRRwdBMueavc(GnU<`15~kvG*?27hGt5=eUv z-Swv{EtjTh%_Pc{@-xJ^aTR4Cqgh0vx!>`KNWCM#cT8Iebevon$ATms%HPG_$@ErgOhU{8cW(vo`r0_1 z!GdK(MZ^QXWs(;lqrf4J3p!i4WjBi|D4l(ceou#JiFsu{WKuAxF$mWoQb|6Ct(RCN z$_NulyKpsl7h*wEu<6o%^^BY24uf5aSF@$?5=mem>04C`cE_ySyqAP!z(4e$CP z3$bt^vZy(9)q-#?tp%5Y6T)NMe~2Rn8qESe1KGLp`d<0TwU~46Qazc$ujol$ABdz< zahdxS@YL6br}fkN*{^jjp2e+8)E1gVJRI-ooAVxcWj1xojDK=j_@ojCFfn32DN^uv z<1Sq*EM|?lAlj!gr36?e4fU~;un;^<5L!{GuTc~F%`edbQkkDm(M@eqzR%t)eTptDoZv z<67>sAZaq5$}5l?ZhQ+SmNa9|Ts+LP2IGp~LeRdWt$$?c)RM@27LX|M$|&$v`)hHO z2SMAMS7OO@p3F+=(GCRf`K_1OMMR>h$N8Km>cJtzVUy>p`~G$wuy#xPdl8kE$urA7 zM>bd-{q{ES95Ri#khenan;0Pa#%2A&iOElN|Lt!@y%FsV-`GZ9I`j|^GhiCI@QvSk z*2f+5|9^f$Pu~;jkSD?&aY&jm`msckJ+L|^VV%W9>Gi`n??L7~tlnp{5(1v^Fv$st zwM_j4a>UztW0OhHsfd*yj$elN_OWf^M9o4Oy*`nNpsX1s*}{)igP7Ne(^)%FPG-Dp zHc_8b+VeF{+s~P@6RtBsYgv&}r!1L}^+Dxboycd|$y44y^=>Fg?i z=Yqxn8sm-TW5(=!P)$d7tzIEY}^vOIBtb?5d*M__xVpglVrWAFQCOw z`zFTQ*BWz!VwPGhtu$e4zvV={_*#>tmYkN7EF|{>Og^x$8&1T#(3&h7zVWCirk%CI zTz^S;-puYgk+`IN3~4*(QhX4!XX)IIRoiA|_AlDg&=OG<#)H zCMDT!M8eAJEaA2Alp^pFSEF~t!c`tCcj-KX13&xCq#L7LK0|r2hYPv<#4pSlUAT_S zPqAqEg&*u|4v|k=CT3)xjr}V6d9EKfvwxtf-)9*2-`lwh1?B~Hu9iO51tFb$O`x4e z^9kB(KceBj_6$b2v0-Ge5&v`i_=;X*9>%-rfx`iDuB{M0qAc4zzDS49t-IFMwRg-vgI_B`WI;XP zjFu9yktu=6B1*G{9Gj(|>dqWJ_A#UrmxG_pELHKjrDB#}b2a%4A>)ut zawc8k)ltGt9JST^2a8i3xq~d(h<|&;g&MGOeC0K%({-;a=kQ|c7D!Z`6u;3}E26;q zGdqvw8I}ISUSnUQ375rB?4usYEX~#+uf43C2K(qI-D9k_lMMR$*Y{PHIhVGW?|(W$uK(>P z#=2Vr=HY=HVu(29Nts^fl->9%Hz^LB%g4FfRi4ZvaWko-%8p2OoqX}(M>~ir%#UkR zr;G?o>&EL;7D%xaq*?F-JQ7mGDOFovs(ZA%Pp@A>-X--R!5VDQG&&v#>%`XO4PxTo zdIx^RN$Qkt81@>`5YTTMs@m{zkn zhRJ}3kMS>q?rl5b9N)6P@Uas)CHi-)-Y@y%ION$CV~~x@2*g2W5rXwZKm{~GTR5Ky z2JaCwY!$J}1eKN-NjYC1Cmu`NUtuM3K?)X3B6r#^peevJ@ir0$yXzOe z!x_5(b0r3!-3cEC*8#GIZvfp*SwN%+h_a^v)z26cL!M2H2JuXOe&EH&!h>G2A>TS% zIgoh-;tX+P2sM~N1b=2370SPZrwET^x77nq1*E6g-s2Cw4D(1rqLy7dV09n>R7G?h z3e4%j90AHtc?+EEly`(Dj>)jupX#BI6Q=0JzNH~49z4CAGNpVX5g#OAq>Jb$u~t5j zd@c*LuVhT-jHvjID73Tk7Qupl>EIsi6Q*v?kgsA5dZkSV?0=uZw>RK!=Oko&>%c_# zSzX9nOGM%C_dEx;0hi!eUum%Z}65d9}#~y z`^M(~y(Z2jX1JMGvS7`V+(S;a^jTRu{E1IUx7Z17A+|Zz#3RtOkAB}QJ!QEZia5R& z5oBs365(@Q3xBGj#MqN&HFcEx0B;52J-e+g;IapG}Z$SGjX4944_>=Api z6-=oFU11k`4EBq6z_?h{g}^hnt8t5|9{;(7&q^fP9>J2jKo@_O}Z9%PRqM&DayR!x_l;3 zc&$1SJok`49i*HCbd2l*4r;f&)v6!mNhnwPzM?|k6Xn;q?&&~$F zGuD{+u4lRb6XxS!fA`NdZM4Cx$u8uwZ#=cX$J8WOKQJ{h)>_R10{5|UeOSpM9-$NY zE^S}e=wCfyF-2H$xH33#UwD5+Htvnge3J*)$$u9&g_#E!TPVqBr!U$T^c!o=w`*R>Qw>-8M``L!H(y{#`8juzsbWX6*p=eIIKh=wcNq|Bc9ON;=Gu&*>{PbkxkR zN*Vb?N90~*;j}zN$syewBa3zjOMr32i^d@aYb*DO3?7MkzSql|M2l;EG`PjI8eL7; zBY)yLkQ^(|KBByo?0IACr^mDXG++Hz&)}S!;{1#s|4U88n^+At!w6&H_SyI{#^8I+ ziyK^La;}~6or`va-GVQimyuVtS@7{tZ}MhERknPQZX#=N8M7zzev$~8lNnWgYDH@| zYaYqxoh#IIj<99~vJF?cAAoQjS*JuY7s0r{8LstO%{N{DppZ0Z^e zAFLNCd;(5`xFjBF11O7-R?!2MXv;)7MG1bbYw;v9M`B)L{R&A-in+4sUaSem9%7!Q z%87$ENqj~|bca}1s^OzH*geY#ZI6tDbbjRa<}HJEQRh070}hsv-%;RXsSfr)3&=En z`+BpymUjWE!AA$ZSJ2X*C#7hjMaNNaY6>H3My{kqag4147f^p8tfDH^XUtCWR zcQf;;GT7CqYxzWbPqbIBrsA6^F)PXVX%uVIHtQUwCJ)h||18 zxuY-s38#7W9gA~14=(WNE^vJ=a23yIO=K`S{xx3e)UG6AAsQS?Mj?Fr#!cpAxOc`d zYc`u|U0>qOL0%hd(?7RECLT1jJ7WM};FW!0B@^)OZ+_mp#3tn@>}C#+HwDPQ!#IVn zeC#ck)~pI2e>a0nVcM~kvdFicA)?W~DYu73kSf8R*EK6vb&*!>tEUQwlv%{2q6>{a zk-N?4z2;Pl0J4ZJ4?G0)hsvD3q23Zt7{$5@9ruNllSt>hYHGw{XOGV+;=CRcN?h;?j#`OtEMo2YdWW*luV zX{mYTI+XrnH1{E{cuY*JfDD<+r?cbB6G5;IVf`7~a1QrqpMAqEe5?^aroeiJk7%F0 zS?m08J@ur)RU5~bEv^a}e+QfQU-rL8E^rZ1W=DJF1r8fxTVoFD8SCpuJ==BH2wLCn znarl%OSwagKE|5cZ%pLu=CLB3o2XNbNE>rNJj6R8N4Z~_81WY;|DoLG^vFfa9Ri@Xgu@ziAM?D+?ih0EA&gZU72f390D?TvTrVk)^C zQ~OUCK*$>`Mp}<(j48Gs6DS(ezqk$+Va!Z@f#2|}&-kIi!^6s8KE%;cDwkL@uAV#N zH(S-erjk2s9^H7P$QT*oE611%d~4&nUz>cB0dJ|il*eO}S6_T%=b1W&UvXc!c3_f$@3^1UxWS}}W?G+1khC5T%y`IzeH31kz+ zph*5KzpzN1`R+=1eC@)3;WRr=I;S&rvm$~;RCT_NApbR$neV99cfhu9WfQUI3mxN7 zezGqfA0d`_npW~%(0u0*)K}~|9qJs|Zk645S+h2}YF_^xf8LX`95*I+BV5%pzNiDF zLxyLDR9XDa3z*ApsDpWqH8(gN=%`{#+@XXiyIoD$--{~9Zd-o&dSm`ky!w;<_^j>n16KSPYm+h zgT`MxPj8Fdf0BgB-F(hxqK9{iwpN1pCMZ|gjYH7hy?C4xlxgKWt?HGBH3OS>RgcAd zO_I$tL3{x86SwXQWQddP;%8sysmZ5PMa_@JRY2jeIjrBZ%#u$15{CzF@v24~J%@t+ za4>H~T5LtFcVcRpNQY>VCZdZYE1R(H1?w|HuGlR+f9E6wgc?UXS2WZoX2q!{MKR!^ zJc*b{&%#o7SDy`|nuot(QD8bVT*>qaQvCzhg8#s^;L7hegduL0L|luTtI?zN=l4Z| zWZDf)U3BzAci^4vjVGP$M~=nC{u@K8AAG7GDFqSD+t(>*kH~yVpZJ5LJWG^z6{CNs z^qHxTe-4d{KEdz$=xhrML0%9yf|xkvDLK~}G_)8kf5aA?`=N6(E$wejrF6a3(Rr#D^o>)ybG!+kGZ*a`gguk!jst8CKAzuij(_sBJ z_yi|~25_7kU?#8pMS$&G<^lh??!6h08}+3+)(&Q0-jm^Mc zqsfVa-xx22`9oQlDA*%y5qrwu>n}w+8ppcZP64mV3E&ZEufrSYHCxHqf{=*MWb!~f z%^N*$$h>f_<@$-dXI`ovCX{k>ynvK;0cryC&m;jSEEXYI&Yiuzg5*IsS4Hk6W#)=3Z_0Y=uCn!K*IcUo;Pf4*1L z@BQ5J3wV<0_SGM&XS-5Y!K{6G=%3etYF;IMse-0?eed5s0&Ty|tB)v{*lm<{@8PU{ z&wG0tzSy6%y5bS%`u6DDM(ezLXWl+ilYYGqZq4k<(|XMAf{}cGWXIz*z=ZvRKm9TE zFS%sa&?|XbH1&1w7cen=%&g%We^*pd22U1z!c>E2u@-0xH#zL3Q$yU6v7{C3YVg3H zK{R1IMb}uIZ-I7hry*+~N2n*@X@3T;rgKduc%6M+gN@fa<n&b;_VB!U zUpxlSqI1o1{QVb*E8vPnX#YI6c-;cC={;V*7YHLYf*@jOcE%u|82ml3f0{jF{jj$N zB*+dp4EL`KXds#c=WL;=g6kHf3<7X!<^lbL8xCU?R}kmC0=9rL;zZ*$&<^##rGzCo z^=O3S;VJe%$Nsy5IzV2al(3dx*H5r!qdP4!U>VMbhtDUE}p z+XfTExey0Lir*eI;dq}MSbKNz-ppM)YwSM-<;h5mjtZ8DkT64JCOTUwgAvBi?lNpP zetsE7*?{SU9$2V@e>YRZL|tq~B)C8$oV9y!aDK=yteepQZ6E~r0OkT31vGntnIe&N z=CChlr^6858+s$B8Qd!Nq^A$?3s|G4Pw=Z&4u!QKH(0I6^u(8N4{QP}Ny>lm{?xo* zg+9D1dIQt>Z|^_AFQs@7xgf{UXf)c7uELT1I8vkg(dg!Lf3zLly^Y$@RXh5%8a>Uf zypipV9!B@CqhmPYpZ4cy-q9f>6m=zz&WUOMT5nn(oikR4~c~w$v*Gn%I$gC z0$H~}n6T2`f7Hhq6B=%TgdrwlvRXE}E2783aoqAu*SoCjJgvqEfvN^9D)G9$9o3fl@R=(*-|?1Q)i z$ei-9+=?Ygd``T#AlnwAx0Wo}l18QIUG3B{`)ZrCe`-ys)(+K#t~YI^2+Lw8x0agJ zi(G7h`HMrkyjG>?`L;SJ%%qn~>SFTzR)k<@jw)MLu9qq8Kwh(C89Vth)qz8DvE`@t zWeTHM@VUr5#~^c*ndj<>D=cWdbOGO|%=_R)xjohK0p9`RoV=^$;;?q_fcjgAKDZax|;TGKRG^fzFY8`SfuZ3zs zVOzvI-?oy+(pv1z|93!hzSy^ry^54-$|F@(e>A}Uv~zI$EpY$fO7P0ErAw)Ur?%<6$gf9@N*y2R*Azr7k9d2PB^7mxP-{pKmTtc;=E%2qGhkhZKA(q&S70#b*UIQVTe|^3M z8B~1Vf>T~xBmIILQ$4&x9ER_a{_k0GhvVNNANnip^i;DN_nm~iqGnB7PSkRVbQr5v zq9r}XwPh_~tWn<2?mNw^p=oZg19PiSy;8f9-oqinf(}5%gp2(!PT-dkeR)4nxj{`%T+QIo$92 zjwI%O5r*6y?ptju3v=JA`i>HF|1k`?Z|>8!#d$uje+z4sUMIQe;iCm-hvx_G+mPx# z(#&~ZI!`2AIBGBGFAXbhcucs3_mD+H#heK+IOTk_g})0i{U=bZ*A^} zl~%J5NKVH(?6t~6$a6~Ye{3Q-pPI85_g+iwS3FB2)GYfC9U}i?9Ql`L_T@j&nHY0h z^mvvlmGq!mxMler?n&g+L@q-DxpOdUmD9MKlGdzGR9(=ZwA~~NG$b1xrLP^4e32}a zUM6j2+V&b+n7sW*+s9O^csqZD^Ub+QYdo7{Pguo1Ph&R^!8PaipJ)uv=Kd_lBrJF3zJ&$Lmx)}4z~z{4&9#GP z+ET;QALc%dl#w~A*v;o^EAAkW)<#3M)U-bJV~O;;W`E?je`DAW{g`S}BX8$#Eo8{A zQLdnWq8UQh0(0=ue5fXcC41&Ks&HZJY z7Mi`R(4wC2lRNBNTu$j&&#E42RXcr5TZj&Lt_*ACYH*S~tYCt&CVu~Y59c;J;F)!9 zORA+N>B1k*f2A4=gc0o z$m5A~n!{oLo!5QrYDQyvrjr)lSz&-&gqg^!?CY;OF(we)v4JA3hK5htECs10cbD>?#}=0dD5>#q1dnQ7M!<9AHE?J#~aw6llt5A8mYhGw+=<{KWM{5A>h2;j3tigc&nTF$Y3 zKkQL_=0i(dCoe*I_^bU6W#ai)`|DGC^4&hi_umKoH}BXP+P2ddRYWyjP4v{m(J^N^hEe-BR@ z&S%~Y?ErSP?TyXw`@xR^F*8T^?{V=2Qt^bd~3bIkSc)ouN}ZUa`VCbrXUR7 zYGcPtLS92&CU|~UPIZg%Dr=s00k|StR5k@Fmf@+bQ*Ya}AeH0f9|{wRIG3W_FHX+^ zPu6I|S#Gl(C7gq@Uq8Sbm0RHZe=VoL(<50*7kKg?H3H`7mvZrcV}}(Bw0wS!MxRg` zxZ^wUT67Lu@On48LVsv6A6?BRSHt~aJi40Dcja+3X~xPtfBLJTP?-IMHIT5Wu^XSS z2^w*m@B0+ve&4^Z8Sn;<-|acjhB)8%9pC~j#OG`GxBD?XNus{5r@$n;K1DcCcLD{F zTkr&IBzZ>X@(x#wD#$gwpxrl8pz+D6gm?7&L}>SBxYC4!n?a$;3%CVr6)12b$jx;I zTSfMlT)_$eR-JQN@RGRFA~71-uE zoM#?kI}IMv=dg|&_-en$IuQb($Muc?Zn0kLd0iqje^ZmscR2OydFU6JgKMr2c%5r< z0IG-iHrMbmydNgu6|mFf2K%!$eg%oY|BCDNfUX6k6Gfg8Cohl?{5SPif_2&7DGckj zG4pEre@U>Pxg@orS4nRF)US=1M~?GY{|r9yhrTM&`%8^ zu8${Rt>F{Ljp>yGpThSTKJba}DKy!i_?R~DNBSQ2LwiXdp(ZorEAy9t!wMh)BA21V z3K=HgfOt2)Mps@9fr2-r-%#TIoSgWrKt5q%Tnf7QkpE64dhuGA0hi#z3KoBtWQy~b z0ZFiqW~Q-o8PdfHJGqo(WBistcHm;nG@XKo;6_miK8H#o#dEmU*g3=wVL41W{-^^o zhp}b_#1@Ptdjwe!3RrWlAyo4Sq(zwGGwd9fw1+SnT#})Lce%UXKGhmyCdkd=V>5?7 zIu_n;dHWJEpH0vA>zJJHOG|$^$=G?{F8QflbQ{AW+qerWm+L5BURP_E)1_O}%&nbl ze0avTixoL;mfh!8#d71;Ec4=*(>srHUc<>hO-7>$F#TWu>wo#*9-FtP&HI1;Pw#IZ z5AXfU!+-iO|Ih#V*gU`gACH^j;r~8;da4fnzXhB5!|MNvHr4aLo3DS{_x|wkZ`J$e zP!+>B`k_+g`@h+i_3!Ol@oyh*hyT3Wyl?&uZ;o{H_&EOe?WTSBW&iIx>)wsjDO891 z1wv*Rhcr5~xgh__pGuwpR4v6)Jr#^_K^sr5g{yYJ$52UDf)15ZKqxqsCp^^^k(!Hb z_jGW`ILxQOls&#l1KxiuH{&ex*QvD}d850WvPdS!X1cv2TsHUF(rT{a&(~ioc~5`c zCzJNqIGiXfcJg)=*{egg+gW$5?snrgq)us5?|ON?JKlY`TXOsG(z@;PI=MeS-{;i2 zs`joQO)Y=_d?lyHU!!<*bGQ2(-QFLP&RboRZk}{q;XTUw<(GfT%fwX=Lh|de-Mv-h1(2wcUIrg%gCQ`-zjKn=QV=f ze|CCgzd>flb$@>t^4*N|ur^s!L}VD6!r+_}W0m;s`4~yAilU32h;df`n zzCh35ZX}2t$B=QV{rOeP@CJUZJz42KIw7A7aA zRli>yN#|63HRyK>e4OJQGWpZOl*PA(4WHayf&P%;jBkGn3#B@sEvJfX>aJ4O@)BH? zc==)CCk0)4-9&>`Nr8+%Vi~NHHH$QTR#`Z_Y}hBFUT@UBKWr=>MehbuRTjn(g|ne> zYR#lZ42XapdZjdE7r1@QX6Zys_e7|YcCI?WuE`A(+MsL+(Orm8;iAgNCS{bJ8e&>{ z^zIjWUHg9r(f)kK<_=QvI~}FDZB_;*iI;bB;Hnu{zjNqz()Gr?m@s+CB{KX2By{rJ`A&?+{k&f_jez-M9e&_F1^^0FrcgW)?uFwa4L&5Wt1h%Nw7y_D z4ZtyO#Y>wM@1eRt&p=O$KJwe1S5Q!J%&~vlrg$6q85T~DJqjA3=4R>KwV4zl>Ymrd z)_qkb$Fv=NhrGFOr{1r-+^b>Hq{^@=X*O(ie~fJIs!nV$Lt-Cuhe|}tfFScfOkO2h zCGcTj`dOg@`(f$reXm@H^sna}`J?6<>#ZZNp)~)kQUC|QF{Q!YRlAUaWj8upf#QGo z*Od$6w0M~crD)u!3WT7xsoH}j2zQKr|8r`-YtwfZl+?S!Ua6(&=~+*5w9~CoA+X7? zVSa8`_wbKV8yob`LFD^`I4lf^7UpSqmwJdmJmyC2xjAHM98CrXS~R$5NGVAt(K znj7ZC+NN)3Dx%%mKy;AW@6!|WeiBG4pZ9B;ekTw=zw=vE!vCZa_a1=EXyU|{?ELna z%uJ;>q2!}A{2@59Z-;Jw*&Ba}a49i(j*mr$(;ivyQ7B>;Sx2VVGd467^-p2!O-k-B zh_s)}sObtD@4BeCQYZC@s{_Uf?r_#+H|amtP9pg%5B`EQ*_2nuJo!`PP7h-JJUs4h zk{LwF1kf||)p-y~FAc)aIaGI`-ba>f$MvZ>xYQz``dp}^hZ_{W+0)L zX-zIFgR7)wPRAzRko9CLll}m9nwq|%bB|-HM(S1SahDLNvOfqH2HRD=qE)`4y;keYldeY|GpH{@9s-(_yI0sm z)DtzHJ0*f7f$ixe68|8JF<*4T4k7W;ZUrjXMbUnh1L%~{QKw6j@WhzvMf;z zeTGT|bo@xR-~IfEpyFTRIWn1%xgn$zVurl#h|;p-oU5|&qtREWimRm5fk+)J@oTPz z9M*SaB@OA?eN}%vUw&3Z=Y^T+Bht3!(VtSE8CgR*0PVtl@dk6cnFwBu<^<9bzXmQp zkR^;^Up3VM+)kdx0=H>f(d{7)(41O-mio-kZL&`qx?8ZY7ZM<_W`$aJ`cYg{XI0<@ z^@aBYDM5D9??l{&b(wt3ier3lTISKCrI4B?K-#xSzR7K^g?W9VitWweo_o%I z-pj(2E1_p=Fe;u2m|RcF`EJPeW^^TChsELNb(_5Enp%*4DgXEs#@=rGy)z*MtfEE= z{PZvYLHui>>qgkbV7UlAXgkS?w&qpW( z#+3@s<`#p0!;#7OAC}!+EaRmr+l&z@z3DhF!}W!&pwy9vMthi8VV=?G_U3+^2AF;d zT4W@PaW6+HOK%;#S~OS~YnAF2Hbs%gd7h_j<>G%wnZQtK@!~y$mea|*A8y&Ac1Xz| zKjeuFPf~(s&kzQbPJ|V6LE*`HBu|t-l%!~~t!^;wi$3JO$5}U`zq-53Rh$))iyBUU z(41+@U0`r&zzhB);yvEpSL?+&} z!Tg`gpWmk4T5Njg4r8G9W=*Vg_qGl?x4hY{K*-nAd^B~*W! zLyCFDHZCgbkPy>BQb;${{DJT!v-w=-+Q4nk>Q4a2Mx85b4*1HovFv#~JF9zg+>COF z`-lqS`O|TUx1BNm3BKFR`!-34E;M7~=`|k7cibD;Yp!{@9$mV@OeK-ER0wZC+)b?-G`L1 z*7tR&b`s+eqH{O<2p}uHC#wvNju}EYN;_YBrwTho}k z%B}&?M}(*WGvXTqvV-$;|U0MDyfk;t;_N)jW^0ZPZXk11osLHfB|#Q7_K#LLR=BA|#7j)O8) zvQVhKCX6pKeO@lO0R`NCk|FNkFSJ;PBT=DTsl59#x%mE;%X`r;%HFW{glhm{kVxeC zx_wROt!MVAghA<2y)}5+Bb#NTnn$8a@iV^deA4zq(!sEkb@S<8;5{2}m+G1P#9;4J z5aD;_XKx`8_A%IhJ28G^z0w%g|07QYb?9tiT5pAs8tDF9eM0>)GmghZK_EisE=~<| zM`51eJ7Lkd_`pXNEi^5Y5_I*GB$L@_g7ck{u81eAT#Z&$m2upw0{MZk-u0Wz^W_PV z%gE7;Kl*+?^m(el6w4uPk$|*Hig1FToBT%V$P>?HtrzNlJu6U-oxU1Mu@y0BnDpac zUqrZ_?mRFrmD27twEe;dq0rnA*N!#9MT%iUH$DbUpW&GD;PyFu*1D>cV!h0JFAj_@ zB~HCxa8cI^TBfNQd4kFJmMg;x=ytNlKOZAUL4RsxRHX93h=p?(kiOh}qcnS~K3X-# zL@qp~)-=+8Rnnh@&BUrIeuv7d%IO#A3B~f}c?u@*IoS{ewhp7geL?EaGa?giAQO=G z?H7@jN{MfSvAXTHE?$)UU@@It7LXepb`T;5*xdYfS+au!RFwBsq#y;29G@Q}&s91; zra3S8Ys^W0U8*SxQ^J9*lyrHe$2_J;*XGwge&9QQTk=3d0T;K!M)-y^o!l)+;#ae4 zquL?U48+nz8L!Es(P)9jgj`EqlA;j$#nz_{Ci^v@NI*(Uq#?dU=0%OG;KoVUie-bV z9Ro1R8hwn>9v(6TbJX|OwMqr`3-zsLj;o_89JC&b+FlQ^C+~96#}{wPI{@WWJLt9{ z!vNxc!b2a35IZ~L)uR@HX}SgmU>5;yH;vZ$s6j6Y^(TY zN=bz$;-+}^h!;ymP`TH5Bp%P#6i?biquB3d;pv=W-uf4Z9`6VK=8L1M#}1Axc!fU*J!;VL zlde=AOx^;FKY7{Y1XvS;=^T%Ml?#p`3HlZw#%3MI>Nx4FMN(|V%qb`a)!U(eb;5zj zv;B-8kJ$NXOCL`UDAE~H4)MQoo3Ph^`pp}ZDl3%X8^vygJC?n^io71{)D{H39X(dh zWm^OXCOnj$jn4@=W-u-;j`&+6#oeDL5Xq9ewX%b^@~B|y?L218N(=J0F7ePT{L@*_^1!H-|gTVKMbEMcwC})K%(~M%NpatF^x6%e2K@w05R&M@f-yJlO0_ zCI+sM@>&rlaun*v$NYXQ;ZC`*$b zwe&3%$N6ekVwQ0>Bsqh8+~MzkJw5z8y!L+D6h)e*0;}ItYOS|QLPM2+%GToIlz!w@ z!;8RbS( zRg5jpjBm6BMLxMom*Lsb7@Z^3GS46G^fw`UbwjFLA7S*aYa$>*s&j&WD5&O#q|BzI zHc!pEWe%J*cS41fK5+~fqduprWLp|1-)18X=NU(pmwxn~N0SNQQosmNTkY|VLA_ng zBV+&{*rp9rxcd@EljUAEoy`aAR(lZN1G|AgtD9Nl5`9hi7=wF5>!wd^sc#|*sFpzY z(VQ&RQJBDRkJ3Pe94L@~hDl=rMM!7IvwZG6tztYjg%*h$R4KeP5=aoyI(3+SVh0M< zK+1$*H{BZK?BtrJ+j$l_hc-ws`f&LzOz2a{Dc-RuXC32Bs4O)G}3J8TK}Nw|@?gJ{DrH;>>n0?Q~=k|1O}LeIADVN>5HG7^2u8Y5|n2}tTN#j!cf*U*iLg89>>bz3E{EEg8YtQ8Bf^1^LQMuoK$_U{8$|C=W1yH|r5PTtzRNn^Q(6v=6z#k&5Sf zp-Q2|w%3Seb1{VNm-&c3T7LkYNBae zFP-~;$ljnf_nbVgcU)H>!_s>!)W@f47fReShDW*LqjDc+fGbz9XD6G*tda^w49eK> zUyK}*qNSk~USF*WsF7aS*cG5te~Bpy{r`?ru-c4>Jx}6(1J!{c%oKTJQFM&F#?9Vr}a()2}V{-srA)Xk_Q1Q=fp; z!7CD&sttfZa})?rV)bMWjL0IM;!Rt@yzIx{PqieNyPCs!ZAAzs1TiOpQRlYJn9sR> zM=lVO^8?=wq)b!@g|)SiIPJuUb6DG)ptW$5t*@_O<-K8i+1yqcIamPrD4m&zm8T(p zbE41-|Mqbt%^Im2ALAFf;H#a0MfEWdS8!@Q=W z(`u=AfWwOm`o8iW&0-KrLoJftgl;lcjB-x)4p5pVfD!c1(;Ov(!-0!;UZK_X8J#@1u(>fctKUl(xXi80+BvmrqX-vEDUw;3TFa_J zomZECBwlsXH@HD|Zg$HboQ2MfSls*Mw_RxY$o~b)ryXV?z*{!sUZ$Hd?)Jrhr(9w2 zfrj&#SMN>O24pjGJ@`^RGD{2|uo9ZEBt0NiaQhqXTcD_EeU0_CycY`jv9u@4F9cR+ zlcv+T+Ws!Eg*QlMT>8PRDrsulyKVxp-=B?0A>!YZNT;ED)CNCq=3s}Qv-T#{nK{6VqJ>li z2OxsR^<0I~s;d;-Rjv7JwQ&`U*ry}<^l4SZNbX&_85~nsQ zpp<#n6#|cgOmm^n-iQs&KrbX=;CJosSrPiiuM;wXiMJbjM%>&)&bwZ8uvz0ai9)lx z!kC%%V>9>bsR^KxKhQLTpZSFwD*+!<#PvQPKSX<(kLMIE<@R`g*hOsVaLb?##EA)%2(Jh&_+G>N$_&#O*a_6Y}3t7QQAEKZcBHBza@hwQt2|w zMuZJ6N)t792hORuxX@V^RV({2G(r~*4YdI6VCUOTixcLc`8wLkjdrYjdmznY>a^np z2s)Nn|-|i@(36R*10Cbykm-~V2LLScW8V(* z!ZaHx7IB^^L0kla>0c;!4}hXyQ|K$5M~BW>qH|;cbcxi{MWunl2t#D5 zhGW>nD&ovy(h?}`IdJisDYIPFk+7}i!q^jpRp*j_XWi0CJ$a31d|1@012yDqZL-0e zfOtazi^9P!dI{Tk@MjO&kJ4OzjJ) z6!}2G^L6(YXMEzD;cMAB^-3)e?IG0S1+;NigJvih-?afVHyFg9B*xO)0 z0U7FlRM-N1u7Fe4b$X125_q>`FNFz_F%P9_+}xtD-{D_GC039*gaO!s2!*@?ozh(w zTLv?pI~hl^;ucbLta4@`xF99!N3WI#>Xet{^{Yq8T`crjS1FsiLg>Ju6&V~T6%w#m zhOCh&r=W?B3|@wGu@>O(7w^{wDR6mJBfQ^#g8#(_zV^li=Ta*DUM`Rm!GW?lbwm|+ zKK7|&U6iqffd_odB80a!I53{*2(h0;2j)OFJTTsYC_RL8YY~V5vN=;E|L)e0N+E@0 z^F|N#_F@^7Zw}e%3o{|S)*!McFMcuMW)y8KyG6jwuU~kW&{_{0I%GPK#qn9ha&bq0 zmV6jU&H8|`ub@;`Mzo~ONpZV!&dmJD;4f^)wn71yGbk|BJupn!DZ_W^-I|gG)l$MN z0}#By59|s6!2v}3CCLZQ9of@j<-D-d5ZVu*%Fe}&G#Ii{j4~h}(Gam?n>H_C1>z3y zv#Gh7xC+jQ24OHv;{tjmP?itkiH}-;fbY{_GoKW-lNFNEEe%eee|4LTi1->DH-;FW zh)gjW#clm$pGD{p1X(qvn-1_6bWOgn8ATiI1OYTTTb7U_(1O##A=1)5IHVR66?4|i zTxqE*DZjiY5m{zqCXP^+1pd}(c35!#y`j%f2zcGy_>;A{f6*(1&k|X9_=ClNhj!ng z%I(#f!c*_aEh7VJ+ZxuqbLXw|O%hwH%|Scg!${47C{JT!v`f1u=hOMl3(=xlYj+q& zAq}vrgqNX74TTQmX-wjshM5GuZRp zNH@y}czDTNlDPWK)$novjodhY38Dhb6J2o4gxpk-P~JEM@R0<2+}W zJ!Wb6Fils8gpjDQ_0i4wg~}AbJ_)kzRJ}>?B7*}Yl!hrBT&}^naoc(k8r?MnXgsSG zjQ@Pp0ui|DtKHiuB)tJ%8APnQL9WX{+OD++kw<#I4k@MxHCcExY*J!>fdT!%tMOOC zXsUYZmR;n_I655LItLz9XFl#21PY@^D>PwAB9B>0h}=+{&KC{8Siqxt0NjMunEqsd zfgDQfBnn$H_%aNFHWqJU(u%deF4(_u_b|$h&EC7-cy>bd1q-ybwp-mV*>Hu&w;$xp z24@o31^h9z8Vjb;mIEPwWzmapn;P6?_|QD%tPF}IJOlDSX&`b37ktlSINrICV(3&M zlKPxBw*kh5Oq2xBuZ*~VF9(LUdDJjQdApTGWs-D|ZNii_Fp}OWVd{`6VWQCE(C;zA zcOb)P{FTljMu0e^KGOo~2)aouh`_-VD2m`u=#UV-5rB7qIT9<~wjRh;fCR_xi zv&ThY+bM1)7z_P>|B3Q$VLWDzqf8Le#QH0-$g4cg?ulR^zm5c?9|cZ0opf^b^sfF6 zmGkZJ7POWEe&(}3PAX+5!5PI}Utk(fX?T#HxL;#R)2N1ZZ*QG06e`Un6FTAQ-j32- zu7ZU6o4}uDPrZg;kdBd}l~8@D!Q8i(;Due?%h&CAb>Jp{MBlc`n720MbrPP4=DF)C zuz9agSil#NJq`K7V!9Na7t273bl@-S0VV34!1GrLQZVSjGv6hFCQ=Z3%?kPyl`7<$ zIVrs&0pONijuMV2R#10($6-DnrUXsTu$>lVzDFeszZ4zagD06=Y->zmZ2)#;bd*8?q%!M)#akwiL`)uPN0 zc2m^37Z_x3G~}o6Z+DxP({2?A8yeoo3)lC~lz0w*(B3>N@4{IN9^yz8D?6wFka_St z6wTo1zThKP9|01b=U!GF171&E+E@gEo<;4$q<=G`dh?^n?)U%&o7j3sGRtT&kjNmJNYH$cSt6sl&9;oHi=X6|HAO1bgHlZ3+%)(v91wKMd=gUA((u6jq(URYe z7eSSOKHkSjTP4r#n~$ynXUo;E4+5u1uAobM2k`TT!X5K|u54uGFIki>ZNZTkfj5tr zS3?RHfG6P+hWOAZjq^+w(|I@}EyK`sDt!4#x%HpW|G)!3o=TEEG>17>%aWHmB==1r zd;!h2D@%4;GZR(!ue||Eu2n9Q_dxBsncs7NBsGcd5aIv!L*zmJL?FYhMD38%Op@U7PXML*fU5rY2I#fO%zkWA}k#KTtXXthiL)E~(oAM=<(wN+f!3j4JiNa;t3dcY(0v%MGhR9`6IgSe!p;-J)Ohx}*0yjT!2H zdUHLXQC4W)d+Th?+4laQCUukmhXVSovqL)x*ehBnul z`X*o(Vw%=u_$J?kF+i?2S2%$IQss^hDr0oI)owh`O>DR@6 z^fPI3+dAMNA3rbP-VJm;{jvtM@)Tg2W1ap8?>_yOKoMC$E?u+y_!JNfWb4hn?4n(fitPVF zqh@};6xxMIHe3lEC$+?cDG`$*O1^;VpTZlkYEjfX&)W0nEnGJnMxgz?meO0#3PJ`@ zW&PD^%atFcyKo`?K~yqW)LJ}18I0NDXAUcKWw&Xch*KBuR&tv$P)yf<9tM&jg&e8} zjrh_mzoBYH(VFt=Vz688`%`>tPX`%&%2w@`VpOf?-{(d@?GA{v*trSxmIHSQLM>?dy$l-Ov!gM zD6ynP7Xbt~{6(Fxq_TN`?w(V{awrrQAOG1Hvq({^(JHB2?TwT|?+innix}9q%_|Uw z4UZO&f3MchL|Yrgqy-};SOPVm`Xx=oO5_w{z!$+vR{Y8;B$kTJs=LdkIN=f;hPu^? z(r`IzJEEQ#4NE9#5KDdPFhFM4PnPo#CRgf$g9rkQDLywmSw=R0?9iKE?ma5lL`r4y zsi0ruTgqEyXYKTy4_pMxh@{oOWerAB^13IgHlabAE@gGIo*wRTGDJ`t&;m9S@s_K? z;wt|mIZ{?z)Q5zXlTSX%C{bUu=DB^S=;%j`DEcZaEy6yLW%U9NGj)>C@25U-MS(C9 zjPkDNc`Zu5(}kyh=DLEr%Z23p%y`acp0C!l{YdWoL~wF4V&)0BPcC?E$DrxdIX4H( z-MfBl;4C;MXqmjTfT{?x*vQuPMi7J9OB2uQTag4b@`JR>pMN0CCd8+kf$odmHnuJb zxo?i#z=-@R(2|lVBwC{ZSrjdmx7TqXeNYg(bXOxc+)tf<`Oa#RWxbW+lV@f35$2{) zEKJr(RCVmhGRCS0^Oo@{neBw1Z1M)6Mu&!%>D3k8eVfS@X?E`RPOdmrY;JYQ*Os5W$2Gpt_2Q(iwppM0*}6%uuL z4cX?MLPhln>-JCl;=WD{I^aL#u@B19%F&~1AIlFtE~Eee%jWSRsiT~*q^%Ko!oCS7v=(ny&94)6amzJ^gTTIiUb7|pSQ zri~r0Ya0r9&|6D7gZD`NgzbKbc0U~N7o6_?3I)rY&*;-o3RCd z50g>9Sca78iq%2HS2| z4@5-LpjZzO=8%{T5QS-w$|FZI`-S3B;VX7qUb%pO=17r9ICNx!iXBF(Bgg$(`NQWI z8Pe-(W4|wCSRJ*gD))x5gGsH#j4n0n466CaY z!P+G1fg=y;dDD*1<3WFO)>JT^ezthKq68znoYHiRdS>}AzCVlo@rMEWIt;dbi<$8G z(ZgAXmy~)I4o+yeKvx{-Ew<+$-mRBSVI~Zn-xXy*l=YY?o`@fW>8!4Qt~q_Kaa~sR z0=#gyE~;Oi+J$~nM;01vSP*9~`$Q%XHN_Y8j;}}TqdmVWHB1Etl>yy+?Bz4LG<6qz z9oY&oJQGpTgg`F`zkW&4PTi_QbPcn18gVh{vtq+E^hfAj6u5lsY}P#pF{w0|TjepO z)47KW$$mR%jI5ef9l!X0HWl4i2~@kISr}V?)B)u$WpjWV!$vuh_Vd`y*Xt;-@wHs@9I6Ts2u%Ca_t%yhA4zj5 zl3jZdIS-%#yhkZ?^z%L~^vYZ;l#4AqbHLPY=khbZG&CV+%91zz9i?7!h8{%G3;pxq z`=u#hx7SH0yApHj21jv%f*&d=MmV#);lx#~{&^+v$&EdKmq$03Jlg@r%n)qZ_s)8v zn&A7yoKwINiWj`g@{m;T;x2TYSSWX;E8bLVU{6?uOodDz~<^U}P6$m{6 zkm)q1ddUN^)Qm6&tNBT*#l#{XE-K1PAAwm^gR5Mqg!E8P_)bvpwIQAZlnb8Sj5ENG zQKBDIBR%_nIub=b5sV0;2laW_$8n}XUv&!3^4{BnGzw%Rdb^fm2O=P5+r0zc`vhFU zP&uz2^^bq5*0{+y8lwZ?rCf8R3k}G%oMXn-kxr22D_&NUwOH#8>_D_GJ4~jep=5c9 z*l33KKsSb1d#@0AL)%BE6EGKe4)Pn05 zLeCzvu*1TWxXE?&J#O-|B;L;UZ^Zy5{-%_@Zcd<59Qu|W=@&|EXXUsCA4zm=xqM4E zDx54vvQ?^nAoBXV1%vVNk4-#e;4ya=<1RO_)k@wvEREBvZo(v6*- z;s_^y7|ZZrwoz~XiR;kCuKQdvB(ChfVz!1<^W&4C_z1Vt8LAV$7Y|yV)eobVY~2u z3}qZj1R<5PGX%@P{Biv5YTPbv7C*v)7ruM$`)Gyzx3u#-4mu2il#G6IPqW2?iY%2R zE0V0JkDNV$>ShS0B^AA)4|uqw@@L!au!34ZL^MUDWs7o?(8sCzrd)$~6pr{%JGnQ( zvrqLxQmtB^^gThGi};=mCX*#LfKgO`LYj#`SE~%!^|zucOzDG)6-E0WQYsOQQpBmU zLTNe)HCC?nOF@wcw~o?WYXF+xP~l}C%E#s&C07n*f~+rf61v+KB3}elaM;Z4oDO6T zLGf)zumxg+T#DRj@FL0Lmbe%WNrhb&TCisM=;G<5P2Z(Ryk$fjr0PF%dk{c>D0rd_ zbE_ECHADKlzV9D;py~Ni`UA5h()w`$II&MB(1?at93Ge=b;Pp5ZOqb-tNJTj8K4gW zT2v;&HABY&!m^rk19fs2`t`LU#SRRDHDv|I>&@W5^3^Tv(EKg*0GwvF_ z;yU-PQk(z=234ZWi!!Is>oL23LeFO0bP_?)6jjYl+tAr%->>v8YH2Y%w>z| zY8n}_5U<@W`e{Ak$ zoe#vly&Mtgs2ao=Ar!ZNsY0y%@*wkyOirEWp<#^?;ff?W8=VA5E zxRiahv_8cEY3J6>a9-iWk}DAL@n~U=%^O>!MpZ1XpTMauBEuR&aZ|vD<~~tm1S9L@ zia$4b(|HY7R@dQw13T|;f9U6Uk^TAM!z(?8IeNLkgQ(vXQt3GbO{1W{RXN7%b43@f zQGHAIf;0D!GaP8nY?OZ>f6hopug}*} zjQHJ|v97+rEi~lnIf*H5$oE_1`c=m{XM~1}c3=Wz;;2x6d)b8Z{?+jD*adnjd)lNK z>F4Nma0j^yWGo!Oua~Yg{xieNsnbUNo8Bd<12A!2Sgy^)_u-^z@~7w#v6*m*26ZO+ zBNymwa=yvM3=vZSPp8cUUv1sDeup#Hr_IqfFT1mLZ_c=R?yMxx$=xf(N(u*+TbIcq zf40}K#{k)Xryv3-Wf+WNJGy{OJD&g61yGT-SSI=7j~{=y+XYlh;RBZEQX*QkL_JBl z{VQGIx!*L2f}W<+@<^_dc-t*MV$F_S&mTe9V9MX}0GzipN5~}k;f&VO?NC04kdH`^ zyB2ZIDK@-<0R8P4jf^*TLa5QGAfK%88@R~y-a4OuKD`GV?%AvkG;8+Jju`=58Y+~^ zhj(18R8`Ivfjj_2a_uHDt-;k`@6!SZlIX{0Uva}|(%po&Um?Ak+JV+x!$8(tgFeoI zPhC)`qRmz~+Ndu}PQ>xM(tZJb)hy^0Cv|gJwRx3iTv<)hmKc~6Qtf5znxM3Jluc zyma%AL%fWFOc7`hJx!6>?6eN}{6|8@0p&Y?%Z3Wihr?3N*+iLaF^Z6E)0zg1pTBt57Ox1Dpa+9DAsXtyxR^ffv=@2?aXf#n*3E5T##x%DGE1u zjYBE&a4Hvz%|LNaZ(|1~{lP3I>WrvHJGp?rcB6*xY92KaHHFnuA$Hz+L51|UjK|&y zDF7UV!lAW)E}N&Zd!S=v@yVTcmUbfhW$vNbX$~M`|4u)*vX+5e z)}fUwg1~O7aBnS#dv{i}x~d=VBa^HVw_-THDOy2GcszH&yH&s7zVPw+$v828Mlx;_!r8$0 zAa>*^Gp^*W2Ge_#LsS|rAJqqzbZTc9`}vpPG2;G-*!?TlEILFX!Ys&uKGdQ~ur50M zIO*@l)X-G9+I?0VkT0INz_}hxbC95ex+mQB}v5AdmigKX&~<-za_`|7TR zn`}G9SsqUwf9Sd&M;j7W`-FdVl-yM}IM5OyUvl;9jV&wg_XdmKr;j!71l%1cueF7s zcG-*A1UL>uKTrsN_-%$_&UIv`Pd4#L;I?9YX5?OP(zeQU74=jUk!>Q-!z)E)_;u)x zjvm!~9lWC0Q_rumkg<7P)E^ZeC_NjdkwR%1hua)I=J^PgXoh8T<#lB*KX-ShpUhg- z-#t$}9!=#WJtE$BlC@~j)~K5r6z&YG;V^-vP;DxIPGf?9{xs&$f}+jz-zZBX=j+-s z45jbt<#KHrwD^n+Wd?blFs=YzDAcd7D-YF*hxRhbPk*`SiT(OxL`d3xb*F~wn5#*m zLxBI&X!TA_E=uSU5-W-ShBQ1?bKw->seMgGJ)CzlzUhv@brvpa0k)3Pppe;b*ZevW zh{O9Swq+iFzQle0z0XT7`{QjYmT=|@n5`cfsx;>{5w6Qo0qn85xT{{}={U&sy&a2= z^PUfgws;MTEY<7UH zS--Bn>V8+1hH%|L_T7`iWUUy7zCoD&y+th(7`|;5rBQ#xOk{BK;`fEU$)^l0)Xa^E zTLEGouMra8ooEzk@6eb!PgaZYd++bjln(K^8kVi4qD))S^n%a1twc$DFWj5mJ5)~o za>S2+`$Kg#$Yrp3C=bYAeh%00QaZkpm@s)iuzJoPTY>kbfo_a0KeT#r@k z$5iPk`1irx%I^q68@|TwD(*!Gu?{!7XwuKC@_H{O!}Bi0a>0a}nU&@h;AaTtG(AyJ z$bK;-EKt#yAO@_zjS=6WhFBA{gxN9S-Sc#RkMH=V-^Q)@tZZ+7V<{%Lc@{CN3zO*G z5G_QR%mn1FB_)TKZC>0uPDe+!t7}X1wk(sNGPeuWp~_YeKOC1|*_W+6Y{J{fhGlmq zVQr9FnI9tRi=}O~9R+F=dvDt?K#>62cfRroVC==lBjN(*qkZnD%)JQB0}0=%9XB9< zK1t;+Cq;a`K2rXbu1tKfA^a4Rw}kiVOU0;HZanKYlaeWk`5U*OD!;SBo5D2>7>Sk) zkKC7h{{F(EDSFW%nu2;Q(e*)pzXRk!llyC;EgLxo;ni5fpbnZ4Ip+qO! zl^B!%#L>9wTx%TXhjfApwUp~x)N&Xe0(YqZDC~&*mRc@qO}*qfsM`u8;2*xSSscC3 z7gK1~21k|h;A1R3ja`(fuZ)}X4dQWRG?wdYY>XZ{LX?(#=mJ#KOLeTlSDll+t?&@O$|8|QCN zrR*zVoTbcGL(6ZgS5Ni?y}l;83!~pW7SJM zn^(T%66DleR{)~syT^>r64zw{qb5}9!TsX4WHlaG=e9nn$zP#?Mt&QVs1aLX|tr(G)u{lgk1Qz zVHznzm=f$1F^uRcjQRc; zMYGNja&Q!Gc{}0M_>yFf0&JNpjdp_ps)Fnh17ezM@Brm+96=ybATavM_KZkgaC_F1 z{40_@PkCg#`mF_D#L{wVHenh2*RE8PK|QvPP0pDCrDrdZf9{qD-AbsDTjRQVS1M4W-9VSkt&a(f7a z_ho@V%oD17p;oLF+`Z-F^t>-W*cBVpjZvZG1{<`t*#uK-O&BgX!T^@NSv3{Wu|r`Z z{||uu-wo{({|_qu@0?=i|8a`H|8R=m`+xTN{)bR(`!Dt9Ut#~r8ARis zy4p!wt(D9pj{f3F^IsG4mzM7|6XLTmnm~UfZnyZC>p!1%SgWbzC1WlX2g9&j^A~CR zldfP!+>&%96-|!*%g_Ih%=cgaUxGY%@-P0MwE?;qhMiD4*$Gt@;@){Pwr|RPbC;C8HTaxzn2%QzZRZ-Bdfyq3^D&w1BQPi z{|zcAU6Ib|2sfqtHwOMMp7MW_WR05?vQa#eAH%rKUp(nwr+fgSih1q~H6ey!_2ZwE z=1+wzMRd!5I3CKr$-nRSZzN{?d+6$L*P2wCt5M!zEJ35YwVK-w{wl`p6Cw+85Nsa=Br_YB&NLD zHyEs-;i3Za3Be`Gul0W<>|-!O3J=n-slR3VdpI6YD~^>-h$6IN0aD*T2ydK-zW z)l7i77tE>q7hdqUSQ~w0H=0I;ejH^n2Jo}q=)0Gw0RHGIc66WeyM3#AU2J{zUdlS6 z!1%o?5ZxO7y4zRX7+<2wk$!9ooRUjXt1l$ae2Q?7@O8yur?N=^9a(MU z`zNzRzOU_fEIu!)H|_I7?hsacqY{M0kKlf6)lFHUx=;kcJ2PchczAl)Jxe z?60-!>kONy)%fEil=I}ui?!A0I}bSa1ZQr49^mB6hP;CFJlxHE&JKzT0(Gl&LS~5E z2w7qh9JCBe2COySS>$|D1{h_0c$MAKd61HXO`81u{hFzXEZa^M;!WLCU~c&_4A7MC z2RPhDmA~bOArffQ$2euP!Z9BolUM1{_IkSFP(UAHbk%(WKa-?Xlh1Qz`H_>Ml9MTa zx=@xUElpS~O+!=;U+g7)RBOq68@r}05h+QV-N}J!6MN2MqN+;xhF+{4dA#(|m9YE# z+}Jr;0U*U_L2H#1s+(0!T#9*=zRc_JIaRW^spP%Qc2unB-I7Pc1D*MXFBJ!y-NN-S zV21D1Vxg?LKfA9-YKqZf|FC^QdQ|a$)svT!F9mAl-q=Q0Y63LBERA}^%!+yJzwqc3 zg`m#0&7Sz%tR-2~eh|?Tt3&p0;!J%h-kpim5 zox=IcK6=5JK=pn(Uh~K;kNdoRi_8z`BV=JE<8@IMk~;N`bcEiBtb}WX+;Y!$SBS$TZl;}fPI!Pdp|?>uSZs0O zsH+*xP1Haq3R{IM0y^<#PRi!H9zc=KSFRTmY&kP>4His0E-TxW zG3b{zBZwuPGi;B~Lj`u7APy*hu2boO>X4f5e@Har(#l2w*Ur@nC=guWtHGt-ewRHp?Ao&_R~+gCaIk_TtKbhiY^x-fMUe46pHtbPS(mRjxWio z-hepm`2BjY)=IVq>_fppeUIus`dQ1Un|Tv&s*es&PtWio&@nQcYwP&Sa;KVO^wD&h z3T1*_m^cEeg)>XJR2xix)M+KZof4=SBr58KrXtm80D?q8rc{8!v5{+j2ULCAcYv1k zfnfL;pUFs(UjbHUgU~t_SI3H@saZm`N^>5)-=yU;4w*uJOs(@4shtdx9;922F2seB zCdUvl2(yuYi~q?<{^{QEF4Ip4 z&E2j?TyUN#p=u!FP^p+)rQg|8_%k(UhuaAnC@&1ES_L&#sj);L5FVJojd<7pMw2sq zk(EhH^4;|isK0*<9js)4jGwNA_YAuIjlX@{WINjK~@E#%^`-OORcE{R_bYM#$6)IowIwm@lUe+*``06*m{{G?47 zfo^MvBL!L^EX~;MEG-Mejxe2~l9vV$lOg=@x#vNEk8`UJ z87CbaKyjII4Cr&Xy)twIIZ0^PB*BYYpn8|abD#b^ymz13qrpbftILg%UM&3mBe1yU zzD}fKtkJF9lkd`N17OhkLFcqQ$$pn2KXt%R7Izy@1JD$tzd=*F7v8vs=f+E^ptSZhn8j8%}pKz^%y?2^%+FVkT@< zI8jhD0SM&zUI;fgQO+A_Q3saK687$1U#iDHqjZ4{2U8>QhRYhRUG1y^hl-NmYm#RB z3Mm-RAv8_GqYuTAC|t)VJtYG*0s}kYdpwHYwNzez;vTT%;t1PcNz!Db*$zeTH-Mhl zS%ms5L?13_*mROqm6cJn=Dc)NND11!Fa1}=*{(Jx)+*b9H&7WYtpN|z#NhK))6#l$ z6B&k-tU^pW8thae3EkGQI$sr}r~0Iel{v~`6n6$*+QOa5RKQ}&`{iu^aKP2ZlE^nW zu;JT(sk1|Huy)c!`}MM;H(HU*7eb`z%KUTG1X;W{#8R6+-fPvZ>>|1lAQ@aSY@Gxo z;adw6hek@E#18wfY6HsqINi9t-e?HdNT2b{o$gK;44pxz3oTWWHMg)V9l_ihxj-~T z<};60Adqr8PqwK$qn8eC|Z#v$DOB+$V0H*kKdE2m;36xh6Kbsw)%-tINCPLM!;MEta8w z4HkW#5@+6GM9ef8!jY)igOR4BUvBszPehYs#URUG-~MJ5E0&BO zes23r`S5~!&&0Uphp{zS9t8$D8$$(xW;RI*{#VRMnj#>vzW3Q3P^ckaUT3ioYwPL?{q_)en-$R2Q6>(sF`1J6sWrArKkXl zO7SGhp)s6r0pgX#7aWLpR%NhHe6sqbb=gidSx(6~Cl|U~Xrp(;h-!sGdI1p?=6PX- zIBtq;Y>rN8l^xQLbcTmv&%-PG)yHB^6}tU#`g6gaJoyIp*9+y68^pa(N8~DhSUpUF zW$ciUgNKkV6H$CsR;M*;m?S%d@c|S zys6!yOWt=34{K(L0xGZeczkh&-`t9OEynD0Lbd>5K%T!G4jwRA5Al8|u8xk3h+?dY zuA&Wol=uVD;NjM;C`&P{Up;D@a*8;se-dH$tgn$?3LN1B8n!?=#!jqAGpZE$nSNIU z5BCA3uAYu^!5F2`xP`IRwm!%3E^Ir4lbnqhuOpazJW3 zd50FsWtL7|$3N6U<8Z36vVkv0e=y+@%Y*Oil?OlR(^o2s33cTBlUs8L3F{~ZfPKUC zb>*r-saKm&&uzgxU_)Muf2U|`$v(9XbQv~$8CK$LZbJIC>UPh*O(<563NgCrOZNq2 zikYd6-8E(a9!o#T1#fdz$XN|S$0lyHkx6M)vu^Na$=#{AC?m#c(sx2%e#g$ z$)Es4+1yB14gexncy7w$ z{VP#>tvY1;ohS)C-l{E~e}$?oLL&gWY>?5~VtXH)41-n@#Ao_(K!#n*D4=5ed*;tdGBp+soc{5w|&)q{Nnml~7=2Qf|cXp+Y|YtDKk zS=}dxtJMAHq)&KYf99032SCL;epc0icgEl;-SV?I9YOV9k z&?7|gLMuu54P{dkg1M|+L0^n6(z1=~yjvWpmOAM9_zXR|^EVJim*aDsRmS?Q8B9dP zzz9)({MoHze_%yINAQ`0+VdWRmhVQQfk>FOnEzH#_}UzW^iF#LGtu4!CX8VRU!m}L zRfJPjMP*F@FcJ6og*I`|2B|rYUB% zopu{SzJu8?FB;m3>x$`>0P06}c^&|s>Rqbi@g5!Ne|s@$x8G?FCoe|dw{w$gLlz&Q zxK--Qm90D*st#GE*QP8!mCuu37e%}luY|L~-gvF5?yen0ENjTcBlL2n0>;Fs6+j|* zgmaa|!q#hl*^#&B2`sJEnl7K4_jj5jld%wFUacoQr_FChBDKL0 z126;Bf5XM41SB=41a9|Ew5s0U@7NBE@{-YnOn(4;(0*++uCdw1zF!;X3p>TBdpe-b3;P1B}ZJ7*|1+qvMtih zvZo=DWiXE;B&)1K5F7gAlZbA%r1pvBg>*}-e{V>LaHY}UtcAhU?tM|J$VAGX7?J)e zOuo#r*XHn#zin2PyJx4biWP7H8a?Ih1ch6gzkO3QE3vlMRmCk4HRf9hCdsBN_)+r1 z#e%^OrkG}r#SK1J)Bcv33OJMW`nJWp=4Bg>R(YWdQ9e29Vjaq)oJCfB1wkt zUp|AS7h~d|WoYC84nXq#n5k4WxqJJsL_Nx!Adnqr7y=K?>^=bBuwXIxrKh%Rmr4t{ zy}+)lKh%ku?0nAgs>sN-w)+d$G;Lv4e}J!1KG49z&o=K6ga=0cU=0(v{rJ%YVCbCR zQa~|-y*p7y?pUD@LoF-~GG3@P(kkOBD-dQ1g=n)XQ^9AW5FMZT5@@|X#a3ZJfHa`y zg|G2MkpVLWn!-Xtg5UwOV<+K)Ro6iWMik=F)}d{bn22X`6vygWpR0p`IQK^7f2Yiy zR|RTUynxk8!gFJcxchuq@0ToyT0g`vbT?Mm9#$m zriC;%F*7FkK=$Nk#`$W2BXLC6G~yx&AsD$&eQj<*s-Q6fw&*Z{Yi`N%h3u<16zGb- zK+%DZg8X1W7SHW7z<^w^gFwAVfBIAY9lah^+xp6r)&e+yjrJKn_m`c>y*~8ht{aT) zr|j%c@!*kCzy+ugAAT-6k5ZhiHkd*qX^Y00!j`g&7i(v(Thdxlg}dteLkdObEW9%i zEn?F~5!B0BtsZyk*ZdSxZYU(vSEUgps^}q~$&mgxe>60_O>W|3 zEL`bJne0Do{mnly3Unq#Jg@OSV|!tZ;Bo4ZB_bT1wI1YXO?+3Uoe{!Y?Rf9E=@>?| zNY-tA8%xj!d03GF_d z741&9z_u#8N)nNi^&-Xwh0U;H%^AE+;%wf7wR^gbqD&5}DpkyFM@90@)Be^Fqk2s- zWMv<9CpleNue@)f`-Rtz9rB{Q<0)Y=i03;@(D*=-?Uc8iKjIeU-i>LUF$-d_4LD%0 za5S9QQF})y{3#>3e?XZ*gk!@f5GF!tmPPvJ!JSL}NI~$EvnRJ_UG|P-l7}6L`kNyo%X8SrXvVdHfY@d#vz4ydd+UaolO9<6|$W# zjTFB$qMv>*f7rFJrkV5`KD)vGmitWIHG3!NGS{w-M4DXda$}1#@~v{f!7H!>glPG6 zc)3KlwQW?nY+ZS7{B5*r!(xYw`ITP#osW5dl_B$OfEA?%%x@S*bp-}<7>M|;=W{jk zN-_Ek@1m^H%V!D9yMlSnLQtrEe|z436f>oJ-PS()e=DpX$1)P10bW23f+-HCDS1F4 zzjW7Yt+eH{Yxy`l<_#G>VGmG@5G^6Y?;=Sv-N|i`6=SV(e zTfBsATB*~})!UpO5*3IaF#b}K^E_WDBv(5#gA=1T>6x#FYstiGq6kp?fE+*w}UC>IpFMwl}_w<_2e=?kHd#i!8iB{BK+_mgo;-KHV z02#=^LMRSjNI%1k2m{5+3kuUw4s@irC|JpNe|_Aw$0^S!n0DEmns{FA`;0Y^+_%`s z9kBrzqI7`>5C$!>r>yYBdoe_Rx;>JnZwL{&=p50DX;!k4wD8!wwWp2c0{+_f^NXsAdpVWG!Ucu`D@WG=|>x?p%Ht7LNSIMdc`R2a|W(N1*t|EL$+C zCJKAWHZq1hEW6~EzLt=9+cI?Ql|Zj1KZALfONzxMEoY*^RhjOv zzxz6&=wmPaz9NyiYllRc8%-QMv^|$QN0b9_C&#~OqpYR;S{y-bqeU*`f^A2Z|6 zhXy#-TZdWMFq<+GRlzlhp+s$S24bk}N80#v(0j#%LMb7@KD-PtC)~UIJP8W0e-mjY z+(%w36ft6XZlKBRUsb^ zNx&Ia9XkCKBN;qvZWIwc61!CH8^Z&}vR>y1Uf{HY!6rxaM{Y+^xCBOnp`5tmhi#Sg9=G~t@l6PP4{;`dCXMkGbvvg`^@(AzA1#^ zk-4ezJx#B(+H2g@8MnZQ@)wW?q*S_#CEwOj+@QwgI2?JS?^xfpmDvO+e@a0LrcQaM zAV2K_8Z!biCIw?k}2~3h5{zFmA<_`~U z`6Qv9a9y>|oHRLQa$P~-bdsi!MV2Y4`xMnDzI!w|llH{uca6-?XiqgX74j)Yervj+ z-%p@G8fd>xfFS8exq2mZf2gc&OO&d7$)uuxECR8~R-y9rn}tnlUK}(6i^i}+OM_CP z=wQZik32JAEIk3wf1m1>WogharL=h~N-83YGy*3p0EVl=V^s-vVI%P3!wMl)s@7GM zG#gGOMGO6UUSw7Rh?vijXI!5ioPnzIW4k}Gjki#UsPq;nh0>VAf1p)%!jZkfQ^?bl z#>E(^K&fU(PMo_I`MONnRty58LERQELq3!#q{_#$?6-(^=c-`~anw`;lXevJ=l~mv zj&^_-xS5ppt5BR;6I=3mGwm2|He46eDS$ExeYx5NpYukBf#SIe`M)LwCCsP~PR}XZ zE7oj0P02`=pNxYWe^3%lUF(hWL@nw3U2G&ow!C&)!Y+wf}F#k4C@$a?vz z*Qz&Wt6@wBLBDItXQ^s6ZD=8&u!^-BRzsuRiQ-v;Nkc`Ety`G1!ppv;&!X1xI7ev--41;nGzk z1b3VC*EZ;-wID)cv71J6grSM6G-+=zdqee@)bUsS!|tun@}8o+H>%wZ0wY zVq{^KNR`o>Yq)9E5f~Jd^U>C6;hdyltw%*vOWqb#7IQK&g&PRD?!N^TlJAOC80r!V z!KGV8u`s$~Z6UCyWMdUB$!Jy>5UBbt<;>xYc#ffFU(y zqmuBvp)}twgbhDBp^p~)QT3!y4`MqsA$?p)uIq2SP_j!Hb36n^Z3EjuWxwm3VP5_0 zx?7&Q`hr)#IeR;Gc(U64eo2eF4)1I%ooHv;f9kxHK)H(Nd88Ewbl@}PRW(QW)0uSM*QZT(yo4J ze_xj;diKUi$XU4aQGU_^KIz|}K^XX@vbA{?Mq50j8cXeuSqUxmPwADR%s7*VfhLjC zbmc9)6*}Tk6<~HI*py~hPw{P@@r=p?;nWiAccx;l+WmDtl#)VPKP)S9q7xMRWe}Dc zm=JW&ud$84hSW8uD>|Bkuq)Mm?$`unf5@EIiN`szCzHMRKOKci-<4MH?wM5~StbZs z8_dhKz6z$74TAl#+)r`hGOVDds_ugX?R6DNvR4>`Q>M^mW?9Erq(#ZL;1ZtGu!6C# zccLkQ&Ec@PNJ}8lig4&3-;63(p45~GhRL=WEwN{F?cJ&dZP)yW{DJlg6xn?MFxpOi?Jfk;^G^HnO=eSjsh-p$16?Em_sMV%6QB?CyBl{kJo0x{ zA^!NH1QYU)14!BismVBK&G5C>#F_TNkPA%O=7wQ2WoGBcGr;^x9lc#;J_1O1D}n1i zw6GLi`}2T(cLulATn?33Namtme`4?3M9=ICJIt2ZHL+(p^%BZGLP{V=gi5Oz&`Ff0 zkuzKApq=$)GBUsuHM7QA?cza&kyo@gTN182+N%j&c@)GFUAB;8x%sun zd1O9)$%9Gn1DN8!J*u*w4~D^=dazMfL82E%*NO5+{qB~$kqJ~znj$N^gfgpOxK4Jq zg(%j+20!@v$uad^7h>aIe|q^a#*YkFXPRc(4@7tA`8bDPf@ivkTH3G-@SBxZD>nb@ zM0JM6-_fqi-SvG9Fqp#&)b}vc8KiBAuIhBATxVO3Fx@`^D~&*#1fm4sxcKRr`KVUL zjDjTuXXzs#NdottL;3~2fqR>tYsC2E0gEWx3?tN87Ip*S3K|uH=Ri$+w<`f-U7de`diEZ5FWaZM}=~Vrb4<%|dx7$oD6jQF5 z%t5i++)Ox(YjGTV(Zlpqa%leO7@4XcyGb3xg*O_D&MWEW-*RyuCCNDoHd1g&x+kD$ z&72I(4<*0Oi|Dqu z{*SQu%14sGE_8G*JZ|45PNNbfx3n6Ce=gP&)oXMdwr(J#e-_;)qFG_<7!q|WY#~8vnrV{uG!nQ2v@qGq3aSuH{hV(`1Sk}HV=mm3H_7UZQ zrxbCOgwBR2f3Q>^W0m$@9;|$%vT_C@tq2s_rw<4dna9NU5tS^n+5G^j^7Jx=jXES1 zHTf<9X=Ct*&Z138+clE>9_iujCk7;@HT{rXSFwsI8`S~Xsr}<(!#GExz_*17Kn&e> z9_$z%`||JuO$do!O1w$1z4h+K=dgdH(^Mbi2i&a`f7spx(o6Dg>#xoI`S@U$Q_&Ts z#j;QBFM0sSo$Sa@(+>QR7s1*A;7`*+T_WdIBiTJCFC%*^&cBXq8Y${_7JoT zSC;#Bw=mmM%2rKz^KJdXcF77P`83FIUzcbxf01uZXf&V{bJO&^R8?V`;PCCsa=?)g zR1lB}zAJsG3Z~>RlxPrIj}p+jpF{6vAh|R28Qm5`iZY+&Tb1A-xXV+J#UiA8Cgj*} z=Z&S?msv}r5^BYTahYO5V@P-5w}|$keX^W)e5YQeX~1*N&p+LJsqBiXUtpB7nJ{<~ ze^Bcowll6m-L}2HVsv~xz7L17j#^~umX*IhPTDL5p`!~mQITH=^{*ry$493i?J^Jk zLiGjV!FI#iSxxnJkv@3*Wm~?0p>;p??YESH2Yx`pqp4v3bz-%B&zV&Xp&+(?ieYkZ zxsjC{kl&FV?0QbO1{5+U{Wf3pom=zwe=wD0MakjjXyE=UPDd>%=yE;_`;%K{Z70;2 z`Htun4T;t^_o{M{8u>MM{OJ>YfLy(C%C45sYitxrw#>OA0M2ezqd}=1c)Yf3{hq zW8g6b#UHdlCGN=-&u9Ny4jAByHk~_~c1iIQ<0i~#btSh?asCpH5)I149Emj*ui9uL zf~LbDpXOK7%YN0fb5fM1eOtrFTwK500LA@SAPAEuf1kl)khHPuutR7>O@N3HI5%$g z(E2TqBr3gYAx;;)mqmcH%eZ^|f9g%V6=Rp0?I0MX)WOfl>|HmQLE19_LCku~}iauozHN zsV&p^Og5Jb%;RpEm=q4{f5NYHwR9hUano>knTN_KQIU9EK!V!qGAzfcMx1$vCri|^ zSE$gpLVV5B#s2qras+4EBxSnjqL&jmP+It9B=JA%PEUgX_oDj7U{tdc_ckHg<+3)u zm%^t-2+$+`dX7+sRjd7UQM)!{9r81mGeFVia6)GR^AxGAHAzd4fBO@i_nEFeY$Mh& z!kVoangwYJ@K~PSvu~-jw=81#3<{#@F$BOXhL=Fs;q~Vgjue#{Mc!&IVxKsyP8^W! zl;8J`E)d)YEK!sK6~7c#kb#+)6aD+4u-nMIEKp*Y!UyF(V4EvVt5ARmZd3x-vL^!C zI^_)F?;*&;;@8I2fOPd(n#(AhfMb5mDKyF3R?=5dBp}%mLc3flbEW3(K{*EuJJvHP z0sdqe%v~BKB9x@?K?ci3K%N~hNdfLrk<|rIjk>g8asX+DfA>s8ur0TdgYHUl^Oj@s z6_D?zkZ~cr1K> zsTA%+;$yuQep~V-e`aGtv?#ibSCxC0*>g<-6Y0KM zauZA{SL_W|XzCIRV|VTeMpRtyP!p|WKj%O;`yB_y#h^oOuIQPd1?`?C9vgJ5^f4S%&PUSY{I_o zVM-8zFK?&n-;7wF>}6xJIW3}~*c5YO4_HUdHnH2*ho%GL*f}l-j9c~sba%e1uHRMo z-BR&K2k={n?JfGctSweUv6<#^39@4yW@K+f*sCE9oY*#;MXQ0VhSAq9l@c}BrFbki zf9OCq;oZZ$DE z@Z^K!L1?Yx*s`|LAGFJ}20p0%>+`y8ZJNrDTOj`N4n@{H^RoM zPexkVlU4EqIIQj3H9ZUZj4d8s&jjiHf1W9WF^|IT^a-NMcdzqNQ<-@_F289kV_DTL zs#i_Hx%w8Sz0NCTrIBU?VqJWt6wY!7ZJg^{5yr}~F*|0fC6W{`ds4)AUw8=d#S-W_ zhE&DMHOg8d8Jq2poj-}t#PTLvu}buC@lIzz;zd9`aoM0IXjaO8eiAf?G>u|Ff4ZV7 zS_S6vW_kwerT}N|yPPRXfAN9{dARXo<D}YV(7yza{RHq}L z$=ix(0*@D``11)uXoxi_&Cf07+g~L(LHGp`0XSNSdqa7WnxnxK|f8TH<19c#dd;wTRETEutrapj+HfSB zK^~*e{8KvH`Q`TxovJNG5Iw=iFMYdcup*#iiJ$`GzL+68^Y<&a8E#W8e=7Gwi`CH( z#!;{&ZjUlRA6y)N@s%%Wg8K5Sj3q2Qjl z{;`g@R}qF&YwOB#_je;I|?X#D0Vea}Ayvw6=|FQ3@Qv;wN^H@^pG#%QRBL%+&G zWYGQrtOzDG`o-E-~FEm#qJnF0-4lg{{7RKzDTa}YB`mqMA#F8;OeUCTN**eEY;>f4H*xFZ%)eM`KW96KUzZKWUbSWW z*E*atmLIxQFHEs~#nc1;EqX~ z2}F;=x2gYT(q_PkYgj zFuEr9Jiv{3d~?JT7sqSFj`2Fe`dLaATV`uo<|;eOoN=UI{dQ8RnU2`#QR0H0yj_4wd98TN+z3MCfzz5Oe$^5{-0+GG_|(<@qJ~pp|@C0rrEIjF;1R z=+|Qyr&z~5Ev~Sh2RhAMWJ||w<)EtLL`=zUk&z-_e+KPmN0kv;8eS0IQBsU%5ETI^ z(4mnS$rV)S9S+q7)vT@~2WuvovZR=`uoL!PlI;V#Il$M_=_mn}SyIDRZrVe8Mx5)c zqsIz_5#L5W-KRrO@HY&fsLBGb$;znIV)Z7*&=Ntx9QPrdRxCtN?^kbYaLmPNC59j? zZtjR-e~xHN=Lbc)?RIwgO-*TDRzp)ekJoL@Du^ZddYs8%l7_`*jh0!D+TB7U@RXO( zncAW8Li}Wf$#pROJUa1Yg}-a0*KdOT*~Oq1xtS`nh*1K_$_kY|llUFn&oSs-uoxF@ z#j)pSo8uEO5wp5*EMHgqDYc|KIHbQnPgy9of0M}XIMfsTrSsWCq#QtkH{*4AZ@nH{ z@g)D&;Cv$ggP%g~N@xbEeAV@U7}fD5$oTtGy%l*TASps{Vv)Rmz!CqXe4a6!YOW9Z zc@}HXS1bX*eTn?G0OOTScJUcdECvWg>+pAtlms9S_k)$MLZQuRq@~A?>rlAjN3Q&g ze`pqp`Ud-$_zzp&caq>0w6*jZed#NiAOJmKW8Fd>cOlpW7W#Ox)M7^~SE5=7UoN)Z z)lG-?uP?+MUlf@Q9sw5h(Vav12{vajg^gotp(0O5LS6yv4brv2D#Bx<&q^UC@ZD9G zedCmNSC_+;OrIrn?fl(i_7u|%yhM}&e+ny&qFuB#v(drwXLfpMzxeBAw)RW84<{`v zS0@5(iyuo+{!{o>VfoLb%R03!%H`TEV8iwKAEkw-+3H==$I1tEIwocix(7`>RRkt{Cnme$| z?i9?V5ldp_75L{aquFPP6g?U*XZ5Yz`e3M7``Hj9Ez>4xr0w9e~JR?T0ikMD+~Pi zFqpoeH{Yl{;sewAq!}rA)YNjY>(KUqfd{{%@}I#*#GefMXLU<1JnQ0=e-E?w8)8N9 z=q&=O?=5_)v$BgkXpr*g3!!WpBvr(A7TW?vdfX+H3k&5y8<))SI0rh6Drd9Z@Hcsb zx-G8x0`VEmG&z>`Sl`%1@i`vaM$s<#K;F=A5o{MIZCG zO23op+F%lVP~O5fa&^GvV9ao?s76)-qH}JZh}nbN(CL`;;ZFHQj790L zO+N@t5PeVv`DN6+D~w|f7pxm&~lyriB6lRg3cKo;c!I7S*eW4YFkSCA;lboJMK4=!lAYKG4K?owNBl; zgo_ozpV|@`;5Ec3E=Vqk`B-c`8evyA=QH<0;2TS0F$7Jr&gu&#W@)kFlJn9!FN{mq z9jP<>#D?=4e|3@)!`l`gKAm?S8O}-8Sn{UsFaISK(S$bLm=v@M^eakejzX;qEw|t| zW>Ig9YuHekGj=tLaHSy*CGUAvP~oNF+M%=xtaN&5ipw%^qt7dfJ%2M`u2|x2?QgZ` znX7Z7!=%)aYL*B15M9v2J_*%_62_t7XfC}w7sF#=f7`({^xon@D;)BwZXJme0+IqS z5OFMF`K0g;^00fbebO%KX{9;q9A0;n19c}+Q;0=`ax{XyZTFqC{?wxjj@Ii8@pthf zy{|niXFo-{&XBIfjAYe2FY-r`#^G3^>S>!KM+j!U*!Y$xu!Sz7IqwMuvl4}}=acxV z4TgC3f5C}_)taoTLQ)k&xrzcO3sh=|U`%|fWgAsuY}UC|#mq@hFTz!Y$at%lE)0$+ zP${;bVv3KU<=(ye%tz1Da;uU|&AjnSPy21N7PAG0tzr5LMmskkI3Wx!M=e ze++djV#fiGviwne?I~uuYSRlxOyq;fbxnJK7V+`J6I~W-DtTD!$p!DFhCw~l9_3pO zvjx-g!;Qc=6x=jvl6a3CzHTdaw?eC(e^cUg((oxU zwQ2C8J=V{U`@8Py?Ps1I>E2qr?sgD_InmnOOsGVmxf5*O~ zER%x<89Nm5AhQbhd2Q4w2tF6?$|eRl9ozyT6s2IY3K=4fp{rSfKm$}mFTAC?zZJg7_O(O7k!_yr&gDXO!Q{}{B7_as0bn(9cC!Qm za}B7$R3D{a2tEc)4Jf-~*sg;WR@s=E6*AFPb~|R76I{59E0|x=@EiFMKLqQMw|4Sj zQ{=2tIaM3b7o_7=cA8GWRhXrb+S&hhZk?aE@-t^vJecC@Q$N7F3}D$Z=XVilab@9W zF9OwZxDM;~xAJ8jgGZ(?>DFSvuqfr(O>8uRW1rmywh{;0*5T` z+yi%mpwy4(9}w2cm_)kogo5DfF9V4l(P~;@#qPO@2nbUmJ%L-z#_=-alWCYAQIe+W ze@$Z7{l2du^f5o((KA`Bg=`i=<`hYc_ahp>>urcGH^8y{tlDM7`ND1Mc8T2OH}=HE z434TRs$`Pg6tmUIK9x#1Eqigw_H9cuqIb)zF-T_Q4r@;8j6IU9ydwwX=pqt;V0b0w zx)_I|u$Rcu$YRMUC@6p}0#yx;vX#vqf0gdsN)KXI-X})3!UN|&{<#{4fL63m^Ed7q zOIEYmg!y)Kg|Est;;!@2CKEsY* zrJv%C?iwwDixg3*(LoE>ATQ2()YJF_8}L%y7VxtK?v&g(v?l5vKK-v3^|+?LfBm$2 zR1nk9eZ&4B0bn-Smy(C!QQd&*>23SX9oL+Qo{n|V@qFK`<$l+(Li>4kCjpeM;g$bJ z3hmj>u?W4W;7^Ovog>#B;=2;@BdNG6l%s}ScMU4 zR%f(=^==tpc7dZAV`Si+hifNgg{ z7Evc**rt?}J2{{3kz6P3+-a7&J-gXGmvEyH*q4>9xeQ!%lw0ZtJ+v+3Of9{frC34Z zdD5%2Nn5vutYBEra4x9oSbw$tqPqJKwh5$e&=hmkt4aNQdn2PY!J4;gukF}MaeJzL z(3ZWYsFB4+w>PD$_YSpif2Nnh*}YV)WAiQeylEuD%YMpc^w9hBwcWUtFYfGW-WesonL< zx^c^o8JUk6sgEY=@_{3}Xa*6mq|a*fD|Rf=M9^UI^)?L*KsO^ zt1?v;Yp19o$$9oySf*I zJCdVmk!=p3or6i+ZCrIK2M!}itjH{y)8r4h93Gk_aYQ74taaL(4jVhqHa~u$WVA}v z?MzkuOxe#$%`QsSMM}kAma^KKGVPm|P7z}&)Lk&Y!O{k&6EW1~IwA0a=D{&-<>LHO zo>qQ~d0*_chF;Au>U{L#%`iW6-NU0K5a_n#Y{f%72$q>kUu%aOZ1Yj)k`F#F>FQFp z%o%W$M714%WGZ)Xh`1s%=5+e$!bdo`>rZE_f_I!%V4j@3Scko;xpPUsOppuNI*K+X zhUB`3zW}`5+z%w(oSu)L$7W$aGmV?&lP4&#KU-rxH#XPRUq9$kkB?&IfXjP@O0@0S z-S8&VhqQPGJH36@Nc-5|ttuh1(QF9Vmkle*t}_t03+=Pw$0IG-$IfaS%=qWMkBmroK+N(^Nw-nbW6|pGl7)buvnCm(~w3@(Zb@5h}(DQ z130BnvM}Ld-kpif3x1=-(@EHqt;e@C{^<69X2^fUw8hRatL)k6Bi|t{w6gp@qT=l^ zVr)U{&7BGZFmA!!Cc^oZm(^vMB5aTuK)ENFltOJOuYN(E|v^=3*K8!9^A* zHf~49kId2JTcXjumT%SG+3nG-^50}K-PLU$6S-CPE&U?J2>Jnfty5>o$?aZ+pb|s< zTJpOcNT6OL2-N%ptf7S-W;}5TF4%;B7W{yWY;qKBr@!O3>{f? z7)gEe#Iu&{PGJ8GEa$$TPKD~M<72>1lNa9+=2$Cn%T4n3s!W}7qtL@tanHo5ly1`k zAU2lp5mEJ~lr9yDOr27_hET#%i#P2b%fZV^j)SVptnr;2rAlT8)POxCjGwpt_-R=W zKJ`WGd}_P)uZ1nQ-+%sd15-bLYVHw#DP{zCX&F;{&{I2L(~twPGM*h;0O~U%aI8J? z;Q^dY=8-CXuWxnl&{P5oI+x}GBEMz@$PL-?B*ny^)=)sDauql+i1U!iZ0EY3jvX7I zVOqMs%mpxj!1Ct;;WyDlttE(V6gPaVY_K(!XB+eP9yGZNO1v}PqG_dnEm4)TDwWL} zFZ6b^4oZxhgp$*JIIL}cNw#1X%9fnp&Ptjtjd>e;=G*a6IIT+V7p$@kf~c;Gz;F0D zeK2jkN<%4PwA|03RsXj&;gzednk-Ex2aa)Ntr z7r0oHe1P4m65-!kv{KxEYWXnD{k?#xiTu1CHKK58A+i4?Gui3uRyD{sb!d?NIq=Rq z)T(mDEilfNG4A{Wjc`@Ircl7+Io=KqoW)O^wCjlu&6&*|H3 ziE|?La}>{Mvj}kyOEFUdogMM;=CW= zA8tMiH()MX#yc_<0t&J(1A~qp({x*5rW}>Qd$k@sQsK9l*z-Pw%a{Ap>FZvFKPuom z5IxV9^pn}+n0xzw{bu2)-}$|n<13F?+)zDyXexs8lp#V-`amEdi@!>`J`x3f4)1$r z6Tdd_Ovb!C19IJrr*GH zs7M#JV&|#5g$;&BxG&4HlOMlrR*gkR)rZR|V(;@Bhw(n|*YIc93T_4d$Os zl=$hwI#_?-3BW>dVTCL77*5Zi7B|))o8#{onXqPmB$Wz)LyBME0zNrzZJ{b)TF_?3 zKxYJum`yai7P-VcKV2!N-X7R5w}i6F;&6zTcu#qvp5pYLnG0p>TFffOiy_MGvdj)AAIXd|SF7UV>IH{V$k#`>i4k~$=f+4rwpZ*@}v}jYAL7U1eXx?iK56m2SE^dYKcmf= zb$A;!^%m&Usm{j3ikcU)*sUbG-~JfB*6JXdAzzgYeHK`K<)_j}^@1S5{#DSS&&146 z8{JpAFaz#m9iMw^5!jbJ#Rgx|P$No3X%#r26od@+{F0%3RHXA_)sB&|7K9$0Ha72n zG}~a|sZ}|?;%ar@$Werh$l=Q*ynz2UP**Mh!0P05 zPeP&Q-?@>#Dkv7Q{fUD~laz)a#BVQu(jRl;`qYOw0fKK;>0@Z+q@W@bRnfW3&69r> zjX!hQ@5F>vh6xyh$1~vA5%fgz@PtXhGWbQYu*vauTXfE`FbpvK zzJIsQB{?miZD%6G-TT#`XV5$5T^7l z0sxk^A^Gn9%0mBztq~GMn;Z!5ZdRG_9tN&Zo1*ngB6hGF-U`A41U%E_sje_>9| znqeyaFAB$I>BLTXq?}-UGmM1(p;s*azbP~SLU?}(u)kL`?e@#e)C)w+B zv6)Zl?+Dl2&BQe))f&RE(4Q-m!=pOE3I2^sX%pDwlkea7Tt{Z>e`B1~E`a{VXm-Kh z^7sFt zeI&PcC)It#!HXihg3LQRf6F>E<~@+aIEo~>$xr8ujB^t`>g!T)3X`i9k?R^=b`qAU zlYarp0;B-uySbxg4@M3cP7mL_|Es}LHuG~(<0}x;Gg|fi+phvKJ_9wsfBPqkOkpu~ zAsb(T{*P}SM`oYm6B|cX?m`m%zx72VGKIvpM#tWm$lisdyvk_$e-3K$1;BI#s@#Re zI)(htxBrfngPN}~scq1)cM|@Mqjeves#Mvdwix{?z}Y#kI)MBALJ*!;aK%&q)aU&T?Hg5|RCe`))(1KCW83~HPG zeNwJoOrH@r)`1MRf7YtGPHfJx1VubJfq%=BfBO7u|Bo-;YGqW|<4Gx6yYiDi(u zspSMxOqNMF_J&yIA|7xHIMzuNo>6$l-C41oAA>hY{;e<9DQtmBT8$B8AHz!ShDwQb z0-?rK-kEKVe;GKTR#?8BSI1Xs#h(k#cP0ZaR<nIsoF%mhF^~ zZEVX`DR}ySgajDZTK)Czu`g7GIk+e!Qzvk<%U|`=wjNqq} zWtPBHg4?|+DP>@7!)=3T%W!ey%;?W^5I65S?4E;wNq9)h!_(3trmhMO&!EzYMq4Zr zF`@W48eQ$UvNKJu4y!2+74lbH>pl)iD7GQRnBhLJ<3s5k?~v|#-TRpA~C1?zwUkdkiUer@`pPv0=%@B?#)Uc)J^{xGV>bN#c;>2IP_m% z=lgh@)8`7X%9oO2p$+#TwpHj%<7Z79cg6?W5LA_0aQY#$<_}bNx6j^N7j%=ktX+ss z%}Ze-mWf-1(?oV{idHk&t80yr2%{<1)zG=Zf8T>s#`)pi2x-S<)~M^p+ARd+DcI7@ zTuJ^~iRAw3Cb9PtCy&w!CP1`4Q!GmLXIM2a!M1#5PONxUR?4=s!pnK$<@aK@Z{q#* zbB>dDb11ax%7Tp_L*_!%b>UyL}y&wM87_bap-`_H(1_1?yL*LVN4MgyUu_?uhs+rut}Onrz$?}IDd6>Hg_OMf=| zc&k^kGvt@YzdOa?f8JLqj?!8AeY~v;%69|)Ir-+0F9)CBmN#KtzJ&YxKYj;@AY@dx zKDwPmXJasyNvk#-++(nvaK^;b&n>nZ_5YahyC8KkMthkn4v6N5*lIy+fio8D$ zSLR?Za@PJYTw;T3NQBS%lvgSj%(bH4HJE^)T&h*-%gPXTm`8Q3YN*KuwB#@wF{2n( zgdYtX{mBKhJ8g)&h=VO+<_cC9gB>PM(<_);cr@@xcF3T&!y8>4bEYloaQkJC>g)4f z#|L%&$qkcyx(MxV!8%26moi-oBY!`~5|{_e9IhPI6L$w3{Nec&tB<*Ri1$v;(K!ay z=R;|XpxA!pN{$>j8o?2?^sx!(=iU((o|p7|v;OCr{^x$jwQyI;#I-?{Kg^PL9i+Q^ zS$QA5pZ=Np@Y0Z<_MeM6LEn#;xC0%XQF#pzN`yAxR^aHt5I%~*3O0k;3x9(igYl6d zJU0!&%}0b+@BfTGV5``Rft-$j&GJUN1_-Z0rY_>4uKPG}#68emi8 z@fqD)!jsU)7lp>%M{GBV`Dh(g)4537ryw(LL1m>x&l5N~D6kyfUj7(=-z;;H;d_2F zpKR8v+WTOOn=ni#KHpDU?|(<$2K!wAsaZ$m?NywV00yaq#4$v7zy-zCl2d%|bbS%e zC{|ER$)W1;)>`*|G1!#aD_8y{3z1^R4#0hf*UuRyP{CmKs{U3dh)qpYS8N>bYp6KhV+*f=3 zGT@%#gg;(-oMHQa&*fGh@3-u~?(26J!8JCPb?vQ6rZ1tlT%&Eh*|qzS9G)2zRos+M z!sX@6wgOGNrnB(5Zhv)BzNoZab7*1)(;0$V3b4LhEmeMi4-Um!2(6w;SP3X+aWz47 zIfFz=<{aaP$!}Of?OVH6OMR=%BwKsC!awY8W{2s9*J97C(A)~8YoXEPoG)`1C9n)^ z&KY<$2jw$F^^~@5!K*mv>`pr!F1OPU-%e+6Z3Q#aIWvayeSeX1XKylR$j)F>;g9 zc4-5?-Eii_FMs9oCm)2I)x~&LL(bF2SEfk8PSAiZ!59WctQ)Y))U<^`=LM)@ZrT}3 zi@DmCO;CYvvfOF5D`Ztxk+)l6{hY3DrXghIAFPs9|5=>bM)i)?>fdQIp`S}^&hOD- zf;V)&^d9Mt*p~x7x{eR#WV^575I^Z0vh$f%`QQhK!G8z-!sc`rdGFWNfTiebsiq!$ zWA;ngyqNFptxR+P9i+Znrz<;Yc%=}#&((WX&ZEO5g)UDR6`9VY_D4Qph~209vDT*=g#K-P z%xm?@4!`Oby}Yoo-j0uF?yIQ@mPQD{Q(?dfutgLsy;g#|_gyK#=?IhJX1;x3%trCr z>Lq5+zUlNzbtOmUJ)@m;s+z1s)!ruuik}WOsJwtP{Y!#d(pz(bRIP<|3aaV5 zFh+v)UiHiLfW}Ue+P(WY=BvH!!uqxfFbPeBPjhRLvAl^;r?SYMa*s?&|U3N}5X!q&)E=SIGNXp+76Q z#156dhR12Fuvmyn-`=4|IWrM9p9I)4k$}&g7Exw=*4L)_4BYOwu}Tnsgtjzj-(ObF z#-g&XVDrP9YZ-@pA@Q@A_qa|d4D!j`2p{%2BO(Z6fHv#FXZ1FSlyYeBb+EtLY^!w!K(4K!^Wa;<0 z&R}$P^Yrr(!D(<}3+dw5qnn~~VvEquaPjkD^y%TIDnhV%%%NbDr2qeS zR0>etAv-P?xsrt#w=F$F#yA$$tOPAQ3TJZp?_QlSgv^D`Dk?{s_8CD zrqdaSG%yqA!{jwgK*tDa*eDIQDE)eIRiXFhcg5YTYWs71S&YWe<;)qh5R`O|pT)L$ zqjL;R@$WUJD|*iKi-#`N-I%lZW4`g^nZq%M#5Gbe0{E13KiS^x(=%_ z=OCBKc)F3>Ia7^(W!4~q{$n)q&{SJ38wrt6K_%0m4QHWyIwjeSlQnr zwOZk$VF$n&$b#-M&$_bb5mc%MtTe=sn{$l>F!(@Ku0*HSn(I~X4+FnA)Z@g{@$w2Y zz3=^DuYdcxmF|PSk8DBgC#?VZojGVHIL~3d0M9U2AXH)$*aBfGh>PRO7EDxHfU&=Y zDHwwBdGafjVv-6_gdaFUDGg{juAxS@)5M#AyZ-=V6__|#%JBnOK|Md=JK-a1BQT1s zD7RSU!=E41(MLgbeZZaP6D9%YI5S#O?S$KLIDgMPhR)uBEx3S5Ky_7f%d%%X;E*|C zvros~9bAKOuyzoAjvwYpwz~(biPyM}4|;v%I*+)uJY!TG?3Qw*i__i*ZuC|i20Wq& zYmCEMQ}06(?�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