From 31bd3185f2cad78fddb776f6875177b638a41339 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Fri, 27 Jun 2025 17:43:51 +0200 Subject: [PATCH 01/63] Use cuBLAS for large batches and quants with block size 16 (#559) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-cuda/mmq.cu | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/ggml/src/ggml-cuda/mmq.cu b/ggml/src/ggml-cuda/mmq.cu index 1788f7a4..deac4d8c 100644 --- a/ggml/src/ggml-cuda/mmq.cu +++ b/ggml/src/ggml-cuda/mmq.cu @@ -163,20 +163,33 @@ bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11) { bool mmq_supported; switch (type) { + case GGML_TYPE_Q2_K: mmq_supported = ne11 < 384; break; + case GGML_TYPE_Q3_K: + case GGML_TYPE_Q6_K: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + mmq_supported = ne11 < 1536; + break; + case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ4_K: + case GGML_TYPE_IQ5_K: + case GGML_TYPE_IQ6_K: + case GGML_TYPE_IQ2_K_R4: + case GGML_TYPE_IQ3_K_R4: + case GGML_TYPE_IQ4_K_R4: + case GGML_TYPE_IQ5_K_R4: + mmq_supported = ne11 < 1024; + break; case GGML_TYPE_Q4_0: case GGML_TYPE_Q4_1: case GGML_TYPE_Q5_0: case GGML_TYPE_Q5_1: case GGML_TYPE_Q6_0: case GGML_TYPE_Q8_0: - case GGML_TYPE_Q2_K: - case GGML_TYPE_Q3_K: case GGML_TYPE_Q4_K: case GGML_TYPE_Q5_K: - case GGML_TYPE_Q6_K: case GGML_TYPE_IQ2_XXS: - case GGML_TYPE_IQ2_XS: - case GGML_TYPE_IQ2_S: case GGML_TYPE_IQ3_XXS: case GGML_TYPE_IQ3_S: case GGML_TYPE_IQ1_S: @@ -188,22 +201,11 @@ bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11) { case GGML_TYPE_IQ5_KS: case GGML_TYPE_IQ5_KS_R4: case GGML_TYPE_IQ2_KS: - case GGML_TYPE_IQ2_K: - case GGML_TYPE_IQ3_K: - case GGML_TYPE_IQ4_K: - case GGML_TYPE_IQ5_K: - case GGML_TYPE_IQ6_K: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: mmq_supported = true; break; - case GGML_TYPE_IQ2_K_R4: - case GGML_TYPE_IQ3_K_R4: - case GGML_TYPE_IQ4_K_R4: - case GGML_TYPE_IQ5_K_R4: - mmq_supported = ne11 < 1024; - break; default: mmq_supported = false; break; From bce7697d64dc09d52dec468b7ed69c768967b8b6 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Fri, 27 Jun 2025 17:44:36 +0200 Subject: [PATCH 02/63] Remove what appears to be unnecessary asserts in ggml_cuda_cpy (#560) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-cuda/cpy.cu | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ggml/src/ggml-cuda/cpy.cu b/ggml/src/ggml-cuda/cpy.cu index 3b87cbad..312e0c09 100644 --- a/ggml/src/ggml-cuda/cpy.cu +++ b/ggml/src/ggml-cuda/cpy.cu @@ -570,8 +570,12 @@ void ggml_cuda_cpy(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, gg 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); + //if (ggml_nbytes(src0) > INT_MAX) { + // printf("%s: %s has %zu bytes\n", __func__, src0->name, ggml_nbytes(src0)); + //} + // These asserts appear to be unnecessary. Why were they added? + //GGML_ASSERT(ggml_nbytes(src0) <= INT_MAX); + //GGML_ASSERT(ggml_nbytes(src1) <= INT_MAX); const int64_t ne00 = src0->ne[0]; const int64_t ne01 = src0->ne[1]; From d5cd99f9c8f652452c8c5229b6ad95d3e80ef0ca Mon Sep 17 00:00:00 2001 From: firecoperana Date: Wed, 2 Jul 2025 01:49:42 -0500 Subject: [PATCH 03/63] Merge vulkan code from mainline up to commit of 6/28/2025 (#563) * Merge vulkan code from mainline up to commit of 6/28/2025 * Vulkan Optimizations and Fixes (#8959) * Optimize Vulkan REPEAT performance * Use Vulkan GLSL fused multiply-add instruction where possible * Add GGML_VULKAN_PERF option to output performance data per operator * Rework and fix Vulkan descriptor set and descriptor pool handling * Fix float32 concat f16 shader validation error * Add Vulkan GROUP_NORM eps parameter * Fix validation error with transfer queue memory barrier flags * Remove trailing whitespaces vulkan : do not use tensor->extra (#9407) * vulkan : do not use tensor->extra This patch allows using the Vulkan backend with the RPC backend as tensor->extra is no longer used. Ref: #8536 * Adapt GGML_VULKAN_CHECK_RESULTS to extra removal (#2) --------- Co-authored-by: 0cc4m # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan : fix build (#0) ggml-ci Improve Vulkan shader build system (#9239) * Improve Vulkan shader builds system - Add dependency to vulkan-shaders-gen to rebuild shaders when changing the shader compilation utility. - Add option to generate debug info for Vulkan shaders to provide shader source to Vulkan shader profiling tools * remove not required self dependency ggml : fix build break for the vulkan-debug (#9265) - windows build : Ok. - linux build : Ok. Signed-off-by: Changyeon Kim vulkan: correctly report support for OP_CONT (ggml/946) test-backend-ops fails because ggml_cont aborts when invoked passing an unsupported type. This commit makes ggml_cont tests pass Signed-off-by: Salvatore Mesoraca vulkan: add dryrun support to sin and cos ops (ggml/947) sin and cos failed test-backend-ops because they tried to dereference a context pointer that is null on dry runs. This commit prevents that segfault. Signed-off-by: Salvatore Mesoraca # Conflicts: # ggml/src/ggml-vulkan.cpp Overlap cmdbuffer creation and cmdbuffer execution in Vulkan backend by submitting smaller cmdbuffers early. (#9118) * Overlap cmdbuffer creation and cmdbuffer execution in Vulkan backend by submitting smaller cmdbuffers early. * fix compile issues * Fix issues where the last submit wasn't executed or handled properly. * remove trailing whitespace * Repair GGML_VULKAN_CHECK_RESULTS * Increase submit counter only if actual work has been submitted and increase submit count to 100. * Fix some nodes are not checked with GGML_VULKAN_CHECK_RESULTS enabled. # Conflicts: # ggml/src/ggml-vulkan.cpp Enable use to the rebar feature to upload buffers to the device. (#9251) vulkan : argsort barriers must be under uniform control flow (ggml/951) a return before a barrier (that happens only in some threads in a workgroup) leads to UB. While the old code actually works on some devices, it fails on some others (i.e. "smaller" GPUs). BTW, I think it would be better to set specialization constants when the graph is built, in that way the local workgroup could be sized appropriately. But it would take a lot of work. Signed-off-by: Salvatore Mesoraca vulkan : fix build for GGML_VULKAN_RUN_TESTS, add TFLOPS to log (ggml/961) vulkan : multithread pipeline creation (ggml/963) vulkan : mul_mat: fix UB with small warps (ggml/952) When the device's warp size is less than 16, it is possible for loadstride_a (mul_mm.comp:114) and loadstride_b (mul_mm.comp:115) to be set to 0. Because they are calculated as: the workgroup size, multiplied by LOAD_VEC_* (which can be 1) and divided by 16. And the workgroup size is set to be the same as the warp/subgroup size. The loadstride_* variables are used as increments in the loops that populate the buffers used for the multiplication. When they are 0 they cause an infinite loop. But infinite loops without side-effects are UB and the values of loadstride_* are known at compile time. So, the compiler quietly optimizes all the loops away. As a consequence, the buffers are not populated and the multiplication result is just a matrix with all elements set to 0. We prevent the UB by making sure that the workgroup size will never be less than 16, even if our device has a smaller warp size (e.g. 8). Signed-off-by: Salvatore Mesoraca vulkan : retry allocation with fallback flags (whisper/2451) Co-authored-by: Samuel Morris vulkan : improve ggml_vk_create_buffer error handling (#9898) vulkan: Fix newly added tests for permuted mul_mat and 1D im2col (#10226) vulkan: Throttle the number of shader compiles during the build step. (#10222) Fixes #9582 Spawning too many concurrent copies of glslc leads to "Failed to create pipes" errors on Linux. This change applies the same throttling we use for multithreaded pipeline creation. # Conflicts: # ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp vulkan: Optimize contiguous copies (#10254) * tests: Fix memory bandwidth calculation for perf tests Add a flops calculation for flash attention. Add one GGML_OP_CPY perf test. * vulkan: Optimize contiguous copies Add a variant of the copy shader for when the tensors are contiguous. Avoid the complex addressing calculations, and do four elements per invocation to hide some other overhead. Apply similar changes to the scale shader, since scale is always contiguous. Add a "progress bar" for shader compiles. # Conflicts: # tests/test-backend-ops.cpp vulkan: Use macros to make the mat mul pipeline creation more concise (#10259) Also add vk_matmul_pipeline2 to hold f16/f32 accumulator versions of a pipeline. This isn't really used yet. vulkan: Optimize binary ops (#10270) Reuse the index calculations across all of src0/src1/dst. Add a shader variant for when src0/src1 are the same dimensions and additional modulus for src1 aren't needed. Div/mod are slow, so add "fast" div/mod that have a fast path when the calculation isn't needed or can be done more cheaply. # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/vulkan-shaders/acc.comp ggml : vulkan logs (whisper/2547) vulkan: Optimize some mat-vec mul quant shaders (#10296) Compute two result elements per workgroup (for Q{4,5}_{0,1}). This reuses the B loads across the rows and also reuses some addressing calculations. This required manually partially unrolling the loop, since the compiler is less willing to unroll outer loops. Add bounds-checking on the last iteration of the loop. I think this was at least partly broken before. Optimize the Q4_K shader to vectorize most loads and reduce the number of bit twiddling instructions. Vulkan: Fix device info output format specifiers (#10366) * Vulkan: Fix device info output format specifiers * Vulkan: Use zu printf specifier for size_t instead of ld vulkan: remove use of null initializer (#10372) Seems like this isn't working for vulkan-over-metal when the array is sized by a spec constant. Maybe a spirv-cross limitation? vulkan: Optimize soft_max (#10301) * vulkan: Optimize soft_max Large soft_max could already saturate memory, but small/medium sizes were pretty slow. The bulk of the gains for them comes from using a smaller workgroup size, and making the workgroup size match the subgroup size also makes the barriers much cheaper. Cache some values in locals to avoid refetching/recomputing. And stamp out a few "template instantiations" so smaller cases will fully unroll. Add a missing early return for OOB rows. This happens when there are more than 512 rows and the dispatch is 512 x H. * vulkan: Further soft_max optimizations Restore the workgroup size of 512 case, use it for >1024. Use unrollable loops for more iteration counts. vulkan: further optimize mul_mat_vec using larger loads (#10387) * vulkan: Use pipeline_robustness to disable robustness in mul_mat_vec. Add some early returns for nonexistent rows in mul_mat_vec shaders. These can only be hit when dispatching a 2D grid of workgroups. Fix the logic for the 2D grid of workgroups to round up. Enable the pipeline robustness extension if it's available, and use it to disable robustness for these pipelines. The instructions to do the bounds checking contend for the same ALU resources as the bit twiddling dequant instructions. * vulkan: Add GLSL structure aliases for quant types to allow larger loads In Vulkan it's not possible to cast pointer types, so instead you have to declare an aliased binding for the memory with a different type. This commit adds aliases for the quant formats using 16b ints, and in a few places where the struct size is a multiple of 4 also using 32b ints. Currently only q4_k's aliases are used, but others will be used in subsequent commits. * vulkan: use larger loads in q5_k and q6_k shaders. Similar to the optimization I did in q4_k recently, this vectorizes some loads and reduces the number of bit twiddling instructions. * vulkan: use larger K step per iteration in mul_mat_vec. Add vec4 dequantization functions, and use them to do K=8 per iteration in mul_mat_vec. This uses 16b loads for the quant values and 128b loads for B which helps reduce the load on the memory system. The K_PER_ITER==2 logic is still there, just for F16/F32, and really only because they support unaligned sizes. Tweak the num_iters/unrolling logic to be simpler and catch a couple missed unrolling opportunities. vulkan: copy iq4_nl LUT into shared memory (#10409) vulkan: predicate max operation in soft_max shaders/soft_max (#10437) Fixes #10434 vulkan: Fix a vulkan-shaders-gen arugment parsing error (#10484) The vulkan-shaders-gen was not parsing the --no-clean argument correctly. Because the previous code was parsing the arguments which have a value only and the --no-clean argument does not have a value, it was not being parsed correctly. This commit can now correctly parse arguments that don't have values. vulkan: fix group_norm (#10496) Fix bad calculation of the end of the range. Add a backend test that covers the bad case (taken from stable diffusion). Fixes https://github.com/leejet/stable-diffusion.cpp/issues/439. # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: optimize Q2_K and Q3_K mul_mat_vec (#10459) vulkan: skip integer div/mod in get_offsets for batch_idx==0 (#10506) vulkan: further optimize q5_k mul_mat_vec (#10479) vulkan: Handle GPUs with less shared memory (#10468) There have been reports of failure to compile on systems with <= 32KB of shared memory (e.g. #10037). This change makes the large tile size fall back to a smaller size if necessary, and makes mul_mat_id fall back to CPU if there's only 16KB of shared memory. vulkan: define all quant data structures in types.comp (#10440) vulkan: get the first command buffer submitted sooner (#10499) This is an incremental improvement over #9118 to get work to the GPU a bit sooner. The first part is to start with a smaller number of nodes before the first submit, and ramp it up to the current 100 nodes/submit. The second part is to reduce the dryrun overhead for all the nodes that just need to request descriptor space. With these changes I get around 1-2% speedup on RTX 4070 combined with my old Haswell-era CPU. vulkan: Dynamic subgroup size support for Q6_K mat_vec (#10536) * subgroup 64 version with subgroup add. 15% faster scalable version tested for subgroup sizes 16-128 * check for subgroup multiple of 16 and greater than 16 * subgroup sizes are always a power of 2 (https://github.com/KhronosGroup/GLSL/issues/45) * force 16 sequential threads per block * make 16 subgroup size a constant vulkan: optimize and reenable split_k (#10637) Use vector loads when possible in mul_mat_split_k_reduce. Use split_k when there aren't enough workgroups to fill the shaders. vulkan: Implement "fast divide" (mul+shift) for unary ops like copy (#10642) vulkan: Add VK_NV_cooperative_matrix2 support for mul_mat and flash attention (#10206) # Conflicts: # ggml/src/vulkan-shaders/dequant_funcs_cm2.comp # ggml/src/vulkan-shaders/flash_attn_cm2.comp # ggml/src/vulkan-shaders/mul_mm_cm2.comp Vulkan: VK_KHR_cooperative_matrix support to speed up prompt processing (#10597) * Vulkan: Implement VK_KHR_cooperative_matrix support in the matrix matrix multiplication shader * Improve performance with better q4_k and q5_k dequant and store unrolling * Add Vulkan MUL_MAT and MUL_MAT_ID accumulator precision selection * Rework mulmat shader selection and compilation logic, avoid compiling shaders that won't get used by device * Vulkan: Implement accumulator switch for specific mul mat mat shaders * Vulkan: Unroll more loops for more mul mat mat performance * Vulkan: Add VK_AMD_shader_core_properties2 support to read Compute Unit count for split_k logic * Disable coopmat support on AMD proprietary driver * Remove redundant checks * Add environment variable GGML_VK_DISABLE_COOPMAT to disable VK_KHR_cooperative_matrix support * Fix rebase typo * Fix coopmat2 MUL_MAT_ID pipeline selection # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: compile a test shader in cmake to check for coopmat2 support (#10713) # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/ggml-vulkan/CMakeLists.txt # ggml/src/vulkan-shaders/test_coopmat2_support.comp Vulkan: fix NaN in tanh.comp with AMD proprietary driver on Windows (#10723) * Vulkan: fix NaN in tanh.comp * Faster NaN-free tanh vulkan: fix compile warnings (#10731) vulkan: disable spirv-opt for coopmat shaders (#10763) There are some bugs in the 1.3.296 SDK, so disable this. It isn't strictly necessary anyway. Add missing dependency on vulkan-shaders-gen, so shaders get recompiled when it changes. Fix coopmat support reporting when glslc doesn't support NV_coopmat2. vulkan: dynamic subgroup size for the remaining k quants (#10745) * q5_k q4_k q3_k q2_k q6_k multi row example * revert as multi row isnt faster for k quants vulkan: request round-to-even for fp16 in im2col/rope_head (#10767) Vulkan doesn't mandate a specific rounding mode, but the shader_float_controls feature allows rounding mode to be requested if the implementation supports it. Vulkan: Add VK_EXT_subgroup_size_control support to ensure full subgroups for coopmats (#10721) * Vulkan: Add VK_EXT_subgroup_size_control support to ensure full subgroups for coopmats * Fix subgroup size control extension support check Add accf32 and accf16 checks for coopmats * Also disable coopmats on amdvlk Vulkan: Use improved q4_k and q5_k dequant code in dequant shaders (#10798) vulkan: small mul_mat_vec optimizations (#10665) * double the number of rows per workgroup * Update ggml-vulkan.cpp * Vulkan: Add VK_EXT_subgroup_size_control support to ensure full subgroups for coopmats * only increase the number of rows for amd and subgroup size 64 * fix missing NUM_ROWS for mul_mat_vec_iq4_nl_f16_f32, untested * use subgroup min and max to check for gcn (requires https://github.com/ggerganov/llama.cpp/pull/10721) * manual merge ggml-vulkan.cpp * set min and max subgroup size in any case * Also double the number of rows for Intel GPUs Change Debug print name add GGML_ROPE_TYPE_MROPE rwkv6: add wkv6 support for Vulkan backend (#10829) * rwkv_wkv6 vulkan shader * RWKV_WKV6 Vulkan op tests passed Signed-off-by: Molly Sophia * Apply code format changes Signed-off-by: Molly Sophia * add [[unroll]] and remove unnecessary conditions * add uma support * fix erros in EditorConfig Checker --------- Signed-off-by: Molly Sophia Co-authored-by: Molly Sophia # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/vulkan-shaders/wkv6.comp vulkan: bugfixes for small subgroup size systems + llvmpipe test (#10809) * ensure mul mat shaders work on systems with subgroup size less than 32 more fixes add test * only s_warptile_mmq needs to be run with 32 threads or more # Conflicts: # .github/workflows/build.yml vulkan : fix soft_max.comp division by zero (whisper/2633) This change prevents a division by zero error when p.KY is 0. vulkan: optimize coopmat2 dequant functions (#10855) Change the code to do 16b loads when possible and extract the appropriate component late, so the code is effectively decoding a pair of elements and then selecting one. This can allow more commoning to happen in the compiler when neighboring elements are loaded. vulkan: build fixes for 32b (#10927) * vulkan: build fixes for 32b Should fix #10923 * vulkan: initialize some buffer/offset variables examples, ggml : fix GCC compiler warnings (#10983) Warning types fixed (observed under MSYS2 GCC 14.2.0): * format '%ld' expects argument of type 'long int', but argument has type 'size_t' * llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp:81:46: warning: missing initializer for member '_STARTUPINFOA::lpDesktop' [-Wmissing-field-initializers] (emitted for all struct field except first) # Conflicts: # examples/export-lora/export-lora.cpp vulkan: multi-row k quants (#10846) * multi row k quant shaders! * better row selection * more row choices * readjust row selection * rm_kq=2 by default vulkan: Use push constant offset to handle misaligned descriptors (#10987) vulkan: im2col and matmul optimizations for stable diffusion (#10942) * tests: Add im2col perf tests * vulkan: optimize im2col, more elements per thread * vulkan: increase small tile size for NV_coopmat2 * vulkan: change im2col to 512 elements per workgroup vulkan: optimize mul_mat for small values of N (#10991) Make the mul_mat_vec shaders support N>1 (as a spec constant, NUM_COLS) where the batch_strides are overloaded to hold the row strides. Put the loads from the B matrix in the innermost loop because it should cache better. Share some code for reducing the result values to memory in mul_mat_vec_base. # Conflicts: # tests/test-backend-ops.cpp fix: Vulkan shader gen binary path (#11037) Vulkan: Add device-specific blacklist for coopmat for the AMD proprietary driver (#11074) * Vulkan: Add device-specific blacklist for coopmat for the AMD proprietary driver * Add (TM) to AMD name check fix lora print Disable GL_KHR_cooperative_matrix Vulkan extension if not available. (#11117) * Disable GL_KHR_cooperative_matrix Vulkan extension if not available. * Perform Vulkan extensions checks in a more sensible order * Remove unnecessary #ifdef directive # Conflicts: # ggml/src/vulkan-shaders/test_coopmat_support.comp llama: add support for QRWKV6 model architecture (#11001) Vulkan: Fix float16 use on devices without float16 support + fix subgroup_size_control validation error (#11161) * Vulkan: Remove float16 use in shaders * Fix validation error about subgroup_size_control extension fix: ggml: fix vulkan-shaders-gen build (#10448) * fix: ggml: fix vulkan-shaders-gen build The vulkan-shaders-gen target was not being built correctly in case of cross-compilation. Other outputs need to be built for the cross compile target, but vulkan-shaders-gen needs to be built for the host. * refactor: ggml: Improve vulkan-shaders-gen toolchain setup - Add GGML_SHADERS_GEN_TOOLCHAIN CMake option. - Auto-detect host toolchain if not set. * refactor: ggml: Improve vulkan-shaders-gen toolchain setup Use configure_file to generate host_toolchain.cmake from template * fix: ggml: Fix compile error Fix compile error not finding vulkan-shaders-gen * fix: vulkan-shaders-gen build and path handling Fix build issues with vulkan-shaders-gen: - Add target dependency for correct build order - Use CMAKE_HOST_SYSTEM_NAME for executable suffix - Fix MSVC output directory in host toolchain - Normalize path handling for cross-compilation * fix: improve host compiler detection in vulkan shader build Improve host compiler detection for vulkan shader generation: - Add NO_CMAKE_FIND_ROOT_PATH to all compiler searches - Consolidate compiler detection logic - Fix Windows-specific MSVC detection - Ensure correct compiler search in cross-compilation * refactor: Simplify CMake function for detecting host compiler Simplified the CMake function to improve the process of detecting the host compiler. * fix: Remove unnecessary Vulkan library linkage in CMakeLists.txt Since `vulkan-shader-gen.cpp` only requires the `glslc` executable and not the Vulkan headers or libraries, CMakeLists.txt needs to be corrected. (See: ecc93d0558fc3ecb8a5af69d2ece02fae4710ade) * refactor: Rename host_toolchain.cmake.in - Rename host_toolchain.cmake.in to cmake/host-toolchain.cmake.in * refactor: GGML_VULKAN_SHADERS_GEN_TOOLCHAIN Rename the macro GGML_SHADERS_GEN_TOOLCHAIN to GGML_VULKAN_SHADERS_GEN_TOOLCHAIN # Conflicts: # ggml/src/ggml-vulkan/CMakeLists.txt vulkan: scale caching for k quants + misc fixes (#11081) * q6_k scale caching * 16 bit unpack * q4_k test (slow) * revert it * q3_k * q2_k * little stuff * try precalculating products of a and q2_k scales * Revert "try precalculating products of a and q2_k scales" This reverts commit 65110b81f23f66331a50c6e889a7c1ab9470a86b. * unpack should be u16, add vim swap to gitignore (about time) * better q4_k scales * q5_k * better q6_k with separate paths for all threads and partial threads in use, plus some more optimizations * q2_k better dequant * q3_k optimizations * q3_k use hmask simd from cpu avx version * make the caches happy * q3_k separate out calculation * q2_k separate out * little stuff * use calc_superblock everywhere * q2_k optimize scale calculation * more barriers vulkan: optimize coopmat2 q2_k dequant function (#11130) vulkan: optimize coopmat2 q4_k/q5_k dequant functions. (#11206) Do masking on whole dwords, fetch all scales at once. vulkan: support copy from f32 to q4_0/q4_1/q5_0/q5_1/q8_0/iq4_nl (#11166) * vulkan: support copy from f32 to q4_0/q4_1/q5_0/q5_1/q8_0/iq4_nl Shaders are based on cpy.cu. * vulkan: support copy from q4_0/q4_1/q5_0/q5_1/q8_0/iq4_nl to f32 * ggml: copy q->f32 assumes some contiguity in the destination # Conflicts: # ggml/src/ggml-cpu/ggml-cpu.c # ggml/src/vulkan-shaders/copy_from_quant.comp # ggml/src/vulkan-shaders/copy_to_quant.comp vulkan: fix coopmat2 flash attention for non-contiguous inputs (#11281) Add code similar to mul_mm_cm2 to force alignment of strides, to avoid a performance regression. Add noncontiguous FA tests in test-backend-ops. Fixes #11268. # Conflicts: # tests/test-backend-ops.cpp vulkan: fix coopmat2 validation failures (#11284) mul mat and flash attention shaders were loading f32 types directly into A/B matrices, which happens to work but is technically invalid usage. For FA, we can load it as an Accumulator matrix and convert and this is not in the inner loop and is cheap enough. For mul mat, it's more efficient to do this conversion in a separate pass and have the input(s) be f16. coopmat2 requires SPIR-V 1.6 (related using to LocalSizeId). LocalSizeId requires maintenance4 be enabled, and SPIR-V 1.6 requires Vulkan 1.3. vulkan: fix diag_mask_inf (#11323) With robustbufferaccess disabled, this shader was showing OOB stores. There is a bounds check in the code, but the workgrouop dimensions were reversed vs CUDA and it was running the wrong number of threads. So fix the workgroup dimensions and disable robustness for this pipeline. vulkan: sort shaders for more deterministic binary (#11315) Fixes #11306. Vulkan-run-test: fix mmq_wg_denoms (#11343) There should be a copy-and-paste error here. *mmq_wg_denoms should be used together with *warptile_mmq, instead of wg_denoms. vulkan: compile shaders on-demand (#11406) Reduce first-run startup time and memory consumption. Should fix #11339. vulkan: Catch pipeline creation failure and print an error message (#11436) * vulkan: Catch pipeline creation failure and print an error message Also, fix some warnings from my on-demand compile change. * vulkan: fix pipeline creation logging vulkan: implement initial support for IQ2 and IQ3 quantizations (#11360) * vulkan: initial support for IQ3_S * vulkan: initial support for IQ3_XXS * vulkan: initial support for IQ2_XXS * vulkan: initial support for IQ2_XS * vulkan: optimize Q3_K by removing branches * vulkan: implement dequantize variants for coopmat2 * vulkan: initial support for IQ2_S * vulkan: vertically realign code * port failing dequant callbacks from mul_mm * Fix array length mismatches * vulkan: avoid using workgroup size before it is referenced * tests: increase timeout for Vulkan llvmpipe backend --------- Co-authored-by: Jeff Bolz # Conflicts: # ggml/src/vulkan-shaders/dequant_iq2_s.comp # ggml/src/vulkan-shaders/dequant_iq2_xs.comp # ggml/src/vulkan-shaders/dequant_iq2_xxs.comp # ggml/src/vulkan-shaders/dequant_iq3_s.comp # ggml/src/vulkan-shaders/dequant_iq3_xxs.comp CUDA: non-contiguous (RMS) norm support (#11659) vulkan: use smaller combined allocations to avoid fragmentation (#11551) # Conflicts: # ggml/src/ggml-alloc.c vulkan: initial support for IQ4_XS quantization (#11501) # Conflicts: # ggml/src/vulkan-shaders/dequant_iq4_xs.comp vulkan: optimize coopmat2 iq2/iq3 callbacks (#11521) * vulkan: optimize coopmat2 iq2/iq3 callbacks * build: trigger CI on GLSL compute shader changes vulkan: print shared memory size (#11719) # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: account for lookup tables when checking shared memory size (#11502) # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: add environment variable GGML_VK_PREFER_HOST_MEMORY to avoid VRAM allocation (#11592) vulkan: linux builds + small subgroup size fixes (#11767) * mm subgroup size * upload vulkan x86 builds vulkan: initial support for IQ1_S and IQ1_M quantizations (#11528) * vulkan: initial support for IQ1_S and IQ1_M quantizations * vulkan: define MMV kernels for IQ1 quantizations * devops: increase timeout of Vulkan tests again * vulkan: simplify ifdef for init_iq_shmem # Conflicts: # ggml/src/vulkan-shaders/dequant_iq1_m.comp # ggml/src/vulkan-shaders/dequant_iq1_s.comp # ggml/src/vulkan-shaders/mul_mat_vec_iq1_m.comp # ggml/src/vulkan-shaders/mul_mat_vec_iq1_s.comp vulkan: support multi/vision rope, and noncontiguous rope (#11902) # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/vulkan-shaders/rope_multi.comp # ggml/src/vulkan-shaders/rope_vision.comp vulkan: implement several ops relevant for ggml_opt (#11769) * vulkan: support memset_tensor * vulkan: support GGML_OP_SUM * vulkan: implement GGML_OP_ARGMAX * vulkan: implement GGML_OP_SUB * vulkan: implement GGML_OP_COUNT_EQUAL * vulkan: implement GGML_OP_OPT_STEP_ADAMW * vulkan: fix check_results RWKV_WKV6 crash and memory leaks * vulkan: implement GGML_OP_REPEAT_BACK * tests: remove invalid test-backend-ops REPEAT_BACK tests * vulkan: fix COUNT_EQUAL memset using a fillBuffer command # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/vulkan-shaders/argmax.comp # ggml/src/vulkan-shaders/count_equal.comp # ggml/src/vulkan-shaders/opt_step_adamw.comp # ggml/src/vulkan-shaders/repeat_back.comp # ggml/src/vulkan-shaders/sub.comp # tests/test-backend-ops.cpp vulkan: implement more backpropagation operators (#11914) * vulkan: implement GGML_OP_ROPE_BACK * vulkan: implement GGML_OP_RMS_NORM_BACK * vulkan: implement GGML_OP_SILU_BACK * vulkan: implement GGML_OP_SOFTMAX_BACK # Conflicts: # ggml/src/vulkan-shaders/rms_norm_back.comp # ggml/src/vulkan-shaders/silu_back.comp # ggml/src/vulkan-shaders/soft_max_back.comp Add memset tensor in all backend interface SYCL: implement memset ggml backend buffer interface (#12580) * SYCL: implement memset ggml backend buffer interface * use GGML_ABORT macro * Do not wait for all queues to finish for memset operation # Conflicts: # ggml/src/ggml-sycl.cpp add OP sigmoid (#12056) Co-authored-by: Judd # Conflicts: # ggml/src/vulkan-shaders/sigmoid.comp vulkan: fix assertion when qy_needs_dequant (#12068) Looks like a copy/paste bug from qx_needs_dequant. vulkan: improve im2col (#11826) * vulkan: improve im2col performance vulkan: matmul dequantization improvements (#12015) * faster dequant for old quants * dont use unpack for iq4_nl * vec2 unpack for q8 vulkan: add specific MMV kernels for IQ2 and IQ3 quants + optimizations (#11595) * vulkan: implement specialized MMV kernels for IQ2 quantizations * vulkan: add MMV kernels for IQ3 quants * vulkan: Increase MMV batch size and unroll IQ LUT setup * vulkan: fix init_iq_shmem for WG sizes larger than tables * vulkan: common batch size for all I-quants # Conflicts: # ggml/src/vulkan-shaders/mul_mat_vec_iq2_s.comp # ggml/src/vulkan-shaders/mul_mat_vec_iq2_xs.comp # ggml/src/vulkan-shaders/mul_mat_vec_iq2_xxs.comp # ggml/src/vulkan-shaders/mul_mat_vec_iq3_s.comp # ggml/src/vulkan-shaders/mul_mat_vec_iq3_xxs.comp cuda/vulkan: specify fp32-only support for some operations in supports_op (ggml/1129) ggml-ci # Conflicts: # ggml/src/ggml-cuda.cu # tests/test-backend-ops.cpp mat vec double buffer (#12188) 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 Update build.yml for Windows Vulkan builder to use Vulkan 1.4.304 SDK for VK_NV_cooperative_matrix2 support (#12301) vulkan: Adjust coopmat2 tile sizes and selection heuristic (#12258) vulkan: Pad N dimension of B matrix for coopmat2 perf, to avoid bounds checking (#12273) * vulkan: Pad N dimension of B matrix for coopmat2 perf, to avoid bounds checking vulkan: use fp32 in coopmat2 q4_k dequant function (#12309) vulkan: subgroup size tuning (#12087) * vulkan: subgroup size test * Vulkan: Add device architecture enum and logic to recognize AMD generations * vulkan: use new architecture logic to specify subgroup size * Initial vulkan subgroup size tuning for RDNA3 * vulkan: commonize RDNA subgroup tuning * vulkan: override subgroup size if required_subgroup_size = 0 * vulkan: disable warp 32 for RDNA3 * vulkan: fine tuned RDNA1 subgroup sizes * vulkan: adjusted subgroup size map * vulkan: fixed RDNA2 subgroup map --------- Co-authored-by: 0cc4m vulkan: Add N/2 and N/4 optimized paths in coopmat2 shader (#12312) ggml-vulkan: remove unused find_program(glslc) (#12416) It's already found by FindVulkan.cmake in the parent CMakeLists Vulkan: Default to 1GB allocations instead of 4GB to avoid fragmentation and driver issues (#12434) vulkan: Submit once enough matmul work has been recorded (#12406) I've been seeing significantly worse performance for tg with flash attention enabled vs disabled, and it seems to be related to the submit heuristic. Change the heuristic to check how many bytes worth of weight matrix are used and flush every 100MB, and ramp up after the first few submits. This seems to resolve the issue, and also increases perf for non-FA a bit. vulkan: optimize iq1 coopmat2 dequant functions (#12427) vulkan: workaround for AMD Windows driver 16 bit unpack8 bug (#12472) Vulkan: RTE rounding for cpy to quant (#12480) * Vulkan: RTE rounding for cpy to quant Co-Authored-By: Jeff Bolz * remove trailing whitespace * avoid duplicating pipeline_cpy_f32_quant * fix copypasting issue * remove duplicated code --------- Co-authored-by: Jeff Bolz vulkan: Optimize mul_mat_vec p021 and nc shaders (#12505) * tests: add mul_mat perf/functional tests for p021/nc vulkan shaders * vulkan: Optimize mul_mat_vec p021 and nc shaders. These shaders are used in attention calculations, and when the KV cache grows large they start to dominate the run time. For the nc shader (which is called with large 'k' dimension), use unrolling and vector loads. For the p021 shader (which is called with large 'm' and small 'k' dimensions), take advantage of grouped query attention to reuse loads from the A matrix for the whole group, and reduce the number of workgroups (too much overhead from tiny dispatches). Using subgroupAdd in the p021 shader also helps, use that conditionally. # Conflicts: # tests/test-backend-ops.cpp vulkan: fix mul_mat_vec failure in backend tests (#12529) The OOB calculation could be wrong if the last iteration was during one of the unrolled loops. Adjust the unrolling counts to avoid this. Add a couple new backend tests that hit this failure on NVIDIA GPUs. vulkan: fix coopmat shader generation when cross-compiling (#12272) * vulkan: fix coopmat shader generation when cross-compiling Previously the status of coopmat{,2} support isn't passed to the vulkan-shaders-gen project building on the host, which leads to build failure because of the cross-compiling code expecting coopmat{,2} shaders that didn't get generated. Fix this by passing the coopmat{,2} support status to vulkan-shaders subproject. Signed-off-by: Icenowy Zheng * Only call coop-mat shaders once * Fix whitespace --------- Signed-off-by: Icenowy Zheng Co-authored-by: bandoti <141645996+bandoti@users.noreply.github.com> cmake: improve Vulkan cooperative matrix support checks (whisper/2966) Co-authored-by: Sandro Hanea cmake : fix whitespace (#0) Vulkan: Add DP4A MMQ and Q8_1 quantization shader (#12135) * Vulkan: Add DP4A MMQ and Q8_1 quantization shader * Add q4_0 x q8_1 matrix matrix multiplication support * Vulkan: Add int8 coopmat MMQ support * Vulkan: Add q4_1, q5_0 and q5_1 quants, improve integer dot code * Add GL_EXT_integer_dot_product check * Remove ggml changes, fix mmq pipeline picker * Remove ggml changes, restore Intel coopmat behaviour * Fix glsl compile attempt when integer vec dot is not supported * Remove redundant code, use non-saturating integer dot, enable all matmul sizes for mmq * Remove redundant comment * Fix integer dot check * Fix compile issue with unsupported int dot glslc * Update Windows build Vulkan SDK version # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/vulkan-shaders/mul_mmq.comp # ggml/src/vulkan-shaders/mul_mmq_funcs.comp # ggml/src/vulkan-shaders/quantize_q8_1.comp # ggml/src/vulkan-shaders/test_integer_dot_support.comp vulkan: fix build when glslc doesn't support coopmat (#12683) Vulkan: Fix mmq int dot float cache size (#12722) vulkan: Implement grouped query attention in the coopmat2 FA shader (#12559) When adjacent batches of Q share the same batches of K/V, batch them into the same workgroup. For example, when: dst(128,32,1,1) = FA(q(128,1,32,1), k(128,16640,8,1), v(128,16640,8,1)) previously we would run 32 workgroups computing 1 result each, now we will run 8 workgroups computing 4 results each. This doesn't directly translate to better performance (at least when you have >=32 SMs), but in a subsequent change I'll enable split_k which will scale much better with 4x fewer workgroups. cmake: remove caching from vulkan coopmat checks (#12719) vulkan: Implement split_k for coopmat2 flash attention. (#12627) When using group query attention, we have one workgroup per KV batch and this can be very few workgroups (e.g. just 8 in some models). Enable split_k to spread the work across SMs. This helps a lot when the KV cache is large. # Conflicts: # ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp vulkan: Fix missing cmake logic for dot product extension (#12721) vulkan: set cmake minimum and project name in vulkan-shaders (#12744) vulkan: Hybrid waitForFences/getFenceStatus to reduce fence latency (#12630) There seems to be a bubble waking up from waitForFences, which costs a few percent performance and also increased variance in performance. This change inserts an "almost_ready" fence when the graph is about 80% complete and we waitForFences for the almost_ready fence and then spin (with _mm_pauses) waiting for the final fence to be signaled. # Conflicts: # ggml/src/ggml-vulkan.cpp cmake: fix ggml-shaders-gen compiler paths containing spaces (#12747) fixes error for compiler paths with spaces Vulkan: Tune Vulkan mmq int dot shader for performance (#12767) vulkan: Use unclamped loads for flash attention mask (#12720) nem1 must be a multiple of GGML_KQ_MASK_PAD, and GGML_KQ_MASK_PAD is a multiple of the number of rows in the matrix. The KV dim is a multiple of the number of columns for the aligned shader. vulkan: fix NaN issue in flash attention shader (#12776) Use -FLT_MAX/2 rather than -inf as the initial value for computing the maximum. vulkan: Use fp16 for the flash attention P*V multiplication (#12783) This is consistent with the ggml-cuda behavior and the mul_mat fallback. vulkan: In coopmat2 mmq, load q4_k/q5_k scales through shared memory (#12833) q4_k and q5_k had a lot of redundant global loads where the same 16B of scale information is repeatedly loaded and decoded during each loop iteration. This change restructures the loops to more explicitly iterate over whole blocks in the outer loop (with unrolled inner loop) and to copy/decode the scale data into shared memory once at the start of each outer loop. The copy is pipelined so the scale load from global memory is relatively cheap. This improves q4_k/q5_k model prompt processing performance by around 5-7%. I briefly tried applying this to q6_k and q4_0, and it didn't help for q6_k and hurt for q4_0. The big "else" path in mul_mm_cm2.comp that had all the clamped/unclamped variants isn't used as often as it originally was (e.g. due to the padded_N change), so I trimmed it down to offset some of the new complexity of the semi-manual loop unrolling. vulkan: use aligned loads for flash attention mask (#12853) Rewrite the stride logic for the mask tensor in the FA shader to force the stride to be aligned, to allow using more efficient loads. vulkan: enable coopmat2 FA gqa and split_k optimizations more often (#12931) The grouped query attention optmization doesn't require a power of two ratio, the only thing relying on it was the modulo operation written as bitwise &. split_k need not depend on gqa_ratio - enable it any time there's only one workgroup in the X dimension. The shader gets the split index from the x coord, and multiple workgroups in the X dimension (pre-split) indicates a larger FA operation that wouldn't need splitting. vulkan: support noncontiguous rms_norm (#13031) # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: matmul gcn tuning (#13016) * tune matmul for gcn * this one is more power efficient * Update ggml/src/ggml-vulkan/ggml-vulkan.cpp Co-authored-by: 0cc4m * disable this tune for the proprietary driver --------- Co-authored-by: 0cc4m vulkan: use uint array index to avoid glslang bug (#13193) vulkan: Handle src1 batch dimension in non-contiguous mat-vec-mul shader (#13191) * vulkan: Handle src1 batch dimension in non-contiguous mat-vec-mul shader vulkan: Add bfloat16 support (#12554) * vulkan: Add bfloat16 support This adds bfloat16 matrix multiply support based on VK_KHR_shader_bfloat16. The extension is required for coopmat multiply support, but matrix-vector multiply trivially promotes bf16 to fp32 and doesn't require the extension. The copy/get_rows shaders also don't require the extension. It's probably possible to fall back to non-coopmat and promote to fp32 when the extension isn't supported, but this change doesn't do that. The coopmat support also requires a glslc that supports the extension, which currently requires a custom build. * vulkan: Support bf16 tensors without the bf16 extension or coopmat support Compile a variant of the scalar mul_mm shader that will promote the bf16 values to float, and use that when either the bf16 extension or the coopmat extensions aren't available. * vulkan: bfloat16 fixes (really works without bfloat16 support now) * vulkan: fix spirv-val failure and reenable -O # Conflicts: # ggml/src/vulkan-shaders/test_bfloat16_support.comp vulkan: Additional type support for unary, binary, and copy (#13266) Support f16->f32 copy. Support f16->f16 and f32->f32 unary ops. Support all combinations of f16/f32 for src0/src1/dst for add/sub/mul/div. # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: Allow up to 4096 elements for mul_mat_id row_ids (#13326) This assert fired running Qwen_Qwen3-30B-A3B-Q2_K.gguf: GGML_ASSERT(nei0 * nei1 <= 3072); The tensor is 8 x 512. Increase this array size to accommodate. vulkan: scalar flash attention implementation (#13324) * vulkan: scalar flash attention implementation * vulkan: always use fp32 for scalar flash attention * vulkan: use vector loads in scalar flash attention shader * vulkan: remove PV matrix, helps with register usage * vulkan: reduce register usage in scalar FA, but perf may be slightly worse * vulkan: load each Q value once. optimize O reduction. more tuning * vulkan: support q4_0/q8_0 KV in scalar FA * CI: increase timeout to accommodate newly-supported tests * vulkan: for scalar FA, select between 1 and 8 rows * vulkan: avoid using Float16 capability in scalar FA # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/vulkan-shaders/flash_attn.comp vulkan: workaround FA compile failures on macos (#13517) vulkan: KHR_coopmat flash attention (#13506) This shader uses coopmat1 to do the Q*K^T multiply. The P*V multiply is more difficult for various reasons so I haven't done it. Performance for this shader is around 2.5x better than for the scalar shader when doing prompt processing. Some of the benefit may be from other optimizations like staging through shared memory, or splitting by rows. # Conflicts: # ggml/src/vulkan-shaders/flash_attn_cm1.comp cmake: simplify vulkan shader test logic (#13263) vulkan: use scalar FA rather than coopmat2 when N==1 (#13554) Add pipeline_acc_f32 vulkan: move common FA code to flash_attn_base.comp (#13556) * vulkan: move common FA code to flash_attn_base.comp * vulkan: move common FA index/stride setup code to flash_attn_base.comp * build fix # Conflicts: # ggml/src/vulkan-shaders/flash_attn_base.comp cmake: use the current build config for vulkan-shaders-gen (#13595) * fix: use the current build config for `vulkan-shaders-gen` * fix: only pass a valid build type to `--config` Vulkan: Add f32 accumulator support to quantized mul mat to fix GLM4 32B incoherence (#13607) # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: fix warnings (#13626) * small fixes * remove ifdef use LOG_WARN to replace `std::cerr` (#13657) vulkan: Disable coopmat/coopmat2/bfloat extensions if glslc doesn't support it (#13696) vulkan: support CPY from any type to itself (#13695) Reuse the f16/f32 copy shaders, and just scale the number of elements according to the type size. add GGML_LOG_WARN vulkan: mark IM2COL as supporting non-contig (#13783) # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: use timestamp queries for GGML_VULKAN_PERF (#13817) Also change it to be controlled by an env var rather than cmake flag vulkan : Remove unexpected ; (ggml/1253) vulkan: fix warnings in perf logger querypool code (#13937) ggml-vulkan: adds support for op CONV_TRANSPOSE_1D (#13813) * * ggml-vulkan: adds op CONV_TRANSPOSE_1D * test-backend-ops: adds more spohisticated tests for CONV_TRANSPOSE_1D * Missing barrier added to shader. Number of additional tests reduced to 108. * * Fixes typo in variable name. * Removes extra whitespaces. * Adds int64->int32 casts to prevent possible warnings. * Problem size reduced in tests to pass tests with llvmpipe. * supports_op condition moved from unintended position # Conflicts: # ggml/src/ggml-vulkan.cpp # ggml/src/vulkan-shaders/conv_transpose_1d.comp vulkan: Enable VK_KHR_cooperative_matrix extension for Intel Xe2 GPUs (#14001) * allowing B580 and U9-288V * experimenting code to detect Xe2 * allowing coopmat only for Xe2 GPUs * fixed comment wording * fixed comment wording * removed unnecessary driver check Vulkan: Don't default to CPU device (like llvmpipe), even if no other device is available, to allow fallback to CPU backend (#14099) # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: force device 0 in CI (#14106) Add GGML_LOG_INFO vulkan: Track descriptor pools/sets per-context (#14109) Use the same descriptor set layout for all pipelines (MAX_PARAMETER_COUNT == 8) and move it to the vk_device. Move all the descriptor pool and set tracking to the context - none of it is specific to pipelines anymore. It has a single vector of pools and vector of sets, and a single counter to track requests and a single counter to track use. vulkan: Better thread-safety for command pools/buffers (#14116) This change moves the command pool/buffer tracking into a vk_command_pool structure. There are two instances per context (for compute+transfer) and two instances per device for operations that don't go through a context. This should prevent separate contexts from stomping on each other. # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: mutex around vkQueueSubmit (#14127) This fixes the remaining crash in test-thread-safety on my system. cmake: clean up external project logic for vulkan-shaders-gen (#14179) * Remove install step for vulkan-shaders-gen * Add install step to normalize msvc with make * Regenerate modified shaders at build-time # Conflicts: # .github/workflows/build.yml cmake: remove shader-gen step-targets from ggml-vulkan (#14226) * Remove step-targets from vulkan-shaders-gen * Unset DESTDIR when building vulkan-shaders-gen Vulkan: Set device max size for host memory to avoid OOM warning and fallback to CPU buffer (#14249) Add support for VK_EXT_debug_utils to add labels to Vulkan objects. (#13792) * Add support for VK_EXT_debug_utils to add labels to Vulkan objects. In step 1 compute pipelines are getting labeled. * remove #ifdef for debug utils and add queue marker. # Conflicts: # ggml/src/ggml-vulkan.cpp vulkan: update windows SDK in CI (#14334) vulkan: update windows SDK in release.yml (#14344) # Conflicts: # .github/workflows/release.yml cmake: regen vulkan shaders when shaders-gen sources change (#14398) * Add shaders-gen sources as target deps vulkan: Fix GGML_VULKAN_SHADER_DEBUG_INFO (#14427) This setting needs to be passed through to vulkan-shaders-gen vulkan: lock accesses of pinned_memory vector (#14333) vulkan: handle noncontig in the final case of ggml_vk_get_cpy_pipeline (#14378) Fix cuda build error test * remove new cpu backend and yml files * remove new op and GGML_ROPE_TYPE_NEOX * fix build error * change cmake file to add matrix operation * remove coopmat2 check in flash attention * print gpu info for vulkan * disable fuse to recover vulkan performance --------- Co-authored-by: 0cc4m Co-authored-by: firecoperana --- .gitignore | 1 + Makefile | 4 + examples/cvector-generator/mean.hpp | 2 +- examples/cvector-generator/pca.hpp | 2 +- examples/export-lora/export-lora.cpp | 6 +- ggml/CMakeLists.txt | 4 + ggml/include/ggml-vulkan.h | 2 +- ggml/include/ggml.h | 3 +- ggml/src/CMakeLists.txt | 169 +- ggml/src/cmake/host-toolchain.cmake.in | 15 + ggml/src/ggml-alloc.c | 6 +- ggml/src/ggml-backend-impl.h | 1 + ggml/src/ggml-backend.c | 24 + ggml/src/ggml-cann.cpp | 1 + ggml/src/ggml-cuda.cu | 21 +- ggml/src/ggml-kompute.cpp | 1 + ggml/src/ggml-metal.m | 7 + ggml/src/ggml-rpc.cpp | 1 + ggml/src/ggml-sycl.cpp | 64 +- ggml/src/ggml-vulkan.cpp | 7487 ++++++++++++----- ggml/src/ggml.c | 1 + ggml/src/vulkan-shaders/CMakeLists.txt | 24 + ggml/src/vulkan-shaders/acc.comp | 29 + ggml/src/vulkan-shaders/add.comp | 25 +- ggml/src/vulkan-shaders/argmax.comp | 51 + ggml/src/vulkan-shaders/argsort.comp | 10 +- ggml/src/vulkan-shaders/clamp.comp | 6 +- ggml/src/vulkan-shaders/concat.comp | 10 +- ggml/src/vulkan-shaders/contig_copy.comp | 49 + .../src/vulkan-shaders/conv_transpose_1d.comp | 98 + ggml/src/vulkan-shaders/copy.comp | 11 +- ggml/src/vulkan-shaders/copy_from_quant.comp | 51 + ggml/src/vulkan-shaders/copy_to_quant.comp | 242 + ggml/src/vulkan-shaders/cos.comp | 17 + ggml/src/vulkan-shaders/count_equal.comp | 31 + ggml/src/vulkan-shaders/dequant_funcs.comp | 422 +- .../src/vulkan-shaders/dequant_funcs_cm2.comp | 699 ++ ggml/src/vulkan-shaders/dequant_iq1_m.comp | 42 + ggml/src/vulkan-shaders/dequant_iq1_s.comp | 35 + ggml/src/vulkan-shaders/dequant_iq2_s.comp | 44 + ggml/src/vulkan-shaders/dequant_iq2_xs.comp | 43 + ggml/src/vulkan-shaders/dequant_iq2_xxs.comp | 48 + ggml/src/vulkan-shaders/dequant_iq3_s.comp | 39 + ggml/src/vulkan-shaders/dequant_iq3_xxs.comp | 49 + ggml/src/vulkan-shaders/dequant_iq4_nl.comp | 2 + ggml/src/vulkan-shaders/dequant_iq4_xs.comp | 34 + ggml/src/vulkan-shaders/dequant_q4_k.comp | 64 +- ggml/src/vulkan-shaders/dequant_q5_k.comp | 68 +- ggml/src/vulkan-shaders/diag_mask_inf.comp | 2 +- ggml/src/vulkan-shaders/div.comp | 23 +- ggml/src/vulkan-shaders/flash_attn.comp | 337 + ggml/src/vulkan-shaders/flash_attn_base.comp | 162 + ggml/src/vulkan-shaders/flash_attn_cm1.comp | 360 + ggml/src/vulkan-shaders/flash_attn_cm2.comp | 267 + .../flash_attn_split_k_reduce.comp | 59 + .../vulkan-shaders/generic_binary_head.comp | 62 +- .../vulkan-shaders/generic_unary_head.comp | 55 +- ggml/src/vulkan-shaders/get_rows.comp | 19 +- ggml/src/vulkan-shaders/get_rows_quant.comp | 10 + ggml/src/vulkan-shaders/group_norm.comp | 2 +- ggml/src/vulkan-shaders/im2col.comp | 87 +- ggml/src/vulkan-shaders/mul.comp | 23 +- .../mul_mat_split_k_reduce.comp | 31 +- ggml/src/vulkan-shaders/mul_mat_vec.comp | 192 +- ggml/src/vulkan-shaders/mul_mat_vec_base.comp | 51 +- .../src/vulkan-shaders/mul_mat_vec_iq1_m.comp | 82 + .../src/vulkan-shaders/mul_mat_vec_iq1_s.comp | 79 + .../src/vulkan-shaders/mul_mat_vec_iq2_s.comp | 90 + .../vulkan-shaders/mul_mat_vec_iq2_xs.comp | 87 + .../vulkan-shaders/mul_mat_vec_iq2_xxs.comp | 87 + .../src/vulkan-shaders/mul_mat_vec_iq3_s.comp | 90 + .../vulkan-shaders/mul_mat_vec_iq3_xxs.comp | 88 + ggml/src/vulkan-shaders/mul_mat_vec_nc.comp | 75 +- ggml/src/vulkan-shaders/mul_mat_vec_p021.comp | 137 +- ggml/src/vulkan-shaders/mul_mat_vec_q2_k.comp | 157 +- ggml/src/vulkan-shaders/mul_mat_vec_q3_k.comp | 150 +- ggml/src/vulkan-shaders/mul_mat_vec_q4_k.comp | 201 +- ggml/src/vulkan-shaders/mul_mat_vec_q5_k.comp | 228 +- ggml/src/vulkan-shaders/mul_mat_vec_q6_k.comp | 155 +- ggml/src/vulkan-shaders/mul_mm.comp | 593 +- ggml/src/vulkan-shaders/mul_mm_cm2.comp | 441 + ggml/src/vulkan-shaders/mul_mmq.comp | 442 + ggml/src/vulkan-shaders/mul_mmq_funcs.comp | 99 + ggml/src/vulkan-shaders/opt_step_adamw.comp | 42 + ggml/src/vulkan-shaders/pad.comp | 4 +- ggml/src/vulkan-shaders/pool2d.comp | 74 + ggml/src/vulkan-shaders/quantize_q8_1.comp | 77 + ggml/src/vulkan-shaders/relu.comp | 2 +- ggml/src/vulkan-shaders/repeat.comp | 26 + ggml/src/vulkan-shaders/repeat_back.comp | 37 + ggml/src/vulkan-shaders/rms_norm.comp | 32 +- ggml/src/vulkan-shaders/rms_norm_back.comp | 55 + ggml/src/vulkan-shaders/rope_head.comp | 14 + ggml/src/vulkan-shaders/rope_multi.comp | 60 + ggml/src/vulkan-shaders/rope_neox.comp | 34 +- ggml/src/vulkan-shaders/rope_norm.comp | 34 +- ggml/src/vulkan-shaders/rope_vision.comp | 47 + ggml/src/vulkan-shaders/scale.comp | 20 +- ggml/src/vulkan-shaders/sigmoid.comp | 20 + ggml/src/vulkan-shaders/silu_back.comp | 26 + ggml/src/vulkan-shaders/sin.comp | 17 + ggml/src/vulkan-shaders/soft_max.comp | 117 +- ggml/src/vulkan-shaders/soft_max_back.comp | 50 + ggml/src/vulkan-shaders/square.comp | 6 +- ggml/src/vulkan-shaders/sub.comp | 29 + ggml/src/vulkan-shaders/tanh.comp | 3 +- .../vulkan-shaders/test_bfloat16_support.comp | 7 + .../vulkan-shaders/test_coopmat2_support.comp | 7 + .../vulkan-shaders/test_coopmat_support.comp | 7 + .../test_integer_dot_support.comp | 7 + ggml/src/vulkan-shaders/types.comp | 1287 ++- ggml/src/vulkan-shaders/upscale.comp | 4 +- .../src/vulkan-shaders/vulkan-shaders-gen.cpp | 548 +- ggml/src/vulkan-shaders/wkv6.comp | 87 + include/llama.h | 2 +- src/llama.cpp | 4 +- 116 files changed, 14579 insertions(+), 3295 deletions(-) create mode 100644 ggml/src/cmake/host-toolchain.cmake.in create mode 100644 ggml/src/vulkan-shaders/acc.comp create mode 100644 ggml/src/vulkan-shaders/argmax.comp create mode 100644 ggml/src/vulkan-shaders/contig_copy.comp create mode 100644 ggml/src/vulkan-shaders/conv_transpose_1d.comp create mode 100644 ggml/src/vulkan-shaders/copy_from_quant.comp create mode 100644 ggml/src/vulkan-shaders/copy_to_quant.comp create mode 100644 ggml/src/vulkan-shaders/cos.comp create mode 100644 ggml/src/vulkan-shaders/count_equal.comp create mode 100644 ggml/src/vulkan-shaders/dequant_funcs_cm2.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq1_m.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq1_s.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq2_s.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq2_xs.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq2_xxs.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq3_s.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq3_xxs.comp create mode 100644 ggml/src/vulkan-shaders/dequant_iq4_xs.comp create mode 100644 ggml/src/vulkan-shaders/flash_attn.comp create mode 100644 ggml/src/vulkan-shaders/flash_attn_base.comp create mode 100644 ggml/src/vulkan-shaders/flash_attn_cm1.comp create mode 100644 ggml/src/vulkan-shaders/flash_attn_cm2.comp create mode 100644 ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp create mode 100644 ggml/src/vulkan-shaders/mul_mat_vec_iq1_m.comp create mode 100644 ggml/src/vulkan-shaders/mul_mat_vec_iq1_s.comp create mode 100644 ggml/src/vulkan-shaders/mul_mat_vec_iq2_s.comp create mode 100644 ggml/src/vulkan-shaders/mul_mat_vec_iq2_xs.comp create mode 100644 ggml/src/vulkan-shaders/mul_mat_vec_iq2_xxs.comp create mode 100644 ggml/src/vulkan-shaders/mul_mat_vec_iq3_s.comp create mode 100644 ggml/src/vulkan-shaders/mul_mat_vec_iq3_xxs.comp create mode 100644 ggml/src/vulkan-shaders/mul_mm_cm2.comp create mode 100644 ggml/src/vulkan-shaders/mul_mmq.comp create mode 100644 ggml/src/vulkan-shaders/mul_mmq_funcs.comp create mode 100644 ggml/src/vulkan-shaders/opt_step_adamw.comp create mode 100644 ggml/src/vulkan-shaders/pool2d.comp create mode 100644 ggml/src/vulkan-shaders/quantize_q8_1.comp create mode 100644 ggml/src/vulkan-shaders/repeat.comp create mode 100644 ggml/src/vulkan-shaders/repeat_back.comp create mode 100644 ggml/src/vulkan-shaders/rms_norm_back.comp create mode 100644 ggml/src/vulkan-shaders/rope_multi.comp create mode 100644 ggml/src/vulkan-shaders/rope_vision.comp create mode 100644 ggml/src/vulkan-shaders/sigmoid.comp create mode 100644 ggml/src/vulkan-shaders/silu_back.comp create mode 100644 ggml/src/vulkan-shaders/sin.comp create mode 100644 ggml/src/vulkan-shaders/soft_max_back.comp create mode 100644 ggml/src/vulkan-shaders/sub.comp create mode 100644 ggml/src/vulkan-shaders/test_bfloat16_support.comp create mode 100644 ggml/src/vulkan-shaders/test_coopmat2_support.comp create mode 100644 ggml/src/vulkan-shaders/test_coopmat_support.comp create mode 100644 ggml/src/vulkan-shaders/test_integer_dot_support.comp create mode 100644 ggml/src/vulkan-shaders/wkv6.comp diff --git a/.gitignore b/.gitignore index 5ae03020..471ba6aa 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ *.metallib *.o *.so +*.swp *.tmp # IDE / OS diff --git a/Makefile b/Makefile index a7a53b1a..f7a40c2b 100644 --- a/Makefile +++ b/Makefile @@ -774,6 +774,10 @@ ifdef GGML_VULKAN_MEMORY_DEBUG MK_CPPFLAGS += -DGGML_VULKAN_MEMORY_DEBUG endif +ifdef GGML_VULKAN_PERF + MK_CPPFLAGS += -DGGML_VULKAN_PERF +endif + ifdef GGML_VULKAN_VALIDATE MK_CPPFLAGS += -DGGML_VULKAN_VALIDATE endif diff --git a/examples/cvector-generator/mean.hpp b/examples/cvector-generator/mean.hpp index 16be5ce3..4eeac1ee 100644 --- a/examples/cvector-generator/mean.hpp +++ b/examples/cvector-generator/mean.hpp @@ -15,7 +15,7 @@ static void run( for (size_t il = 0; il < v_input.size(); ++il) { // prepare output vector struct ggml_tensor * ctrl_out = v_output[il]; - ggml_format_name(ctrl_out, "direction.%ld", il+1); + ggml_format_name(ctrl_out, "direction.%zu", il+1); // calculate mean vector struct ggml_tensor * t_layer = v_input[il]; diff --git a/examples/cvector-generator/pca.hpp b/examples/cvector-generator/pca.hpp index 6ec3141a..85be07dd 100644 --- a/examples/cvector-generator/pca.hpp +++ b/examples/cvector-generator/pca.hpp @@ -312,7 +312,7 @@ static void run_pca( // prepare output vector struct ggml_tensor * ctrl_out = v_output[il]; - ggml_format_name(ctrl_out, "direction.%ld", il+1); + ggml_format_name(ctrl_out, "direction.%zu", il+1); // run power_iteration params.i_layer = il; diff --git a/examples/export-lora/export-lora.cpp b/examples/export-lora/export-lora.cpp index 3176d6e2..1aaf281e 100644 --- a/examples/export-lora/export-lora.cpp +++ b/examples/export-lora/export-lora.cpp @@ -251,8 +251,8 @@ struct lora_merge_ctx { fout.write((const char *)data.data(), data.size()); } - printf("%s : merged %ld tensors with lora adapters\n", __func__, n_merged); - printf("%s : wrote %ld tensors to output file\n", __func__, base_to_out_tensors.size()); + printf("%s : merged %zu tensors with lora adapters\n", __func__, n_merged); + printf("%s : wrote %zu tensors to output file\n", __func__, base_to_out_tensors.size()); } void copy_tensor(struct ggml_tensor * base) { @@ -334,7 +334,7 @@ struct lora_merge_ctx { const float scale = alpha ? adapters[i]->scale * alpha / rank : adapters[i]->scale; delta = ggml_scale(ctx0, delta, scale); cur = ggml_add(ctx0, delta, cur); - printf("%s : + merging from adapter[%ld] type=%s\n", __func__, i, ggml_type_name(inp_a[i]->type)); + printf("%s : + merging from adapter[%zu] type=%s\n", __func__, i, ggml_type_name(inp_a[i]->type)); printf("%s : input_scale=%f calculated_scale=%f rank=%d\n", __func__, adapters[i]->scale, scale, (int) inp_b[i]->ne[0]); } cur = ggml_cast(ctx0, cur, out->type); diff --git a/ggml/CMakeLists.txt b/ggml/CMakeLists.txt index 5c891105..4dbd8d34 100644 --- a/ggml/CMakeLists.txt +++ b/ggml/CMakeLists.txt @@ -143,6 +143,7 @@ option(GGML_VULKAN "ggml: use Vulkan" option(GGML_VULKAN_CHECK_RESULTS "ggml: run Vulkan op checks" OFF) option(GGML_VULKAN_DEBUG "ggml: enable Vulkan debug output" OFF) option(GGML_VULKAN_MEMORY_DEBUG "ggml: enable Vulkan memory debug output" OFF) +option(GGML_VULKAN_SHADER_DEBUG_INFO "ggml: enable Vulkan shader debug info" OFF) option(GGML_VULKAN_VALIDATE "ggml: enable Vulkan validation" OFF) option(GGML_VULKAN_RUN_TESTS "ggml: run Vulkan tests" OFF) option(GGML_KOMPUTE "ggml: use Kompute" OFF) @@ -160,6 +161,9 @@ option(GGML_SYCL_F16 "ggml: use 16 bit floats for sycl ca set (GGML_SYCL_TARGET "INTEL" CACHE STRING "ggml: sycl target device") +# toolchain for vulkan-shaders-gen +set (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN "" CACHE FILEPATH "ggml: toolchain file for vulkan-shaders-gen") + # extra artifacts option(GGML_BUILD_TESTS "ggml: build tests" ${GGML_STANDALONE}) option(GGML_BUILD_EXAMPLES "ggml: build examples" ${GGML_STANDALONE}) diff --git a/ggml/include/ggml-vulkan.h b/ggml/include/ggml-vulkan.h index af661c2d..e3e62864 100644 --- a/ggml/include/ggml-vulkan.h +++ b/ggml/include/ggml-vulkan.h @@ -10,7 +10,7 @@ extern "C" { #define GGML_VK_NAME "Vulkan" #define GGML_VK_MAX_DEVICES 16 -GGML_API void ggml_vk_instance_init(void); +GGML_API GGML_CALL void ggml_vk_instance_init(void); // backend API GGML_API GGML_CALL ggml_backend_t ggml_backend_vk_init(size_t dev_num); diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index 0a14ba57..67551eb2 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -628,7 +628,6 @@ extern "C" { GGML_OP_WIN_UNPART, GGML_OP_GET_REL_POS, GGML_OP_ADD_REL_POS, - GGML_OP_UNARY, GGML_OP_MAP_UNARY, @@ -644,7 +643,6 @@ extern "C" { GGML_OP_CROSS_ENTROPY_LOSS, GGML_OP_CROSS_ENTROPY_LOSS_BACK, - GGML_OP_COUNT, }; @@ -1130,6 +1128,7 @@ extern "C" { struct ggml_context * ctx, struct ggml_tensor * a); + // if a is the same shape as b, and a is not parameter, return a // otherwise, return a new tensor: repeat(a) to fit in b GGML_API struct ggml_tensor * ggml_repeat( diff --git a/ggml/src/CMakeLists.txt b/ggml/src/CMakeLists.txt index 4f181841..4f9428f9 100644 --- a/ggml/src/CMakeLists.txt +++ b/ggml/src/CMakeLists.txt @@ -643,12 +643,85 @@ if (GGML_RPC) set(GGML_SOURCES_RPC ggml-rpc.cpp) endif() +find_package(Vulkan COMPONENTS glslc REQUIRED) + +function(detect_host_compiler) + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + find_program(HOST_C_COMPILER NAMES cl gcc clang NO_CMAKE_FIND_ROOT_PATH) + find_program(HOST_CXX_COMPILER NAMES cl g++ clang++ NO_CMAKE_FIND_ROOT_PATH) + else() + find_program(HOST_C_COMPILER NAMES gcc clang NO_CMAKE_FIND_ROOT_PATH) + find_program(HOST_CXX_COMPILER NAMES g++ clang++ NO_CMAKE_FIND_ROOT_PATH) + endif() + set(HOST_C_COMPILER "${HOST_C_COMPILER}" PARENT_SCOPE) + set(HOST_CXX_COMPILER "${HOST_CXX_COMPILER}" PARENT_SCOPE) +endfunction() + +# Function to test shader extension support +# Parameters: +# EXTENSION_NAME - Name of the extension to test (e.g., "GL_EXT_integer_dot_product") +# TEST_SHADER_FILE - Path to the test shader file +# RESULT_VARIABLE - Name of the variable to set (ON/OFF) based on test result +function(test_shader_extension_support EXTENSION_NAME TEST_SHADER_FILE RESULT_VARIABLE) + execute_process( + COMMAND ${Vulkan_GLSLC_EXECUTABLE} -o - -fshader-stage=compute --target-env=vulkan1.3 "${TEST_SHADER_FILE}" + OUTPUT_VARIABLE glslc_output + ERROR_VARIABLE glslc_error + ) + + if (${glslc_error} MATCHES ".*extension not supported: ${EXTENSION_NAME}.*") + message(STATUS "${EXTENSION_NAME} not supported by glslc") + set(${RESULT_VARIABLE} OFF PARENT_SCOPE) + else() + message(STATUS "${EXTENSION_NAME} supported by glslc") + set(${RESULT_VARIABLE} ON PARENT_SCOPE) + add_compile_definitions(${RESULT_VARIABLE}) + + # Ensure the extension support is forwarded to vulkan-shaders-gen + list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -D${RESULT_VARIABLE}=ON) + set(VULKAN_SHADER_GEN_CMAKE_ARGS "${VULKAN_SHADER_GEN_CMAKE_ARGS}" PARENT_SCOPE) + endif() +endfunction() + if (GGML_VULKAN) find_package(Vulkan COMPONENTS glslc REQUIRED) if (Vulkan_FOUND) message(STATUS "Vulkan found") + # add vulkan test + + set(VULKAN_SHADER_GEN_CMAKE_ARGS "") + + # Test all shader extensions + test_shader_extension_support( + "GL_KHR_cooperative_matrix" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat_support.comp" + "GGML_VULKAN_COOPMAT_GLSLC_SUPPORT" + ) + + test_shader_extension_support( + "GL_NV_cooperative_matrix2" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat2_support.comp" + "GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT" + ) + + test_shader_extension_support( + "GL_EXT_integer_dot_product" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_integer_dot_support.comp" + "GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT" + ) + + test_shader_extension_support( + "GL_EXT_bfloat16" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_bfloat16_support.comp" + "GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT" + ) + + + + + # end vulkan test list(APPEND GGML_CDEF_PUBLIC GGML_USE_VULKAN) # Workaround to the "can't dereference invalidated vector iterator" bug in clang-cl debug build @@ -669,6 +742,14 @@ if (GGML_VULKAN) add_compile_definitions(GGML_VULKAN_MEMORY_DEBUG) endif() + if (GGML_VULKAN_SHADER_DEBUG_INFO) + add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO) + endif() + + if (GGML_VULKAN_PERF) + add_compile_definitions(GGML_VULKAN_PERF) + endif() + if (GGML_VULKAN_VALIDATE) add_compile_definitions(GGML_VULKAN_VALIDATE) endif() @@ -677,31 +758,79 @@ if (GGML_VULKAN) add_compile_definitions(GGML_VULKAN_RUN_TESTS) endif() - add_subdirectory(vulkan-shaders) + # Set up toolchain for host compilation whether cross-compiling or not + if (CMAKE_CROSSCOMPILING) + if (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN) + set(HOST_CMAKE_TOOLCHAIN_FILE ${GGML_VULKAN_SHADERS_GEN_TOOLCHAIN}) + else() + detect_host_compiler() + if (NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER) + message(FATAL_ERROR "Host compiler not found") + else() + message(STATUS "Host compiler: ${HOST_C_COMPILER} ${HOST_CXX_COMPILER}") + endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/host-toolchain.cmake.in ${CMAKE_BINARY_DIR}/host-toolchain.cmake @ONLY) + set(HOST_CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/host-toolchain.cmake) + endif() + else() + # For non-cross-compiling, use empty toolchain (use host compiler) + set(HOST_CMAKE_TOOLCHAIN_FILE "") + endif() - set (_ggml_vk_genshaders_cmd vulkan-shaders-gen) - set (_ggml_vk_header ${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp) - set (_ggml_vk_source ${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.cpp) - set (_ggml_vk_input_dir ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders) - set (_ggml_vk_output_dir ${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv) + include(ExternalProject) - file(GLOB _ggml_vk_shader_deps "${_ggml_vk_input_dir}/*.comp") + if (CMAKE_CROSSCOMPILING) + list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${HOST_CMAKE_TOOLCHAIN_FILE}) + message(STATUS "vulkan-shaders-gen toolchain file: ${HOST_CMAKE_TOOLCHAIN_FILE}") + endif() - add_custom_command( - OUTPUT ${_ggml_vk_header} - ${_ggml_vk_source} + ExternalProject_Add( + vulkan-shaders-gen + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/$ + -DCMAKE_INSTALL_BINDIR=. + -DCMAKE_BUILD_TYPE=$ + ${VULKAN_SHADER_GEN_CMAKE_ARGS} - COMMAND ${_ggml_vk_genshaders_cmd} - --glslc ${Vulkan_GLSLC_EXECUTABLE} - --input-dir ${_ggml_vk_input_dir} - --output-dir ${_ggml_vk_output_dir} - --target-hpp ${_ggml_vk_header} - --target-cpp ${_ggml_vk_source} - --no-clean + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $ - DEPENDS ${_ggml_vk_shader_deps} - COMMENT "Generate vulkan shaders" - ) + # NOTE: When DESTDIR is set using Makefile generators and + # "make install" triggers the build step, vulkan-shaders-gen + # would be installed into the DESTDIR prefix, so it is unset + # to ensure that does not happen. + + INSTALL_COMMAND ${CMAKE_COMMAND} -E env --unset=DESTDIR + ${CMAKE_COMMAND} --install . --config $ + ) + + set (_ggml_vk_host_suffix $,.exe,>) + set (_ggml_vk_genshaders_dir "${CMAKE_BINARY_DIR}/$") + set (_ggml_vk_genshaders_cmd "${_ggml_vk_genshaders_dir}/vulkan-shaders-gen${_ggml_vk_host_suffix}") + set (_ggml_vk_header "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp") + set (_ggml_vk_source "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.cpp") + set (_ggml_vk_input_dir "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders") + set (_ggml_vk_output_dir "${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv") + + file(GLOB _ggml_vk_shader_files CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.comp") + + add_custom_command( + OUTPUT ${_ggml_vk_header} + ${_ggml_vk_source} + + COMMAND ${_ggml_vk_genshaders_cmd} + --glslc ${Vulkan_GLSLC_EXECUTABLE} + --input-dir ${_ggml_vk_input_dir} + --output-dir ${_ggml_vk_output_dir} + --target-hpp ${_ggml_vk_header} + --target-cpp ${_ggml_vk_source} + --no-clean + + DEPENDS ${_ggml_vk_shader_files} + ${_ggml_vk_shader_gens_sources} + vulkan-shaders-gen + + COMMENT "Generate vulkan shaders" + ) set(GGML_HEADERS_VULKAN ${CMAKE_CURRENT_SOURCE_DIR}/../include/ggml-vulkan.h ${_ggml_vk_header}) set(GGML_SOURCES_VULKAN ggml-vulkan.cpp ${_ggml_vk_source}) diff --git a/ggml/src/cmake/host-toolchain.cmake.in b/ggml/src/cmake/host-toolchain.cmake.in new file mode 100644 index 00000000..2d8a8569 --- /dev/null +++ b/ggml/src/cmake/host-toolchain.cmake.in @@ -0,0 +1,15 @@ +set(CMAKE_BUILD_TYPE Release) +set(CMAKE_C_FLAGS -O2) +set(CMAKE_CXX_FLAGS -O2) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) +set(CMAKE_C_COMPILER "@HOST_C_COMPILER@") +set(CMAKE_CXX_COMPILER "@HOST_CXX_COMPILER@") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY @CMAKE_RUNTIME_OUTPUT_DIRECTORY@) + +if("@CMAKE_C_COMPILER_ID@" STREQUAL "MSVC") + foreach(CONFIG IN ITEMS DEBUG RELEASE MINSIZEREL RELWITHDEBINFO) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + endforeach() +endif() diff --git a/ggml/src/ggml-alloc.c b/ggml/src/ggml-alloc.c index 3f2d2023..67c1ba18 100644 --- a/ggml/src/ggml-alloc.c +++ b/ggml/src/ggml-alloc.c @@ -987,9 +987,9 @@ ggml_backend_buffer_t ggml_backend_alloc_ctx_tensors_from_buft(struct ggml_conte if (this_size > max_size) { fprintf(stderr, "%s: tensor %s is too large to fit in a %s buffer (tensor size: %zu, max buffer size: %zu)\n", - __func__, t->name, - ggml_backend_buft_name(buft), - this_size, max_size); + __func__, t->name, + ggml_backend_buft_name(buft), + this_size, max_size); for (size_t i = 0; i < n_buffers; i++) { ggml_backend_buffer_free(buffers[i]); } diff --git a/ggml/src/ggml-backend-impl.h b/ggml/src/ggml-backend-impl.h index 36ca3708..e08bde83 100644 --- a/ggml/src/ggml-backend-impl.h +++ b/ggml/src/ggml-backend-impl.h @@ -42,6 +42,7 @@ extern "C" { void (*GGML_CALL free_buffer)(ggml_backend_buffer_t buffer); void * (*GGML_CALL get_base) (ggml_backend_buffer_t buffer); void (*GGML_CALL init_tensor)(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor); + void (*GGML_CALL memset_tensor) (ggml_backend_buffer_t buffer, struct ggml_tensor* tensor, uint8_t value, size_t offset, size_t size); void (*GGML_CALL set_tensor) (ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, const void * data, size_t offset, size_t size); void (*GGML_CALL get_tensor) (ggml_backend_buffer_t buffer, const struct ggml_tensor * tensor, void * data, size_t offset, size_t size); bool (*GGML_CALL cpy_tensor) (ggml_backend_buffer_t buffer, const struct ggml_tensor * src, struct ggml_tensor * dst); // dst is in the buffer, src may be in any buffer diff --git a/ggml/src/ggml-backend.c b/ggml/src/ggml-backend.c index 5903c89c..28850e0d 100644 --- a/ggml/src/ggml-backend.c +++ b/ggml/src/ggml-backend.c @@ -266,6 +266,21 @@ GGML_CALL void ggml_backend_tensor_get(const struct ggml_tensor * tensor, void * #endif } +GGML_CALL void ggml_backend_tensor_memset(struct ggml_tensor* tensor, uint8_t value, size_t offset, size_t size) { + ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer; + + if (size == 0) { + return; + } + + GGML_ASSERT(buf != NULL && "tensor buffer not set"); + GGML_ASSERT(tensor->data != NULL && "tensor not allocated"); + GGML_ASSERT(offset + size <= ggml_nbytes(tensor) && "tensor write out of bounds"); + GGML_ASSERT(buf->iface.memset_tensor != NULL && "memset not implemented by backend buffer"); + + buf->iface.memset_tensor(buf, tensor, value, offset, size); +} + void ggml_backend_synchronize(ggml_backend_t backend) { if (backend->iface.synchronize == NULL) { return; @@ -593,6 +608,12 @@ GGML_CALL static void ggml_backend_cpu_buffer_free_buffer(ggml_backend_buffer_t free(buffer->context); } +static void ggml_backend_cpu_buffer_memset_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor* tensor, uint8_t value, size_t offset, size_t size) { + memset((char*)tensor->data + offset, value, size); + + GGML_UNUSED(buffer); +} + GGML_CALL static void ggml_backend_cpu_buffer_set_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, const void * data, size_t offset, size_t size) { memcpy((char *)tensor->data + offset, data, size); @@ -624,6 +645,7 @@ static struct ggml_backend_buffer_i cpu_backend_buffer_i = { /* .free_buffer = */ ggml_backend_cpu_buffer_free_buffer, /* .get_base = */ ggml_backend_cpu_buffer_get_base, /* .init_tensor = */ NULL, // no initialization required + /* .memset_tensor = */ ggml_backend_cpu_buffer_memset_tensor, /* .set_tensor = */ ggml_backend_cpu_buffer_set_tensor, /* .get_tensor = */ ggml_backend_cpu_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_cpu_buffer_cpy_tensor, @@ -637,6 +659,7 @@ static struct ggml_backend_buffer_i cpu_backend_buffer_i_from_ptr = { /* .free_buffer = */ NULL, // ptr is not owned by the buffer, so it does not need to be freed /* .get_base = */ ggml_backend_cpu_buffer_get_base, /* .init_tensor = */ NULL, // no initialization required + /* .memset_tensor = */ ggml_backend_cpu_buffer_memset_tensor, /* .set_tensor = */ ggml_backend_cpu_buffer_set_tensor, /* .get_tensor = */ ggml_backend_cpu_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_cpu_buffer_cpy_tensor, @@ -993,6 +1016,7 @@ static struct ggml_backend_buffer_i ggml_backend_multi_buffer_context_interface( /* .free_buffer = */ ggml_backend_multi_buffer_free_buffer, /* .get_base = */ NULL, /* .init_tensor = */ NULL, + /* .memset_tensor = */ NULL, /* .set_tensor = */ NULL, /* .get_tensor = */ NULL, /* .cpy_tensor = */ NULL, diff --git a/ggml/src/ggml-cann.cpp b/ggml/src/ggml-cann.cpp index 06930ba2..a2d64da5 100644 --- a/ggml/src/ggml-cann.cpp +++ b/ggml/src/ggml-cann.cpp @@ -1036,6 +1036,7 @@ static ggml_backend_buffer_i ggml_backend_cann_buffer_interface = { /* .free_buffer = */ ggml_backend_cann_buffer_free_buffer, /* .get_base = */ ggml_backend_cann_buffer_get_base, /* .init_tensor = */ ggml_backend_cann_buffer_init_tensor, + /* .memset_tensor = */ NULL, /* .set_tensor = */ ggml_backend_cann_buffer_set_tensor, /* .get_tensor = */ ggml_backend_cann_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_cann_buffer_cpy_tensor, diff --git a/ggml/src/ggml-cuda.cu b/ggml/src/ggml-cuda.cu index da3dc334..ae7a55c6 100644 --- a/ggml/src/ggml-cuda.cu +++ b/ggml/src/ggml-cuda.cu @@ -500,6 +500,14 @@ GGML_CALL static void ggml_backend_cuda_buffer_init_tensor(ggml_backend_buffer_t } } +GGML_CALL static void ggml_backend_cuda_buffer_memset_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, uint8_t value, size_t offset, size_t size) { + ggml_backend_cuda_buffer_context * ctx = (ggml_backend_cuda_buffer_context *)buffer->context; + + ggml_cuda_set_device(ctx->device); + CUDA_CHECK(cudaMemsetAsync((char *)tensor->data + offset, value, size, cudaStreamPerThread)); + CUDA_CHECK(cudaStreamSynchronize(cudaStreamPerThread)); +} + GGML_CALL static void ggml_backend_cuda_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, const void * data, size_t offset, size_t size) { ggml_backend_cuda_buffer_context * ctx = (ggml_backend_cuda_buffer_context *)buffer->context; @@ -551,6 +559,7 @@ static ggml_backend_buffer_i ggml_backend_cuda_buffer_interface = { /* .free_buffer = */ ggml_backend_cuda_buffer_free_buffer, /* .get_base = */ ggml_backend_cuda_buffer_get_base, /* .init_tensor = */ ggml_backend_cuda_buffer_init_tensor, + /* .memset_tensor = */ ggml_backend_cuda_buffer_memset_tensor, /* .set_tensor = */ ggml_backend_cuda_buffer_set_tensor, /* .get_tensor = */ ggml_backend_cuda_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_cuda_buffer_cpy_tensor, @@ -867,6 +876,7 @@ static struct ggml_backend_buffer_i ggml_backend_cuda_split_buffer_interface = { /* .free_buffer = */ ggml_backend_cuda_split_buffer_free_buffer, /* .get_base = */ ggml_backend_cuda_split_buffer_get_base, /* .init_tensor = */ ggml_backend_cuda_split_buffer_init_tensor, + /* .memset_tensor = */ NULL, /* .set_tensor = */ ggml_backend_cuda_split_buffer_set_tensor, /* .get_tensor = */ ggml_backend_cuda_split_buffer_get_tensor, /* .cpy_tensor = */ NULL, @@ -3566,17 +3576,24 @@ GGML_CALL static bool ggml_backend_cuda_supports_op(ggml_backend_t backend, cons } return false; } break; + case GGML_OP_SILU_BACK: + return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32; + break; + case GGML_OP_NORM: + case GGML_OP_RMS_NORM: + return true; + case GGML_OP_RMS_NORM_BACK: + return ggml_is_contiguous(op->src[0]) && op->ne[0] % WARP_SIZE == 0; + break; case GGML_OP_NONE: case GGML_OP_RESHAPE: case GGML_OP_VIEW: case GGML_OP_PERMUTE: case GGML_OP_TRANSPOSE: - case GGML_OP_NORM: case GGML_OP_ADD: case GGML_OP_MULTI_ADD: case GGML_OP_MUL: case GGML_OP_DIV: - case GGML_OP_RMS_NORM: case GGML_OP_FUSED_RMS_NORM: case GGML_OP_SCALE: case GGML_OP_SOFTCAP: diff --git a/ggml/src/ggml-kompute.cpp b/ggml/src/ggml-kompute.cpp index 41ac63fa..d0395ff9 100644 --- a/ggml/src/ggml-kompute.cpp +++ b/ggml/src/ggml-kompute.cpp @@ -1872,6 +1872,7 @@ static ggml_backend_buffer_i ggml_backend_kompute_buffer_i = { /* .free_buffer = */ ggml_backend_kompute_buffer_free_buffer, /* .get_base = */ ggml_backend_kompute_buffer_get_base, /* .init_tensor = */ NULL, + /* .memset_tensor = */ NULL, /* .set_tensor = */ ggml_backend_kompute_buffer_set_tensor, /* .get_tensor = */ ggml_backend_kompute_buffer_get_tensor, /* .cpy_tensor = */ NULL, diff --git a/ggml/src/ggml-metal.m b/ggml/src/ggml-metal.m index 4cd44cb9..ff68ee19 100644 --- a/ggml/src/ggml-metal.m +++ b/ggml/src/ggml-metal.m @@ -4068,6 +4068,12 @@ GGML_CALL static void * ggml_backend_metal_buffer_get_base(ggml_backend_buffer_t return ctx->all_data; } +GGML_CALL void ggml_backend_metal_buffer_memset_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, uint8_t value, size_t offset, size_t size) { + memset((char *)tensor->data + offset, value, size); + + GGML_UNUSED(buffer); +} + GGML_CALL static void ggml_backend_metal_buffer_set_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, const void * data, size_t offset, size_t size) { memcpy((char *)tensor->data + offset, data, size); @@ -4101,6 +4107,7 @@ static struct ggml_backend_buffer_i ggml_backend_metal_buffer_i = { /* .free_buffer = */ ggml_backend_metal_buffer_free_buffer, /* .get_base = */ ggml_backend_metal_buffer_get_base, /* .init_tensor = */ NULL, + /* .memset_tensor = */ ggml_backend_metal_buffer_memset_tensor, /* .set_tensor = */ ggml_backend_metal_buffer_set_tensor, /* .get_tensor = */ ggml_backend_metal_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_metal_buffer_cpy_tensor, diff --git a/ggml/src/ggml-rpc.cpp b/ggml/src/ggml-rpc.cpp index 3b5c8f46..4c44ae54 100644 --- a/ggml/src/ggml-rpc.cpp +++ b/ggml/src/ggml-rpc.cpp @@ -631,6 +631,7 @@ static ggml_backend_buffer_i ggml_backend_rpc_buffer_interface = { /* .free_buffer = */ ggml_backend_rpc_buffer_free_buffer, /* .get_base = */ ggml_backend_rpc_buffer_get_base, /* .init_tensor = */ ggml_backend_rpc_buffer_init_tensor, + /* .memset_tensor =*/ NULL, /* .set_tensor = */ ggml_backend_rpc_buffer_set_tensor, /* .get_tensor = */ ggml_backend_rpc_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_rpc_buffer_cpy_tensor, diff --git a/ggml/src/ggml-sycl.cpp b/ggml/src/ggml-sycl.cpp index d8eb86c2..e0f8536a 100644 --- a/ggml/src/ggml-sycl.cpp +++ b/ggml/src/ggml-sycl.cpp @@ -37,6 +37,7 @@ #include "ggml-backend-impl.h" #include "ggml-sycl/backend.hpp" +#include "ggml-sycl/common.hpp" #include "ggml-sycl/presets.hpp" bool ggml_sycl_loaded(void); @@ -83,12 +84,64 @@ static __dpct_inline__ float op_add(const float a, const float b) { return a + b; } -static __dpct_inline__ float op_mul(const float a, const float b) { - return a * b; +static void ggml_backend_sycl_buffer_memset_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, uint8_t value, + size_t offset, size_t size) { + GGML_SYCL_DEBUG(" [SYCL] call %s\n", __func__); + ggml_backend_sycl_buffer_context * ctx = (ggml_backend_sycl_buffer_context *) buffer->context; + SYCL_CHECK(ggml_sycl_set_device(ctx->device)); + auto stream = &(dpct::dev_mgr::instance().get_device(ctx->device).default_queue()); + if (size == 0) { + return; // Nothing to do + } + if (tensor->data == nullptr) { + GGML_ABORT("Error: Tensor data pointer is null.\n"); + } + void * target_ptr = static_cast(tensor->data) + offset; + SYCL_CHECK(CHECK_TRY_ERROR((*stream).memset(target_ptr, value, size))); + SYCL_CHECK(CHECK_TRY_ERROR((*stream).wait())); } -static __dpct_inline__ float op_div(const float a, const float b) { - return a / b; +static void ggml_backend_sycl_buffer_reset(ggml_backend_buffer_t buffer) { + GGML_SYCL_DEBUG("[SYCL] call %s\n", __func__); + if (buffer == nullptr) { + return; + } + + ggml_backend_sycl_buffer_context * ctx = (ggml_backend_sycl_buffer_context *) buffer->context; + + if (ctx != nullptr) { + for (ggml_tensor_extra_gpu * extra : ctx->tensor_extras) { + release_extra_gpu(extra); + } + ctx->tensor_extras.clear(); // reset the tensor_extras vector + } +} + +static const ggml_backend_buffer_i ggml_backend_sycl_buffer_interface = { + /* .free_buffer = */ ggml_backend_sycl_buffer_free_buffer, + /* .get_base = */ ggml_backend_sycl_buffer_get_base, + /* .init_tensor = */ ggml_backend_sycl_buffer_init_tensor, + /* .memset_tensor = */ ggml_backend_sycl_buffer_memset_tensor, + /* .set_tensor = */ ggml_backend_sycl_buffer_set_tensor, + /* .get_tensor = */ ggml_backend_sycl_buffer_get_tensor, + /* .cpy_tensor = */ ggml_backend_sycl_buffer_cpy_tensor, + /* .clear = */ ggml_backend_sycl_buffer_clear, + /* .reset = */ ggml_backend_sycl_buffer_reset, +}; + +// sycl buffer type +struct ggml_backend_sycl_buffer_type_context { + int device; + std::string name; + + // each buffer type has its own stream + queue_ptr stream = nullptr; +}; + +static const char * ggml_backend_sycl_buffer_type_get_name(ggml_backend_buffer_type_t buft) { + ggml_backend_sycl_buffer_type_context * ctx = (ggml_backend_sycl_buffer_type_context *)buft->context; + + return ctx->name.c_str(); } template @@ -4407,7 +4460,9 @@ static struct ggml_backend_buffer_i ggml_backend_sycl_buffer_interface = { /* .free_buffer = */ ggml_backend_sycl_buffer_free_buffer, /* .get_base = */ ggml_backend_sycl_buffer_get_base, /* .init_tensor = */ ggml_backend_sycl_buffer_init_tensor, + /* .memset_tensor = */ ggml_backend_sycl_buffer_memset_tensor, /* .set_tensor = */ ggml_backend_sycl_buffer_set_tensor, + /* .memset_tensor =*/ NULL, /* .get_tensor = */ ggml_backend_sycl_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_sycl_buffer_cpy_tensor, /* .clear = */ ggml_backend_sycl_buffer_clear, @@ -4810,6 +4865,7 @@ static struct ggml_backend_buffer_i ggml_backend_sycl_split_buffer_interface = { /* .free_buffer = */ ggml_backend_sycl_split_buffer_free_buffer, /* .get_base = */ ggml_backend_sycl_split_buffer_get_base, /* .init_tensor = */ ggml_backend_sycl_split_buffer_init_tensor, + /* .memset_tensor =*/ NULL, /* .set_tensor = */ ggml_backend_sycl_split_buffer_set_tensor, /* .get_tensor = */ ggml_backend_sycl_split_buffer_get_tensor, /* .cpy_tensor = */ NULL, diff --git a/ggml/src/ggml-vulkan.cpp b/ggml/src/ggml-vulkan.cpp index 86732837..c0bdfb7b 100644 --- a/ggml/src/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan.cpp @@ -1,7 +1,8 @@ #include "ggml-vulkan.h" #include -#ifdef GGML_VULKAN_RUN_TESTS +#if defined(GGML_VULKAN_RUN_TESTS) || defined(GGML_VULKAN_CHECK_RESULTS) #include +#include "ggml-cpu.h" #endif #include @@ -17,37 +18,72 @@ #include #include #include +#include #include #include +#include +#include -#include "ggml.h" +#if defined(_MSC_VER) +# define NOMINMAX 1 +# include +# define YIELD() YieldProcessor() +#elif defined(__clang__) || defined(__GNUC__) +# if defined(__x86_64__) ||defined(__i386__) +# include +# define YIELD() _mm_pause() +# elif defined(__arm__) || defined(__aarch64__) +# if defined(__clang__) +# include +# define YIELD() __yield() +# else +# define YIELD() asm volatile("yield") +# endif +# endif +#endif + +#if !defined(YIELD) +#define YIELD() +#endif + +#include "ggml-impl.h" #include "ggml-backend-impl.h" #include "ggml-vulkan-shaders.hpp" -#define VK_API_VERSION VK_API_VERSION_1_2 +// remove this once it's more widely available in the SDK +#if !defined(VK_KHR_shader_bfloat16) +#define VK_KHR_shader_bfloat16 1 +#define VK_KHR_SHADER_BFLOAT16_SPEC_VERSION 1 +#define VK_KHR_SHADER_BFLOAT16_EXTENSION_NAME "VK_KHR_shader_bfloat16" +#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_BFLOAT16_FEATURES_KHR ((VkStructureType)1000141000) +#define VK_COMPONENT_TYPE_BFLOAT16_KHR ((VkComponentTypeKHR)1000141000) + +typedef struct VkPhysicalDeviceShaderBfloat16FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderBFloat16Type; + VkBool32 shaderBFloat16DotProduct; + VkBool32 shaderBFloat16CooperativeMatrix; +} VkPhysicalDeviceShaderBfloat16FeaturesKHR; +#endif + +#define ROUNDUP_POW2(M, N) (((M) + (N) - 1) & ~((N) - 1)) #define CEIL_DIV(M, N) (((M) + (N)-1) / (N)) +static bool is_pow2(uint32_t x) { return x > 1 && (x & (x-1)) == 0; } #define VK_VENDOR_ID_AMD 0x1002 #define VK_VENDOR_ID_APPLE 0x106b #define VK_VENDOR_ID_INTEL 0x8086 #define VK_VENDOR_ID_NVIDIA 0x10de -#define VK_DEVICE_DESCRIPTOR_POOL_MODE_UNKNOWN 0 -#define VK_DEVICE_DESCRIPTOR_POOL_MODE_MULTI 1 -#define VK_DEVICE_DESCRIPTOR_POOL_MODE_SINGLE 2 +#define VK_DEVICE_DESCRIPTOR_POOL_SIZE 256 #define GGML_VK_MAX_NODES 8192 #define MAX_VK_BUFFERS 256 -#ifndef K_QUANTS_PER_ITERATION -#define K_QUANTS_PER_ITERATION 1 -#else -static_assert(K_QUANTS_PER_ITERATION == 1 || K_QUANTS_PER_ITERATION == 2, "K_QUANTS_PER_ITERATION must be 1 or 2"); -#endif - #define VK_CHECK(err, msg) \ do { \ vk::Result err_ = (err); \ @@ -63,32 +99,32 @@ static_assert(K_QUANTS_PER_ITERATION == 1 || K_QUANTS_PER_ITERATION == 2, "K_QUA #else #define VK_LOG_DEBUG(msg) ((void) 0) #endif // GGML_VULKAN_DEBUG +#define GGML_DEBUG 0 +#if (GGML_DEBUG >= 1) +#define GGML_LOG_DEBUG(...) printf(__VA_ARGS__) +#else +#define GGML_LOG_DEBUG(...) +#endif +#define GGML_LOG_WARN(...) printf(__VA_ARGS__) +#define GGML_LOG_INFO(...) printf(__VA_ARGS__) struct ggml_backend_vk_context; -struct vk_queue { - uint32_t queue_family_index; - vk::Queue queue; - vk::CommandPool pool; - uint32_t cmd_buffer_idx; - std::vector cmd_buffers; - - vk::PipelineStageFlags stage_flags; -}; +#define MAX_PARAMETER_COUNT 8 struct vk_pipeline_struct { std::string name; vk::ShaderModule shader_module; - vk::DescriptorSetLayout dsl; - std::vector descriptor_pools; - std::vector descriptor_sets; - uint32_t descriptor_set_idx; vk::PipelineLayout layout; vk::Pipeline pipeline; uint32_t push_constant_size; uint32_t parameter_count; std::array wg_denoms; uint32_t align; + // set to true to request the pipeline is compiled after the dryrun + bool needed {}; + // set to true when the shader has been compiled + bool compiled {}; }; typedef std::shared_ptr vk_pipeline; @@ -103,6 +139,15 @@ struct vk_matmul_pipeline_struct { typedef std::shared_ptr vk_matmul_pipeline; +struct vk_matmul_pipeline2 { + vk_matmul_pipeline2() { + f16acc = std::make_shared(); + f32acc = std::make_shared(); + } + vk_matmul_pipeline f32acc; + vk_matmul_pipeline f16acc; +}; + struct vk_device_struct; typedef std::shared_ptr vk_device; typedef std::weak_ptr vk_device_ref; @@ -116,11 +161,50 @@ struct ggml_backend_vk_buffer_type_context { vk_device device; }; -GGML_CALL static const char * ggml_backend_vk_buffer_type_name(ggml_backend_buffer_type_t buft); -GGML_CALL static ggml_backend_buffer_t ggml_backend_vk_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size); -GGML_CALL static size_t ggml_backend_vk_buffer_type_get_alignment(ggml_backend_buffer_type_t buft); -GGML_CALL static size_t ggml_backend_vk_buffer_type_get_max_size(ggml_backend_buffer_type_t buft); -GGML_CALL static size_t ggml_backend_vk_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor); +struct vk_queue; + +// Stores command pool/buffers. There's an instance of this +// for each (context,queue) pair and for each (device,queue) pair. +struct vk_command_pool { + void init(vk_device& device, vk_queue *q_); + void destroy(vk::Device& device); + + vk::CommandPool pool; + uint32_t cmd_buffer_idx; + std::vector cmd_buffers; + + vk_queue *q; +}; + +// Prevent simultaneous submissions to the same queue. +// This could be per vk_queue if we stopped having two vk_queue structures +// sharing the same vk::Queue. +static std::mutex queue_mutex; + +struct vk_queue { + uint32_t queue_family_index; + vk::Queue queue; + + vk_command_pool cmd_pool; + + vk::PipelineStageFlags stage_flags; + + bool transfer_only; + + // copy everything except the cmd_pool + void copyFrom(vk_queue &other) { + queue_family_index = other.queue_family_index; + queue = other.queue; + stage_flags = other.stage_flags; + transfer_only = other.transfer_only; + } +}; + +static const char * ggml_backend_vk_buffer_type_name(ggml_backend_buffer_type_t buft); +static ggml_backend_buffer_t ggml_backend_vk_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size); +static size_t ggml_backend_vk_buffer_type_get_alignment(ggml_backend_buffer_type_t buft); +static size_t ggml_backend_vk_buffer_type_get_max_size(ggml_backend_buffer_type_t buft); +static size_t ggml_backend_vk_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor); static ggml_backend_buffer_type_i ggml_backend_vk_buffer_type_interface = { /* .get_name = */ ggml_backend_vk_buffer_type_name, /* .alloc_buffer = */ ggml_backend_vk_buffer_type_alloc_buffer, @@ -133,79 +217,276 @@ static ggml_backend_buffer_type_i ggml_backend_vk_buffer_type_interface = { #ifdef GGML_VULKAN_MEMORY_DEBUG class vk_memory_logger; #endif +class vk_perf_logger; static void ggml_vk_destroy_buffer(vk_buffer& buf); +static constexpr uint32_t mul_mat_vec_max_cols = 8; +static constexpr uint32_t p021_max_gqa_ratio = 8; + +enum vk_device_architecture { + OTHER, + AMD_GCN, + AMD_RDNA1, + AMD_RDNA2, + AMD_RDNA3, + INTEL_XE2, +}; + +static vk_device_architecture get_device_architecture(const vk::PhysicalDevice& device) { + vk::PhysicalDeviceProperties props = device.getProperties(); + + if (props.vendorID == VK_VENDOR_ID_AMD) { + const std::vector ext_props = device.enumerateDeviceExtensionProperties(); + + bool amd_shader_core_properties = false; + bool integer_dot_product = false; + bool subgroup_size_control = false; + + for (const auto& properties : ext_props) { + if (strcmp("VK_AMD_shader_core_properties", properties.extensionName) == 0) { + amd_shader_core_properties = true; + } else if (strcmp("VK_KHR_shader_integer_dot_product", properties.extensionName) == 0) { + integer_dot_product = true; + } else if (strcmp("VK_EXT_subgroup_size_control", properties.extensionName) == 0) { + subgroup_size_control = true; + } + } + + if (!amd_shader_core_properties || !integer_dot_product || !subgroup_size_control) { + return vk_device_architecture::OTHER; + } + + vk::PhysicalDeviceProperties2 props2; + vk::PhysicalDeviceShaderCorePropertiesAMD shader_core_props_amd; + vk::PhysicalDeviceShaderIntegerDotProductPropertiesKHR integer_dot_props; + vk::PhysicalDeviceSubgroupSizeControlPropertiesEXT subgroup_size_control_props; + + props2.pNext = &shader_core_props_amd; + shader_core_props_amd.pNext = &integer_dot_props; + integer_dot_props.pNext = &subgroup_size_control_props; + + device.getProperties2(&props2); + + if (subgroup_size_control_props.maxSubgroupSize == 64 && subgroup_size_control_props.minSubgroupSize == 64) { + return vk_device_architecture::AMD_GCN; + } + if (subgroup_size_control_props.maxSubgroupSize == 64 && subgroup_size_control_props.minSubgroupSize == 32) { + // RDNA + if (shader_core_props_amd.wavefrontsPerSimd == 20) { + return vk_device_architecture::AMD_RDNA1; + } + if (integer_dot_props.integerDotProduct4x8BitPackedMixedSignednessAccelerated) { + return vk_device_architecture::AMD_RDNA3; + } + return vk_device_architecture::AMD_RDNA2; + } + } else if (props.vendorID == VK_VENDOR_ID_INTEL) { + const std::vector ext_props = device.enumerateDeviceExtensionProperties(); + + bool subgroup_size_control = false; + + for (const auto& properties : ext_props) { + if (strcmp("VK_EXT_subgroup_size_control", properties.extensionName) == 0) { + subgroup_size_control = true; + } + } + + if (!subgroup_size_control) { + return vk_device_architecture::OTHER; + } + + vk::PhysicalDeviceProperties2 props2; + vk::PhysicalDeviceSubgroupSizeControlPropertiesEXT subgroup_size_control_props; + + props2.pNext = &subgroup_size_control_props; + device.getProperties2(&props2); + + if (subgroup_size_control_props.minSubgroupSize == 16) { + // Xe2 architecture uses SIMD16 while previous Xe and Gen architecture uses SIMD8. + // Minimum subgroup size matches the SIMD width so we distinguish architecture by checking this value. + // https://www.intel.com/content/www/us/en/content-details/824434/2024-intel-tech-tour-xe2-and-lunar-lake-s-gpu.html + // https://www.intel.com/content/www/us/en/docs/oneapi/optimization-guide-gpu/2025-0/intel-xe-gpu-architecture.html + return vk_device_architecture::INTEL_XE2; + } + } + return vk_device_architecture::OTHER; +} + struct vk_device_struct { - std::mutex mutex; + std::recursive_mutex mutex; vk::PhysicalDevice physical_device; vk::PhysicalDeviceProperties properties; std::string name; uint64_t max_memory_allocation_size; + uint64_t suballocation_block_size; bool fp16; + bool pipeline_robustness; vk::Device device; uint32_t vendor_id; + vk::DriverId driver_id; + vk_device_architecture architecture; vk_queue compute_queue; vk_queue transfer_queue; bool single_queue; - uint32_t descriptor_set_mode; uint32_t subgroup_size; + uint32_t shader_core_count; bool uma; + bool prefer_host_memory; + bool float_controls_rte_fp16; + bool subgroup_add; + bool subgroup_shuffle; + + bool integer_dot_product; + + bool subgroup_size_control; + uint32_t subgroup_min_size; + uint32_t subgroup_max_size; + bool subgroup_require_full_support; + + bool coopmat_support; + bool coopmat_acc_f32_support {}; + bool coopmat_acc_f16_support {}; + bool coopmat_bf16_support {}; + bool coopmat_support_16x16x16_f16acc {}; + bool coopmat_support_16x16x16_f32acc {}; + bool coopmat1_fa_support {}; + uint32_t coopmat_m; + uint32_t coopmat_n; + uint32_t coopmat_k; + + bool coopmat_int_support; + uint32_t coopmat_int_m; + uint32_t coopmat_int_n; + uint32_t coopmat_int_k; + + bool coopmat2; size_t idx; - vk_matmul_pipeline pipeline_matmul_f32; - vk_matmul_pipeline pipeline_matmul_f32_f16; - vk_matmul_pipeline pipeline_matmul_f16; - vk_matmul_pipeline pipeline_matmul_f16_f32; + bool mul_mat_l[GGML_TYPE_COUNT]; + bool mul_mat_m[GGML_TYPE_COUNT]; + bool mul_mat_s[GGML_TYPE_COUNT]; + bool mul_mat_id_l[GGML_TYPE_COUNT]; + bool mul_mat_id_m[GGML_TYPE_COUNT]; + bool mul_mat_id_s[GGML_TYPE_COUNT]; + + // set to true to indicate that some shaders need to be compiled after the dryrun + bool need_compiles {}; + + vk::DescriptorSetLayout dsl; + + vk_matmul_pipeline pipeline_matmul_f32 {}; + vk_matmul_pipeline pipeline_matmul_f32_f16 {}; + vk_matmul_pipeline pipeline_matmul_bf16 {}; + vk_matmul_pipeline2 pipeline_matmul_f16; + vk_matmul_pipeline2 pipeline_matmul_f16_f32; + + vk_matmul_pipeline2 pipeline_dequant_mul_mat_mat[GGML_TYPE_COUNT]; + vk_matmul_pipeline2 pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_COUNT]; + vk_matmul_pipeline2 pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_COUNT]; + + vk_matmul_pipeline pipeline_matmul_id_f32 {}; + vk_matmul_pipeline pipeline_matmul_id_bf16 {}; + vk_matmul_pipeline2 pipeline_matmul_id_f16; + vk_matmul_pipeline2 pipeline_matmul_id_f16_f32; + + vk_matmul_pipeline2 pipeline_dequant_mul_mat_mat_id[GGML_TYPE_COUNT]; + vk_pipeline pipeline_matmul_split_k_reduce; - - vk_matmul_pipeline pipeline_dequant_mul_mat_mat[GGML_TYPE_COUNT]; - - vk_matmul_pipeline pipeline_matmul_id_f32; - vk_matmul_pipeline pipeline_matmul_id_f16; - vk_matmul_pipeline pipeline_matmul_id_f16_f32; - - vk_matmul_pipeline pipeline_dequant_mul_mat_mat_id[GGML_TYPE_COUNT]; + vk_pipeline pipeline_quantize_q8_1; vk_pipeline pipeline_dequant[GGML_TYPE_COUNT]; - vk_pipeline pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_COUNT]; - vk_pipeline pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_COUNT]; + vk_pipeline pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_COUNT][mul_mat_vec_max_cols]; + vk_pipeline pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_COUNT][mul_mat_vec_max_cols]; vk_pipeline pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_COUNT]; - vk_pipeline pipeline_mul_mat_vec_p021_f16_f32; + vk_pipeline pipeline_mul_mat_vec_p021_f16_f32[p021_max_gqa_ratio]; vk_pipeline pipeline_mul_mat_vec_nc_f16_f32; vk_pipeline pipeline_get_rows[GGML_TYPE_COUNT]; vk_pipeline pipeline_get_rows_f32[GGML_TYPE_COUNT]; - vk_pipeline pipeline_add_f32, pipeline_add_f16_f32_f16; - vk_pipeline pipeline_mul_f32; - vk_pipeline pipeline_div_f32; + vk_pipeline pipeline_acc_f32; + + // [src0 0=fp32,1=fp16][src1 0=fp32,1=fp16][dst 0=fp32,1=fp16] + vk_pipeline pipeline_add[2][2][2]; + vk_pipeline pipeline_add_norepeat[2][2][2]; + vk_pipeline pipeline_sub[2][2][2]; + vk_pipeline pipeline_sub_norepeat[2][2][2]; + vk_pipeline pipeline_mul[2][2][2]; + vk_pipeline pipeline_mul_norepeat[2][2][2]; + vk_pipeline pipeline_div[2][2][2]; + vk_pipeline pipeline_div_norepeat[2][2][2]; + vk_pipeline pipeline_concat_f32, pipeline_concat_f16, pipeline_concat_i32; vk_pipeline pipeline_upscale_f32; vk_pipeline pipeline_scale_f32; vk_pipeline pipeline_sqr_f32; vk_pipeline pipeline_clamp_f32; vk_pipeline pipeline_pad_f32; - vk_pipeline pipeline_cpy_f32_f32, pipeline_cpy_f32_f16, pipeline_cpy_f16_f16; + vk_pipeline pipeline_repeat_f32, pipeline_repeat_back_f32; + vk_pipeline pipeline_cpy_f32_f32, pipeline_cpy_f32_f16, pipeline_cpy_f16_f16, pipeline_cpy_f16_f32, pipeline_cpy_f32_bf16; + vk_pipeline pipeline_contig_cpy_f32_f32, pipeline_contig_cpy_f32_f16, pipeline_contig_cpy_f16_f16, pipeline_contig_cpy_f16_f32, pipeline_contig_cpy_f32_bf16; + vk_pipeline pipeline_cpy_f32_quant[GGML_TYPE_COUNT]; + vk_pipeline pipeline_cpy_quant_f32[GGML_TYPE_COUNT]; vk_pipeline pipeline_norm_f32; vk_pipeline pipeline_group_norm_f32; vk_pipeline pipeline_rms_norm_f32; - vk_pipeline pipeline_gelu_f32; - vk_pipeline pipeline_gelu_quick_f32; - vk_pipeline pipeline_silu_f32; - vk_pipeline pipeline_relu_f32; + vk_pipeline pipeline_rms_norm_back_f32; + + // [src/dst 0=fp32,1=fp16] + vk_pipeline pipeline_gelu[2]; + vk_pipeline pipeline_gelu_quick[2]; + vk_pipeline pipeline_silu[2]; + vk_pipeline pipeline_relu[2]; + vk_pipeline pipeline_tanh[2]; + vk_pipeline pipeline_sigmoid[2]; + vk_pipeline pipeline_leaky_relu_f32; - vk_pipeline pipeline_tanh_f32; + vk_pipeline pipeline_silu_back_f32; vk_pipeline pipeline_diag_mask_inf_f32; vk_pipeline pipeline_soft_max_f32, pipeline_soft_max_f32_f16; + vk_pipeline pipeline_soft_max_f32_wg512, pipeline_soft_max_f32_f16_wg512; + vk_pipeline pipeline_soft_max_back_f32; vk_pipeline pipeline_rope_norm_f32, pipeline_rope_norm_f16; vk_pipeline pipeline_rope_neox_f32, pipeline_rope_neox_f16; + vk_pipeline pipeline_rope_multi_f32, pipeline_rope_multi_f16; + vk_pipeline pipeline_rope_vision_f32, pipeline_rope_vision_f16; vk_pipeline pipeline_argsort_f32; vk_pipeline pipeline_sum_rows_f32; + vk_pipeline pipeline_argmax_f32; + vk_pipeline pipeline_count_equal_i32; vk_pipeline pipeline_im2col_f32, pipeline_im2col_f32_f16; vk_pipeline pipeline_timestep_embedding_f32; + vk_pipeline pipeline_conv_transpose_1d_f32; + vk_pipeline pipeline_pool2d_f32; + vk_pipeline pipeline_rwkv_wkv6_f32; + vk_pipeline pipeline_opt_step_adamw_f32; - std::vector pipelines; + // [2][2][2] is for {f16acc,f32acc}x{large,small_rows}x{unaligned, aligned} + vk_pipeline pipeline_flash_attn_f32_f16_D64_cm2[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D80_cm2[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D96_cm2[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D112_cm2[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D128_cm2[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D256_cm2[GGML_TYPE_COUNT][2][2][2]; + + vk_pipeline pipeline_flash_attn_f32_f16_D64_cm1[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D80_cm1[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D96_cm1[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D112_cm1[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D128_cm1[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D256_cm1[GGML_TYPE_COUNT][2][2][2]; + + vk_pipeline pipeline_flash_attn_f32_f16_D64[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D80[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D96[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D112[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D128[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_D256[GGML_TYPE_COUNT][2][2][2]; + + vk_pipeline pipeline_flash_attn_split_k_reduce; + + std::unordered_map pipelines; std::vector> pinned_memory; @@ -218,6 +499,11 @@ struct vk_device_struct { std::unique_ptr memory_logger; #endif + // for GGML_VK_PERF_LOGGER + std::unique_ptr perf_logger; + vk::QueryPool query_pool; + int32_t num_queries; + ~vk_device_struct() { VK_LOG_DEBUG("destroy device " << name); @@ -225,25 +511,39 @@ struct vk_device_struct { ggml_vk_destroy_buffer(sync_staging); - device.destroyCommandPool(compute_queue.pool); - if (!single_queue) { - device.destroyCommandPool(transfer_queue.pool); - } + compute_queue.cmd_pool.destroy(device); + transfer_queue.cmd_pool.destroy(device); for (auto& pipeline : pipelines) { - if (pipeline.expired()) { + if (pipeline.second.expired()) { continue; } - vk_pipeline pl = pipeline.lock(); + vk_pipeline pl = pipeline.second.lock(); ggml_vk_destroy_pipeline(device, pl); } pipelines.clear(); + device.destroyDescriptorSetLayout(dsl); + device.destroy(); } }; +void vk_command_pool::init(vk_device& device, vk_queue *q_) { + cmd_buffer_idx = 0; + q = q_; + + vk::CommandPoolCreateInfo command_pool_create_info(vk::CommandPoolCreateFlags(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT), q->queue_family_index); + pool = device->device.createCommandPool(command_pool_create_info); +} + +void vk_command_pool::destroy(vk::Device& device) { + device.destroyCommandPool(pool); + pool = nullptr; + cmd_buffers.clear(); +} + struct vk_buffer_struct { vk::Buffer buffer = VK_NULL_HANDLE; vk::DeviceMemory device_memory = VK_NULL_HANDLE; @@ -293,6 +593,7 @@ struct vk_mat_mat_push_constants { uint32_t batch_stride_a; uint32_t batch_stride_b; uint32_t batch_stride_d; uint32_t k_split; uint32_t ne02; uint32_t ne12; uint32_t broadcast2; uint32_t broadcast3; + uint32_t padded_N; }; struct vk_mat_vec_push_constants { uint32_t ncols; uint32_t stride_a; uint32_t stride_b; uint32_t stride_d; @@ -305,6 +606,7 @@ struct vk_mat_mat_id_push_constants { uint32_t stride_a; uint32_t stride_b; uint32_t stride_d; uint32_t batch_stride_a; uint32_t batch_stride_b; uint32_t batch_stride_d; uint32_t nei0; uint32_t nei1; uint32_t nbi1; uint32_t ne11; + uint32_t padded_N; }; struct vk_mat_vec_id_push_constants { uint32_t ncols; uint32_t stride_a; uint32_t stride_b; uint32_t stride_d; @@ -312,6 +614,47 @@ struct vk_mat_vec_id_push_constants { uint32_t nei0; uint32_t ne11; }; +struct vk_flash_attn_push_constants { + uint32_t N; + uint32_t KV; + + uint32_t ne1; + uint32_t ne2; + uint32_t ne3; + + uint32_t neq2; + uint32_t neq3; + uint32_t nek2; + uint32_t nek3; + uint32_t nev2; + uint32_t nev3; + uint32_t nem1; + + uint32_t nb01; + uint32_t nb02; + uint32_t nb03; + uint32_t nb11; + uint32_t nb12; + uint32_t nb13; + uint32_t nb21; + uint32_t nb22; + uint32_t nb23; + uint32_t nb31; + + float scale; + float max_bias; + float logit_softcap; + + uint32_t mask; + uint32_t n_head_log2; + float m0; + float m1; + + uint32_t gqa_ratio; + uint32_t split_kv; + uint32_t k_num; +}; + struct vk_op_push_constants { uint32_t KX; uint32_t KY; @@ -323,16 +666,55 @@ struct vk_op_unary_push_constants { uint32_t ne; uint32_t ne00; uint32_t ne01; uint32_t ne02; uint32_t ne03; uint32_t nb00; uint32_t nb01; uint32_t nb02; uint32_t nb03; uint32_t ne10; uint32_t ne11; uint32_t ne12; uint32_t ne13; uint32_t nb10; uint32_t nb11; uint32_t nb12; uint32_t nb13; - uint32_t d_offset; + uint32_t misalign_offsets; float param1; float param2; + uint32_t ne0_012mp; uint32_t ne0_012L; + uint32_t ne0_01mp; uint32_t ne0_01L; + uint32_t ne0_0mp; uint32_t ne0_0L; + uint32_t ne1_012mp; uint32_t ne1_012L; + uint32_t ne1_01mp; uint32_t ne1_01L; + uint32_t ne1_0mp; uint32_t ne1_0L; }; +static_assert(sizeof(vk_op_unary_push_constants) <= 128, "sizeof(vk_op_unary_push_constants) must be <= 128"); + +// See https://gmplib.org/~tege/divcnst-pldi94.pdf figure 4.1. +// Precompute mp (m' in the paper) and L such that division +// can be computed using a multiply (high 32b of 64b result) +// and a shift: +// +// n/d = (mulhi(n, mp) + n) >> L; +static void init_fastdiv_values(uint32_t d, uint32_t &mp, uint32_t &L) +{ + // compute L = ceil(log2(d)); + L = 0; + while (L < 32 && (uint32_t{1} << L) < d) { + L++; + } + + mp = (uint32_t)((uint64_t{1} << 32) * ((uint64_t{1} << L) - d) / d + 1); +} + +template void init_pushconst_fastdiv(T &p) { + GGML_UNUSED(p); + static_assert(!std::is_const::value, "unexpected type"); +} + +template <> void init_pushconst_fastdiv(vk_op_unary_push_constants &p) { + // Compute magic values to divide by these six numbers. + init_fastdiv_values(p.ne02*p.ne01*p.ne00, p.ne0_012mp, p.ne0_012L); + init_fastdiv_values(p.ne01*p.ne00, p.ne0_01mp, p.ne0_01L); + init_fastdiv_values(p.ne00, p.ne0_0mp, p.ne0_0L); + init_fastdiv_values(p.ne12*p.ne11*p.ne10, p.ne1_012mp, p.ne1_012L); + init_fastdiv_values(p.ne11*p.ne10, p.ne1_01mp, p.ne1_01L); + init_fastdiv_values(p.ne10, p.ne1_0mp, p.ne1_0L); +} struct vk_op_binary_push_constants { uint32_t ne; uint32_t ne00; uint32_t ne01; uint32_t ne02; uint32_t ne03; uint32_t nb00; uint32_t nb01; uint32_t nb02; uint32_t nb03; uint32_t ne10; uint32_t ne11; uint32_t ne12; uint32_t ne13; uint32_t nb10; uint32_t nb11; uint32_t nb12; uint32_t nb13; uint32_t ne20; uint32_t ne21; uint32_t ne22; uint32_t ne23; uint32_t nb20; uint32_t nb21; uint32_t nb22; uint32_t nb23; - uint32_t d_offset; + uint32_t misalign_offsets; float param1; float param2; int32_t param3; }; @@ -353,6 +735,11 @@ struct vk_op_rope_push_constants { float corr_dims[2]; float theta_scale; uint32_t has_ff; + uint32_t ne02; + uint32_t s1; + uint32_t s2; + int32_t sections[4]; + uint32_t is_back; }; struct vk_op_soft_max_push_constants { @@ -363,6 +750,7 @@ struct vk_op_soft_max_push_constants { float m0; float m1; uint32_t n_head_log2; + uint32_t nrows_x; }; struct vk_op_argsort_push_constants { @@ -390,6 +778,66 @@ struct vk_op_timestep_embedding_push_constants { uint32_t max_period; }; +struct vk_op_conv_transpose_1d_push_constants { + uint32_t Cout; + uint32_t Cin; + uint32_t K; + uint32_t L; + uint32_t KL; + + uint32_t nb01; + uint32_t nb02; + uint32_t nb11; + uint32_t nb1; + + int32_t s0; +}; + +struct vk_op_pool2d_push_constants { + uint32_t IW; uint32_t IH; + uint32_t OW; uint32_t OH; + uint32_t OC; + uint32_t pelements; + uint32_t op; + int32_t k0; int32_t k1; + int32_t s0; int32_t s1; + int32_t p0; int32_t p1; +}; + +struct vk_op_rwkv_wkv6_push_constants { + uint32_t B; + uint32_t T; + uint32_t C; + uint32_t H; +}; + + +struct vk_op_conv2d_dw_push_constants { + uint32_t ne; + uint32_t batches; + uint32_t channels; + uint32_t dst_w; + uint32_t dst_h; + uint32_t src_w; + uint32_t src_h; + uint32_t knl_w; + uint32_t knl_h; + int32_t stride_x; + int32_t stride_y; + int32_t pad_x; + int32_t pad_y; + int32_t dilation_x; + int32_t dilation_y; +}; + + +struct vk_op_upscale_push_constants { + uint32_t ne; uint32_t a_offset; uint32_t d_offset; + uint32_t nb00; uint32_t nb01; uint32_t nb02; uint32_t nb03; + uint32_t ne10; uint32_t ne11; uint32_t ne12; uint32_t ne13; + float sf0; float sf1; float sf2; float sf3; +}; + // Allow pre-recording command buffers struct vk_staging_memcpy { vk_staging_memcpy(void * _dst, const void * _src, size_t _n) : dst(_dst), src(_src), n(_n) {} @@ -399,13 +847,6 @@ struct vk_staging_memcpy { size_t n; }; -struct vk_op_upscale_push_constants { - uint32_t ne; uint32_t d_offset; - uint32_t nb00; uint32_t nb01; uint32_t nb02; uint32_t nb03; - uint32_t ne10; uint32_t ne11; uint32_t ne12; uint32_t ne13; - float sf0; float sf1; float sf2; float sf3; -}; - struct vk_context_struct { vk_submission * s; std::vector seqs; @@ -415,21 +856,11 @@ struct vk_context_struct { std::vector in_memcpys; std::vector out_memcpys; - vk_queue * q; + vk_command_pool * p {}; }; typedef std::shared_ptr vk_context; typedef std::weak_ptr vk_context_ref; -struct ggml_tensor_extra_gpu { - vk_buffer_ref buffer_gpu; - uint64_t offset; - - void reset() { - buffer_gpu.reset(); - offset = 0; - } -}; - struct ggml_vk_garbage_collector { std::vector tl_semaphores; std::vector semaphores; @@ -479,6 +910,45 @@ private: #define VK_LOG_MEMORY(msg) ((void) 0) #endif // GGML_VULKAN_MEMORY_DEBUG +class vk_perf_logger { +public: + void print_timings() { + std::cerr << "----------------\nVulkan Timings:" << std::endl; + for (const auto& t : timings) { + uint64_t total = 0; + for (const auto& time : t.second) { + total += time; + } + std::cerr << t.first << ": " << t.second.size() << " x " << (total / t.second.size() / 1000.0) << " us" << std::endl; + } + + timings.clear(); + } + + void log_timing(const ggml_tensor * node, uint64_t time) { + if (node->op == GGML_OP_UNARY) { + timings[ggml_unary_op_name(ggml_get_unary_op(node))].push_back(time); + return; + } + if (node->op == GGML_OP_MUL_MAT || node->op == GGML_OP_MUL_MAT_ID) { + const uint64_t m = node->src[0]->ne[1]; + const uint64_t n = node->src[1]->ne[1]; + const uint64_t k = node->src[1]->ne[0]; + std::string name = ggml_op_name(node->op); + if (n == 1) { + name += "_VEC m=" + std::to_string(m) + " k=" + std::to_string(k); + } else { + name += " m=" + std::to_string(m) + " n=" + std::to_string(n) + " k=" + std::to_string(k); + } + timings[name].push_back(time); + return; + } + timings[ggml_op_name(node->op)].push_back(time); + } +private: + std::map> timings; +}; + struct ggml_backend_vk_context { std::string name; @@ -488,10 +958,8 @@ struct ggml_backend_vk_context { ggml_vk_garbage_collector gc; size_t prealloc_size_x, prealloc_size_y, prealloc_size_split_k; vk_buffer prealloc_x, prealloc_y, prealloc_split_k; - vk::Fence fence; - vk_buffer staging; - size_t staging_size; - size_t staging_offset; + vk::Fence fence, almost_ready_fence; + bool almost_ready_fence_pending {}; vk_buffer buffer_pool[MAX_VK_BUFFERS]; @@ -499,6 +967,39 @@ struct ggml_backend_vk_context { vk_context_ref transfer_ctx; std::vector tensor_ctxs; + + std::vector descriptor_pools; + std::vector descriptor_sets; + uint32_t descriptor_set_idx {}; + uint32_t pipeline_descriptor_set_requirements {}; + + vk_command_pool compute_cmd_pool; + vk_command_pool transfer_cmd_pool; +}; + +static void * const vk_ptr_base = (void *)(uintptr_t) 0x1000; // NOLINT + +static uint64_t vk_tensor_offset(const ggml_tensor * tensor) { + if (tensor->view_src) { + return (uint8_t *) tensor->view_src->data - (uint8_t *) vk_ptr_base; + } + return (uint8_t *) tensor->data - (uint8_t *) vk_ptr_base; +} + +struct ggml_backend_vk_buffer_context { + vk_device_ref device; + vk_buffer dev_buffer; + std::string name; + + ggml_backend_vk_buffer_context(vk_device_ref device, vk_buffer&& dev_buffer, std::string& name) : + device(device), + dev_buffer(dev_buffer), + name(name) { + } + + ~ggml_backend_vk_buffer_context() { + ggml_vk_destroy_buffer(dev_buffer); + } }; #ifdef GGML_VULKAN_MEMORY_DEBUG @@ -537,6 +1038,14 @@ void vk_memory_logger::log_deallocation(vk_buffer_ref buf_ref) { struct vk_instance_t { vk::Instance instance; + bool debug_utils_support = false; // VK_EXT_debug_utils enabled + PFN_vkSetDebugUtilsObjectNameEXT pfn_vkSetDebugUtilsObjectNameEXT = {}; + PFN_vkQueueBeginDebugUtilsLabelEXT pfn_vkQueueBeginDebugUtilsLabelEXT = {}; + PFN_vkQueueEndDebugUtilsLabelEXT pfn_vkQueueEndDebugUtilsLabelEXT = {}; + PFN_vkCmdBeginDebugUtilsLabelEXT pfn_vkCmdBeginDebugUtilsLabelEXT = {}; + PFN_vkCmdEndDebugUtilsLabelEXT pfn_vkCmdEndDebugUtilsLabelEXT = {}; + PFN_vkCmdInsertDebugUtilsLabelEXT pfn_vkCmdInsertDebugUtilsLabelEXT = {}; + std::vector device_indices; vk_device devices[GGML_VK_MAX_DEVICES]; }; @@ -544,6 +1053,8 @@ struct vk_instance_t { static bool vk_instance_initialized = false; static vk_instance_t vk_instance; +static bool vk_perf_logger_enabled = false; + #ifdef GGML_VULKAN_CHECK_RESULTS static size_t vk_skip_checks; static size_t vk_output_tensor; @@ -557,77 +1068,64 @@ typedef void (*ggml_vk_func_t)(ggml_backend_vk_context * ctx, vk_context& subctx GGML_CALL static void ggml_backend_vk_free(ggml_backend_t backend); -static void ggml_vk_create_pipeline(vk_device& device, vk_pipeline& pipeline, const std::string& name, size_t spv_size, const void* spv_data, const std::string& entrypoint, uint32_t parameter_count, uint32_t push_constant_size, std::array wg_denoms, std::vector&& specialization_constants, uint32_t align) { - VK_LOG_DEBUG("ggml_vk_create_pipeline(" << device->name << ", " << name << ", " << entrypoint << ", " << parameter_count << ", " << push_constant_size << ", (" << wg_denoms[0] << "," << wg_denoms[1] << "," << wg_denoms[2] << "), specialization_constants, " << align << ")"); +// Wait for ctx->fence to be signaled. +static void ggml_vk_wait_for_fence(ggml_backend_vk_context * ctx) { + // Use waitForFences while most of the graph executes. Hopefully the CPU can sleep + // during this wait. + if (ctx->almost_ready_fence_pending) { + VK_CHECK(ctx->device->device.waitForFences({ ctx->almost_ready_fence }, true, UINT64_MAX), "almost_ready_fence"); + ctx->device->device.resetFences({ ctx->almost_ready_fence }); + ctx->almost_ready_fence_pending = false; + } + + // Spin (w/pause) waiting for the graph to finish executing. + vk::Result result; + while ((result = ctx->device->device.getFenceStatus(ctx->fence)) != vk::Result::eSuccess) { + if (result != vk::Result::eNotReady) { + fprintf(stderr, "ggml_vulkan: error %s at %s:%d\n", to_string(result).c_str(), __FILE__, __LINE__); + exit(1); + } + for (uint32_t i = 0; i < 100; ++i) { + YIELD(); + YIELD(); + YIELD(); + YIELD(); + YIELD(); + YIELD(); + YIELD(); + YIELD(); + YIELD(); + YIELD(); + } + } + ctx->device->device.resetFences({ ctx->fence }); +} + +// variables to track number of compiles in progress +static uint32_t compile_count = 0; +static std::mutex compile_count_mutex; +static std::condition_variable compile_count_cond; + +static void ggml_vk_create_pipeline_func(vk_device& device, vk_pipeline& pipeline, size_t spv_size, const void* spv_data, const std::string entrypoint, + uint32_t parameter_count, std::array wg_denoms, std::vector specialization_constants, + bool disable_robustness, bool require_full_subgroups, uint32_t required_subgroup_size) { + VK_LOG_DEBUG("ggml_vk_create_pipeline(" << device->name << ", " << pipeline->name << ", " << entrypoint << ", " << parameter_count << + ", (" << wg_denoms[0] << "," << wg_denoms[1] << "," << wg_denoms[2] << "), specialization_constants, " << + disable_robustness << ", " << require_full_subgroups << ", " << required_subgroup_size << ")"); GGML_ASSERT(parameter_count > 0); + GGML_ASSERT(parameter_count <= MAX_PARAMETER_COUNT); GGML_ASSERT(wg_denoms[0] > 0 && wg_denoms[1] > 0 && wg_denoms[2] > 0); // NOLINT - std::lock_guard guard(device->mutex); - - pipeline = std::make_shared(); - pipeline->name = name; - pipeline->parameter_count = parameter_count; - pipeline->push_constant_size = push_constant_size; - pipeline->wg_denoms = wg_denoms; - pipeline->align = align; - vk::ShaderModuleCreateInfo shader_module_create_info({}, spv_size, reinterpret_cast(spv_data)); pipeline->shader_module = device->device.createShaderModule(shader_module_create_info); - std::vector dsl_binding; - std::vector dsl_binding_flags; - for (uint32_t i = 0; i < parameter_count; i++) { - dsl_binding.push_back({i, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute}); - dsl_binding_flags.push_back({}); - } - - vk::DescriptorSetLayoutBindingFlagsCreateInfo dslbfci = { dsl_binding_flags }; - vk::PushConstantRange pcr( vk::ShaderStageFlagBits::eCompute, 0, pipeline->push_constant_size ); - vk::DescriptorSetLayoutCreateInfo descriptor_set_layout_create_info( - {}, - dsl_binding); - descriptor_set_layout_create_info.setPNext(&dslbfci); - pipeline->dsl = device->device.createDescriptorSetLayout(descriptor_set_layout_create_info); - - // Check if device supports multiple descriptors per pool - if (device->descriptor_set_mode == VK_DEVICE_DESCRIPTOR_POOL_MODE_UNKNOWN) { - const uint32_t alloc_count = 2; - - // Try allocating multiple sets from one pool - // This fails on AMD for some reason, so add a fall back to allocating one pool per set - vk::DescriptorPoolSize descriptor_pool_size(vk::DescriptorType::eStorageBuffer, pipeline->parameter_count); - vk::DescriptorPoolCreateInfo descriptor_pool_create_info({}, alloc_count, descriptor_pool_size); - vk::DescriptorPool pool = device->device.createDescriptorPool(descriptor_pool_create_info); - - std::vector layouts(alloc_count); - for (uint32_t i = 0; i < alloc_count; i++) { - layouts[i] = pipeline->dsl; - } - try { - vk::DescriptorSetAllocateInfo descriptor_set_alloc_info(pool, alloc_count, layouts.data()); - std::vector sets = device->device.allocateDescriptorSets(descriptor_set_alloc_info); - } catch(vk::OutOfPoolMemoryError const&) { - device->descriptor_set_mode = VK_DEVICE_DESCRIPTOR_POOL_MODE_SINGLE; - } - - device->device.destroyDescriptorPool(pool); - } - - if (device->descriptor_set_mode == VK_DEVICE_DESCRIPTOR_POOL_MODE_MULTI) { - vk::DescriptorPoolSize descriptor_pool_size(vk::DescriptorType::eStorageBuffer, pipeline->parameter_count); - vk::DescriptorPoolCreateInfo descriptor_pool_create_info({}, 128, descriptor_pool_size); - pipeline->descriptor_pools.push_back(device->device.createDescriptorPool(descriptor_pool_create_info)); - } - - pipeline->descriptor_set_idx = 0; - - vk::PipelineLayoutCreateInfo pipeline_layout_create_info(vk::PipelineLayoutCreateFlags(), pipeline->dsl, pcr); + vk::PipelineLayoutCreateInfo pipeline_layout_create_info(vk::PipelineLayoutCreateFlags(), device->dsl, pcr); pipeline->layout = device->device.createPipelineLayout(pipeline_layout_create_info); std::vector specialization_entries(specialization_constants.size()); @@ -645,32 +1143,71 @@ static void ggml_vk_create_pipeline(vk_device& device, vk_pipeline& pipeline, co specialization_constants.data() ); + vk::PipelineShaderStageCreateFlags pipeline_shader_stage_create_flags{}; + + if (device->subgroup_require_full_support && require_full_subgroups) { + pipeline_shader_stage_create_flags |= vk::PipelineShaderStageCreateFlagBits::eRequireFullSubgroupsEXT; + } + vk::PipelineShaderStageCreateInfo pipeline_shader_create_info( - vk::PipelineShaderStageCreateFlags(), + pipeline_shader_stage_create_flags, vk::ShaderStageFlagBits::eCompute, pipeline->shader_module, entrypoint.c_str(), &specialization_info); + + vk::PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT pipeline_shader_stage_required_subgroup_size_create_info; + pipeline_shader_stage_required_subgroup_size_create_info.requiredSubgroupSize = required_subgroup_size; + if (device->subgroup_size_control && required_subgroup_size > 0) { + GGML_ASSERT(device->subgroup_min_size <= required_subgroup_size && required_subgroup_size <= device->subgroup_max_size); + pipeline_shader_create_info.setPNext(&pipeline_shader_stage_required_subgroup_size_create_info); + } + vk::ComputePipelineCreateInfo compute_pipeline_create_info( - vk::PipelineCreateFlags(), + vk::PipelineCreateFlags{}, pipeline_shader_create_info, pipeline->layout); - pipeline->pipeline = device->device.createComputePipeline(VK_NULL_HANDLE, compute_pipeline_create_info).value; - device->pipelines.push_back(pipeline); + vk::PipelineRobustnessCreateInfoEXT rci; + + if (device->pipeline_robustness && disable_robustness) { + rci.storageBuffers = vk::PipelineRobustnessBufferBehaviorEXT::eDisabled; + rci.uniformBuffers = vk::PipelineRobustnessBufferBehaviorEXT::eDisabled; + compute_pipeline_create_info.setPNext(&rci); + } + + try { + pipeline->pipeline = device->device.createComputePipeline(VK_NULL_HANDLE, compute_pipeline_create_info).value; + } catch (const vk::SystemError& e) { + std::cerr << "ggml_vulkan: Compute pipeline creation failed for " << pipeline->name << std::endl; + std::cerr << "ggml_vulkan: " << e.what() << std::endl; + throw e; + } + pipeline->compiled = true; + + if (vk_instance.debug_utils_support) { + vk::DebugUtilsObjectNameInfoEXT duoni; + duoni.objectType = vk::ObjectType::ePipeline; + duoni.pObjectName = pipeline->name.c_str(); + duoni.objectHandle = reinterpret_cast(static_cast(pipeline->pipeline)); + vk_instance.pfn_vkSetDebugUtilsObjectNameEXT(device->device, &static_cast(duoni)); + } + + { + std::lock_guard guard(device->mutex); + device->pipelines.insert({ pipeline->name, pipeline }); + } + + { + std::lock_guard guard(compile_count_mutex); + assert(compile_count > 0); + compile_count--; + } + compile_count_cond.notify_all(); } static void ggml_vk_destroy_pipeline(vk::Device& device, vk_pipeline& pipeline) { VK_LOG_DEBUG("ggml_pipeline_destroy_pipeline(" << pipeline->name << ")"); - for (auto& pool : pipeline->descriptor_pools) { - device.destroyDescriptorPool(pool); - } - pipeline->descriptor_pools.clear(); - pipeline->descriptor_sets.clear(); - pipeline->descriptor_set_idx = 0; - - device.destroyDescriptorSetLayout(pipeline->dsl); - device.destroyPipelineLayout(pipeline->layout); device.destroyShaderModule(pipeline->shader_module); @@ -678,76 +1215,78 @@ static void ggml_vk_destroy_pipeline(vk::Device& device, vk_pipeline& pipeline) device.destroyPipeline(pipeline->pipeline); } -static void ggml_pipeline_allocate_descriptor_sets(vk_device& device, vk_pipeline& pipeline, uint32_t n) { - VK_LOG_DEBUG("ggml_pipeline_allocate_descriptor_sets(" << pipeline->name << ", " << n << ")"); - if (pipeline->descriptor_sets.size() >= pipeline->descriptor_set_idx + n) { +static void ggml_pipeline_request_descriptor_sets(ggml_backend_vk_context *ctx, vk_pipeline& pipeline, uint32_t n) { + VK_LOG_DEBUG("ggml_pipeline_request_descriptor_sets(" << pipeline->name << ", " << n << ")"); + ctx->pipeline_descriptor_set_requirements += n; + if (!pipeline->compiled) { + pipeline->needed = true; + ctx->device->need_compiles = true; + } +} + +static void ggml_pipeline_allocate_descriptor_sets(ggml_backend_vk_context * ctx) { + + if (ctx->descriptor_sets.size() >= ctx->pipeline_descriptor_set_requirements) { // Enough descriptors are available return; } - std::lock_guard guard(device->mutex); + vk_device& device = ctx->device; - if (device->descriptor_set_mode == VK_DEVICE_DESCRIPTOR_POOL_MODE_MULTI) { - const uint32_t alloc_count = pipeline->descriptor_set_idx + n - pipeline->descriptor_sets.size(); + uint32_t to_alloc = ctx->pipeline_descriptor_set_requirements - ctx->descriptor_sets.size(); + uint32_t pool_remaining = VK_DEVICE_DESCRIPTOR_POOL_SIZE - ctx->descriptor_sets.size() % VK_DEVICE_DESCRIPTOR_POOL_SIZE; + uint32_t pool_idx = ctx->descriptor_sets.size() / VK_DEVICE_DESCRIPTOR_POOL_SIZE; + + while (to_alloc > 0) { + const uint32_t alloc_count = std::min(pool_remaining, to_alloc); + to_alloc -= alloc_count; + pool_remaining = VK_DEVICE_DESCRIPTOR_POOL_SIZE; + + if (pool_idx >= ctx->descriptor_pools.size()) { + vk::DescriptorPoolSize descriptor_pool_size(vk::DescriptorType::eStorageBuffer, MAX_PARAMETER_COUNT * VK_DEVICE_DESCRIPTOR_POOL_SIZE); + vk::DescriptorPoolCreateInfo descriptor_pool_create_info({}, VK_DEVICE_DESCRIPTOR_POOL_SIZE, descriptor_pool_size); + ctx->descriptor_pools.push_back(device->device.createDescriptorPool(descriptor_pool_create_info)); + } std::vector layouts(alloc_count); for (uint32_t i = 0; i < alloc_count; i++) { - layouts[i] = pipeline->dsl; + layouts[i] = device->dsl; } - vk::DescriptorSetAllocateInfo descriptor_set_alloc_info(pipeline->descriptor_pools[0], alloc_count, layouts.data()); + vk::DescriptorSetAllocateInfo descriptor_set_alloc_info(ctx->descriptor_pools[pool_idx], alloc_count, layouts.data()); std::vector sets = device->device.allocateDescriptorSets(descriptor_set_alloc_info); - pipeline->descriptor_sets.insert(pipeline->descriptor_sets.end(), sets.begin(), sets.end()); - } else { - for (uint32_t i = pipeline->descriptor_sets.size(); i < pipeline->descriptor_set_idx + n; i++) { - vk::DescriptorPoolSize descriptor_pool_size(vk::DescriptorType::eStorageBuffer, pipeline->parameter_count); - vk::DescriptorPoolCreateInfo descriptor_pool_create_info({}, 1, descriptor_pool_size); - pipeline->descriptor_pools.push_back(device->device.createDescriptorPool(descriptor_pool_create_info)); + ctx->descriptor_sets.insert(ctx->descriptor_sets.end(), sets.begin(), sets.end()); - vk::DescriptorSetAllocateInfo descriptor_set_alloc_info(pipeline->descriptor_pools[i], 1, &pipeline->dsl); - std::vector sets = device->device.allocateDescriptorSets(descriptor_set_alloc_info); - pipeline->descriptor_sets.push_back(sets[0]); - } + pool_idx++; } } -static void ggml_pipeline_cleanup(vk_pipeline& pipeline) { - VK_LOG_DEBUG("ggml_pipeline_cleanup(" << pipeline->name << ")"); - pipeline->descriptor_set_idx = 0; -} - -static vk::CommandBuffer ggml_vk_create_cmd_buffer(vk_device& device, vk_queue& q) { +static vk::CommandBuffer ggml_vk_create_cmd_buffer(vk_device& device, vk_command_pool& p) { VK_LOG_DEBUG("ggml_vk_create_cmd_buffer()"); - std::lock_guard guard(device->mutex); - if (q.cmd_buffers.size() > q.cmd_buffer_idx) { + if (p.cmd_buffers.size() > p.cmd_buffer_idx) { // Reuse command buffer - return q.cmd_buffers[q.cmd_buffer_idx++]; + return p.cmd_buffers[p.cmd_buffer_idx++]; } vk::CommandBufferAllocateInfo command_buffer_alloc_info( - q.pool, + p.pool, vk::CommandBufferLevel::ePrimary, 1); const std::vector cmd_buffers = device->device.allocateCommandBuffers(command_buffer_alloc_info); auto buf = cmd_buffers.front(); - q.cmd_buffers.push_back(buf); - q.cmd_buffer_idx++; + p.cmd_buffers.push_back(buf); + p.cmd_buffer_idx++; return buf; } -static vk_submission ggml_vk_create_submission(vk_device& device, vk_queue& q, std::vector wait_semaphores, std::vector signal_semaphores) { - VK_LOG_DEBUG("ggml_vk_create_submission()"); - vk_submission s; - s.buffer = ggml_vk_create_cmd_buffer(device, q); - s.wait_semaphores = std::move(wait_semaphores); - s.signal_semaphores = std::move(signal_semaphores); - return s; -} - static void ggml_vk_submit(vk_context& ctx, vk::Fence fence) { if (ctx->seqs.empty()) { + if (fence) { + std::lock_guard guard(queue_mutex); + ctx->p->q->queue.submit({}, fence); + } return; } VK_LOG_DEBUG("ggml_vk_submit(" << ctx << ", " << fence << ")"); @@ -785,7 +1324,7 @@ static void ggml_vk_submit(vk_context& ctx, vk::Fence fence) { tl_signal_vals.push_back({}); tl_signal_semaphores.push_back({}); for (size_t i = 0; i < submission.wait_semaphores.size(); i++) { - stage_flags[idx].push_back(ctx->q->stage_flags); + stage_flags[idx].push_back(ctx->p->q->stage_flags); tl_wait_vals[idx].push_back(submission.wait_semaphores[i].value); tl_wait_semaphores[idx].push_back(submission.wait_semaphores[i].s); } @@ -815,7 +1354,8 @@ static void ggml_vk_submit(vk_context& ctx, vk::Fence fence) { } } - ctx->q->queue.submit(submit_infos, fence); + std::lock_guard guard(queue_mutex); + ctx->p->q->queue.submit(submit_infos, fence); ctx->seqs.clear(); } @@ -866,34 +1406,32 @@ static uint32_t ggml_vk_find_queue_family_index(std::vector guard(device->mutex); + std::lock_guard guard(device->mutex); q.queue_family_index = queue_family_index; + q.transfer_only = transfer_only; - vk::CommandPoolCreateInfo command_pool_create_info_compute(vk::CommandPoolCreateFlags(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT), queue_family_index); - q.pool = device->device.createCommandPool(command_pool_create_info_compute); - - q.cmd_buffer_idx = 0; + q.cmd_pool.init(device, &q); q.queue = device->device.getQueue(queue_family_index, queue_index); q.stage_flags = stage_flags; } -static vk_context ggml_vk_create_context(ggml_backend_vk_context * ctx, vk_queue& q) { +static vk_context ggml_vk_create_context(ggml_backend_vk_context * ctx, vk_command_pool& p) { vk_context result = std::make_shared(); VK_LOG_DEBUG("ggml_vk_create_context(" << result << ")"); ctx->gc.contexts.emplace_back(result); - result->q = &q; + result->p = &p; return result; } -static vk_context ggml_vk_create_temporary_context(vk_queue& q) { +static vk_context ggml_vk_create_temporary_context(vk_command_pool& p) { vk_context result = std::make_shared(); VK_LOG_DEBUG("ggml_vk_create_temporary_context(" << result << ")"); - result->q = &q; + result->p = &p; return result; } @@ -926,15 +1464,29 @@ static vk::Event ggml_vk_create_event(ggml_backend_vk_context * ctx) { return ctx->gc.events[ctx->event_idx++]; } -static void ggml_vk_queue_cleanup(vk_device& device, vk_queue& q) { - VK_LOG_DEBUG("ggml_vk_queue_cleanup()"); - std::lock_guard guard(device->mutex); +static void ggml_vk_command_pool_cleanup(vk_device& device, vk_command_pool& p) { + VK_LOG_DEBUG("ggml_vk_command_pool_cleanup()"); // Requires command buffers to be done - device->device.resetCommandPool(q.pool); - q.cmd_buffer_idx = 0; + device->device.resetCommandPool(p.pool); + p.cmd_buffer_idx = 0; } +static void ggml_vk_queue_command_pools_cleanup(vk_device& device) { + VK_LOG_DEBUG("ggml_vk_queue_command_pools_cleanup()"); + + // Arbitrary frequency to cleanup/reuse command buffers + static constexpr uint32_t cleanup_frequency = 10; + + if (device->compute_queue.cmd_pool.cmd_buffer_idx >= cleanup_frequency) { + ggml_vk_command_pool_cleanup(device, device->compute_queue.cmd_pool); + } + if (device->transfer_queue.cmd_pool.cmd_buffer_idx >= cleanup_frequency) { + ggml_vk_command_pool_cleanup(device, device->transfer_queue.cmd_pool); + } +} + + static uint32_t find_properties(const vk::PhysicalDeviceMemoryProperties* mem_props, vk::MemoryRequirements* mem_req, vk::MemoryPropertyFlags flags) { for (uint32_t i = 0; i < mem_props->memoryTypeCount; ++i) { vk::MemoryType memory_type = mem_props->memoryTypes[i]; @@ -953,8 +1505,6 @@ static vk_buffer ggml_vk_create_buffer(vk_device& device, size_t size, vk::Memor throw vk::OutOfDeviceMemoryError("Requested buffer size exceeds device memory allocation limit"); } - std::lock_guard guard(device->mutex); - vk_buffer buf = std::make_shared(); if (size == 0) { @@ -962,7 +1512,6 @@ static vk_buffer ggml_vk_create_buffer(vk_device& device, size_t size, vk::Memor return buf; } - buf->size = size; vk::BufferCreateInfo buffer_create_info{ vk::BufferCreateFlags(), size, @@ -990,17 +1539,29 @@ static vk_buffer ggml_vk_create_buffer(vk_device& device, size_t size, vk::Memor if (memory_type_index == UINT32_MAX) { device->device.destroyBuffer(buf->buffer); - buf->size = 0; throw vk::OutOfDeviceMemoryError("No suitable memory type found"); } try { buf->device_memory = device->device.allocateMemory({ mem_req.size, memory_type_index }); } catch (const vk::SystemError& e) { - // Out of Host/Device memory, clean up buffer - device->device.destroyBuffer(buf->buffer); - buf->size = 0; - throw e; + if (buf->memory_property_flags != fallback_flags) { + // Try again with fallback flags + memory_type_index = find_properties(&mem_props, &mem_req, fallback_flags); + buf->memory_property_flags = fallback_flags; + + try { + buf->device_memory = device->device.allocateMemory({ mem_req.size, memory_type_index }); + } + catch (const vk::SystemError& e) { + device->device.destroyBuffer(buf->buffer); + throw e; + } + } else { + // Out of Host/Device memory, clean up buffer + device->device.destroyBuffer(buf->buffer); + throw e; + } } buf->ptr = nullptr; @@ -1011,6 +1572,7 @@ static vk_buffer ggml_vk_create_buffer(vk_device& device, size_t size, vk::Memor device->device.bindBufferMemory(buf->buffer, buf->device_memory, 0); buf->device = device; + buf->size = size; #ifdef GGML_VULKAN_MEMORY_DEBUG device->memory_logger->log_allocation(buf, size); @@ -1032,11 +1594,14 @@ static vk_buffer ggml_vk_create_buffer_check(vk_device& device, size_t size, vk: static vk_buffer ggml_vk_create_buffer_device(vk_device& device, size_t size) { vk_buffer buf; try { - if (device->uma) { + if (device->prefer_host_memory) { + buf = ggml_vk_create_buffer(device, size, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, vk::MemoryPropertyFlagBits::eDeviceLocal); + } else if (device->uma) { // Fall back to host memory type buf = ggml_vk_create_buffer(device, size, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); } else { - buf = ggml_vk_create_buffer(device, size, vk::MemoryPropertyFlagBits::eDeviceLocal); + // use rebar if available, otherwise fallback to device only visible memory + buf = ggml_vk_create_buffer(device, size, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, vk::MemoryPropertyFlagBits::eDeviceLocal); } } catch (const vk::SystemError& e) { std::cerr << "ggml_vulkan: Device memory allocation of size " << size << " failed." << std::endl; @@ -1067,13 +1632,16 @@ static vk_subbuffer ggml_vk_subbuffer(vk_buffer& buf) { static void ggml_vk_sync_buffers(vk_context& ctx) { VK_LOG_DEBUG("ggml_vk_sync_buffers()"); + + const bool transfer_queue = ctx->p->q->transfer_only; + ctx->s->buffer.pipelineBarrier( - ctx->q->stage_flags, - ctx->q->stage_flags, + ctx->p->q->stage_flags, + ctx->p->q->stage_flags, {}, { { - {vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite}, - {vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite} + { !transfer_queue ? (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite) : (vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite) }, + { !transfer_queue ? (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite) : (vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite) } } }, {}, {} @@ -1088,515 +1656,927 @@ static void ggml_vk_wait_events(vk_context& ctx, std::vector&& events ctx->s->buffer.waitEvents( events, - ctx->q->stage_flags, - ctx->q->stage_flags, + ctx->p->q->stage_flags, + ctx->p->q->stage_flags, {}, {}, {} ); } +enum FaCodePath { + FA_SCALAR, + FA_COOPMAT1, + FA_COOPMAT2, +}; + +// number of rows/cols for flash attention shader +static constexpr uint32_t flash_attention_num_small_rows = 32; +static constexpr uint32_t scalar_flash_attention_num_small_rows = 1; +static constexpr uint32_t scalar_flash_attention_num_large_rows = 8; + +// The FA coopmat1 shader assumes 16x16x16 matrix multiply support. +// 128 threads split into four subgroups, each subgroup does 1/4 +// of the Bc dimension. +static constexpr uint32_t coopmat1_flash_attention_num_large_rows = 16; +static constexpr uint32_t scalar_flash_attention_Bc = 64; +static constexpr uint32_t scalar_flash_attention_workgroup_size = 128; + +static uint32_t get_fa_num_small_rows(FaCodePath path) { + if (path == FA_COOPMAT2) { + return flash_attention_num_small_rows; + } else { + return scalar_flash_attention_num_small_rows; + } +} + +static std::array fa_rows_cols(FaCodePath path, uint32_t D, uint32_t clamp, ggml_type type, bool small_rows) { + GGML_UNUSED(clamp); + + if (path == FA_SCALAR) { + if (small_rows) { + return {scalar_flash_attention_num_small_rows, 64}; + } else { + return {scalar_flash_attention_num_large_rows, 32}; + } + } + + if (path == FA_COOPMAT1) { + if (small_rows) { + return {scalar_flash_attention_num_small_rows, scalar_flash_attention_Bc}; + } else { + return {coopmat1_flash_attention_num_large_rows, scalar_flash_attention_Bc}; + } + } + + // small rows, large cols + if (small_rows) { + return {get_fa_num_small_rows(FA_COOPMAT2), 32}; + } + + // small cols to reduce register count + if (ggml_is_quantized(type) || D == 256) { + return {64, 32}; + } + return {64, 64}; +} + +static bool ggml_vk_matmul_shmem_support(const vk_device& device, const std::vector& warptile, bool mul_mat_id, ggml_type src0_type) { + + uint32_t lut_size = 0; + switch (src0_type) { + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + lut_size = 2*2048; + break; + case GGML_TYPE_IQ2_XXS: + lut_size = 8*256; + break; + case GGML_TYPE_IQ2_XS: + lut_size = 8*512; + break; + case GGML_TYPE_IQ2_S: + lut_size = 8*1024; + break; + case GGML_TYPE_IQ3_XXS: + lut_size = 4*256; + break; + case GGML_TYPE_IQ3_S: + lut_size = 4*512; + break; + case GGML_TYPE_IQ4_NL: + case GGML_TYPE_IQ4_XS: + lut_size = 4*16; + break; + default: + break; + } + + // Needs to be kept up to date on shader changes + const uint32_t bank_conflict_offset = device->coopmat_support ? 8 : 1; + const uint32_t type_size = device->fp16 ? sizeof(ggml_fp16_t) : sizeof(float); + const uint32_t warps = warptile[0] / warptile[10]; + + const uint32_t load_bufs = (warptile[1] + warptile[2]) * (warptile[3] + bank_conflict_offset) * type_size; + const uint32_t mmid_row_ids = mul_mat_id ? 4096 * sizeof(uint32_t) : 0; + const uint32_t coopmat_stage = device->coopmat_support ? warptile[7] * warptile[8] / warps * sizeof(float) : 0; + + const uint32_t total_size = load_bufs + mmid_row_ids + coopmat_stage + lut_size; + const bool supported = total_size <= device->properties.limits.maxComputeSharedMemorySize; + + VK_LOG_DEBUG("ggml_vk_matmul_shmem_support(warptile=(" << warptile[0] << "," << warptile[1] << "," << warptile[2] << "), " + "mul_mat_id=" << mul_mat_id << ", src0_type=" << ggml_type_name(src0_type) << ", supported=" << supported); + + return supported; +} + +struct GpuPipelineConfig { + // GPU architecture identifier. + // Example: vk_device_architecture::AMD_GCN + vk_device_architecture arch; + + // Mapping of pipeline names to their specific subgroup sizes. + // Example: {"soft_max_f32", 64} + std::unordered_map pipelines; + + // Default subgroup size for this GPU. + // Defaults to 0 if not explicitly provided. + uint32_t default_subgroup_size = 0; +}; + +// Pipeline configuration for RDNA1 GPUs. +static const std::unordered_map rdna1_pipelines = { + {"soft_max", 64}, {"im2col", 64}, + {"argmax", 64}, {"mul_mat_vec", 64}, + {"mul_mat_vec_f16", 32}, {"mul_mat_vec_f32_f16", 32} +}; + +// Pipeline configuration for RDNA2 GPUs. +static const std::unordered_map rdna2_pipelines = { + {"soft_max", 64}, {"im2col", 64}, +}; + +static constexpr uint32_t RDNA_DEFAULT_SUBGROUP_SIZE = 32; + +// Define configurations for different GPUs. +static std::vector gpu_pipeline_configs = { + { + vk_device_architecture::AMD_RDNA1, + { + rdna1_pipelines, + }, + RDNA_DEFAULT_SUBGROUP_SIZE + }, + { + vk_device_architecture::AMD_RDNA2, + { + rdna2_pipelines, + }, + RDNA_DEFAULT_SUBGROUP_SIZE + }, +}; + +static uint32_t get_subgroup_size(const std::string &pipeline_name, const vk_device_architecture &arch) { + for (const auto &config : gpu_pipeline_configs) { + if (config.arch == arch) { + auto pipIt = config.pipelines.find(pipeline_name); + if (pipIt != config.pipelines.end()) { + return pipIt->second; + } + std::vector> sorted_pipelines(config.pipelines.begin(), config.pipelines.end()); + std::sort(sorted_pipelines.begin(), sorted_pipelines.end(), + [](const auto &a, const auto &b) { return a.first.size() > b.first.size(); }); + for (const auto &entry : sorted_pipelines) { + if (pipeline_name.find(entry.first) != std::string::npos) { + return entry.second; + } + } + return config.default_subgroup_size; + } + } + return 0; // If no matching configuration is found +} + static void ggml_vk_load_shaders(vk_device& device) { VK_LOG_DEBUG("ggml_vk_load_shaders(" << device->name << ")"); + // some shaders have a minimum subgroup size + const uint32_t subgroup_size_8 = std::max(device->subgroup_size, 8u); + const uint32_t subgroup_size_16 = std::max(device->subgroup_size, 16u); + const uint32_t subgroup_size_32 = std::max(device->subgroup_size, 32u); + // mulmat - std::initializer_list warptile_l = { 128, 128, 128, 16, device->subgroup_size * 2, 64, 2, 4, 4, device->subgroup_size }; - std::initializer_list warptile_m = { 128, 64, 64, 16, device->subgroup_size, 32, 2, 4, 2, device->subgroup_size }; - std::initializer_list warptile_s = { device->subgroup_size, 32, 32, 16, 32, 32, 2, 2, 2, device->subgroup_size }; + std::vector l_warptile, m_warptile, s_warptile, + l_warptile_mmq, m_warptile_mmq, s_warptile_mmq, + l_warptile_mmq_int, m_warptile_mmq_int, s_warptile_mmq_int, + l_warptile_mmq_k, m_warptile_mmq_k, s_warptile_mmq_k, + l_warptile_mmqid, m_warptile_mmqid, s_warptile_mmqid; + std::array l_wg_denoms, m_wg_denoms, s_wg_denoms, + l_mmq_wg_denoms, m_mmq_wg_denoms, s_mmq_wg_denoms, + l_mmq_wg_denoms_k, m_mmq_wg_denoms_k, s_mmq_wg_denoms_k, + l_mmqid_wg_denoms, m_mmqid_wg_denoms, s_mmqid_wg_denoms; - std::initializer_list warptile_mmq_l = { 128, 128, 128, 32, device->subgroup_size * 2, 64, 2, 4, 4, device->subgroup_size }; - std::initializer_list warptile_mmq_m = { 128, 64, 64, 32, device->subgroup_size, 32, 2, 4, 2, device->subgroup_size }; - std::initializer_list warptile_mmq_s = { device->subgroup_size, 32, 32, 32, 32, 32, 2, 2, 2, device->subgroup_size }; + uint32_t l_align, m_align, s_align; + if (device->coopmat2) { + // spec constants and tile sizes for non-quant matmul/matmul_id + l_warptile = { 256, 128, 256, 64, 1 }; + m_warptile = { 256, 128, 128, 64, 0 }; + s_warptile = { 128, 64, 64, 64, 0 }; + l_wg_denoms = {128, 256, 1 }; + m_wg_denoms = {128, 128, 1 }; + s_wg_denoms = { 64, 64, 1 }; - std::array l_wg_denoms = {128, 128, 1 }; - std::array m_wg_denoms = { 64, 64, 1 }; - std::array s_wg_denoms = { 32, 32, 1 }; + // spec constants and tile sizes for quant matmul (non-Qi_K) + l_warptile_mmq = { 256, 128, 256, 64, 1 }; + m_warptile_mmq = { 256, 128, 128, 64, 1 }; + s_warptile_mmq = { 256, 32, 64, 128, 0 }; + l_mmq_wg_denoms = { 128, 256, 1 }; + m_mmq_wg_denoms = { 128, 128, 1 }; + s_mmq_wg_denoms = { 32, 64, 1 }; - uint32_t l_align = 128; - uint32_t m_align = 64; - uint32_t s_align = 32; + // spec constants and tile sizes for quant matmul (Qi_K) + l_warptile_mmq_k = { 256, 64, 128, 64, 1 }; + m_warptile_mmq_k = { 256, 32, 64, 64, 0 }; + s_warptile_mmq_k = { 256, 32, 32, 128, 0 }; + l_mmq_wg_denoms_k = { 64, 128, 1 }; + m_mmq_wg_denoms_k = { 32, 64, 1 }; + s_mmq_wg_denoms_k = { 32, 32, 1 }; - device->pipeline_matmul_f32 = std::make_shared(); - device->pipeline_matmul_f32_f16 = std::make_shared(); - device->pipeline_matmul_f16_f32 = std::make_shared(); - device->pipeline_matmul_f16 = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL] = std::make_shared(); + // spec constants and tile sizes for quant matmul_id + l_warptile_mmqid = { 256, 128, 64, 16, 0 }; + m_warptile_mmqid = { 256, 128, 64, 16, 0 }; + s_warptile_mmqid = { 256, 128, 64, 16, 0 }; + l_mmqid_wg_denoms = { 128, 64, 1 }; + m_mmqid_wg_denoms = { 128, 64, 1 }; + s_mmqid_wg_denoms = { 128, 64, 1 }; - device->pipeline_matmul_id_f32 = std::make_shared(); - device->pipeline_matmul_id_f16_f32 = std::make_shared(); - device->pipeline_matmul_id_f16 = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K] = std::make_shared(); - device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL] = std::make_shared(); - - if (device->fp16) { - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->l, "matmul_f32_l", matmul_f32_f32_len, matmul_f32_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->m, "matmul_f32_m", matmul_f32_f32_len, matmul_f32_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->s, "matmul_f32_s", matmul_f32_f32_len, matmul_f32_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->a_l, "matmul_f32_aligned_l", matmul_f32_f32_aligned_len, matmul_f32_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->a_m, "matmul_f32_aligned_m", matmul_f32_f32_aligned_len, matmul_f32_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->a_s, "matmul_f32_aligned_s", matmul_f32_f32_aligned_len, matmul_f32_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->l, "matmul_f32_f16_l", matmul_f32_f16_len, matmul_f32_f16_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->m, "matmul_f32_f16_m", matmul_f32_f16_len, matmul_f32_f16_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->s, "matmul_f32_f16_s", matmul_f32_f16_len, matmul_f32_f16_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->a_l, "matmul_f32_f16_aligned_l", matmul_f32_f16_aligned_len, matmul_f32_f16_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->a_m, "matmul_f32_f16_aligned_m", matmul_f32_f16_aligned_len, matmul_f32_f16_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->a_s, "matmul_f32_f16_aligned_s", matmul_f32_f16_aligned_len, matmul_f32_f16_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->l, "matmul_f16_l", matmul_f16_len, matmul_f16_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->m, "matmul_f16_m", matmul_f16_len, matmul_f16_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->s, "matmul_f16_s", matmul_f16_len, matmul_f16_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->a_l, "matmul_f16_aligned_l", matmul_f16_aligned_len, matmul_f16_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->a_m, "matmul_f16_aligned_m", matmul_f16_aligned_len, matmul_f16_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->a_s, "matmul_f16_aligned_s", matmul_f16_aligned_len, matmul_f16_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->l, "matmul_f16_f32_l", matmul_f16_f32_len, matmul_f16_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->m, "matmul_f16_f32_m", matmul_f16_f32_len, matmul_f16_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->s, "matmul_f16_f32_s", matmul_f16_f32_len, matmul_f16_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->a_l, "matmul_f16_f32_aligned_l", matmul_f16_f32_aligned_len, matmul_f16_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->a_m, "matmul_f16_f32_aligned_m", matmul_f16_f32_aligned_len, matmul_f16_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->a_s, "matmul_f16_f32_aligned_s", matmul_f16_f32_aligned_len, matmul_f16_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->l, "matmul_q4_0_f32_l", matmul_q4_0_f32_len, matmul_q4_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->m, "matmul_q4_0_f32_m", matmul_q4_0_f32_len, matmul_q4_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->s, "matmul_q4_0_f32_s", matmul_q4_0_f32_len, matmul_q4_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->a_l, "matmul_q4_0_f32_aligned_l", matmul_q4_0_f32_aligned_len, matmul_q4_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->a_m, "matmul_q4_0_f32_aligned_m", matmul_q4_0_f32_aligned_len, matmul_q4_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->a_s, "matmul_q4_0_f32_aligned_s", matmul_q4_0_f32_aligned_len, matmul_q4_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->l, "matmul_q4_1_f32_l", matmul_q4_1_f32_len, matmul_q4_1_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->m, "matmul_q4_1_f32_m", matmul_q4_1_f32_len, matmul_q4_1_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->s, "matmul_q4_1_f32_s", matmul_q4_1_f32_len, matmul_q4_1_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->a_l, "matmul_q4_1_f32_aligned_l", matmul_q4_1_f32_aligned_len, matmul_q4_1_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->a_m, "matmul_q4_1_f32_aligned_m", matmul_q4_1_f32_aligned_len, matmul_q4_1_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->a_s, "matmul_q4_1_f32_aligned_s", matmul_q4_1_f32_aligned_len, matmul_q4_1_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->l, "matmul_q5_0_f32_l", matmul_q5_0_f32_len, matmul_q5_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->m, "matmul_q5_0_f32_m", matmul_q5_0_f32_len, matmul_q5_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->s, "matmul_q5_0_f32_s", matmul_q5_0_f32_len, matmul_q5_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->a_l, "matmul_q5_0_f32_aligned_l", matmul_q5_0_f32_aligned_len, matmul_q5_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->a_m, "matmul_q5_0_f32_aligned_m", matmul_q5_0_f32_aligned_len, matmul_q5_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->a_s, "matmul_q5_0_f32_aligned_s", matmul_q5_0_f32_aligned_len, matmul_q5_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->l, "matmul_q5_1_f32_l", matmul_q5_1_f32_len, matmul_q5_1_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->m, "matmul_q5_1_f32_m", matmul_q5_1_f32_len, matmul_q5_1_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->s, "matmul_q5_1_f32_s", matmul_q5_1_f32_len, matmul_q5_1_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->a_l, "matmul_q5_1_f32_aligned_l", matmul_q5_1_f32_aligned_len, matmul_q5_1_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->a_m, "matmul_q5_1_f32_aligned_m", matmul_q5_1_f32_aligned_len, matmul_q5_1_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->a_s, "matmul_q5_1_f32_aligned_s", matmul_q5_1_f32_aligned_len, matmul_q5_1_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->l, "matmul_q8_0_f32_l", matmul_q8_0_f32_len, matmul_q8_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->m, "matmul_q8_0_f32_m", matmul_q8_0_f32_len, matmul_q8_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->s, "matmul_q8_0_f32_s", matmul_q8_0_f32_len, matmul_q8_0_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->a_l, "matmul_q8_0_f32_aligned_l", matmul_q8_0_f32_aligned_len, matmul_q8_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->a_m, "matmul_q8_0_f32_aligned_m", matmul_q8_0_f32_aligned_len, matmul_q8_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->a_s, "matmul_q8_0_f32_aligned_s", matmul_q8_0_f32_aligned_len, matmul_q8_0_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->l, "matmul_q2_k_f32_l", matmul_q2_k_f32_len, matmul_q2_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->m, "matmul_q2_k_f32_m", matmul_q2_k_f32_len, matmul_q2_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->s, "matmul_q2_k_f32_s", matmul_q2_k_f32_len, matmul_q2_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->a_l, "matmul_q2_k_f32_aligned_l", matmul_q2_k_f32_aligned_len, matmul_q2_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->a_m, "matmul_q2_k_f32_aligned_m", matmul_q2_k_f32_aligned_len, matmul_q2_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->a_s, "matmul_q2_k_f32_aligned_s", matmul_q2_k_f32_aligned_len, matmul_q2_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->l, "matmul_q3_k_f32_l", matmul_q3_k_f32_len, matmul_q3_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->m, "matmul_q3_k_f32_m", matmul_q3_k_f32_len, matmul_q3_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->s, "matmul_q3_k_f32_s", matmul_q3_k_f32_len, matmul_q3_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->a_l, "matmul_q3_k_f32_aligned_l", matmul_q3_k_f32_aligned_len, matmul_q3_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->a_m, "matmul_q3_k_f32_aligned_m", matmul_q3_k_f32_aligned_len, matmul_q3_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->a_s, "matmul_q3_k_f32_aligned_s", matmul_q3_k_f32_aligned_len, matmul_q3_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->l, "matmul_q4_k_f32_l", matmul_q4_k_f32_len, matmul_q4_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->m, "matmul_q4_k_f32_m", matmul_q4_k_f32_len, matmul_q4_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->s, "matmul_q4_k_f32_s", matmul_q4_k_f32_len, matmul_q4_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->a_l, "matmul_q4_k_f32_aligned_l", matmul_q4_k_f32_aligned_len, matmul_q4_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->a_m, "matmul_q4_k_f32_aligned_m", matmul_q4_k_f32_aligned_len, matmul_q4_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->a_s, "matmul_q4_k_f32_aligned_s", matmul_q4_k_f32_aligned_len, matmul_q4_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->l, "matmul_q5_k_f32_l", matmul_q5_k_f32_len, matmul_q5_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->m, "matmul_q5_k_f32_m", matmul_q5_k_f32_len, matmul_q5_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->s, "matmul_q5_k_f32_s", matmul_q5_k_f32_len, matmul_q5_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->a_l, "matmul_q5_k_f32_aligned_l", matmul_q5_k_f32_aligned_len, matmul_q5_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->a_m, "matmul_q5_k_f32_aligned_m", matmul_q5_k_f32_aligned_len, matmul_q5_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->a_s, "matmul_q5_k_f32_aligned_s", matmul_q5_k_f32_aligned_len, matmul_q5_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->l, "matmul_q6_k_f32_l", matmul_q6_k_f32_len, matmul_q6_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->m, "matmul_q6_k_f32_m", matmul_q6_k_f32_len, matmul_q6_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->s, "matmul_q6_k_f32_s", matmul_q6_k_f32_len, matmul_q6_k_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->a_l, "matmul_q6_k_f32_aligned_l", matmul_q6_k_f32_aligned_len, matmul_q6_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->a_m, "matmul_q6_k_f32_aligned_m", matmul_q6_k_f32_aligned_len, matmul_q6_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->a_s, "matmul_q6_k_f32_aligned_s", matmul_q6_k_f32_aligned_len, matmul_q6_k_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->l, "matmul_iq4_nl_f32_l", matmul_iq4_nl_f32_len, matmul_iq4_nl_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->m, "matmul_iq4_nl_f32_m", matmul_iq4_nl_f32_len, matmul_iq4_nl_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->s, "matmul_iq4_nl_f32_s", matmul_iq4_nl_f32_len, matmul_iq4_nl_f32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->a_l, "matmul_iq4_nl_f32_aligned_l", matmul_iq4_nl_f32_aligned_len, matmul_iq4_nl_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->a_m, "matmul_iq4_nl_f32_aligned_m", matmul_iq4_nl_f32_aligned_len, matmul_iq4_nl_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->a_s, "matmul_iq4_nl_f32_aligned_s", matmul_iq4_nl_f32_aligned_len, matmul_iq4_nl_f32_aligned_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->l, "matmul_id_f32_l", matmul_id_f32_f32_len, matmul_id_f32_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->m, "matmul_id_f32_m", matmul_id_f32_f32_len, matmul_id_f32_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->s, "matmul_id_f32_s", matmul_id_f32_f32_len, matmul_id_f32_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->a_l, "matmul_id_f32_aligned_l", matmul_id_f32_f32_aligned_len, matmul_id_f32_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->a_m, "matmul_id_f32_aligned_m", matmul_id_f32_f32_aligned_len, matmul_id_f32_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->a_s, "matmul_id_f32_aligned_s", matmul_id_f32_f32_aligned_len, matmul_id_f32_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->l, "matmul_id_f16_l", matmul_id_f16_len, matmul_id_f16_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->m, "matmul_id_f16_m", matmul_id_f16_len, matmul_id_f16_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->s, "matmul_id_f16_s", matmul_id_f16_len, matmul_id_f16_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->a_l, "matmul_id_f16_aligned_l", matmul_id_f16_aligned_len, matmul_id_f16_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->a_m, "matmul_id_f16_aligned_m", matmul_id_f16_aligned_len, matmul_id_f16_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->a_s, "matmul_id_f16_aligned_s", matmul_id_f16_aligned_len, matmul_id_f16_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->l, "matmul_id_f16_f32_l", matmul_id_f16_f32_len, matmul_id_f16_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->m, "matmul_id_f16_f32_m", matmul_id_f16_f32_len, matmul_id_f16_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->s, "matmul_id_f16_f32_s", matmul_id_f16_f32_len, matmul_id_f16_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->a_l, "matmul_id_f16_f32_aligned_l", matmul_id_f16_f32_aligned_len, matmul_id_f16_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->a_m, "matmul_id_f16_f32_aligned_m", matmul_id_f16_f32_aligned_len, matmul_id_f16_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->a_s, "matmul_id_f16_f32_aligned_s", matmul_id_f16_f32_aligned_len, matmul_id_f16_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->l, "matmul_id_q4_0_f32_l", matmul_id_q4_0_f32_len, matmul_id_q4_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->m, "matmul_id_q4_0_f32_m", matmul_id_q4_0_f32_len, matmul_id_q4_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->s, "matmul_id_q4_0_f32_s", matmul_id_q4_0_f32_len, matmul_id_q4_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->a_l, "matmul_id_q4_0_f32_aligned_l", matmul_id_q4_0_f32_aligned_len, matmul_id_q4_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->a_m, "matmul_id_q4_0_f32_aligned_m", matmul_id_q4_0_f32_aligned_len, matmul_id_q4_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->a_s, "matmul_id_q4_0_f32_aligned_s", matmul_id_q4_0_f32_aligned_len, matmul_id_q4_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->l, "matmul_id_q4_1_f32_l", matmul_id_q4_1_f32_len, matmul_id_q4_1_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->m, "matmul_id_q4_1_f32_m", matmul_id_q4_1_f32_len, matmul_id_q4_1_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->s, "matmul_id_q4_1_f32_s", matmul_id_q4_1_f32_len, matmul_id_q4_1_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->a_l, "matmul_id_q4_1_f32_aligned_l", matmul_id_q4_1_f32_aligned_len, matmul_id_q4_1_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->a_m, "matmul_id_q4_1_f32_aligned_m", matmul_id_q4_1_f32_aligned_len, matmul_id_q4_1_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->a_s, "matmul_id_q4_1_f32_aligned_s", matmul_id_q4_1_f32_aligned_len, matmul_id_q4_1_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->l, "matmul_id_q5_0_f32_l", matmul_id_q5_0_f32_len, matmul_id_q5_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->m, "matmul_id_q5_0_f32_m", matmul_id_q5_0_f32_len, matmul_id_q5_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->s, "matmul_id_q5_0_f32_s", matmul_id_q5_0_f32_len, matmul_id_q5_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->a_l, "matmul_id_q5_0_f32_aligned_l", matmul_id_q5_0_f32_aligned_len, matmul_id_q5_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->a_m, "matmul_id_q5_0_f32_aligned_m", matmul_id_q5_0_f32_aligned_len, matmul_id_q5_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->a_s, "matmul_id_q5_0_f32_aligned_s", matmul_id_q5_0_f32_aligned_len, matmul_id_q5_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->l, "matmul_id_q5_1_f32_l", matmul_id_q5_1_f32_len, matmul_id_q5_1_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->m, "matmul_id_q5_1_f32_m", matmul_id_q5_1_f32_len, matmul_id_q5_1_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->s, "matmul_id_q5_1_f32_s", matmul_id_q5_1_f32_len, matmul_id_q5_1_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->a_l, "matmul_id_q5_1_f32_aligned_l", matmul_id_q5_1_f32_aligned_len, matmul_id_q5_1_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->a_m, "matmul_id_q5_1_f32_aligned_m", matmul_id_q5_1_f32_aligned_len, matmul_id_q5_1_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->a_s, "matmul_id_q5_1_f32_aligned_s", matmul_id_q5_1_f32_aligned_len, matmul_id_q5_1_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->l, "matmul_id_q8_0_f32_l", matmul_id_q8_0_f32_len, matmul_id_q8_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->m, "matmul_id_q8_0_f32_m", matmul_id_q8_0_f32_len, matmul_id_q8_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->s, "matmul_id_q8_0_f32_s", matmul_id_q8_0_f32_len, matmul_id_q8_0_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->a_l, "matmul_id_q8_0_f32_aligned_l", matmul_id_q8_0_f32_aligned_len, matmul_id_q8_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->a_m, "matmul_id_q8_0_f32_aligned_m", matmul_id_q8_0_f32_aligned_len, matmul_id_q8_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->a_s, "matmul_id_q8_0_f32_aligned_s", matmul_id_q8_0_f32_aligned_len, matmul_id_q8_0_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->l, "matmul_id_q2_k_f32_l", matmul_id_q2_k_f32_len, matmul_id_q2_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->m, "matmul_id_q2_k_f32_m", matmul_id_q2_k_f32_len, matmul_id_q2_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->s, "matmul_id_q2_k_f32_s", matmul_id_q2_k_f32_len, matmul_id_q2_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->a_l, "matmul_id_q2_k_f32_aligned_l", matmul_id_q2_k_f32_aligned_len, matmul_id_q2_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->a_m, "matmul_id_q2_k_f32_aligned_m", matmul_id_q2_k_f32_aligned_len, matmul_id_q2_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->a_s, "matmul_id_q2_k_f32_aligned_s", matmul_id_q2_k_f32_aligned_len, matmul_id_q2_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->l, "matmul_id_q3_k_f32_l", matmul_id_q3_k_f32_len, matmul_id_q3_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->m, "matmul_id_q3_k_f32_m", matmul_id_q3_k_f32_len, matmul_id_q3_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->s, "matmul_id_q3_k_f32_s", matmul_id_q3_k_f32_len, matmul_id_q3_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->a_l, "matmul_id_q3_k_f32_aligned_l", matmul_id_q3_k_f32_aligned_len, matmul_id_q3_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->a_m, "matmul_id_q3_k_f32_aligned_m", matmul_id_q3_k_f32_aligned_len, matmul_id_q3_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->a_s, "matmul_id_q3_k_f32_aligned_s", matmul_id_q3_k_f32_aligned_len, matmul_id_q3_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->l, "matmul_id_q4_k_f32_l", matmul_id_q4_k_f32_len, matmul_id_q4_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->m, "matmul_id_q4_k_f32_m", matmul_id_q4_k_f32_len, matmul_id_q4_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->s, "matmul_id_q4_k_f32_s", matmul_id_q4_k_f32_len, matmul_id_q4_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->a_l, "matmul_id_q4_k_f32_aligned_l", matmul_id_q4_k_f32_aligned_len, matmul_id_q4_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->a_m, "matmul_id_q4_k_f32_aligned_m", matmul_id_q4_k_f32_aligned_len, matmul_id_q4_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->a_s, "matmul_id_q4_k_f32_aligned_s", matmul_id_q4_k_f32_aligned_len, matmul_id_q4_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->l, "matmul_id_q5_k_f32_l", matmul_id_q5_k_f32_len, matmul_id_q5_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->m, "matmul_id_q5_k_f32_m", matmul_id_q5_k_f32_len, matmul_id_q5_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->s, "matmul_id_q5_k_f32_s", matmul_id_q5_k_f32_len, matmul_id_q5_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->a_l, "matmul_id_q5_k_f32_aligned_l", matmul_id_q5_k_f32_aligned_len, matmul_id_q5_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->a_m, "matmul_id_q5_k_f32_aligned_m", matmul_id_q5_k_f32_aligned_len, matmul_id_q5_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->a_s, "matmul_id_q5_k_f32_aligned_s", matmul_id_q5_k_f32_aligned_len, matmul_id_q5_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->l, "matmul_id_q6_k_f32_l", matmul_id_q6_k_f32_len, matmul_id_q6_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->m, "matmul_id_q6_k_f32_m", matmul_id_q6_k_f32_len, matmul_id_q6_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->s, "matmul_id_q6_k_f32_s", matmul_id_q6_k_f32_len, matmul_id_q6_k_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->a_l, "matmul_id_q6_k_f32_aligned_l", matmul_id_q6_k_f32_aligned_len, matmul_id_q6_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->a_m, "matmul_id_q6_k_f32_aligned_m", matmul_id_q6_k_f32_aligned_len, matmul_id_q6_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->a_s, "matmul_id_q6_k_f32_aligned_s", matmul_id_q6_k_f32_aligned_len, matmul_id_q6_k_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->l, "matmul_id_iq4_nl_f32_l", matmul_id_iq4_nl_f32_len, matmul_id_iq4_nl_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->m, "matmul_id_iq4_nl_f32_m", matmul_id_iq4_nl_f32_len, matmul_id_iq4_nl_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->s, "matmul_id_iq4_nl_f32_s", matmul_id_iq4_nl_f32_len, matmul_id_iq4_nl_f32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->a_l, "matmul_id_iq4_nl_f32_aligned_l", matmul_id_iq4_nl_f32_aligned_len, matmul_id_iq4_nl_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->a_m, "matmul_id_iq4_nl_f32_aligned_m", matmul_id_iq4_nl_f32_aligned_len, matmul_id_iq4_nl_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->a_s, "matmul_id_iq4_nl_f32_aligned_s", matmul_id_iq4_nl_f32_aligned_len, matmul_id_iq4_nl_f32_aligned_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); + l_align = 128; + m_align = 64; + s_align = 32; } else { - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->l, "matmul_f32_l", matmul_f32_f32_fp32_len, matmul_f32_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->m, "matmul_f32_m", matmul_f32_f32_fp32_len, matmul_f32_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->s, "matmul_f32_s", matmul_f32_f32_fp32_len, matmul_f32_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->a_l, "matmul_f32_aligned_l", matmul_f32_f32_aligned_fp32_len, matmul_f32_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->a_m, "matmul_f32_aligned_m", matmul_f32_f32_aligned_fp32_len, matmul_f32_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32->a_s, "matmul_f32_aligned_s", matmul_f32_f32_aligned_fp32_len, matmul_f32_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); + // Matrix cores require different warp group sizes + const uint32_t tm_l = device->coopmat_support ? device->coopmat_m : 4; + const uint32_t tm_m = device->coopmat_support ? device->coopmat_m : 4; + const uint32_t tm_s = device->coopmat_support ? device->coopmat_m : 2; + const uint32_t tn_l = device->coopmat_support ? device->coopmat_n : 4; + const uint32_t tn_m = device->coopmat_support ? device->coopmat_n : 2; + const uint32_t tn_s = device->coopmat_support ? device->coopmat_n : 2; + const uint32_t tk_l = device->coopmat_support ? device->coopmat_k : 1; + const uint32_t tk_m = device->coopmat_support ? device->coopmat_k : 1; + const uint32_t tk_s = device->coopmat_support ? device->coopmat_k : 1; - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->l, "matmul_f32_f16_l", matmul_f32_f16_fp32_len, matmul_f32_f16_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->m, "matmul_f32_f16_m", matmul_f32_f16_fp32_len, matmul_f32_f16_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->s, "matmul_f32_f16_s", matmul_f32_f16_fp32_len, matmul_f32_f16_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->a_l, "matmul_f32_f16_aligned_l", matmul_f32_f16_aligned_fp32_len, matmul_f32_f16_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->a_m, "matmul_f32_f16_aligned_m", matmul_f32_f16_aligned_fp32_len, matmul_f32_f16_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f32_f16->a_s, "matmul_f32_f16_aligned_s", matmul_f32_f16_aligned_fp32_len, matmul_f32_f16_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); + l_warptile = { 128, 128, 128, 16, subgroup_size_8 * 2, 64, 2, tm_l, tn_l, tk_l, subgroup_size_8 }; + m_warptile = { 128, 64, 64, 16, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; + s_warptile = { subgroup_size_16, 32, 32, 16, 32, 32, 2, tm_s, tn_s, tk_s, subgroup_size_8 }; - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->l, "matmul_f16_l", matmul_f16_fp32_len, matmul_f16_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->m, "matmul_f16_m", matmul_f16_fp32_len, matmul_f16_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->s, "matmul_f16_s", matmul_f16_fp32_len, matmul_f16_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->a_l, "matmul_f16_aligned_l", matmul_f16_aligned_fp32_len, matmul_f16_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->a_m, "matmul_f16_aligned_m", matmul_f16_aligned_fp32_len, matmul_f16_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16->a_s, "matmul_f16_aligned_s", matmul_f16_aligned_fp32_len, matmul_f16_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); + l_warptile_mmq = { 128, 128, 128, 32, subgroup_size_8 * 2, 64, 2, tm_l, tn_l, tk_l, subgroup_size_8 }; + m_warptile_mmq = { 128, 64, 64, 32, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; + s_warptile_mmq = { subgroup_size_32, 32, 32, 32, 32, 32, 2, tm_s, tn_s, tk_s, subgroup_size_8 }; - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->l, "matmul_f16_f32_l", matmul_f16_f32_fp32_len, matmul_f16_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->m, "matmul_f16_f32_m", matmul_f16_f32_fp32_len, matmul_f16_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->s, "matmul_f16_f32_s", matmul_f16_f32_fp32_len, matmul_f16_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->a_l, "matmul_f16_f32_aligned_l", matmul_f16_f32_aligned_fp32_len, matmul_f16_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->a_m, "matmul_f16_f32_aligned_m", matmul_f16_f32_aligned_fp32_len, matmul_f16_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_f16_f32->a_s, "matmul_f16_f32_aligned_s", matmul_f16_f32_aligned_fp32_len, matmul_f16_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_s, s_align); + l_warptile_mmq_int = { 128, 128, 128, 32, subgroup_size_8 * 2, 64, 2, 4, 4, 1, subgroup_size_8 }; + m_warptile_mmq_int = { 128, 64, 64, 32, subgroup_size_8, 32, 2, 2, 2, 1, subgroup_size_8 }; + s_warptile_mmq_int = { subgroup_size_32, 32, 32, 32, 32, 32, 2, 2, 1, 1, subgroup_size_8 }; - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->l, "matmul_q4_0_f32_l", matmul_q4_0_f32_fp32_len, matmul_q4_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->m, "matmul_q4_0_f32_m", matmul_q4_0_f32_fp32_len, matmul_q4_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->s, "matmul_q4_0_f32_s", matmul_q4_0_f32_fp32_len, matmul_q4_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->a_l, "matmul_q4_0_f32_aligned_l", matmul_q4_0_f32_aligned_fp32_len, matmul_q4_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->a_m, "matmul_q4_0_f32_aligned_m", matmul_q4_0_f32_aligned_fp32_len, matmul_q4_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0]->a_s, "matmul_q4_0_f32_aligned_s", matmul_q4_0_f32_aligned_fp32_len, matmul_q4_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); + // chip specific tuning + if ((device->architecture == AMD_GCN) && (device->driver_id != vk::DriverId::eAmdProprietary)) { + m_warptile_mmq = m_warptile_mmq_int = { 256, 64, 64, 32, 16, 16, 2, 2, 2, 1, 16 }; + } - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->l, "matmul_q4_1_f32_l", matmul_q4_1_f32_fp32_len, matmul_q4_1_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->m, "matmul_q4_1_f32_m", matmul_q4_1_f32_fp32_len, matmul_q4_1_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->s, "matmul_q4_1_f32_s", matmul_q4_1_f32_fp32_len, matmul_q4_1_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->a_l, "matmul_q4_1_f32_aligned_l", matmul_q4_1_f32_aligned_fp32_len, matmul_q4_1_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->a_m, "matmul_q4_1_f32_aligned_m", matmul_q4_1_f32_aligned_fp32_len, matmul_q4_1_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1]->a_s, "matmul_q4_1_f32_aligned_s", matmul_q4_1_f32_aligned_fp32_len, matmul_q4_1_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); + l_mmq_wg_denoms = l_wg_denoms = {128, 128, 1 }; + m_mmq_wg_denoms = m_wg_denoms = { 64, 64, 1 }; + s_mmq_wg_denoms = s_wg_denoms = { 32, 32, 1 }; + l_align = 128; + m_align = 64; + s_align = 32; - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->l, "matmul_q5_0_f32_l", matmul_q5_0_f32_fp32_len, matmul_q5_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->m, "matmul_q5_0_f32_m", matmul_q5_0_f32_fp32_len, matmul_q5_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->s, "matmul_q5_0_f32_s", matmul_q5_0_f32_fp32_len, matmul_q5_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->a_l, "matmul_q5_0_f32_aligned_l", matmul_q5_0_f32_aligned_fp32_len, matmul_q5_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->a_m, "matmul_q5_0_f32_aligned_m", matmul_q5_0_f32_aligned_fp32_len, matmul_q5_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0]->a_s, "matmul_q5_0_f32_aligned_s", matmul_q5_0_f32_aligned_fp32_len, matmul_q5_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); + for (uint32_t i = 0; i < GGML_TYPE_COUNT; ++i) { + ggml_type t = (ggml_type)i; + // Disable medium and large matrix multiplication if not enough shared memory is available + // Check mmq warptiles as the largest configuration + // Throw an error if not enough for any matrix multiplication is available + if (!ggml_vk_matmul_shmem_support(device, s_warptile_mmq, false, t)) { + std::cerr << "ggml_vulkan: Error: Shared memory size too small for matrix multiplication." << std::endl; + throw std::runtime_error("Shared memory size too small for matrix multiplication."); + } else if (!ggml_vk_matmul_shmem_support(device, m_warptile_mmq, false, t)) { + device->mul_mat_m[i] = false; + device->mul_mat_l[i] = false; + } else if (!ggml_vk_matmul_shmem_support(device, l_warptile_mmq, false, t)) { + device->mul_mat_l[i] = false; + } - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->l, "matmul_q5_1_f32_l", matmul_q5_1_f32_fp32_len, matmul_q5_1_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->m, "matmul_q5_1_f32_m", matmul_q5_1_f32_fp32_len, matmul_q5_1_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->s, "matmul_q5_1_f32_s", matmul_q5_1_f32_fp32_len, matmul_q5_1_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->a_l, "matmul_q5_1_f32_aligned_l", matmul_q5_1_f32_aligned_fp32_len, matmul_q5_1_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->a_m, "matmul_q5_1_f32_aligned_m", matmul_q5_1_f32_aligned_fp32_len, matmul_q5_1_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1]->a_s, "matmul_q5_1_f32_aligned_s", matmul_q5_1_f32_aligned_fp32_len, matmul_q5_1_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->l, "matmul_q8_0_f32_l", matmul_q8_0_f32_fp32_len, matmul_q8_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->m, "matmul_q8_0_f32_m", matmul_q8_0_f32_fp32_len, matmul_q8_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->s, "matmul_q8_0_f32_s", matmul_q8_0_f32_fp32_len, matmul_q8_0_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->a_l, "matmul_q8_0_f32_aligned_l", matmul_q8_0_f32_aligned_fp32_len, matmul_q8_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->a_m, "matmul_q8_0_f32_aligned_m", matmul_q8_0_f32_aligned_fp32_len, matmul_q8_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0]->a_s, "matmul_q8_0_f32_aligned_s", matmul_q8_0_f32_aligned_fp32_len, matmul_q8_0_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->l, "matmul_q2_k_f32_l", matmul_q2_k_f32_fp32_len, matmul_q2_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->m, "matmul_q2_k_f32_m", matmul_q2_k_f32_fp32_len, matmul_q2_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->s, "matmul_q2_k_f32_s", matmul_q2_k_f32_fp32_len, matmul_q2_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->a_l, "matmul_q2_k_f32_aligned_l", matmul_q2_k_f32_aligned_fp32_len, matmul_q2_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->a_m, "matmul_q2_k_f32_aligned_m", matmul_q2_k_f32_aligned_fp32_len, matmul_q2_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K]->a_s, "matmul_q2_k_f32_aligned_s", matmul_q2_k_f32_aligned_fp32_len, matmul_q2_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->l, "matmul_q3_k_f32_l", matmul_q3_k_f32_fp32_len, matmul_q3_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->m, "matmul_q3_k_f32_m", matmul_q3_k_f32_fp32_len, matmul_q3_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->s, "matmul_q3_k_f32_s", matmul_q3_k_f32_fp32_len, matmul_q3_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->a_l, "matmul_q3_k_f32_aligned_l", matmul_q3_k_f32_aligned_fp32_len, matmul_q3_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->a_m, "matmul_q3_k_f32_aligned_m", matmul_q3_k_f32_aligned_fp32_len, matmul_q3_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K]->a_s, "matmul_q3_k_f32_aligned_s", matmul_q3_k_f32_aligned_fp32_len, matmul_q3_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->l, "matmul_q4_k_f32_l", matmul_q4_k_f32_fp32_len, matmul_q4_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->m, "matmul_q4_k_f32_m", matmul_q4_k_f32_fp32_len, matmul_q4_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->s, "matmul_q4_k_f32_s", matmul_q4_k_f32_fp32_len, matmul_q4_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->a_l, "matmul_q4_k_f32_aligned_l", matmul_q4_k_f32_aligned_fp32_len, matmul_q4_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->a_m, "matmul_q4_k_f32_aligned_m", matmul_q4_k_f32_aligned_fp32_len, matmul_q4_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K]->a_s, "matmul_q4_k_f32_aligned_s", matmul_q4_k_f32_aligned_fp32_len, matmul_q4_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->l, "matmul_q5_k_f32_l", matmul_q5_k_f32_fp32_len, matmul_q5_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->m, "matmul_q5_k_f32_m", matmul_q5_k_f32_fp32_len, matmul_q5_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->s, "matmul_q5_k_f32_s", matmul_q5_k_f32_fp32_len, matmul_q5_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->a_l, "matmul_q5_k_f32_aligned_l", matmul_q5_k_f32_aligned_fp32_len, matmul_q5_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->a_m, "matmul_q5_k_f32_aligned_m", matmul_q5_k_f32_aligned_fp32_len, matmul_q5_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K]->a_s, "matmul_q5_k_f32_aligned_s", matmul_q5_k_f32_aligned_fp32_len, matmul_q5_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->l, "matmul_q6_k_f32_l", matmul_q6_k_f32_fp32_len, matmul_q6_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->m, "matmul_q6_k_f32_m", matmul_q6_k_f32_fp32_len, matmul_q6_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->s, "matmul_q6_k_f32_s", matmul_q6_k_f32_fp32_len, matmul_q6_k_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->a_l, "matmul_q6_k_f32_aligned_l", matmul_q6_k_f32_aligned_fp32_len, matmul_q6_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->a_m, "matmul_q6_k_f32_aligned_m", matmul_q6_k_f32_aligned_fp32_len, matmul_q6_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K]->a_s, "matmul_q6_k_f32_aligned_s", matmul_q6_k_f32_aligned_fp32_len, matmul_q6_k_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->l, "matmul_iq4_nl_f32_l", matmul_iq4_nl_f32_fp32_len, matmul_iq4_nl_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->m, "matmul_iq4_nl_f32_m", matmul_iq4_nl_f32_fp32_len, matmul_iq4_nl_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->s, "matmul_iq4_nl_f32_s", matmul_iq4_nl_f32_fp32_len, matmul_iq4_nl_f32_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->a_l, "matmul_iq4_nl_f32_aligned_l", matmul_iq4_nl_f32_aligned_fp32_len, matmul_iq4_nl_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->a_m, "matmul_iq4_nl_f32_aligned_m", matmul_iq4_nl_f32_aligned_fp32_len, matmul_iq4_nl_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL]->a_s, "matmul_iq4_nl_f32_aligned_s", matmul_iq4_nl_f32_aligned_fp32_len, matmul_iq4_nl_f32_aligned_fp32_data, "main", 3, sizeof(vk_mat_mat_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->l, "matmul_id_f32_l", matmul_id_f32_f32_fp32_len, matmul_id_f32_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->m, "matmul_id_f32_m", matmul_id_f32_f32_fp32_len, matmul_id_f32_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->s, "matmul_id_f32_s", matmul_id_f32_f32_fp32_len, matmul_id_f32_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->a_l, "matmul_id_f32_aligned_l", matmul_id_f32_f32_aligned_fp32_len, matmul_id_f32_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->a_m, "matmul_id_f32_aligned_m", matmul_id_f32_f32_aligned_fp32_len, matmul_id_f32_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f32->a_s, "matmul_id_f32_aligned_s", matmul_id_f32_f32_aligned_fp32_len, matmul_id_f32_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->l, "matmul_id_f16_l", matmul_id_f16_fp32_len, matmul_id_f16_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->m, "matmul_id_f16_m", matmul_id_f16_fp32_len, matmul_id_f16_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->s, "matmul_id_f16_s", matmul_id_f16_fp32_len, matmul_id_f16_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->a_l, "matmul_id_f16_aligned_l", matmul_id_f16_aligned_fp32_len, matmul_id_f16_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->a_m, "matmul_id_f16_aligned_m", matmul_id_f16_aligned_fp32_len, matmul_id_f16_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16->a_s, "matmul_id_f16_aligned_s", matmul_id_f16_aligned_fp32_len, matmul_id_f16_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->l, "matmul_id_f16_f32_l", matmul_id_f16_f32_fp32_len, matmul_id_f16_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->m, "matmul_id_f16_f32_m", matmul_id_f16_f32_fp32_len, matmul_id_f16_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->s, "matmul_id_f16_f32_s", matmul_id_f16_f32_fp32_len, matmul_id_f16_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->a_l, "matmul_id_f16_f32_aligned_l", matmul_id_f16_f32_aligned_fp32_len, matmul_id_f16_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->a_m, "matmul_id_f16_f32_aligned_m", matmul_id_f16_f32_aligned_fp32_len, matmul_id_f16_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_matmul_id_f16_f32->a_s, "matmul_id_f16_f32_aligned_s", matmul_id_f16_f32_aligned_fp32_len, matmul_id_f16_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->l, "matmul_id_q4_0_f32_l", matmul_id_q4_0_f32_fp32_len, matmul_id_q4_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->m, "matmul_id_q4_0_f32_m", matmul_id_q4_0_f32_fp32_len, matmul_id_q4_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->s, "matmul_id_q4_0_f32_s", matmul_id_q4_0_f32_fp32_len, matmul_id_q4_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->a_l, "matmul_id_q4_0_f32_aligned_l", matmul_id_q4_0_f32_aligned_fp32_len, matmul_id_q4_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->a_m, "matmul_id_q4_0_f32_aligned_m", matmul_id_q4_0_f32_aligned_fp32_len, matmul_id_q4_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0]->a_s, "matmul_id_q4_0_f32_aligned_s", matmul_id_q4_0_f32_aligned_fp32_len, matmul_id_q4_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->l, "matmul_id_q4_1_f32_l", matmul_id_q4_1_f32_fp32_len, matmul_id_q4_1_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->m, "matmul_id_q4_1_f32_m", matmul_id_q4_1_f32_fp32_len, matmul_id_q4_1_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->s, "matmul_id_q4_1_f32_s", matmul_id_q4_1_f32_fp32_len, matmul_id_q4_1_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->a_l, "matmul_id_q4_1_f32_aligned_l", matmul_id_q4_1_f32_aligned_fp32_len, matmul_id_q4_1_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->a_m, "matmul_id_q4_1_f32_aligned_m", matmul_id_q4_1_f32_aligned_fp32_len, matmul_id_q4_1_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1]->a_s, "matmul_id_q4_1_f32_aligned_s", matmul_id_q4_1_f32_aligned_fp32_len, matmul_id_q4_1_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->l, "matmul_id_q5_0_f32_l", matmul_id_q5_0_f32_fp32_len, matmul_id_q5_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->m, "matmul_id_q5_0_f32_m", matmul_id_q5_0_f32_fp32_len, matmul_id_q5_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->s, "matmul_id_q5_0_f32_s", matmul_id_q5_0_f32_fp32_len, matmul_id_q5_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->a_l, "matmul_id_q5_0_f32_aligned_l", matmul_id_q5_0_f32_aligned_fp32_len, matmul_id_q5_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->a_m, "matmul_id_q5_0_f32_aligned_m", matmul_id_q5_0_f32_aligned_fp32_len, matmul_id_q5_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0]->a_s, "matmul_id_q5_0_f32_aligned_s", matmul_id_q5_0_f32_aligned_fp32_len, matmul_id_q5_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->l, "matmul_id_q5_1_f32_l", matmul_id_q5_1_f32_fp32_len, matmul_id_q5_1_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->m, "matmul_id_q5_1_f32_m", matmul_id_q5_1_f32_fp32_len, matmul_id_q5_1_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->s, "matmul_id_q5_1_f32_s", matmul_id_q5_1_f32_fp32_len, matmul_id_q5_1_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->a_l, "matmul_id_q5_1_f32_aligned_l", matmul_id_q5_1_f32_aligned_fp32_len, matmul_id_q5_1_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->a_m, "matmul_id_q5_1_f32_aligned_m", matmul_id_q5_1_f32_aligned_fp32_len, matmul_id_q5_1_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1]->a_s, "matmul_id_q5_1_f32_aligned_s", matmul_id_q5_1_f32_aligned_fp32_len, matmul_id_q5_1_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->l, "matmul_id_q8_0_f32_l", matmul_id_q8_0_f32_fp32_len, matmul_id_q8_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->m, "matmul_id_q8_0_f32_m", matmul_id_q8_0_f32_fp32_len, matmul_id_q8_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->s, "matmul_id_q8_0_f32_s", matmul_id_q8_0_f32_fp32_len, matmul_id_q8_0_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->a_l, "matmul_id_q8_0_f32_aligned_l", matmul_id_q8_0_f32_aligned_fp32_len, matmul_id_q8_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->a_m, "matmul_id_q8_0_f32_aligned_m", matmul_id_q8_0_f32_aligned_fp32_len, matmul_id_q8_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0]->a_s, "matmul_id_q8_0_f32_aligned_s", matmul_id_q8_0_f32_aligned_fp32_len, matmul_id_q8_0_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->l, "matmul_id_q2_k_f32_l", matmul_id_q2_k_f32_fp32_len, matmul_id_q2_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->m, "matmul_id_q2_k_f32_m", matmul_id_q2_k_f32_fp32_len, matmul_id_q2_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->s, "matmul_id_q2_k_f32_s", matmul_id_q2_k_f32_fp32_len, matmul_id_q2_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->a_l, "matmul_id_q2_k_f32_aligned_l", matmul_id_q2_k_f32_aligned_fp32_len, matmul_id_q2_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->a_m, "matmul_id_q2_k_f32_aligned_m", matmul_id_q2_k_f32_aligned_fp32_len, matmul_id_q2_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K]->a_s, "matmul_id_q2_k_f32_aligned_s", matmul_id_q2_k_f32_aligned_fp32_len, matmul_id_q2_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->l, "matmul_id_q3_k_f32_l", matmul_id_q3_k_f32_fp32_len, matmul_id_q3_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->m, "matmul_id_q3_k_f32_m", matmul_id_q3_k_f32_fp32_len, matmul_id_q3_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->s, "matmul_id_q3_k_f32_s", matmul_id_q3_k_f32_fp32_len, matmul_id_q3_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->a_l, "matmul_id_q3_k_f32_aligned_l", matmul_id_q3_k_f32_aligned_fp32_len, matmul_id_q3_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->a_m, "matmul_id_q3_k_f32_aligned_m", matmul_id_q3_k_f32_aligned_fp32_len, matmul_id_q3_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K]->a_s, "matmul_id_q3_k_f32_aligned_s", matmul_id_q3_k_f32_aligned_fp32_len, matmul_id_q3_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->l, "matmul_id_q4_k_f32_l", matmul_id_q4_k_f32_fp32_len, matmul_id_q4_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->m, "matmul_id_q4_k_f32_m", matmul_id_q4_k_f32_fp32_len, matmul_id_q4_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->s, "matmul_id_q4_k_f32_s", matmul_id_q4_k_f32_fp32_len, matmul_id_q4_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->a_l, "matmul_id_q4_k_f32_aligned_l", matmul_id_q4_k_f32_aligned_fp32_len, matmul_id_q4_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->a_m, "matmul_id_q4_k_f32_aligned_m", matmul_id_q4_k_f32_aligned_fp32_len, matmul_id_q4_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K]->a_s, "matmul_id_q4_k_f32_aligned_s", matmul_id_q4_k_f32_aligned_fp32_len, matmul_id_q4_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->l, "matmul_id_q5_k_f32_l", matmul_id_q5_k_f32_fp32_len, matmul_id_q5_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->m, "matmul_id_q5_k_f32_m", matmul_id_q5_k_f32_fp32_len, matmul_id_q5_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->s, "matmul_id_q5_k_f32_s", matmul_id_q5_k_f32_fp32_len, matmul_id_q5_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->a_l, "matmul_id_q5_k_f32_aligned_l", matmul_id_q5_k_f32_aligned_fp32_len, matmul_id_q5_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->a_m, "matmul_id_q5_k_f32_aligned_m", matmul_id_q5_k_f32_aligned_fp32_len, matmul_id_q5_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K]->a_s, "matmul_id_q5_k_f32_aligned_s", matmul_id_q5_k_f32_aligned_fp32_len, matmul_id_q5_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->l, "matmul_id_q6_k_f32_l", matmul_id_q6_k_f32_fp32_len, matmul_id_q6_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->m, "matmul_id_q6_k_f32_m", matmul_id_q6_k_f32_fp32_len, matmul_id_q6_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->s, "matmul_id_q6_k_f32_s", matmul_id_q6_k_f32_fp32_len, matmul_id_q6_k_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->a_l, "matmul_id_q6_k_f32_aligned_l", matmul_id_q6_k_f32_aligned_fp32_len, matmul_id_q6_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->a_m, "matmul_id_q6_k_f32_aligned_m", matmul_id_q6_k_f32_aligned_fp32_len, matmul_id_q6_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K]->a_s, "matmul_id_q6_k_f32_aligned_s", matmul_id_q6_k_f32_aligned_fp32_len, matmul_id_q6_k_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->l, "matmul_id_iq4_nl_f32_l", matmul_id_iq4_nl_f32_fp32_len, matmul_id_iq4_nl_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->m, "matmul_id_iq4_nl_f32_m", matmul_id_iq4_nl_f32_fp32_len, matmul_id_iq4_nl_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->s, "matmul_id_iq4_nl_f32_s", matmul_id_iq4_nl_f32_fp32_len, matmul_id_iq4_nl_f32_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->a_l, "matmul_id_iq4_nl_f32_aligned_l", matmul_id_iq4_nl_f32_aligned_fp32_len, matmul_id_iq4_nl_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), l_wg_denoms, warptile_mmq_l, l_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->a_m, "matmul_id_iq4_nl_f32_aligned_m", matmul_id_iq4_nl_f32_aligned_fp32_len, matmul_id_iq4_nl_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), m_wg_denoms, warptile_mmq_m, m_align); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL]->a_s, "matmul_id_iq4_nl_f32_aligned_s", matmul_id_iq4_nl_f32_aligned_fp32_len, matmul_id_iq4_nl_f32_aligned_fp32_data, "main", 4, sizeof(vk_mat_mat_id_push_constants), s_wg_denoms, warptile_mmq_s, s_align); + // Disable mul_mat_id if not enough shared memory is available + if (!ggml_vk_matmul_shmem_support(device, s_warptile_mmq, true, t)) { + device->mul_mat_id_s[i] = false; + device->mul_mat_id_m[i] = false; + device->mul_mat_id_l[i] = false; + } else if (!ggml_vk_matmul_shmem_support(device, m_warptile_mmq, true, t)) { + device->mul_mat_id_m[i] = false; + device->mul_mat_id_l[i] = false; + } else if (!ggml_vk_matmul_shmem_support(device, l_warptile_mmq, true, t)) { + device->mul_mat_id_l[i] = false; + } + } } + if (!device->pipeline_matmul_f32) { + device->pipeline_matmul_f32 = std::make_shared(); + } + if (!device->pipeline_matmul_f32_f16) { + device->pipeline_matmul_f32_f16 = std::make_shared(); + } + if (!device->pipeline_matmul_id_f32) { + device->pipeline_matmul_id_f32 = std::make_shared(); + } + if (!device->pipeline_matmul_bf16) { + device->pipeline_matmul_bf16 = std::make_shared(); + } + if (!device->pipeline_matmul_id_bf16) { + device->pipeline_matmul_id_bf16 = std::make_shared(); + } + + std::vector> compiles; + auto const &ggml_vk_create_pipeline = [&](vk_device& device, vk_pipeline& pipeline, const std::string &name, size_t spv_size, const void* spv_data, const std::string &entrypoint, + uint32_t parameter_count, uint32_t push_constant_size, std::array wg_denoms, const std::vector& specialization_constants, + uint32_t align, bool disable_robustness = false, bool require_full_subgroups = false, uint32_t required_subgroup_size = 0) { + + if (!require_full_subgroups && required_subgroup_size == 0) { + required_subgroup_size = get_subgroup_size(name, device->architecture); + } + + if (!pipeline) { + pipeline = std::make_shared(); + pipeline->name = name; + pipeline->parameter_count = parameter_count; + pipeline->push_constant_size = push_constant_size; + pipeline->wg_denoms = wg_denoms; + pipeline->align = align; + } + + if (!pipeline->needed || pipeline->compiled) { + return; + } + { + // wait until fewer than N compiles are in progress + uint32_t N = std::max(1u, std::thread::hardware_concurrency()); + std::unique_lock guard(compile_count_mutex); + while (compile_count >= N) { + compile_count_cond.wait(guard); + } + compile_count++; + } + compiles.push_back(std::async(ggml_vk_create_pipeline_func, std::ref(device), std::ref(pipeline), spv_size, spv_data, entrypoint, + parameter_count, wg_denoms, specialization_constants, disable_robustness, require_full_subgroups, required_subgroup_size)); + }; + + auto const &fa_wg_denoms = [&](FaCodePath path, uint32_t D, uint32_t clamp, ggml_type type, bool small_rows) -> std::array { + return {fa_rows_cols(path, D, clamp, type, small_rows)[0], 1, 1}; + }; + + auto const &fa_spec_constants = [&](FaCodePath path, uint32_t D, uint32_t clamp, ggml_type type, bool small_rows) -> std::vector { + // For large number of rows, 128 invocations seems to work best. + // For small number of rows (e.g. N==1), 256 works better. But matrix granularity for 256 is 32, so we + // can't use 256 for D==80. + // For scalar, use 128 (arbitrary) + uint32_t wg_size = (path == FA_SCALAR || path == FA_COOPMAT1) + ? scalar_flash_attention_workgroup_size + : ((small_rows && (D % 32) == 0) ? 256 : 128); + auto rows_cols = fa_rows_cols(path, D, clamp, type, small_rows); + + // D_split can't be larger than a subgroup because we use subgroupShuffle to reduce it. + // D_split can't be larger than the LSB of D divided by 4 due to vectorization in the shader. + const uint32_t D_lsb = D ^ (D & (D-1)); + uint32_t D_split = std::min(std::min(device->subgroup_size, 8u), D_lsb / 4); + + // mask dim1 is padded to 64, we rely on this to avoid clamping mask loads + GGML_ASSERT((GGML_KQ_MASK_PAD % rows_cols[0]) == 0); + return {wg_size, rows_cols[0], rows_cols[1], (D), clamp, D_split}; + }; + +#define CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, D) \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][0][0], "flash_attn_f32_f16_D" #D "_f16acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,false), fa_spec_constants(FAPATH, D,1,TYPE,false), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][0][1], "flash_attn_f32_f16_D" #D "_aligned_f16acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,false), fa_spec_constants(FAPATH, D,0,TYPE,false), fa_rows_cols(FAPATH,D,0,TYPE,false)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][0][0], "flash_attn_f32_f16_D" #D "_f32acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,false), fa_spec_constants(FAPATH, D,1,TYPE,false), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][0][1], "flash_attn_f32_f16_D" #D "_aligned_f32acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,false), fa_spec_constants(FAPATH, D,0,TYPE,false), fa_rows_cols(FAPATH,D,0,TYPE,false)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][1][0], "flash_attn_f32_f16_D" #D "_f16acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,true), fa_spec_constants(FAPATH, D,1,TYPE,true), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][1][1], "flash_attn_f32_f16_D" #D "_aligned_f16acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,true), fa_spec_constants(FAPATH, D,0,TYPE,true), fa_rows_cols(FAPATH,D,0,TYPE,true)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][1][0], "flash_attn_f32_f16_D" #D "_f32acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,true), fa_spec_constants(FAPATH, D,1,TYPE,true), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][1][1], "flash_attn_f32_f16_D" #D "_aligned_f32acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,true), fa_spec_constants(FAPATH, D,0,TYPE,true), fa_rows_cols(FAPATH,D,0,TYPE,true)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + +#define CREATE_FA(TYPE, NAMELC, FAPATH, SUFFIX) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 64) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 80) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 96) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 112) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 128) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 256) + + CREATE_FA(GGML_TYPE_F16, f16, FA_SCALAR, ) + CREATE_FA(GGML_TYPE_Q4_0, q4_0, FA_SCALAR, ) + CREATE_FA(GGML_TYPE_Q8_0, q8_0, FA_SCALAR, ) +#if defined(VK_KHR_cooperative_matrix) && defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + if (device->coopmat1_fa_support) { + CREATE_FA(GGML_TYPE_F16, f16, FA_COOPMAT1, _cm1) + CREATE_FA(GGML_TYPE_Q4_0, q4_0, FA_COOPMAT1, _cm1) + CREATE_FA(GGML_TYPE_Q8_0, q8_0, FA_COOPMAT1, _cm1) + } +#endif +#if defined(VK_NV_cooperative_matrix2) && defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + if (device->coopmat2) { + CREATE_FA(GGML_TYPE_F16, f16, FA_COOPMAT2, _cm2) + CREATE_FA(GGML_TYPE_Q4_0, q4_0, FA_COOPMAT2, _cm2) + CREATE_FA(GGML_TYPE_Q4_1, q4_1, FA_COOPMAT2, _cm2) + CREATE_FA(GGML_TYPE_Q5_0, q5_0, FA_COOPMAT2, _cm2) + CREATE_FA(GGML_TYPE_Q5_1, q5_1, FA_COOPMAT2, _cm2) + CREATE_FA(GGML_TYPE_Q8_0, q8_0, FA_COOPMAT2, _cm2) + CREATE_FA(GGML_TYPE_IQ4_NL, iq4_nl, FA_COOPMAT2, _cm2) + } +#endif +#undef CREATE_FA2 +#undef CREATE_FA + +#if defined(VK_NV_cooperative_matrix2) && defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + if (device->coopmat2) { + + // Create 6 variants, {s,m,l}x{unaligned,aligned} +#define CREATE_MM(PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _cm2_len, NAMELC ## _aligned ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _cm2_len, NAMELC ## _aligned ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _cm2_len, NAMELC ## _aligned ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align); \ + + // Create 2 variants, {f16,f32} accumulator +#define CREATE_MM2(PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT) \ + CREATE_MM(PIPELINE_NAME . f16acc, NAMELC, _f16acc, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT) \ + CREATE_MM(PIPELINE_NAME . f32acc, NAMELC, , WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT) \ + + CREATE_MM2(pipeline_matmul_f16, matmul_f16, wg_denoms, warptile, vk_mat_mat_push_constants, 3) +#if defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + if (device->coopmat_bf16_support) { + CREATE_MM(pipeline_matmul_bf16, matmul_bf16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3) + } +#endif + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q4_0], matmul_q4_0_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q4_1], matmul_q4_1_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q5_0], matmul_q5_0_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q5_1], matmul_q5_1_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q8_0], matmul_q8_0_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q2_K], matmul_q2_k_f16, mmq_wg_denoms_k, warptile_mmq_k, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q3_K], matmul_q3_k_f16, mmq_wg_denoms_k, warptile_mmq_k, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q4_K], matmul_q4_k_f16, mmq_wg_denoms_k, warptile_mmq_k, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q5_K], matmul_q5_k_f16, mmq_wg_denoms_k, warptile_mmq_k, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_Q6_K], matmul_q6_k_f16, mmq_wg_denoms_k, warptile_mmq_k, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ1_S], matmul_iq1_s_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ1_M], matmul_iq1_m_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ2_XXS], matmul_iq2_xxs_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ2_XS], matmul_iq2_xs_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ2_S], matmul_iq2_s_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ3_XXS], matmul_iq3_xxs_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ3_S], matmul_iq3_s_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ4_XS], matmul_iq4_xs_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + CREATE_MM2(pipeline_dequant_mul_mat_mat_f16[GGML_TYPE_IQ4_NL], matmul_iq4_nl_f16, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3) + + CREATE_MM2(pipeline_matmul_id_f16, matmul_id_f16, wg_denoms, warptile, vk_mat_mat_id_push_constants, 4) +#if defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + if (device->coopmat_bf16_support) { + CREATE_MM(pipeline_matmul_id_bf16, matmul_id_bf16, , wg_denoms, warptile, vk_mat_mat_id_push_constants, 4) + } +#endif + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0].f16acc, matmul_id_q4_0_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1].f16acc, matmul_id_q4_1_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0].f16acc, matmul_id_q5_0_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1].f16acc, matmul_id_q5_1_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0].f16acc, matmul_id_q8_0_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K].f16acc, matmul_id_q2_k_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K].f16acc, matmul_id_q3_k_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K].f16acc, matmul_id_q4_k_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K].f16acc, matmul_id_q5_k_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K].f16acc, matmul_id_q6_k_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_S].f16acc, matmul_id_iq1_s_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_M].f16acc, matmul_id_iq1_m_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XXS].f16acc, matmul_id_iq2_xxs_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XS].f16acc, matmul_id_iq2_xs_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_S].f16acc, matmul_id_iq2_s_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_XXS].f16acc, matmul_id_iq3_xxs_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_S].f16acc, matmul_id_iq3_s_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_XS].f16acc, matmul_id_iq4_xs_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) + CREATE_MM(pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL].f16acc, matmul_id_iq4_nl_f16, , mmqid_wg_denoms, warptile_mmqid, vk_mat_mat_id_push_constants, 4) +#undef CREATE_MM +#undef CREATE_MM2 + } else +#endif // defined(VK_NV_cooperative_matrix2) && defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) +#if defined(VK_KHR_cooperative_matrix) && defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + if (device->coopmat_support) { + // Create 6 variants, {s,m,l}x{unaligned,aligned} +#define CREATE_MM(TYPE, PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + if (device->mul_mat ## ID ## _l[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1, false, true); \ + if (device->mul_mat ## ID ## _m[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1, false, true); \ + if (device->mul_mat ## ID ## _s[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1, false, true); \ + if (device->mul_mat ## ID ## _l[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _cm1_len, NAMELC ## _aligned ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align, false, true); \ + if (device->mul_mat ## ID ## _m[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _cm1_len, NAMELC ## _aligned ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align, false, true); \ + if (device->mul_mat ## ID ## _s[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _cm1_len, NAMELC ## _aligned ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align, false, true); \ + + // Create 2 variants, {f16,f32} accumulator +#define CREATE_MM2(TYPE, PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + if (device->coopmat_acc_f16_support) { \ + CREATE_MM(TYPE, PIPELINE_NAME . f16acc, NAMELC, _f16acc, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + } \ + if (device->coopmat_acc_f32_support) { \ + CREATE_MM(TYPE, PIPELINE_NAME . f32acc, NAMELC, , WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + } \ + + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_f32, matmul_f32_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_f32_f16, matmul_f32_f16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_f16, matmul_f16, wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_f16_f32, matmul_f16_f32, wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); +#if defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + if (device->coopmat_bf16_support) { + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_bf16, matmul_bf16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ) + } +#endif + + if (device->coopmat_acc_f16_support) { + CREATE_MM2(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0], matmul_q4_0_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1], matmul_q4_1_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0], matmul_q5_0_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1], matmul_q5_1_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0], matmul_q8_0_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + + CREATE_MM2(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K], matmul_q2_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K], matmul_q3_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K], matmul_q4_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K], matmul_q5_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K], matmul_q6_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_S], matmul_iq1_s_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_M], matmul_iq1_m_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XXS], matmul_iq2_xxs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XS], matmul_iq2_xs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_S], matmul_iq2_s_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_XXS], matmul_iq3_xxs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_S], matmul_iq3_s_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_XS], matmul_iq4_xs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL], matmul_iq4_nl_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + } else { + CREATE_MM(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0].f32acc, matmul_q4_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1].f32acc, matmul_q4_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0].f32acc, matmul_q5_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1].f32acc, matmul_q5_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0].f32acc, matmul_q8_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + + CREATE_MM(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K].f32acc, matmul_q2_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K].f32acc, matmul_q3_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K].f32acc, matmul_q4_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K].f32acc, matmul_q5_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K].f32acc, matmul_q6_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_S].f32acc, matmul_iq1_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_M].f32acc, matmul_iq1_m_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XXS].f32acc, matmul_iq2_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XS].f32acc, matmul_iq2_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_S].f32acc, matmul_iq2_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_XXS].f32acc, matmul_iq3_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_S].f32acc, matmul_iq3_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_XS].f32acc, matmul_iq4_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL].f32acc, matmul_iq4_nl_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + } + + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_id_f32, matmul_id_f32_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_id_f16, matmul_id_f16, wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_id_f16_f32, matmul_id_f16_f32, wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); +#if defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + if (device->coopmat_bf16_support) { + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_id_bf16, matmul_id_bf16, , wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + } +#endif + + if (device->coopmat_acc_f16_support) { + CREATE_MM(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0].f16acc, matmul_id_q4_0_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1].f16acc, matmul_id_q4_1_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0].f16acc, matmul_id_q5_0_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1].f16acc, matmul_id_q5_1_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0].f16acc, matmul_id_q8_0_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K].f16acc, matmul_id_q2_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K].f16acc, matmul_id_q3_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K].f16acc, matmul_id_q4_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K].f16acc, matmul_id_q5_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K].f16acc, matmul_id_q6_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_S].f16acc, matmul_id_iq1_s_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_M].f16acc, matmul_id_iq1_m_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XXS].f16acc, matmul_id_iq2_xxs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XS].f16acc, matmul_id_iq2_xs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_S].f16acc, matmul_id_iq2_s_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_XXS].f16acc, matmul_id_iq3_xxs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_S].f16acc, matmul_id_iq3_s_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_XS].f16acc, matmul_id_iq4_xs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL].f16acc, matmul_id_iq4_nl_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + } else { + CREATE_MM(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0].f16acc, matmul_id_q4_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1].f16acc, matmul_id_q4_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0].f16acc, matmul_id_q5_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1].f16acc, matmul_id_q5_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0].f16acc, matmul_id_q8_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K].f16acc, matmul_id_q2_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K].f16acc, matmul_id_q3_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K].f16acc, matmul_id_q4_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K].f16acc, matmul_id_q5_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K].f16acc, matmul_id_q6_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_S].f16acc, matmul_id_iq1_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_M].f16acc, matmul_id_iq1_m_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XXS].f16acc, matmul_id_iq2_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XS].f16acc, matmul_id_iq2_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_S].f16acc, matmul_id_iq2_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_XXS].f16acc, matmul_id_iq3_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_S].f16acc, matmul_id_iq3_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_XS].f16acc, matmul_id_iq4_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL].f16acc, matmul_id_iq4_nl_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + } +#undef CREATE_MM2 +#undef CREATE_MM + } else +#endif // defined(VK_KHR_cooperative_matrix) && defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + if (device->fp16) { + // Create 6 variants, {s,m,l}x{unaligned,aligned} +#define CREATE_MM(TYPE, PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + if (device->mul_mat ## ID ## _l[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _m[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _s[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _l[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _len, NAMELC ## _aligned ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align); \ + if (device->mul_mat ## ID ## _m[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _len, NAMELC ## _aligned ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align); \ + if (device->mul_mat ## ID ## _s[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _len, NAMELC ## _aligned ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align); \ + +#define CREATE_MMQ(TYPE, PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + if (device->mul_mat ## ID ## _l[TYPE]) { \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME .f16acc->l, #NAMELC "_f16acc_l", NAMELC ## _f16acc_len, NAMELC ## _f16acc_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME .f32acc->l, #NAMELC "_l", NAMELC ## _len, NAMELC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1); \ + } \ + if (device->mul_mat ## ID ## _m[TYPE]) { \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME .f16acc->m, #NAMELC "_f16acc_m", NAMELC ## _f16acc_len, NAMELC ## _f16acc_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME .f32acc->m, #NAMELC "_m", NAMELC ## _len, NAMELC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1); \ + } \ + if (device->mul_mat ## ID ## _s[TYPE]) { \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME .f16acc->s, #NAMELC "_f16acc_s", NAMELC ## _f16acc_len, NAMELC ## _f16acc_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1); \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME .f32acc->s, #NAMELC "_s", NAMELC ## _len, NAMELC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1); \ + } \ + + // Create 2 variants, {f16,f32} accumulator +#define CREATE_MM2(TYPE, PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + CREATE_MM(TYPE, PIPELINE_NAME . f16acc, NAMELC, _f16acc, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + CREATE_MM(TYPE, PIPELINE_NAME . f32acc, NAMELC, , WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_f32, matmul_f32_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_f32_f16, matmul_f32_f16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_f16, matmul_f16, wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_f16_f32, matmul_f16_f32, wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_bf16, matmul_bf16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + + CREATE_MM2(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0], matmul_q4_0_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1], matmul_q4_1_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0], matmul_q5_0_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1], matmul_q5_1_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0], matmul_q8_0_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + + CREATE_MM2(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K], matmul_q2_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K], matmul_q3_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K], matmul_q4_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K], matmul_q5_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K], matmul_q6_k_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_S], matmul_iq1_s_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_M], matmul_iq1_m_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XXS], matmul_iq2_xxs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XS], matmul_iq2_xs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_S], matmul_iq2_s_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_XXS], matmul_iq3_xxs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_S], matmul_iq3_s_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_XS], matmul_iq4_xs_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM2(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL], matmul_iq4_nl_f32, mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + +#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + if (device->integer_dot_product) { + CREATE_MMQ(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q4_0], matmul_q4_0_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q4_1], matmul_q4_1_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q5_0], matmul_q5_0_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q5_1], matmul_q5_1_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q8_0], matmul_q8_0_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + } +#endif + + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_id_f32, matmul_id_f32_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_id_f16, matmul_id_f16, wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + CREATE_MM2(GGML_TYPE_F16, pipeline_matmul_id_f16_f32, matmul_id_f16_f32, wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_id_bf16, matmul_id_bf16, , wg_denoms, warptile, vk_mat_mat_id_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0].f16acc, matmul_id_q4_0_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1].f16acc, matmul_id_q4_1_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0].f16acc, matmul_id_q5_0_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1].f16acc, matmul_id_q5_1_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0].f16acc, matmul_id_q8_0_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K].f16acc, matmul_id_q2_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K].f16acc, matmul_id_q3_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K].f16acc, matmul_id_q4_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K].f16acc, matmul_id_q5_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K].f16acc, matmul_id_q6_k_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_S].f16acc, matmul_id_iq1_s_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_M].f16acc, matmul_id_iq1_m_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XXS].f16acc, matmul_id_iq2_xxs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XS].f16acc, matmul_id_iq2_xs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_S].f16acc, matmul_id_iq2_s_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_XXS].f16acc, matmul_id_iq3_xxs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_S].f16acc, matmul_id_iq3_s_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_XS].f16acc, matmul_id_iq4_xs_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL].f16acc, matmul_id_iq4_nl_f32, _f16acc, mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); +#undef CREATE_MM2 +#undef CREATE_MMQ +#undef CREATE_MM + } else { + // Create 6 variants, {s,m,l}x{unaligned,aligned} +#define CREATE_MM(TYPE, PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + if (device->mul_mat ## ID ## _l[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _m[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _s[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _l[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _fp32_len, NAMELC ## _aligned ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align); \ + if (device->mul_mat ## ID ## _m[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _fp32_len, NAMELC ## _aligned ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align); \ + if (device->mul_mat ## ID ## _s[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _fp32_len, NAMELC ## _aligned ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align); \ + +#define CREATE_MMQ(TYPE, PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \ + if (device->mul_mat ## ID ## _l[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC "_l", NAMELC ## _fp32_len, NAMELC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _m[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC "_m", NAMELC ## _fp32_len, NAMELC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1); \ + if (device->mul_mat ## ID ## _s[TYPE]) \ + ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC "_s", NAMELC ## _fp32_len, NAMELC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1); \ + + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_f32, matmul_f32_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_f32_f16, matmul_f32_f16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_F16, pipeline_matmul_f16.f32acc, matmul_f16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_F16, pipeline_matmul_f16_f32.f32acc, matmul_f16_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_bf16, matmul_bf16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + + CREATE_MM(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_0].f32acc, matmul_q4_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_1].f32acc, matmul_q4_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_0].f32acc, matmul_q5_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_1].f32acc, matmul_q5_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q8_0].f32acc, matmul_q8_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + + CREATE_MM(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q2_K].f32acc, matmul_q2_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q3_K].f32acc, matmul_q3_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q4_K].f32acc, matmul_q4_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q5_K].f32acc, matmul_q5_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat[GGML_TYPE_Q6_K].f32acc, matmul_q6_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_S].f32acc, matmul_iq1_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ1_M].f32acc, matmul_iq1_m_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XXS].f32acc, matmul_iq2_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_XS].f32acc, matmul_iq2_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ2_S].f32acc, matmul_iq2_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_XXS].f32acc, matmul_iq3_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ3_S].f32acc, matmul_iq3_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_XS].f32acc, matmul_iq4_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat[GGML_TYPE_IQ4_NL].f32acc, matmul_iq4_nl_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_push_constants, 3, ); + +#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + if (device->integer_dot_product) { + CREATE_MMQ(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q4_0].f32acc, matmul_q4_0_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q4_1].f32acc, matmul_q4_1_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q5_0].f32acc, matmul_q5_0_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q5_1].f32acc, matmul_q5_1_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + CREATE_MMQ(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat_q8_1[GGML_TYPE_Q8_0].f32acc, matmul_q8_0_q8_1, mmq_wg_denoms, warptile_mmq_int, vk_mat_mat_push_constants, 3, ); + } +#endif + + CREATE_MM(GGML_TYPE_F32, pipeline_matmul_id_f32, matmul_id_f32_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_F16, pipeline_matmul_id_f16.f32acc, matmul_id_f16, , wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_F16, pipeline_matmul_id_f16_f32.f32acc, matmul_id_f16_f32, , wg_denoms, warptile, vk_mat_mat_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_id_bf16, matmul_id_bf16, , wg_denoms, warptile, vk_mat_mat_id_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_Q4_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_0].f32acc, matmul_id_q4_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_1].f32acc, matmul_id_q4_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_0].f32acc, matmul_id_q5_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_1, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_1].f32acc, matmul_id_q5_1_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q8_0, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q8_0].f32acc, matmul_id_q8_0_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + + CREATE_MM(GGML_TYPE_Q2_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q2_K].f32acc, matmul_id_q2_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q3_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q3_K].f32acc, matmul_id_q3_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q4_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q4_K].f32acc, matmul_id_q4_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q5_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q5_K].f32acc, matmul_id_q5_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_Q6_K, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_Q6_K].f32acc, matmul_id_q6_k_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_S].f32acc, matmul_id_iq1_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ1_M, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ1_M].f32acc, matmul_id_iq1_m_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XXS].f32acc, matmul_id_iq2_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_XS].f32acc, matmul_id_iq2_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ2_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ2_S].f32acc, matmul_id_iq2_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_XXS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_XXS].f32acc, matmul_id_iq3_xxs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ3_S, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ3_S].f32acc, matmul_id_iq3_s_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_XS, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_XS].f32acc, matmul_id_iq4_xs_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + CREATE_MM(GGML_TYPE_IQ4_NL, pipeline_dequant_mul_mat_mat_id[GGML_TYPE_IQ4_NL].f32acc, matmul_id_iq4_nl_f32, , mmq_wg_denoms, warptile_mmq, vk_mat_mat_id_push_constants, 4, _id); + } + // reusing CREATE_MM from the fp32 path + if ((device->coopmat2 || device->coopmat_support) +#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + && !device->coopmat_bf16_support +#endif + ) { + // use scalar tile sizes + l_warptile = { 128, 128, 128, 16, subgroup_size_8 * 2, 64, 2, 4, 4, 1, subgroup_size_8 }; + m_warptile = { 128, 64, 64, 16, subgroup_size_8, 32, 2, 4, 2, 1, subgroup_size_8 }; + s_warptile = { subgroup_size_16, 32, 32, 16, 32, 32, 2, 2, 2, 1, subgroup_size_8 }; + + l_wg_denoms = {128, 128, 1 }; + m_wg_denoms = { 64, 64, 1 }; + s_wg_denoms = { 32, 32, 1 }; + + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_bf16, matmul_bf16, , wg_denoms, warptile, vk_mat_mat_push_constants, 3, ); + CREATE_MM(GGML_TYPE_BF16, pipeline_matmul_id_bf16, matmul_id_bf16, , wg_denoms, warptile, vk_mat_mat_id_push_constants, 4, _id); + } +#undef CREATE_MM + // mul mat vec - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_F32 ], "mul_mat_vec_f32_f32_f32", mul_mat_vec_f32_f32_f32_len, mul_mat_vec_f32_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_F16 ], "mul_mat_vec_f16_f32_f32", mul_mat_vec_f16_f32_f32_len, mul_mat_vec_f16_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q4_0], "mul_mat_vec_q4_0_f32_f32", mul_mat_vec_q4_0_f32_f32_len, mul_mat_vec_q4_0_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q4_1], "mul_mat_vec_q4_1_f32_f32", mul_mat_vec_q4_1_f32_f32_len, mul_mat_vec_q4_1_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q5_0], "mul_mat_vec_q5_0_f32_f32", mul_mat_vec_q5_0_f32_f32_len, mul_mat_vec_q5_0_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q5_1], "mul_mat_vec_q5_1_f32_f32", mul_mat_vec_q5_1_f32_f32_len, mul_mat_vec_q5_1_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q8_0], "mul_mat_vec_q8_0_f32_f32", mul_mat_vec_q8_0_f32_f32_len, mul_mat_vec_q8_0_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q2_K], "mul_mat_vec_q2_k_f32_f32", mul_mat_vec_q2_k_f32_f32_len, mul_mat_vec_q2_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q3_K], "mul_mat_vec_q3_k_f32_f32", mul_mat_vec_q3_k_f32_f32_len, mul_mat_vec_q3_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q4_K], "mul_mat_vec_q4_k_f32_f32", mul_mat_vec_q4_k_f32_f32_len, mul_mat_vec_q4_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q5_K], "mul_mat_vec_q5_k_f32_f32", mul_mat_vec_q5_k_f32_f32_len, mul_mat_vec_q5_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q6_K], "mul_mat_vec_q6_k_f32_f32", mul_mat_vec_q6_k_f32_f32_len, mul_mat_vec_q6_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ4_NL], "mul_mat_vec_iq4_nl_f32_f32", mul_mat_vec_iq4_nl_f32_f32_len, mul_mat_vec_iq4_nl_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_F32 ], "mul_mat_vec_f32_f16_f32", mul_mat_vec_f32_f16_f32_len, mul_mat_vec_f32_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_F16 ], "mul_mat_vec_f16_f16_f32", mul_mat_vec_f16_f16_f32_len, mul_mat_vec_f16_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q4_0], "mul_mat_vec_q4_0_f16_f32", mul_mat_vec_q4_0_f16_f32_len, mul_mat_vec_q4_0_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q4_1], "mul_mat_vec_q4_1_f16_f32", mul_mat_vec_q4_1_f16_f32_len, mul_mat_vec_q4_1_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q5_0], "mul_mat_vec_q5_0_f16_f32", mul_mat_vec_q5_0_f16_f32_len, mul_mat_vec_q5_0_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q5_1], "mul_mat_vec_q5_1_f16_f32", mul_mat_vec_q5_1_f16_f32_len, mul_mat_vec_q5_1_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q8_0], "mul_mat_vec_q8_0_f16_f32", mul_mat_vec_q8_0_f16_f32_len, mul_mat_vec_q8_0_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q2_K], "mul_mat_vec_q2_k_f16_f32", mul_mat_vec_q2_k_f16_f32_len, mul_mat_vec_q2_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q3_K], "mul_mat_vec_q3_k_f16_f32", mul_mat_vec_q3_k_f16_f32_len, mul_mat_vec_q3_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q4_K], "mul_mat_vec_q4_k_f16_f32", mul_mat_vec_q4_k_f16_f32_len, mul_mat_vec_q4_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q5_K], "mul_mat_vec_q5_k_f16_f32", mul_mat_vec_q5_k_f16_f32_len, mul_mat_vec_q5_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q6_K], "mul_mat_vec_q6_k_f16_f32", mul_mat_vec_q6_k_f16_f32_len, mul_mat_vec_q6_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ4_NL], "mul_mat_vec_iq4_nl_f16_f32", mul_mat_vec_iq4_nl_f16_f32_len, mul_mat_vec_iq4_nl_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); + // the number of rows computed per shader depends on GPU model and quant + uint32_t rm_stdq = 1; + uint32_t rm_kq = 2; + if (device->vendor_id == VK_VENDOR_ID_AMD) { + if (device->architecture == AMD_GCN) { + rm_stdq = 2; + rm_kq = 4; + } + } else if (device->vendor_id == VK_VENDOR_ID_INTEL) + rm_stdq = 2; + uint32_t rm_iq = 2 * rm_kq; - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_F32 ], "mul_mat_vec_id_f32_f32", mul_mat_vec_id_f32_f32_len, mul_mat_vec_id_f32_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_F16 ], "mul_mat_vec_id_f16_f32", mul_mat_vec_id_f16_f32_len, mul_mat_vec_id_f16_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q4_0], "mul_mat_vec_id_q4_0_f32", mul_mat_vec_id_q4_0_f32_len, mul_mat_vec_id_q4_0_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q4_1], "mul_mat_vec_id_q4_1_f32", mul_mat_vec_id_q4_1_f32_len, mul_mat_vec_id_q4_1_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q5_0], "mul_mat_vec_id_q5_0_f32", mul_mat_vec_id_q5_0_f32_len, mul_mat_vec_id_q5_0_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q5_1], "mul_mat_vec_id_q5_1_f32", mul_mat_vec_id_q5_1_f32_len, mul_mat_vec_id_q5_1_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q8_0], "mul_mat_vec_id_q8_0_f32", mul_mat_vec_id_q8_0_f32_len, mul_mat_vec_id_q8_0_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q2_K], "mul_mat_vec_id_q2_k_f32", mul_mat_vec_id_q2_k_f32_len, mul_mat_vec_id_q2_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q3_K], "mul_mat_vec_id_q3_k_f32", mul_mat_vec_id_q3_k_f32_len, mul_mat_vec_id_q3_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q4_K], "mul_mat_vec_id_q4_k_f32", mul_mat_vec_id_q4_k_f32_len, mul_mat_vec_id_q4_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q5_K], "mul_mat_vec_id_q5_k_f32", mul_mat_vec_id_q5_k_f32_len, mul_mat_vec_id_q5_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q6_K], "mul_mat_vec_id_q6_k_f32", mul_mat_vec_id_q6_k_f32_len, mul_mat_vec_id_q6_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ4_NL], "mul_mat_vec_id_iq4_nl_f32", mul_mat_vec_id_iq4_nl_f32_len, mul_mat_vec_id_iq4_nl_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); + for (uint32_t i = 0; i < mul_mat_vec_max_cols; ++i) { + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_F32 ][i], "mul_mat_vec_f32_f32_f32_"+std::to_string(i+1), mul_mat_vec_f32_f32_f32_len, mul_mat_vec_f32_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2, 1, 1}, {device->subgroup_size, 2, i+1}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_F16 ][i], "mul_mat_vec_f16_f32_f32_"+std::to_string(i+1), mul_mat_vec_f16_f32_f32_len, mul_mat_vec_f16_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2, 1, 1}, {device->subgroup_size, 2, i+1}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_BF16][i], "mul_mat_vec_bf16_f32_f32_"+std::to_string(i+1), mul_mat_vec_bf16_f32_f32_len, mul_mat_vec_bf16_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2, 1, 1}, {device->subgroup_size, 2, i+1}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q4_0][i], "mul_mat_vec_q4_0_f32_f32_"+std::to_string(i+1), mul_mat_vec_q4_0_f32_f32_len, mul_mat_vec_q4_0_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q4_1][i], "mul_mat_vec_q4_1_f32_f32_"+std::to_string(i+1), mul_mat_vec_q4_1_f32_f32_len, mul_mat_vec_q4_1_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q5_0][i], "mul_mat_vec_q5_0_f32_f32_"+std::to_string(i+1), mul_mat_vec_q5_0_f32_f32_len, mul_mat_vec_q5_0_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q5_1][i], "mul_mat_vec_q5_1_f32_f32_"+std::to_string(i+1), mul_mat_vec_q5_1_f32_f32_len, mul_mat_vec_q5_1_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q8_0][i], "mul_mat_vec_q8_0_f32_f32_"+std::to_string(i+1), mul_mat_vec_q8_0_f32_f32_len, mul_mat_vec_q8_0_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1*rm_stdq, 1, 1}, {device->subgroup_size, 1*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q2_K][i], "mul_mat_vec_q2_k_f32_f32_"+std::to_string(i+1), mul_mat_vec_q2_k_f32_f32_len, mul_mat_vec_q2_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q3_K][i], "mul_mat_vec_q3_k_f32_f32_"+std::to_string(i+1), mul_mat_vec_q3_k_f32_f32_len, mul_mat_vec_q3_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q4_K][i], "mul_mat_vec_q4_k_f32_f32_"+std::to_string(i+1), mul_mat_vec_q4_k_f32_f32_len, mul_mat_vec_q4_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q5_K][i], "mul_mat_vec_q5_k_f32_f32_"+std::to_string(i+1), mul_mat_vec_q5_k_f32_f32_len, mul_mat_vec_q5_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_Q6_K][i], "mul_mat_vec_q6_k_f32_f32_"+std::to_string(i+1), mul_mat_vec_q6_k_f32_f32_len, mul_mat_vec_q6_k_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ1_S][i], "mul_mat_vec_iq1_s_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq1_s_f32_f32_len, mul_mat_vec_iq1_s_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ1_M][i], "mul_mat_vec_iq1_m_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq1_m_f32_f32_len, mul_mat_vec_iq1_m_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ2_XXS][i], "mul_mat_vec_iq2_xxs_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq2_xxs_f32_f32_len, mul_mat_vec_iq2_xxs_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ2_XS][i], "mul_mat_vec_iq2_xs_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq2_xs_f32_f32_len, mul_mat_vec_iq2_xs_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ2_S][i], "mul_mat_vec_iq2_s_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq2_s_f32_f32_len, mul_mat_vec_iq2_s_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ3_XXS][i], "mul_mat_vec_iq3_xxs_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq3_xxs_f32_f32_len, mul_mat_vec_iq3_xxs_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ3_S][i], "mul_mat_vec_iq3_s_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq3_s_f32_f32_len, mul_mat_vec_iq3_s_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ4_XS][i], "mul_mat_vec_iq4_xs_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq4_xs_f32_f32_len, mul_mat_vec_iq4_xs_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f32_f32[GGML_TYPE_IQ4_NL][i], "mul_mat_vec_iq4_nl_f32_f32_"+std::to_string(i+1), mul_mat_vec_iq4_nl_f32_f32_len, mul_mat_vec_iq4_nl_f32_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_F32 ][i], "mul_mat_vec_f32_f16_f32_"+std::to_string(i+1), mul_mat_vec_f32_f16_f32_len, mul_mat_vec_f32_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2, 1, 1}, {device->subgroup_size, 2, i+1}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_F16 ][i], "mul_mat_vec_f16_f16_f32_"+std::to_string(i+1), mul_mat_vec_f16_f16_f32_len, mul_mat_vec_f16_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2, 1, 1}, {device->subgroup_size, 2, i+1}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_BF16][i], "mul_mat_vec_bf16_f16_f32_"+std::to_string(i+1), mul_mat_vec_bf16_f16_f32_len, mul_mat_vec_bf16_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2, 1, 1}, {device->subgroup_size, 2, i+1}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q4_0][i], "mul_mat_vec_q4_0_f16_f32_"+std::to_string(i+1), mul_mat_vec_q4_0_f16_f32_len, mul_mat_vec_q4_0_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q4_1][i], "mul_mat_vec_q4_1_f16_f32_"+std::to_string(i+1), mul_mat_vec_q4_1_f16_f32_len, mul_mat_vec_q4_1_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q5_0][i], "mul_mat_vec_q5_0_f16_f32_"+std::to_string(i+1), mul_mat_vec_q5_0_f16_f32_len, mul_mat_vec_q5_0_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q5_1][i], "mul_mat_vec_q5_1_f16_f32_"+std::to_string(i+1), mul_mat_vec_q5_1_f16_f32_len, mul_mat_vec_q5_1_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q8_0][i], "mul_mat_vec_q8_0_f16_f32_"+std::to_string(i+1), mul_mat_vec_q8_0_f16_f32_len, mul_mat_vec_q8_0_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {1*rm_stdq, 1, 1}, {device->subgroup_size, 1*rm_stdq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q2_K][i], "mul_mat_vec_q2_k_f16_f32_"+std::to_string(i+1), mul_mat_vec_q2_k_f16_f32_len, mul_mat_vec_q2_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q3_K][i], "mul_mat_vec_q3_k_f16_f32_"+std::to_string(i+1), mul_mat_vec_q3_k_f16_f32_len, mul_mat_vec_q3_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q4_K][i], "mul_mat_vec_q4_k_f16_f32_"+std::to_string(i+1), mul_mat_vec_q4_k_f16_f32_len, mul_mat_vec_q4_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q5_K][i], "mul_mat_vec_q5_k_f16_f32_"+std::to_string(i+1), mul_mat_vec_q5_k_f16_f32_len, mul_mat_vec_q5_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_Q6_K][i], "mul_mat_vec_q6_k_f16_f32_"+std::to_string(i+1), mul_mat_vec_q6_k_f16_f32_len, mul_mat_vec_q6_k_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ1_S][i], "mul_mat_vec_iq1_s_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq1_s_f16_f32_len, mul_mat_vec_iq1_s_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ1_M][i], "mul_mat_vec_iq1_m_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq1_m_f16_f32_len, mul_mat_vec_iq1_m_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ2_XXS][i], "mul_mat_vec_iq2_xxs_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq2_xxs_f16_f32_len, mul_mat_vec_iq2_xxs_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ2_XS][i], "mul_mat_vec_iq2_xs_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq2_xs_f16_f32_len, mul_mat_vec_iq2_xs_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ2_S][i], "mul_mat_vec_iq2_s_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq2_s_f16_f32_len, mul_mat_vec_iq2_s_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ3_XXS][i], "mul_mat_vec_iq3_xxs_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq3_xxs_f16_f32_len, mul_mat_vec_iq3_xxs_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ3_S][i], "mul_mat_vec_iq3_s_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq3_s_f16_f32_len, mul_mat_vec_iq3_s_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ4_XS][i], "mul_mat_vec_iq4_xs_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq4_xs_f16_f32_len, mul_mat_vec_iq4_xs_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_f16_f32[GGML_TYPE_IQ4_NL][i], "mul_mat_vec_iq4_nl_f16_f32_"+std::to_string(i+1), mul_mat_vec_iq4_nl_f16_f32_len, mul_mat_vec_iq4_nl_f16_f32_data, "main", 3, sizeof(vk_mat_vec_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq, i+1}, 1, true); + } + + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_F32 ], "mul_mat_vec_id_f32_f32", mul_mat_vec_id_f32_f32_len, mul_mat_vec_id_f32_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {2, 1, 1}, {device->subgroup_size, 2}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_F16 ], "mul_mat_vec_id_f16_f32", mul_mat_vec_id_f16_f32_len, mul_mat_vec_id_f16_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {2, 1, 1}, {device->subgroup_size, 2}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_BF16], "mul_mat_vec_id_bf16_f32", mul_mat_vec_id_bf16_f32_len, mul_mat_vec_id_bf16_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {2, 1, 1}, {device->subgroup_size, 2}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q4_0], "mul_mat_vec_id_q4_0_f32", mul_mat_vec_id_q4_0_f32_len, mul_mat_vec_id_q4_0_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q4_1], "mul_mat_vec_id_q4_1_f32", mul_mat_vec_id_q4_1_f32_len, mul_mat_vec_id_q4_1_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q5_0], "mul_mat_vec_id_q5_0_f32", mul_mat_vec_id_q5_0_f32_len, mul_mat_vec_id_q5_0_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q5_1], "mul_mat_vec_id_q5_1_f32", mul_mat_vec_id_q5_1_f32_len, mul_mat_vec_id_q5_1_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {2*rm_stdq, 1, 1}, {device->subgroup_size, 2*rm_stdq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q8_0], "mul_mat_vec_id_q8_0_f32", mul_mat_vec_id_q8_0_f32_len, mul_mat_vec_id_q8_0_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {1*rm_stdq, 1, 1}, {device->subgroup_size, 1*rm_stdq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q2_K], "mul_mat_vec_id_q2_k_f32", mul_mat_vec_id_q2_k_f32_len, mul_mat_vec_id_q2_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q3_K], "mul_mat_vec_id_q3_k_f32", mul_mat_vec_id_q3_k_f32_len, mul_mat_vec_id_q3_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q4_K], "mul_mat_vec_id_q4_k_f32", mul_mat_vec_id_q4_k_f32_len, mul_mat_vec_id_q4_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q5_K], "mul_mat_vec_id_q5_k_f32", mul_mat_vec_id_q5_k_f32_len, mul_mat_vec_id_q5_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_Q6_K], "mul_mat_vec_id_q6_k_f32", mul_mat_vec_id_q6_k_f32_len, mul_mat_vec_id_q6_k_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_kq, 1, 1}, {subgroup_size_16, rm_kq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ1_S], "mul_mat_vec_id_iq1_s_f32", mul_mat_vec_id_iq1_s_f32_len, mul_mat_vec_id_iq1_s_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ1_M], "mul_mat_vec_id_iq1_m_f32", mul_mat_vec_id_iq1_m_f32_len, mul_mat_vec_id_iq1_m_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ2_XXS], "mul_mat_vec_id_iq2_xxs_f32", mul_mat_vec_id_iq2_xxs_f32_len, mul_mat_vec_id_iq2_xxs_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ2_XS], "mul_mat_vec_id_iq2_xs_f32", mul_mat_vec_id_iq2_xs_f32_len, mul_mat_vec_id_iq2_xs_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ2_S], "mul_mat_vec_id_iq2_s_f32", mul_mat_vec_id_iq2_s_f32_len, mul_mat_vec_id_iq2_s_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ3_XXS], "mul_mat_vec_id_iq3_xxs_f32", mul_mat_vec_id_iq3_xxs_f32_len, mul_mat_vec_id_iq3_xxs_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ3_S], "mul_mat_vec_id_iq3_s_f32", mul_mat_vec_id_iq3_s_f32_len, mul_mat_vec_id_iq3_s_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ4_XS], "mul_mat_vec_id_iq4_xs_f32", mul_mat_vec_id_iq4_xs_f32_len, mul_mat_vec_id_iq4_xs_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_dequant_mul_mat_vec_id_f32[GGML_TYPE_IQ4_NL], "mul_mat_vec_id_iq4_nl_f32", mul_mat_vec_id_iq4_nl_f32_len, mul_mat_vec_id_iq4_nl_f32_data, "main", 4, sizeof(vk_mat_vec_id_push_constants), {rm_iq, 1, 1}, {subgroup_size_16, rm_iq}, 1, true); // dequant shaders ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_F32 ], "f32_to_f16", dequant_f32_len, dequant_f32_data, "main", 2, 5 * sizeof(uint32_t), {256 * 16, 1, 1}, {}, 1); @@ -1610,45 +2590,131 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_Q4_K], "dequant_q4_k", dequant_q4_k_len, dequant_q4_k_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_Q5_K], "dequant_q5_k", dequant_q5_k_len, dequant_q5_k_data, "main", 2, 5 * sizeof(uint32_t), {256 * 64, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_Q6_K], "dequant_q6_k", dequant_q6_k_len, dequant_q6_k_data, "main", 2, 5 * sizeof(uint32_t), {256 * 64, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ4_NL], "dequant_iq4_nl", dequant_iq4_nl_len, dequant_iq4_nl_data, "main", 2, 5 * sizeof(uint32_t), {256 * 16, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ1_S], "dequant_iq1_s", dequant_iq1_s_len, dequant_iq1_s_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ1_M], "dequant_iq1_m", dequant_iq1_m_len, dequant_iq1_m_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ2_XXS], "dequant_iq2_xxs", dequant_iq2_xxs_len, dequant_iq2_xxs_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ2_XS], "dequant_iq2_xs", dequant_iq2_xs_len, dequant_iq2_xs_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ2_S], "dequant_iq2_s", dequant_iq2_s_len, dequant_iq2_s_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ3_XXS], "dequant_iq3_xxs", dequant_iq3_xxs_len, dequant_iq3_xxs_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ3_S], "dequant_iq3_s", dequant_iq3_s_len, dequant_iq3_s_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ4_XS], "dequant_iq4_xs", dequant_iq4_xs_len, dequant_iq4_xs_data, "main", 2, 5 * sizeof(uint32_t), {256 * 32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_dequant[GGML_TYPE_IQ4_NL], "dequant_iq4_nl", dequant_iq4_nl_len, dequant_iq4_nl_data, "main", 2, 5 * sizeof(uint32_t), {256 * 16, 1, 1}, {}, 1); // get_rows ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_F32 ], "get_rows_f32", get_rows_f32_len, get_rows_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), { 512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_F16 ], "get_rows_f16", get_rows_f16_len, get_rows_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), { 512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_BF16], "get_rows_bf16", get_rows_bf16_len, get_rows_bf16_data, "main", 3, sizeof(vk_op_binary_push_constants), { 512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_Q4_0], "get_rows_q4_0", get_rows_q4_0_len, get_rows_q4_0_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_Q4_1], "get_rows_q4_1", get_rows_q4_1_len, get_rows_q4_1_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_Q5_0], "get_rows_q5_0", get_rows_q5_0_len, get_rows_q5_0_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_Q5_1], "get_rows_q5_1", get_rows_q5_1_len, get_rows_q5_1_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_Q8_0], "get_rows_q8_0", get_rows_q8_0_len, get_rows_q8_0_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ4_NL], "get_rows_iq4_nl", get_rows_iq4_nl_len, get_rows_iq4_nl_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ1_S], "get_rows_iq1_s", get_rows_iq1_s_len, get_rows_iq1_s_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ1_M], "get_rows_iq1_m", get_rows_iq1_m_len, get_rows_iq1_m_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ2_XXS], "get_rows_iq2_xxs", get_rows_iq2_xxs_len, get_rows_iq2_xxs_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ2_XS], "get_rows_iq2_xs", get_rows_iq2_xs_len, get_rows_iq2_xs_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ2_S], "get_rows_iq2_s", get_rows_iq2_s_len, get_rows_iq2_s_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ3_XXS], "get_rows_iq3_xxs", get_rows_iq3_xxs_len, get_rows_iq3_xxs_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ3_S], "get_rows_iq3_s", get_rows_iq3_s_len, get_rows_iq3_s_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ4_XS], "get_rows_iq4_xs", get_rows_iq4_xs_len, get_rows_iq4_xs_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows[GGML_TYPE_IQ4_NL], "get_rows_iq4_nl", get_rows_iq4_nl_len, get_rows_iq4_nl_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_F32 ], "get_rows_f32_f32", get_rows_f32_f32_len, get_rows_f32_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), { 512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_F16 ], "get_rows_f16_f32", get_rows_f16_f32_len, get_rows_f16_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), { 512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_BF16], "get_rows_bf16_f32", get_rows_bf16_f32_len, get_rows_bf16_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), { 512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_Q4_0], "get_rows_q4_0_f32", get_rows_q4_0_f32_len, get_rows_q4_0_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_Q4_1], "get_rows_q4_1_f32", get_rows_q4_1_f32_len, get_rows_q4_1_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_Q5_0], "get_rows_q5_0_f32", get_rows_q5_0_f32_len, get_rows_q5_0_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_Q5_1], "get_rows_q5_1_f32", get_rows_q5_1_f32_len, get_rows_q5_1_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_Q8_0], "get_rows_q8_0_f32", get_rows_q8_0_f32_len, get_rows_q8_0_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ4_NL], "get_rows_iq4_nl_f32", get_rows_iq4_nl_f32_len, get_rows_iq4_nl_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ1_S], "get_rows_iq1_s_f32", get_rows_iq1_s_f32_len, get_rows_iq1_s_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ1_M], "get_rows_iq1_m_f32", get_rows_iq1_m_f32_len, get_rows_iq1_m_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ2_XXS], "get_rows_iq2_xxs_f32", get_rows_iq2_xxs_f32_len, get_rows_iq2_xxs_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ2_XS], "get_rows_iq2_xs_f32", get_rows_iq2_xs_f32_len, get_rows_iq2_xs_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ2_S], "get_rows_iq2_s_f32", get_rows_iq2_s_f32_len, get_rows_iq2_s_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ3_XXS], "get_rows_iq3_xxs_f32", get_rows_iq3_xxs_f32_len, get_rows_iq3_xxs_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ3_S], "get_rows_iq3_s_f32", get_rows_iq3_s_f32_len, get_rows_iq3_s_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ4_XS], "get_rows_iq4_xs_f32", get_rows_iq4_xs_f32_len, get_rows_iq4_xs_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ4_NL], "get_rows_iq4_nl_f32", get_rows_iq4_nl_f32_len, get_rows_iq4_nl_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_matmul_split_k_reduce, "split_k_reduce", split_k_reduce_len, split_k_reduce_data, "main", 2, 2 * sizeof(uint32_t), {256, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_matmul_split_k_reduce, "split_k_reduce", split_k_reduce_len, split_k_reduce_data, "main", 2, 2 * sizeof(uint32_t), {256 * 4, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_split_k_reduce, "fa_split_k_reduce", fa_split_k_reduce_len, fa_split_k_reduce_data, "main", 2, 3 * sizeof(uint32_t), {1, 1, 1}, {}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_quantize_q8_1, "quantize_q8_1", quantize_q8_1_len, quantize_q8_1_data, "main", 2, 1 * sizeof(uint32_t), {32 * device->subgroup_size / 8, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_mul_mat_vec_p021_f16_f32, "mul_mat_vec_p021_f16_f32", mul_mat_vec_p021_f16_f32_len, mul_mat_vec_p021_f16_f32_data, "main", 3, 6 * sizeof(uint32_t), {1, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_mul_mat_vec_nc_f16_f32, "mul_mat_vec_nc_f16_f32", mul_mat_vec_nc_f16_f32_len, mul_mat_vec_nc_f16_f32_data, "main", 3, 7 * sizeof(uint32_t), {1, 1, 1}, {}, 1); + for (uint32_t i = 0; i < p021_max_gqa_ratio; ++i) { + if (device->subgroup_add && device->subgroup_require_full_support) { + ggml_vk_create_pipeline(device, device->pipeline_mul_mat_vec_p021_f16_f32[i], "mul_mat_vec_p021_f16_f32"+std::to_string(i+1), mul_mat_vec_p021_f16_f32_subgroup_add_len, mul_mat_vec_p021_f16_f32_subgroup_add_data, "main", 3, 6 * sizeof(uint32_t), {1, 1, 1}, {device->subgroup_size, i + 1}, 1, true, true); + } else { + ggml_vk_create_pipeline(device, device->pipeline_mul_mat_vec_p021_f16_f32[i], "mul_mat_vec_p021_f16_f32"+std::to_string(i+1), mul_mat_vec_p021_f16_f32_len, mul_mat_vec_p021_f16_f32_data, "main", 3, 6 * sizeof(uint32_t), {1, 1, 1}, {device->subgroup_size, i + 1}, 1, true); + } + } + ggml_vk_create_pipeline(device, device->pipeline_mul_mat_vec_nc_f16_f32, "mul_mat_vec_nc_f16_f32", mul_mat_vec_nc_f16_f32_len, mul_mat_vec_nc_f16_f32_data, "main", 3, 9 * sizeof(uint32_t), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_norm_f32, "norm_f32", norm_f32_len, norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_group_norm_f32, "group_norm_f32", group_norm_f32_len, group_norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_rms_norm_f32, "rms_norm_f32", rms_norm_f32_len, rms_norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rms_norm_f32, "rms_norm_f32", rms_norm_f32_len, rms_norm_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rms_norm_back_f32, "rms_norm_back_f32", rms_norm_back_f32_len, rms_norm_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_f32, "cpy_f32_f32", cpy_f32_f32_len, cpy_f32_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_f16, "cpy_f32_f16", cpy_f32_f16_len, cpy_f32_f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_cpy_f16_f16, "cpy_f16_f16", cpy_f16_f16_len, cpy_f16_f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f16_f32, "cpy_f16_f32", cpy_f16_f32_len, cpy_f16_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_bf16,"cpy_f32_bf16",cpy_f32_bf16_len,cpy_f32_bf16_data,"main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_add_f32, "add_f32", add_f32_len, add_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_add_f16_f32_f16, "add_f16_f32_f16", add_f16_f32_f16_len, add_f16_f32_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_f32_f32, "contig_cpy_f32_f32", contig_cpy_f32_f32_len, contig_cpy_f32_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_f32_f16, "contig_cpy_f32_f16", contig_cpy_f32_f16_len, contig_cpy_f32_f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_f16_f16, "contig_cpy_f16_f16", contig_cpy_f16_f16_len, contig_cpy_f16_f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_f16_f32, "contig_cpy_f16_f32", contig_cpy_f16_f32_len, contig_cpy_f16_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_f32_bf16,"contig_cpy_f32_bf16",contig_cpy_f32_bf16_len,contig_cpy_f32_bf16_data,"main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_mul_f32, "mul_f32", mul_f32_len, mul_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_div_f32, "div_f32", div_f32_len, div_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); + if (device->float_controls_rte_fp16) { + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_0], "cpy_f32_q4_0", cpy_f32_q4_0_rte_len, cpy_f32_q4_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_1], "cpy_f32_q4_1", cpy_f32_q4_1_rte_len, cpy_f32_q4_1_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_1), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_0], "cpy_f32_q5_0", cpy_f32_q5_0_rte_len, cpy_f32_q5_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_1], "cpy_f32_q5_1", cpy_f32_q5_1_rte_len, cpy_f32_q5_1_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_1), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_rte_len, cpy_f32_q8_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q8_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_rte_len, cpy_f32_iq4_nl_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_IQ4_NL), 1, 1}, {}, 1); + } else { + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_0], "cpy_f32_q4_0", cpy_f32_q4_0_len, cpy_f32_q4_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_1], "cpy_f32_q4_1", cpy_f32_q4_1_len, cpy_f32_q4_1_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_1), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_0], "cpy_f32_q5_0", cpy_f32_q5_0_len, cpy_f32_q5_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_1], "cpy_f32_q5_1", cpy_f32_q5_1_len, cpy_f32_q5_1_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_1), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_len, cpy_f32_q8_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q8_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_len, cpy_f32_iq4_nl_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_IQ4_NL), 1, 1}, {}, 1); + } + + ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q4_0], "cpy_q4_0_f32", cpy_q4_0_f32_len, cpy_q4_0_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q4_1], "cpy_q4_1_f32", cpy_q4_1_f32_len, cpy_q4_1_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_1), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q5_0], "cpy_q5_0_f32", cpy_q5_0_f32_len, cpy_q5_0_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q5_1], "cpy_q5_1_f32", cpy_q5_1_f32_len, cpy_q5_1_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_1), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q8_0], "cpy_q8_0_f32", cpy_q8_0_f32_len, cpy_q8_0_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q8_0), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_IQ4_NL], "cpy_iq4_nl_f32", cpy_iq4_nl_f32_len, cpy_iq4_nl_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_IQ4_NL), 1, 1}, {}, 1); + + auto get_suffix = [](bool src0_f16, bool src1_f16, bool dst_f16) { + std::string s; + s += std::string(src0_f16 ? "_f16" : "_f32"); + s += std::string(src1_f16 ? "_f16" : "_f32"); + s += std::string(dst_f16 ? "_f16" : "_f32"); + return s; + }; + +#define CREATE_BINARY(name, namemod, spec) \ + for (int s0 : {0,1}) for (int s1 : {0,1}) for (int d : {0,1}) \ + ggml_vk_create_pipeline(device, device->pipeline_ ## name ## namemod[s0][s1][d], \ + #name + get_suffix(s0, s1, d) + #namemod, name ## _len[s0][s1][d], name ## _data[s0][s1][d], \ + "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, spec, 1); + + CREATE_BINARY(add, , {0}) + CREATE_BINARY(add, _norepeat, {1}) + CREATE_BINARY(sub, , {0}) + CREATE_BINARY(sub, _norepeat, {1}) + CREATE_BINARY(mul, , {0}) + CREATE_BINARY(mul, _norepeat, {1}) + CREATE_BINARY(div, , {0}) + CREATE_BINARY(div, _norepeat, {1}) +#undef CREATE_BINARY + + ggml_vk_create_pipeline(device, device->pipeline_acc_f32, "acc_f32", acc_f32_len, acc_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_concat_f32, "concat_f32", concat_f32_len, concat_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_concat_f16, "concat_f16", concat_f16_len, concat_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); @@ -1664,34 +2730,82 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_pad_f32, "pad_f32", pad_f32_len, pad_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_gelu_f32, "gelu_f32", gelu_f32_len, gelu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_gelu_quick_f32, "gelu_quick_f32", gelu_quick_f32_len, gelu_quick_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_silu_f32, "silu_f32", silu_f32_len, silu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_relu_f32, "relu_f32", relu_f32_len, relu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_repeat_f32, "repeat_f32", repeat_f32_len, repeat_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_repeat_back_f32, "repeat_back_f32", repeat_back_f32_len, repeat_back_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + +#define CREATE_UNARY(name) \ + ggml_vk_create_pipeline(device, device->pipeline_ ## name [0], #name "_f32", name ## _f32_len, name ## _f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); \ + ggml_vk_create_pipeline(device, device->pipeline_ ## name [1], #name "_f16", name ## _f16_len, name ## _f16_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + + CREATE_UNARY(gelu) + CREATE_UNARY(gelu_quick) + CREATE_UNARY(silu) + CREATE_UNARY(relu) + CREATE_UNARY(tanh) + CREATE_UNARY(sigmoid) +#undef CREATE_UNARY + ggml_vk_create_pipeline(device, device->pipeline_leaky_relu_f32, "leaky_relu_f32", leaky_relu_f32_len, leaky_relu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_tanh_f32, "tanh_f32", tanh_f32_len, tanh_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_silu_back_f32, "silu_back_f32", silu_back_f32_len, silu_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_diag_mask_inf_f32, "diag_mask_inf_f32", diag_mask_inf_f32_len, diag_mask_inf_f32_data, "main", 2, sizeof(vk_op_diag_mask_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_diag_mask_inf_f32, "diag_mask_inf_f32", diag_mask_inf_f32_len, diag_mask_inf_f32_data, "main", 2, sizeof(vk_op_diag_mask_push_constants), {1, 512, 1}, {}, 1, true); - ggml_vk_create_pipeline(device, device->pipeline_soft_max_f32, "soft_max_f32", soft_max_f32_len, soft_max_f32_data, "main", 3, sizeof(vk_op_soft_max_push_constants), {1, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_soft_max_f32_f16, "soft_max_f32_f16", soft_max_f32_f16_len, soft_max_f32_f16_data, "main", 3, sizeof(vk_op_soft_max_push_constants), {1, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_soft_max_f32, "soft_max_f32", soft_max_f32_len, soft_max_f32_data, "main", 3, sizeof(vk_op_soft_max_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); + ggml_vk_create_pipeline(device, device->pipeline_soft_max_f32_wg512, "soft_max_f32_wg512", soft_max_f32_len, soft_max_f32_data, "main", 3, sizeof(vk_op_soft_max_push_constants), {1, 1, 1}, { 512 }, 1); + ggml_vk_create_pipeline(device, device->pipeline_soft_max_f32_f16, "soft_max_f32_f16", soft_max_f32_f16_len, soft_max_f32_f16_data, "main", 3, sizeof(vk_op_soft_max_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); + ggml_vk_create_pipeline(device, device->pipeline_soft_max_f32_f16_wg512, "soft_max_f32_f16_wg512", soft_max_f32_f16_len, soft_max_f32_f16_data, "main", 3, sizeof(vk_op_soft_max_push_constants), {1, 1, 1}, { 512 }, 1); + ggml_vk_create_pipeline(device, device->pipeline_soft_max_back_f32, "soft_max_back_f32", soft_max_back_f32_len, soft_max_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); ggml_vk_create_pipeline(device, device->pipeline_rope_norm_f32, "rope_norm_f32", rope_norm_f32_len, rope_norm_f32_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_rope_norm_f16, "rope_norm_f16", rope_norm_f16_len, rope_norm_f16_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_rope_neox_f32, "rope_neox_f32", rope_neox_f32_len, rope_neox_f32_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_rope_neox_f16, "rope_neox_f16", rope_neox_f16_len, rope_neox_f16_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_multi_f32, "rope_multi_f32", rope_multi_f32_len, rope_multi_f32_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_vision_f32, "rope_vision_f32", rope_vision_f32_len, rope_vision_f32_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + + if (device->float_controls_rte_fp16) { + ggml_vk_create_pipeline(device, device->pipeline_rope_norm_f16, "rope_norm_f16", rope_norm_f16_rte_len, rope_norm_f16_rte_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_neox_f16, "rope_neox_f16", rope_neox_f16_rte_len, rope_neox_f16_rte_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_multi_f16, "rope_multi_f16", rope_multi_f16_rte_len, rope_multi_f16_rte_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_vision_f16, "rope_vision_f16", rope_vision_f16_rte_len, rope_vision_f16_rte_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + } else { + ggml_vk_create_pipeline(device, device->pipeline_rope_norm_f16, "rope_norm_f16", rope_norm_f16_len, rope_norm_f16_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_neox_f16, "rope_neox_f16", rope_neox_f16_len, rope_neox_f16_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_multi_f16, "rope_multi_f16", rope_multi_f16_len, rope_multi_f16_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rope_vision_f16, "rope_vision_f16", rope_vision_f16_len, rope_vision_f16_data, "main", 4, sizeof(vk_op_rope_push_constants), {1, 512, 1}, {}, 1); + } ggml_vk_create_pipeline(device, device->pipeline_argsort_f32, "argsort_f32", argsort_f32_len, argsort_f32_data, "main", 2, sizeof(vk_op_argsort_push_constants), {1024, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_argmax_f32, "argmax_f32", argmax_f32_len, argmax_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); + ggml_vk_create_pipeline(device, device->pipeline_sum_rows_f32, "sum_rows_f32", sum_rows_f32_len, sum_rows_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - ggml_vk_create_pipeline(device, device->pipeline_im2col_f32, "im2col_f32", im2col_f32_len, im2col_f32_data, "main", 2, sizeof(vk_op_im2col_push_constants), {256, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_im2col_f32_f16, "im2col_f32_f16", im2col_f32_f16_len, im2col_f32_f16_data, "main", 2, sizeof(vk_op_im2col_push_constants), {256, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_count_equal_i32, "count_equal_i32", count_equal_i32_len, count_equal_i32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, { device->subgroup_size }, 1); + + ggml_vk_create_pipeline(device, device->pipeline_im2col_f32, "im2col_f32", im2col_f32_len, im2col_f32_data, "main", 2, sizeof(vk_op_im2col_push_constants), {512, 1, 1}, { device->subgroup_size }, 1, true); + if (device->float_controls_rte_fp16) { + ggml_vk_create_pipeline(device, device->pipeline_im2col_f32_f16, "im2col_f32_f16", im2col_f32_f16_rte_len, im2col_f32_f16_rte_data, "main", 2, sizeof(vk_op_im2col_push_constants), {512, 1, 1}, { device->subgroup_size }, 1, true); + } else { + ggml_vk_create_pipeline(device, device->pipeline_im2col_f32_f16, "im2col_f32_f16", im2col_f32_f16_len, im2col_f32_f16_data, "main", 2, sizeof(vk_op_im2col_push_constants), {512, 1, 1}, { device->subgroup_size }, 1, true); + } ggml_vk_create_pipeline(device, device->pipeline_timestep_embedding_f32, "timestep_embedding_f32", timestep_embedding_f32_len, timestep_embedding_f32_data, "main", 2, sizeof(vk_op_timestep_embedding_push_constants), {256, 1, 1}, {}, 1); + + ggml_vk_create_pipeline(device, device->pipeline_conv_transpose_1d_f32, "conv_transpose_1d_f32", conv_transpose_1d_f32_len, conv_transpose_1d_f32_data, "main", 3, sizeof(vk_op_conv_transpose_1d_push_constants), {1, 1, 1}, {}, 1); + + ggml_vk_create_pipeline(device, device->pipeline_pool2d_f32, "pool2d_f32", pool2d_f32_len, pool2d_f32_data, "main", 2, sizeof(vk_op_pool2d_push_constants), {512, 1, 1}, {}, 1); + + ggml_vk_create_pipeline(device, device->pipeline_rwkv_wkv6_f32, "rwkv_wkv6_f32", rwkv_wkv6_f32_len, rwkv_wkv6_f32_data, "main", 7, sizeof(vk_op_rwkv_wkv6_push_constants), {1, 1, 1}, {device->subgroup_size}, 1); + + ggml_vk_create_pipeline(device, device->pipeline_opt_step_adamw_f32, "opt_step_adamw_f32", opt_step_adamw_f32_len, opt_step_adamw_f32_data, "main", 5, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + + for (auto &c : compiles) { + c.wait(); + } + device->need_compiles = false; } +static bool ggml_vk_khr_cooperative_matrix_support(const vk::PhysicalDeviceProperties& props, const vk::PhysicalDeviceDriverProperties& driver_props, vk_device_architecture arch); + static vk_device ggml_vk_get_device(size_t idx) { VK_LOG_DEBUG("ggml_vk_get_device(" << idx << ")"); @@ -1703,6 +2817,9 @@ static vk_device ggml_vk_get_device(size_t idx) { #ifdef GGML_VULKAN_MEMORY_DEBUG device->memory_logger = std::unique_ptr(new vk_memory_logger()); #endif + if (vk_perf_logger_enabled) { + device->perf_logger = std::unique_ptr(new vk_perf_logger()); + } size_t dev_num = vk_instance.device_indices[idx]; @@ -1716,12 +2833,60 @@ static vk_device ggml_vk_get_device(size_t idx) { device->physical_device = physical_devices[dev_num]; const std::vector ext_props = device->physical_device.enumerateDeviceExtensionProperties(); - bool maintenance4_support = false; + device->architecture = get_device_architecture(device->physical_device); + + const char* GGML_VK_PREFER_HOST_MEMORY = getenv("GGML_VK_PREFER_HOST_MEMORY"); + device->prefer_host_memory = GGML_VK_PREFER_HOST_MEMORY != nullptr; + + bool fp16_storage = false; + bool fp16_compute = false; + bool maintenance4_support = false; + bool sm_builtins = false; + bool amd_shader_core_properties2 = false; + bool pipeline_robustness = false; + bool coopmat2_support = false; + device->coopmat_support = false; + device->integer_dot_product = false; + bool bfloat16_support = false; - // Check if maintenance4 is supported for (const auto& properties : ext_props) { if (strcmp("VK_KHR_maintenance4", properties.extensionName) == 0) { maintenance4_support = true; + } else if (strcmp("VK_KHR_16bit_storage", properties.extensionName) == 0) { + fp16_storage = true; + } else if (strcmp("VK_KHR_shader_float16_int8", properties.extensionName) == 0) { + fp16_compute = true; + } else if (strcmp("VK_NV_shader_sm_builtins", properties.extensionName) == 0) { + sm_builtins = true; + } else if (strcmp("VK_AMD_shader_core_properties2", properties.extensionName) == 0) { + amd_shader_core_properties2 = true; + } else if (strcmp("VK_EXT_pipeline_robustness", properties.extensionName) == 0) { + pipeline_robustness = true; + } else if (strcmp("VK_EXT_subgroup_size_control", properties.extensionName) == 0) { + device->subgroup_size_control = true; +#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + } else if (strcmp("VK_KHR_cooperative_matrix", properties.extensionName) == 0 && + !getenv("GGML_VK_DISABLE_COOPMAT")) { + device->coopmat_support = true; + device->coopmat_m = 0; + device->coopmat_n = 0; + device->coopmat_k = 0; +#endif +#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + } else if (strcmp("VK_NV_cooperative_matrix2", properties.extensionName) == 0 && + !getenv("GGML_VK_DISABLE_COOPMAT2")) { + coopmat2_support = true; +#endif +#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + } else if (strcmp("VK_KHR_shader_integer_dot_product", properties.extensionName) == 0 && + !getenv("GGML_VK_DISABLE_INTEGER_DOT_PRODUCT")) { + device->integer_dot_product = true; +#endif +#if defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + } else if (strcmp("VK_KHR_shader_bfloat16", properties.extensionName) == 0 && + !getenv("GGML_VK_DISABLE_BFLOAT16")) { + bfloat16_support = true; +#endif } } @@ -1729,44 +2894,104 @@ static vk_device ggml_vk_get_device(size_t idx) { vk::PhysicalDeviceMaintenance3Properties props3; vk::PhysicalDeviceMaintenance4Properties props4; vk::PhysicalDeviceSubgroupProperties subgroup_props; + vk::PhysicalDeviceDriverProperties driver_props; + vk::PhysicalDeviceShaderSMBuiltinsPropertiesNV sm_props; + vk::PhysicalDeviceShaderCoreProperties2AMD amd_shader_core_properties2_props; + vk::PhysicalDeviceVulkan11Properties vk11_props; + vk::PhysicalDeviceVulkan12Properties vk12_props; + vk::PhysicalDeviceSubgroupSizeControlPropertiesEXT subgroup_size_control_props; + vk::PhysicalDeviceShaderIntegerDotProductPropertiesKHR shader_integer_dot_product_props; + props2.pNext = &props3; props3.pNext = &subgroup_props; + subgroup_props.pNext = &driver_props; + driver_props.pNext = &vk11_props; + vk11_props.pNext = &vk12_props; + + VkBaseOutStructure * last_struct = (VkBaseOutStructure *)&vk12_props; + if (maintenance4_support) { - subgroup_props.pNext = &props4; + last_struct->pNext = (VkBaseOutStructure *)&props4; + last_struct = (VkBaseOutStructure *)&props4; } + if (sm_builtins) { + last_struct->pNext = (VkBaseOutStructure *)&sm_props; + last_struct = (VkBaseOutStructure *)&sm_props; + } + if (amd_shader_core_properties2) { + last_struct->pNext = (VkBaseOutStructure *)&amd_shader_core_properties2_props; + last_struct = (VkBaseOutStructure *)&amd_shader_core_properties2_props; + } + if (device->subgroup_size_control) { + last_struct->pNext = (VkBaseOutStructure *)&subgroup_size_control_props; + last_struct = (VkBaseOutStructure *)&subgroup_size_control_props; + } + +#if defined(VK_NV_cooperative_matrix2) + vk::PhysicalDeviceCooperativeMatrix2PropertiesNV coopmat2_props; + if (coopmat2_support) { + last_struct->pNext = (VkBaseOutStructure *)&coopmat2_props; + last_struct = (VkBaseOutStructure *)&coopmat2_props; + } +#endif + + if (device->integer_dot_product) { + last_struct->pNext = (VkBaseOutStructure *)&shader_integer_dot_product_props; + last_struct = (VkBaseOutStructure *)&shader_integer_dot_product_props; + } + device->physical_device.getProperties2(&props2); device->properties = props2.properties; + device->vendor_id = device->properties.vendorID; + device->driver_id = driver_props.driverID; const char* GGML_VK_FORCE_MAX_ALLOCATION_SIZE = getenv("GGML_VK_FORCE_MAX_ALLOCATION_SIZE"); if (GGML_VK_FORCE_MAX_ALLOCATION_SIZE != nullptr) { - device->max_memory_allocation_size = std::stoi(GGML_VK_FORCE_MAX_ALLOCATION_SIZE); + device->max_memory_allocation_size = std::stoul(GGML_VK_FORCE_MAX_ALLOCATION_SIZE); } else if (maintenance4_support) { device->max_memory_allocation_size = std::min(props3.maxMemoryAllocationSize, props4.maxBufferSize); } else { device->max_memory_allocation_size = props3.maxMemoryAllocationSize; } - device->vendor_id = device->properties.vendorID; + const char* GGML_VK_SUBALLOCATION_BLOCK_SIZE = getenv("GGML_VK_SUBALLOCATION_BLOCK_SIZE"); + + if (GGML_VK_SUBALLOCATION_BLOCK_SIZE != nullptr) { + device->suballocation_block_size = std::stoul(GGML_VK_SUBALLOCATION_BLOCK_SIZE); + } else { + // Limit batching of allocations to 1GB by default to avoid fragmentation issues + device->suballocation_block_size = 1024*1024*1024; + } + device->suballocation_block_size = std::min(device->suballocation_block_size, device->max_memory_allocation_size); + device->subgroup_size = subgroup_props.subgroupSize; device->uma = device->properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu; - - bool fp16_storage = false; - bool fp16_compute = false; - - for (const auto& properties : ext_props) { - if (strcmp("VK_KHR_16bit_storage", properties.extensionName) == 0) { - fp16_storage = true; - } else if (strcmp("VK_KHR_shader_float16_int8", properties.extensionName) == 0) { - fp16_compute = true; - } + if (sm_builtins) { + device->shader_core_count = sm_props.shaderSMCount; + } else if (amd_shader_core_properties2) { + device->shader_core_count = amd_shader_core_properties2_props.activeComputeUnitCount; + } else { + device->shader_core_count = 0; } + device->float_controls_rte_fp16 = vk12_props.shaderRoundingModeRTEFloat16; - const char* GGML_VK_DISABLE_F16 = getenv("GGML_VK_DISABLE_F16"); - const bool force_disable_f16 = GGML_VK_DISABLE_F16 != nullptr; + device->subgroup_add = (vk11_props.subgroupSupportedStages & vk::ShaderStageFlagBits::eCompute) && + (vk11_props.subgroupSupportedOperations & vk::SubgroupFeatureFlagBits::eArithmetic); + + device->subgroup_shuffle = (vk11_props.subgroupSupportedStages & vk::ShaderStageFlagBits::eCompute) && + (vk11_props.subgroupSupportedOperations & vk::SubgroupFeatureFlagBits::eShuffle); + + const bool force_disable_f16 = getenv("GGML_VK_DISABLE_F16") != nullptr; device->fp16 = !force_disable_f16 && fp16_storage && fp16_compute; + if (!ggml_vk_khr_cooperative_matrix_support(device->properties, driver_props, device->architecture)) { + device->coopmat_support = false; + } + + device->integer_dot_product = device->integer_dot_product && shader_integer_dot_product_props.integerDotProduct4x8BitPackedSignedAccelerated; + std::vector queue_family_props = device->physical_device.getQueueFamilyProperties(); // Try to find a non-graphics compute queue and transfer-focused queues @@ -1804,10 +3029,185 @@ static vk_device ggml_vk_get_device(size_t idx) { vk12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; vk11_features.pNext = &vk12_features; + last_struct = (VkBaseOutStructure *)&vk12_features; + + VkPhysicalDevicePipelineRobustnessFeaturesEXT pl_robustness_features; + pl_robustness_features.pNext = nullptr; + pl_robustness_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT; + pl_robustness_features.pipelineRobustness = VK_FALSE; + + if (pipeline_robustness) { + last_struct->pNext = (VkBaseOutStructure *)&pl_robustness_features; + last_struct = (VkBaseOutStructure *)&pl_robustness_features; + device_extensions.push_back("VK_EXT_pipeline_robustness"); + } + + VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroup_size_control_features; + subgroup_size_control_features.pNext = nullptr; + subgroup_size_control_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT; + subgroup_size_control_features.computeFullSubgroups = false; + subgroup_size_control_features.subgroupSizeControl = false; + + if (device->subgroup_size_control) { + last_struct->pNext = (VkBaseOutStructure *)&subgroup_size_control_features; + last_struct = (VkBaseOutStructure *)&subgroup_size_control_features; + } + +#if defined(VK_KHR_cooperative_matrix) + VkPhysicalDeviceCooperativeMatrixFeaturesKHR coopmat_features; + coopmat_features.pNext = nullptr; + coopmat_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR; + coopmat_features.cooperativeMatrix = VK_FALSE; + + if (device->coopmat_support) { + last_struct->pNext = (VkBaseOutStructure *)&coopmat_features; + last_struct = (VkBaseOutStructure *)&coopmat_features; + } +#endif + +#if defined(VK_NV_cooperative_matrix2) + VkPhysicalDeviceCooperativeMatrix2FeaturesNV coopmat2_features {}; + coopmat2_features.pNext = nullptr; + coopmat2_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_FEATURES_NV; + if (coopmat2_support) { + last_struct->pNext = (VkBaseOutStructure *)&coopmat2_features; + last_struct = (VkBaseOutStructure *)&coopmat2_features; + device_extensions.push_back("VK_NV_cooperative_matrix2"); + } +#endif + +#if defined(VK_KHR_shader_bfloat16) + VkPhysicalDeviceShaderBfloat16FeaturesKHR bfloat16_features {}; + bfloat16_features.pNext = nullptr; + bfloat16_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_BFLOAT16_FEATURES_KHR; + if (bfloat16_support) { + last_struct->pNext = (VkBaseOutStructure *)&bfloat16_features; + last_struct = (VkBaseOutStructure *)&bfloat16_features; + device_extensions.push_back("VK_KHR_shader_bfloat16"); + } +#endif + + VkPhysicalDeviceMaintenance4Features maint4_features {}; + maint4_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES; + if (maintenance4_support) { + last_struct->pNext = (VkBaseOutStructure *)&maint4_features; + last_struct = (VkBaseOutStructure *)&maint4_features; + device_extensions.push_back("VK_KHR_maintenance4"); + } + + VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR shader_integer_dot_product_features {}; + shader_integer_dot_product_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR; + if (device->integer_dot_product) { + last_struct->pNext = (VkBaseOutStructure *)&shader_integer_dot_product_features; + last_struct = (VkBaseOutStructure *)&shader_integer_dot_product_features; + device_extensions.push_back("VK_KHR_shader_integer_dot_product"); + } + vkGetPhysicalDeviceFeatures2(device->physical_device, &device_features2); device->fp16 = device->fp16 && vk12_features.shaderFloat16; + device->pipeline_robustness = pl_robustness_features.pipelineRobustness; + + if (device->subgroup_size_control) { + device->subgroup_min_size = subgroup_size_control_props.minSubgroupSize; + device->subgroup_max_size = subgroup_size_control_props.maxSubgroupSize; + device_extensions.push_back("VK_EXT_subgroup_size_control"); + } + + device->subgroup_size_control = device->subgroup_size_control && + (subgroup_size_control_props.requiredSubgroupSizeStages & vk::ShaderStageFlagBits::eCompute) && + subgroup_size_control_features.subgroupSizeControl; + + if (device->subgroup_size_control) { + device->subgroup_require_full_support = subgroup_size_control_features.computeFullSubgroups; + } + +#if defined(VK_KHR_cooperative_matrix) + device->coopmat_support = device->coopmat_support && coopmat_features.cooperativeMatrix; + + // coopmat1 fa shader currently assumes 32 invocations per subgroup + device->coopmat1_fa_support = device->coopmat_support && device->subgroup_require_full_support && + device->subgroup_size_control && device->subgroup_min_size <= 32 && + device->subgroup_max_size >= 32; +#endif + + if (coopmat2_support) { +#if defined(VK_NV_cooperative_matrix2) && defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + if (coopmat2_features.cooperativeMatrixWorkgroupScope && + coopmat2_features.cooperativeMatrixFlexibleDimensions && + coopmat2_features.cooperativeMatrixReductions && + coopmat2_features.cooperativeMatrixConversions && + coopmat2_features.cooperativeMatrixPerElementOperations && + coopmat2_features.cooperativeMatrixTensorAddressing && + coopmat2_features.cooperativeMatrixBlockLoads && + vk12_features.bufferDeviceAddress) { + + std::vector flexible_dimensions; + uint32_t count = 0; + + PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV + _vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV = + (PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV) + vk_instance.instance.getProcAddr("vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV"); + + _vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV(device->physical_device, &count, nullptr); + + VkCooperativeMatrixFlexibleDimensionsPropertiesNV empty_prop {}; + empty_prop.sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_FLEXIBLE_DIMENSIONS_PROPERTIES_NV; + flexible_dimensions.resize(count, empty_prop); + + _vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV(device->physical_device, &count, flexible_dimensions.data()); + + bool found_fp16_128 = false, + found_fp16_256 = false, + found_fp32_128 = false, + found_fp32_256 = false; + // need to support fp16*fp16 with fp16/fp32 accumulator, for workgroupsize 128 + // with 32x16x16 and 256 with 32x32x16. + for (auto &prop : flexible_dimensions) { + if (prop.saturatingAccumulation == VK_FALSE && + prop.scope == VK_SCOPE_WORKGROUP_KHR && + prop.AType == VK_COMPONENT_TYPE_FLOAT16_KHR && + prop.BType == VK_COMPONENT_TYPE_FLOAT16_KHR) { + + if (prop.workgroupInvocations == 128 && + prop.MGranularity <= 32 && + prop.NGranularity <= 16 && + prop.KGranularity <= 16) { + if (prop.CType == VK_COMPONENT_TYPE_FLOAT16_KHR && + prop.ResultType == VK_COMPONENT_TYPE_FLOAT16_KHR) { + found_fp16_128 = true; + } + if (prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR && + prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR) { + found_fp32_128 = true; + } + } + if (prop.workgroupInvocations == 256 && + prop.MGranularity <= 32 && + prop.NGranularity <= 32 && + prop.KGranularity <= 16) { + if (prop.CType == VK_COMPONENT_TYPE_FLOAT16_KHR && + prop.ResultType == VK_COMPONENT_TYPE_FLOAT16_KHR) { + found_fp16_256 = true; + } + if (prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR && + prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR) { + found_fp32_256 = true; + } + } + } + } + if (found_fp16_128 && found_fp16_256 && + found_fp32_128 && found_fp32_256 && + coopmat2_props.cooperativeMatrixFlexibleDimensionsMaxDimension >= 512) { + device->coopmat2 = true; + } + } +#endif + } + if (!vk11_features.storageBuffer16BitAccess) { std::cerr << "ggml_vulkan: device " << GGML_VK_NAME << idx << " does not support 16-bit storage." << std::endl; throw std::runtime_error("Unsupported device"); @@ -1822,7 +3222,120 @@ static vk_device ggml_vk_get_device(size_t idx) { if (device->fp16) { device_extensions.push_back("VK_KHR_shader_float16_int8"); } - device->name = device->properties.deviceName.data(); + +#if defined(VK_KHR_cooperative_matrix) + if (device->coopmat_support) { + // Query supported shapes + std::vector cm_props; + + PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR pfn_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR = + (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)vkGetInstanceProcAddr(vk_instance.instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR"); + + uint32_t cm_props_num; + + pfn_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR(device->physical_device, &cm_props_num, nullptr); + + cm_props.resize(cm_props_num); + + for (auto& prop : cm_props) { + prop.sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR; + } + + pfn_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR(device->physical_device, &cm_props_num, cm_props.data()); + + VK_LOG_DEBUG("ggml_vulkan: Cooperative Matrix Shapes: " << cm_props.size()); + + for (auto& prop : cm_props) { + VK_LOG_DEBUG("ggml_vulkan: M: " << prop.MSize << " N: " << prop.NSize << " K: " << prop.KSize << " A: " << vk::to_string((vk::ComponentTypeKHR)prop.AType) << " B: " << vk::to_string((vk::ComponentTypeKHR)prop.BType) << " C: " << vk::to_string((vk::ComponentTypeKHR)prop.CType) << " Result: " << vk::to_string((vk::ComponentTypeKHR)prop.ResultType) << " saturatingAccumulation: " << prop.saturatingAccumulation << " scope: " << vk::to_string((vk::ScopeKHR)prop.scope)); + + if ((vk::ComponentTypeKHR)prop.AType == vk::ComponentTypeKHR::eFloat16 && + (vk::ComponentTypeKHR)prop.BType == vk::ComponentTypeKHR::eFloat16 && + (vk::ScopeKHR)prop.scope == vk::ScopeKHR::eSubgroup + ) { + if ((vk::ComponentTypeKHR)prop.CType == vk::ComponentTypeKHR::eFloat32 && + (vk::ComponentTypeKHR)prop.ResultType == vk::ComponentTypeKHR::eFloat32) { + // coopmat sizes not set yet + if (device->coopmat_m == 0) { + device->coopmat_acc_f32_support = true; + device->coopmat_m = prop.MSize; + device->coopmat_n = prop.NSize; + device->coopmat_k = prop.KSize; + } else if (device->coopmat_m == prop.MSize && device->coopmat_n == prop.NSize && device->coopmat_k == prop.KSize) { + // Only enable if shape is identical + device->coopmat_acc_f32_support = true; + } + if (prop.MSize == 16 && prop.NSize == 16 && prop.KSize == 16) { + device->coopmat_support_16x16x16_f32acc = true; + } + } else if ((vk::ComponentTypeKHR)prop.CType == vk::ComponentTypeKHR::eFloat16 && + (vk::ComponentTypeKHR)prop.ResultType == vk::ComponentTypeKHR::eFloat16) { + // coopmat sizes not set yet + if (device->coopmat_m == 0) { + device->coopmat_acc_f16_support = true; + device->coopmat_m = prop.MSize; + device->coopmat_n = prop.NSize; + device->coopmat_k = prop.KSize; + } else if (device->coopmat_m == prop.MSize && device->coopmat_n == prop.NSize && device->coopmat_k == prop.KSize) { + // Only enable if shape is identical + device->coopmat_acc_f16_support = true; + } + if (prop.MSize == 16 && prop.NSize == 16 && prop.KSize == 16) { + device->coopmat_support_16x16x16_f16acc = true; + } + } + } else if ((vk::ComponentTypeKHR)prop.AType == vk::ComponentTypeKHR::eSint8 && + (vk::ComponentTypeKHR)prop.BType == vk::ComponentTypeKHR::eSint8 && + (vk::ComponentTypeKHR)prop.CType == vk::ComponentTypeKHR::eSint32 && + (vk::ComponentTypeKHR)prop.ResultType == vk::ComponentTypeKHR::eSint32 && + (vk::ScopeKHR)prop.scope == vk::ScopeKHR::eSubgroup && + device->coopmat_int_m == 0 + ) { + device->coopmat_int_support = true; + device->coopmat_int_m = prop.MSize; + device->coopmat_int_n = prop.NSize; + device->coopmat_int_k = prop.KSize; + } +#if defined(VK_KHR_shader_bfloat16) && defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + if (prop.AType == VK_COMPONENT_TYPE_BFLOAT16_KHR && + prop.BType == VK_COMPONENT_TYPE_BFLOAT16_KHR && + prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR && + prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR && + (vk::ScopeKHR)prop.scope == vk::ScopeKHR::eSubgroup + ) { + // coopmat sizes not set yet + if (device->coopmat_m == 0) { + device->coopmat_bf16_support = true; + device->coopmat_m = prop.MSize; + device->coopmat_n = prop.NSize; + device->coopmat_k = prop.KSize; + } else if (device->coopmat_m == prop.MSize && device->coopmat_n == prop.NSize && device->coopmat_k == prop.KSize) { + // Only enable if shape is identical + device->coopmat_bf16_support = true; + } + } +#endif + } + + if (device->coopmat_m == 0 || !device->coopmat_acc_f32_support) { + // No suitable matmul mode found + GGML_LOG_DEBUG("ggml_vulkan: WARNING: No suitable matrix core mode found. Disabling matrix cores.\n"); + device->coopmat_support = false; + } + if (getenv("GGML_VK_DISABLE_BFLOAT16")) { + device->coopmat_bf16_support = false; + } + } + + if (device->coopmat_support) { + device_extensions.push_back("VK_KHR_cooperative_matrix"); + } +#if defined(VK_KHR_shader_bfloat16) + if (device->coopmat_bf16_support) { + device_extensions.push_back("VK_KHR_shader_bfloat16"); + } +#endif +#endif + device->name = GGML_VK_NAME + std::to_string(idx); device_create_info = { vk::DeviceCreateFlags(), @@ -1833,20 +3346,68 @@ static vk_device ggml_vk_get_device(size_t idx) { device_create_info.setPNext(&device_features2); device->device = device->physical_device.createDevice(device_create_info); - device->descriptor_set_mode = VK_DEVICE_DESCRIPTOR_POOL_MODE_UNKNOWN; - // Queues - ggml_vk_create_queue(device, device->compute_queue, compute_queue_family_index, 0, { vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eTransfer }); + ggml_vk_create_queue(device, device->compute_queue, compute_queue_family_index, 0, { vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eTransfer }, false); // Shaders + // Disable matmul tile sizes early if performance low or not supported + for (uint32_t i = 0; i < GGML_TYPE_COUNT; ++i) { + switch (device->vendor_id) { +#ifndef GGML_VULKAN_RUN_TESTS + case VK_VENDOR_ID_AMD: + case VK_VENDOR_ID_INTEL: + device->mul_mat_l[i] = false; + device->mul_mat_m[i] = true; + device->mul_mat_s[i] = true; + device->mul_mat_id_l[i] = false; + device->mul_mat_id_m[i] = true; + device->mul_mat_id_s[i] = true; + break; + case VK_VENDOR_ID_APPLE: + device->mul_mat_l[i] = false; + device->mul_mat_m[i] = true; + device->mul_mat_s[i] = false; + device->mul_mat_id_l[i] = false; + device->mul_mat_id_m[i] = true; + device->mul_mat_id_s[i] = false; + break; +#endif + default: + device->mul_mat_l[i] = true; + device->mul_mat_m[i] = true; + device->mul_mat_s[i] = true; + device->mul_mat_id_l[i] = true; + device->mul_mat_id_m[i] = true; + device->mul_mat_id_s[i] = true; + break; + } + } + + + std::vector dsl_binding; + std::vector dsl_binding_flags; + for (uint32_t i = 0; i < MAX_PARAMETER_COUNT; i++) { + dsl_binding.push_back({i, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute}); + dsl_binding_flags.push_back({}); + } + + vk::DescriptorSetLayoutBindingFlagsCreateInfo dslbfci = { dsl_binding_flags }; + + vk::DescriptorSetLayoutCreateInfo descriptor_set_layout_create_info( + {}, + dsl_binding); + descriptor_set_layout_create_info.setPNext(&dslbfci); + device->dsl = device->device.createDescriptorSetLayout(descriptor_set_layout_create_info); + ggml_vk_load_shaders(device); if (!device->single_queue) { const uint32_t transfer_queue_index = compute_queue_family_index == transfer_queue_family_index ? 1 : 0; - ggml_vk_create_queue(device, device->transfer_queue, transfer_queue_family_index, transfer_queue_index, { vk::PipelineStageFlagBits::eTransfer }); + ggml_vk_create_queue(device, device->transfer_queue, transfer_queue_family_index, transfer_queue_index, { vk::PipelineStageFlagBits::eTransfer }, true); } else { // TODO: Use pointer or reference to avoid copy - device->transfer_queue = device->compute_queue; + device->transfer_queue.copyFrom(device->compute_queue); + device->transfer_queue.cmd_pool.init(device, &device->transfer_queue); } device->buffer_type = { @@ -1864,7 +3425,6 @@ static vk_device ggml_vk_get_device(size_t idx) { return vk_instance.devices[idx]; } - static void ggml_vk_print_gpu_info(size_t idx) { GGML_ASSERT(idx < vk_instance.device_indices.size()); size_t dev_num = vk_instance.device_indices[idx]; @@ -1881,40 +3441,64 @@ static void ggml_vk_print_gpu_info(size_t idx) { vk::PhysicalDevice physical_device = devices[dev_num]; std::vector ext_props = physical_device.enumerateDeviceExtensionProperties(); - vk::PhysicalDeviceProperties2 props2; - vk::PhysicalDeviceMaintenance3Properties props3; - vk::PhysicalDeviceSubgroupProperties subgroup_props; - vk::PhysicalDeviceDriverProperties driver_props; - props2.pNext = &props3; - props3.pNext = &subgroup_props; - subgroup_props.pNext = &driver_props; - physical_device.getProperties2(&props2); - - const size_t subgroup_size = subgroup_props.subgroupSize; - const bool uma = props2.properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu; - bool fp16_storage = false; bool fp16_compute = false; + bool coopmat_support = false; + bool coopmat2_support = false; + bool integer_dot_product = false; for (auto properties : ext_props) { if (strcmp("VK_KHR_16bit_storage", properties.extensionName) == 0) { fp16_storage = true; } else if (strcmp("VK_KHR_shader_float16_int8", properties.extensionName) == 0) { fp16_compute = true; +#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + } else if (strcmp("VK_KHR_cooperative_matrix", properties.extensionName) == 0 && + !getenv("GGML_VK_DISABLE_COOPMAT")) { + coopmat_support = true; +#endif +#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + } else if (strcmp("VK_NV_cooperative_matrix2", properties.extensionName) == 0 && + !getenv("GGML_VK_DISABLE_COOPMAT2")) { + coopmat2_support = true; +#endif +#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + } else if (strcmp("VK_KHR_shader_integer_dot_product", properties.extensionName) == 0 && + !getenv("GGML_VK_DISABLE_INTEGER_DOT_PRODUCT")) { + integer_dot_product = true; +#endif } } + const vk_device_architecture device_architecture = get_device_architecture(physical_device); + const char* GGML_VK_DISABLE_F16 = getenv("GGML_VK_DISABLE_F16"); bool force_disable_f16 = GGML_VK_DISABLE_F16 != nullptr; bool fp16 = !force_disable_f16 && fp16_storage && fp16_compute; - vk::PhysicalDeviceFeatures device_features = physical_device.getFeatures(); + vk::PhysicalDeviceProperties2 props2; + vk::PhysicalDeviceMaintenance3Properties props3; + vk::PhysicalDeviceSubgroupProperties subgroup_props; + vk::PhysicalDeviceDriverProperties driver_props; + vk::PhysicalDeviceShaderIntegerDotProductPropertiesKHR shader_integer_dot_product_props; + props2.pNext = &props3; + props3.pNext = &subgroup_props; + subgroup_props.pNext = &driver_props; + + // Pointer to the last chain element + VkBaseOutStructure * last_struct = (VkBaseOutStructure *)&driver_props; + + if (integer_dot_product) { + last_struct->pNext = (VkBaseOutStructure *)&shader_integer_dot_product_props; + last_struct = (VkBaseOutStructure *)&shader_integer_dot_product_props; + } + + physical_device.getProperties2(&props2); VkPhysicalDeviceFeatures2 device_features2; device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; device_features2.pNext = nullptr; - device_features2.features = (VkPhysicalDeviceFeatures)device_features; VkPhysicalDeviceVulkan11Features vk11_features; vk11_features.pNext = nullptr; @@ -1926,22 +3510,64 @@ static void ggml_vk_print_gpu_info(size_t idx) { vk12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; vk11_features.pNext = &vk12_features; + // Pointer to the last chain element + last_struct = (VkBaseOutStructure *)&vk12_features; + +#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + VkPhysicalDeviceCooperativeMatrixFeaturesKHR coopmat_features; + coopmat_features.pNext = nullptr; + coopmat_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR; + coopmat_features.cooperativeMatrix = VK_FALSE; + + if (coopmat_support) { + last_struct->pNext = (VkBaseOutStructure *)&coopmat_features; + last_struct = (VkBaseOutStructure *)&coopmat_features; + } +#endif + + VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR shader_integer_dot_product_features {}; + shader_integer_dot_product_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR; + if (integer_dot_product) { + last_struct->pNext = (VkBaseOutStructure *)&shader_integer_dot_product_features; + last_struct = (VkBaseOutStructure *)&shader_integer_dot_product_features; + } + vkGetPhysicalDeviceFeatures2(physical_device, &device_features2); fp16 = fp16 && vk12_features.shaderFloat16; + uint32_t default_subgroup_size = get_subgroup_size("", device_architecture); + const size_t subgroup_size = (default_subgroup_size != 0) ? default_subgroup_size : subgroup_props.subgroupSize; + const bool uma = props2.properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu; + + integer_dot_product = integer_dot_product + && shader_integer_dot_product_props.integerDotProduct4x8BitPackedSignedAccelerated + && shader_integer_dot_product_features.shaderIntegerDotProduct; + + coopmat_support = coopmat_support +#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + && coopmat_features.cooperativeMatrix +#endif + && ggml_vk_khr_cooperative_matrix_support(props2.properties, driver_props, device_architecture); + + std::string matrix_cores = coopmat2_support ? "NV_coopmat2" : coopmat_support ? "KHR_coopmat" : "none"; + std::string device_name = props2.properties.deviceName.data(); - std::cerr << GGML_VK_NAME << idx << ": " << device_name << " (" << driver_props.driverName << ") | uma: " << uma << " | fp16: " << fp16 << " | warp size: " << subgroup_size << std::endl; + GGML_LOG_INFO("ggml_vulkan: %zu = %s (%s) | uma: %d | fp16: %d | warp size: %zu | shared memory: %d | int dot: %d | matrix cores: %s\n", + idx, device_name.c_str(), driver_props.driverName.data(), uma, fp16, subgroup_size, + props2.properties.limits.maxComputeSharedMemorySize, integer_dot_product, matrix_cores.c_str()); if (props2.properties.deviceType == vk::PhysicalDeviceType::eCpu) { - std::cerr << "ggml_vulkan: Warning: Device type is CPU. This is probably not the device you want." << std::endl; + GGML_LOG_INFO("ggml_vulkan: Warning: Device type is CPU. This is probably not the device you want.\n"); } } static bool ggml_vk_instance_validation_ext_available(const std::vector& instance_extensions); static bool ggml_vk_instance_portability_enumeration_ext_available(const std::vector& instance_extensions); -void ggml_vk_instance_init() { +static bool ggml_vk_instance_debug_utils_ext_available(const std::vector & instance_extensions); + +GGML_CALL void ggml_vk_instance_init() { if (vk_instance_initialized) { return; } @@ -1949,14 +3575,21 @@ void ggml_vk_instance_init() { vk_instance_initialized = true; - vk::ApplicationInfo app_info{ "ggml-vulkan", 1, nullptr, 0, VK_API_VERSION }; + uint32_t api_version = vk::enumerateInstanceVersion(); + + if (api_version < VK_API_VERSION_1_2) { + std::cerr << "ggml_vulkan: Error: Vulkan 1.2 required." << std::endl; + GGML_ABORT("fatal error"); + } + + vk::ApplicationInfo app_info{ "ggml-vulkan", 1, nullptr, 0, api_version }; const std::vector instance_extensions = vk::enumerateInstanceExtensionProperties(); const bool validation_ext = ggml_vk_instance_validation_ext_available(instance_extensions); #ifdef __APPLE__ const bool portability_enumeration_ext = ggml_vk_instance_portability_enumeration_ext_available(instance_extensions); #endif - + const bool debug_utils_ext = ggml_vk_instance_debug_utils_ext_available(instance_extensions) && getenv("GGML_VK_DEBUG_MARKERS") != nullptr; std::vector layers; if (validation_ext) { @@ -1971,6 +3604,9 @@ void ggml_vk_instance_init() { extensions.push_back("VK_KHR_portability_enumeration"); } #endif + if (debug_utils_ext) { + extensions.push_back("VK_EXT_debug_utils"); + } vk::InstanceCreateInfo instance_create_info(vk::InstanceCreateFlags{}, &app_info, layers, extensions); #ifdef __APPLE__ if (portability_enumeration_ext) { @@ -1989,16 +3625,29 @@ void ggml_vk_instance_init() { }; validation_features.setPNext(nullptr); instance_create_info.setPNext(&validation_features); - - std::cerr << "ggml_vulkan: Validation layers enabled" << std::endl; + GGML_LOG_DEBUG("ggml_vulkan: Validation layers enabled\n"); } vk_instance.instance = vk::createInstance(instance_create_info); + if (debug_utils_ext) { + vk_instance.debug_utils_support = true; + vk_instance.pfn_vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT) vkGetInstanceProcAddr(vk_instance.instance, "vkSetDebugUtilsObjectNameEXT"); + vk_instance.pfn_vkQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.instance, "vkQueueBeginDebugUtilsLabelEXT"); + vk_instance.pfn_vkQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.instance, "vkQueueEndDebugUtilsLabelEXT"); + vk_instance.pfn_vkCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.instance, "vkCmdBeginDebugUtilsLabelEXT"); + vk_instance.pfn_vkCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.instance, "vkCmdEndDebugUtilsLabelEXT"); + vk_instance.pfn_vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT) vkGetInstanceProcAddr(vk_instance.instance, "vkCmdInsertDebugUtilsLabelEXT"); + + } + size_t num_available_devices = vk_instance.instance.enumeratePhysicalDevices().size(); + vk_perf_logger_enabled = getenv("GGML_VK_PERF_LOGGER") != nullptr; // Emulate behavior of CUDA_VISIBLE_DEVICES for Vulkan char * devices_env = getenv("GGML_VK_VISIBLE_DEVICES"); if (devices_env != nullptr) { + size_t num_available_devices = vk_instance.instance.enumeratePhysicalDevices().size(); + std::string devices(devices_env); std::replace(devices.begin(), devices.end(), ',', ' '); @@ -2014,9 +3663,9 @@ void ggml_vk_instance_init() { } else { std::vector devices = vk_instance.instance.enumeratePhysicalDevices(); - // Make sure at least one device exists + // If no vulkan devices are found, return early if (devices.empty()) { - std::cerr << "ggml_vulkan: Error: No devices found." << std::endl; + GGML_LOG_INFO("ggml_vulkan: No devices found.\n"); GGML_ABORT("fatal error"); } @@ -2099,13 +3748,23 @@ void ggml_vk_instance_init() { } } - // If no dedicated GPUs found, fall back to GPU 0 + // If no dedicated GPUs found, fall back to the first non-CPU device. + // If only CPU devices are available, return without devices. if (vk_instance.device_indices.empty()) { - vk_instance.device_indices.push_back(0); + for (size_t i = 0; i < devices.size(); i++) { + if (devices[i].getProperties().deviceType != vk::PhysicalDeviceType::eCpu) { + vk_instance.device_indices.push_back(i); + break; + } + } + } + + if (vk_instance.device_indices.empty()) { + GGML_LOG_INFO("ggml_vulkan: No devices found.\n"); + return; } } - - std::cerr << "ggml_vulkan: Found " << vk_instance.device_indices.size() << " Vulkan devices:" << std::endl; + GGML_LOG_DEBUG("ggml_vulkan: Found %zu Vulkan devices:\n", vk_instance.device_indices.size()); for (size_t i = 0; i < vk_instance.device_indices.size(); i++) { ggml_vk_print_gpu_info(i); @@ -2129,9 +3788,10 @@ static void ggml_vk_init(ggml_backend_vk_context * ctx, size_t idx) { ctx->prealloc_size_split_k = 0; ctx->fence = ctx->device->device.createFence({}); + ctx->almost_ready_fence = ctx->device->device.createFence({}); - ctx->staging_size = 0; - ctx->staging_offset = 0; + ctx->compute_cmd_pool.init(ctx->device, &ctx->device->compute_queue); + ctx->transfer_cmd_pool.init(ctx->device, &ctx->device->transfer_queue); #ifdef GGML_VULKAN_CHECK_RESULTS const char* skip_checks = getenv("GGML_VULKAN_SKIP_CHECKS"); @@ -2155,6 +3815,14 @@ static vk_pipeline ggml_vk_get_to_fp16(ggml_backend_vk_context * ctx, ggml_type case GGML_TYPE_Q4_K: case GGML_TYPE_Q5_K: case GGML_TYPE_Q6_K: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: break; default: @@ -2164,22 +3832,45 @@ static vk_pipeline ggml_vk_get_to_fp16(ggml_backend_vk_context * ctx, ggml_type return ctx->device->pipeline_dequant[type]; } -static vk_matmul_pipeline ggml_vk_get_mul_mat_mat_pipeline(ggml_backend_vk_context * ctx, ggml_type src0_type, ggml_type src1_type) { - VK_LOG_DEBUG("ggml_vk_get_mul_mat_mat_pipeline(" << ggml_type_name(src0_type) << ", " << ggml_type_name(src1_type) << ")"); +static vk_matmul_pipeline ggml_vk_get_mul_mat_mat_pipeline(ggml_backend_vk_context * ctx, ggml_type src0_type, ggml_type src1_type, ggml_prec prec) { + VK_LOG_DEBUG("ggml_vk_get_mul_mat_mat_pipeline(" << ggml_type_name(src0_type) << ", " << ggml_type_name(src1_type) << ", " << prec << ")"); if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F32) { return ctx->device->pipeline_matmul_f32; } if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F16) { return ctx->device->pipeline_matmul_f32_f16; } - if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) { - return ctx->device->pipeline_matmul_f16_f32; + if (src0_type == GGML_TYPE_BF16 && src1_type == GGML_TYPE_BF16) { + return ctx->device->pipeline_matmul_bf16; } - if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) { - return ctx->device->pipeline_matmul_f16; + if (prec == GGML_PREC_DEFAULT && ctx->device->fp16 && !(ctx->device->coopmat_support && !ctx->device->coopmat_acc_f16_support)) { + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) { + return ctx->device->pipeline_matmul_f16_f32.f16acc; + } + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) { + return ctx->device->pipeline_matmul_f16.f16acc; + } + } else { + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) { + return ctx->device->pipeline_matmul_f16_f32.f32acc; + } + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) { + return ctx->device->pipeline_matmul_f16.f32acc; + } } - if (src1_type != GGML_TYPE_F32) { + // MMQ + if (src1_type == GGML_TYPE_Q8_1) { + vk_matmul_pipeline pipelines = (ctx->device->fp16 && prec == GGML_PREC_DEFAULT) ? ctx->device->pipeline_dequant_mul_mat_mat_q8_1[src0_type].f16acc : ctx->device->pipeline_dequant_mul_mat_mat_q8_1[src0_type].f32acc; + + if (pipelines->s == nullptr && pipelines->m == nullptr && pipelines->l == nullptr) { + return nullptr; + } + + return pipelines; + } + + if (src1_type != GGML_TYPE_F32 && !ctx->device->coopmat2) { return nullptr; } @@ -2194,22 +3885,39 @@ static vk_matmul_pipeline ggml_vk_get_mul_mat_mat_pipeline(ggml_backend_vk_conte case GGML_TYPE_Q4_K: case GGML_TYPE_Q5_K: case GGML_TYPE_Q6_K: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: break; default: return nullptr; } - return ctx->device->pipeline_dequant_mul_mat_mat[src0_type]; + if (ctx->device->coopmat2) { + assert(src1_type == GGML_TYPE_F16); + return prec == GGML_PREC_DEFAULT ? ctx->device->pipeline_dequant_mul_mat_mat_f16[src0_type].f16acc : ctx->device->pipeline_dequant_mul_mat_mat_f16[src0_type].f32acc; + } + if (ctx->device->coopmat_support) { + return (ctx->device->fp16 && ctx->device->coopmat_acc_f16_support && prec == GGML_PREC_DEFAULT) ? ctx->device->pipeline_dequant_mul_mat_mat[src0_type].f16acc : ctx->device->pipeline_dequant_mul_mat_mat[src0_type].f32acc; + } + return (ctx->device->fp16 && prec == GGML_PREC_DEFAULT) ? ctx->device->pipeline_dequant_mul_mat_mat[src0_type].f16acc : ctx->device->pipeline_dequant_mul_mat_mat[src0_type].f32acc; } -static vk_pipeline ggml_vk_get_dequantize_mul_mat_vec(ggml_backend_vk_context * ctx, ggml_type a_type, ggml_type b_type) { +static vk_pipeline ggml_vk_get_dequantize_mul_mat_vec(ggml_backend_vk_context * ctx, ggml_type a_type, ggml_type b_type, uint32_t num_cols) { VK_LOG_DEBUG("ggml_vk_get_dequantize_mul_mat_vec()"); GGML_ASSERT(b_type == GGML_TYPE_F32 || b_type == GGML_TYPE_F16); + GGML_ASSERT(num_cols >= 1 && num_cols <= mul_mat_vec_max_cols); switch (a_type) { case GGML_TYPE_F32: case GGML_TYPE_F16: + case GGML_TYPE_BF16: case GGML_TYPE_Q4_0: case GGML_TYPE_Q4_1: case GGML_TYPE_Q5_0: @@ -2220,28 +3928,48 @@ static vk_pipeline ggml_vk_get_dequantize_mul_mat_vec(ggml_backend_vk_context * case GGML_TYPE_Q4_K: case GGML_TYPE_Q5_K: case GGML_TYPE_Q6_K: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: break; default: return nullptr; } - return b_type == GGML_TYPE_F32 ? ctx->device->pipeline_dequant_mul_mat_vec_f32_f32[a_type] : ctx->device->pipeline_dequant_mul_mat_vec_f16_f32[a_type]; + return b_type == GGML_TYPE_F32 ? ctx->device->pipeline_dequant_mul_mat_vec_f32_f32[a_type][num_cols-1] : ctx->device->pipeline_dequant_mul_mat_vec_f16_f32[a_type][num_cols-1]; } -static vk_matmul_pipeline ggml_vk_get_mul_mat_mat_id_pipeline(ggml_backend_vk_context * ctx, ggml_type src0_type, ggml_type src1_type) { +static vk_matmul_pipeline ggml_vk_get_mul_mat_mat_id_pipeline(ggml_backend_vk_context * ctx, ggml_type src0_type, ggml_type src1_type, ggml_prec prec) { VK_LOG_DEBUG("ggml_vk_get_mul_mat_mat_id_pipeline()"); if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F32) { return ctx->device->pipeline_matmul_id_f32; } - if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) { - return ctx->device->pipeline_matmul_id_f16_f32; + if (src0_type == GGML_TYPE_BF16 && src1_type == GGML_TYPE_BF16) { + return ctx->device->pipeline_matmul_id_bf16; } - if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) { - return ctx->device->pipeline_matmul_id_f16; + if (prec == GGML_PREC_DEFAULT && ctx->device->fp16 && !(ctx->device->coopmat_support && !ctx->device->coopmat_acc_f16_support)) { + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) { + return ctx->device->pipeline_matmul_id_f16_f32.f16acc; + } + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) { + return ctx->device->pipeline_matmul_id_f16.f16acc; + } + } else { + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) { + return ctx->device->pipeline_matmul_id_f16_f32.f32acc; + } + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) { + return ctx->device->pipeline_matmul_id_f16.f32acc; + } } - GGML_ASSERT(src1_type == GGML_TYPE_F32); + GGML_ASSERT(src1_type == GGML_TYPE_F32 || (ctx->device->coopmat2 && src1_type == GGML_TYPE_F16)); switch (src0_type) { case GGML_TYPE_Q4_0: @@ -2254,13 +3982,21 @@ static vk_matmul_pipeline ggml_vk_get_mul_mat_mat_id_pipeline(ggml_backend_vk_co case GGML_TYPE_Q4_K: case GGML_TYPE_Q5_K: case GGML_TYPE_Q6_K: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: break; default: return nullptr; } - return ctx->device->pipeline_dequant_mul_mat_mat_id[src0_type]; + return ctx->device->fp16 ? ctx->device->pipeline_dequant_mul_mat_mat_id[src0_type].f16acc : ctx->device->pipeline_dequant_mul_mat_mat_id[src0_type].f32acc; } static vk_pipeline ggml_vk_get_dequantize_mul_mat_vec_id(ggml_backend_vk_context * ctx, ggml_type a_type, ggml_type b_type) { @@ -2270,6 +4006,7 @@ static vk_pipeline ggml_vk_get_dequantize_mul_mat_vec_id(ggml_backend_vk_context switch (a_type) { case GGML_TYPE_F32: case GGML_TYPE_F16: + case GGML_TYPE_BF16: case GGML_TYPE_Q4_0: case GGML_TYPE_Q4_1: case GGML_TYPE_Q5_0: @@ -2280,6 +4017,14 @@ static vk_pipeline ggml_vk_get_dequantize_mul_mat_vec_id(ggml_backend_vk_context case GGML_TYPE_Q4_K: case GGML_TYPE_Q5_K: case GGML_TYPE_Q6_K: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: break; default: @@ -2368,6 +4113,7 @@ static void * ggml_vk_host_malloc(vk_device& device, size_t size) { return nullptr; } + std::lock_guard guard(device->mutex); device->pinned_memory.push_back(std::make_tuple(buf->ptr, size, buf)); return buf->ptr; @@ -2378,6 +4124,8 @@ static void ggml_vk_host_free(vk_device& device, void* ptr) { return; } VK_LOG_MEMORY("ggml_vk_host_free(" << ptr << ")"); + std::lock_guard guard(device->mutex); + vk_buffer buf; size_t index; for (size_t i = 0; i < device->pinned_memory.size(); i++) { @@ -2400,6 +4148,7 @@ static void ggml_vk_host_free(vk_device& device, void* ptr) { } static void ggml_vk_host_get(vk_device& device, const void * ptr, vk_buffer& buf, size_t& buf_offset) { + std::lock_guard guard(device->mutex); buf = nullptr; buf_offset = 0; for (size_t i = 0; i < device->pinned_memory.size(); i++) { @@ -2413,9 +4162,9 @@ static void ggml_vk_host_get(vk_device& device, const void * ptr, vk_buffer& buf } } -static vk_submission ggml_vk_begin_submission(vk_device& device, vk_queue& q, bool one_time = true) { +static vk_submission ggml_vk_begin_submission(vk_device& device, vk_command_pool& p, bool one_time = true) { vk_submission s; - s.buffer = ggml_vk_create_cmd_buffer(device, q); + s.buffer = ggml_vk_create_cmd_buffer(device, p); if (one_time) { s.buffer.begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit }); } else { @@ -2425,21 +4174,19 @@ static vk_submission ggml_vk_begin_submission(vk_device& device, vk_queue& q, bo return s; } - - static void ggml_vk_dispatch_pipeline(ggml_backend_vk_context* ctx, vk_context& subctx, vk_pipeline& pipeline, std::initializer_list const& descriptor_buffer_infos, size_t push_constant_size, const void* push_constants, std::array elements) { const uint32_t wg0 = CEIL_DIV(elements[0], pipeline->wg_denoms[0]); const uint32_t wg1 = CEIL_DIV(elements[1], pipeline->wg_denoms[1]); const uint32_t wg2 = CEIL_DIV(elements[2], pipeline->wg_denoms[2]); VK_LOG_DEBUG("ggml_vk_dispatch_pipeline(" << pipeline->name << ", {"; for (auto& buffer : descriptor_buffer_infos) { - std::cerr << "(" << buffer << ", " << buffer.offset << ", " << buffer.size << "), "; + std::cerr << "(" << buffer.buffer << ", " << buffer.offset << ", " << buffer.range << "), "; } std::cerr << "}, (" << wg0 << "," << wg1 << "," << wg2 << "))"); - GGML_ASSERT(pipeline->descriptor_set_idx < pipeline->descriptor_sets.size()); - GGML_ASSERT(descriptor_buffer_infos.size() == pipeline->parameter_count); + GGML_ASSERT(ctx->descriptor_set_idx < ctx->descriptor_sets.size()); + GGML_ASSERT(descriptor_buffer_infos.size() <= MAX_PARAMETER_COUNT); - vk::DescriptorSet& descriptor_set = pipeline->descriptor_sets[pipeline->descriptor_set_idx++]; + vk::DescriptorSet& descriptor_set = ctx->descriptor_sets[ctx->descriptor_set_idx++]; vk::WriteDescriptorSet write_descriptor_set{ descriptor_set, 0, 0, pipeline->parameter_count, vk::DescriptorType::eStorageBuffer, nullptr, descriptor_buffer_infos.begin() }; ctx->device->device.updateDescriptorSets({ write_descriptor_set }, {}); @@ -2476,7 +4223,7 @@ static void ggml_vk_ctx_begin(vk_device& device, vk_context& subctx) { ggml_vk_ctx_end(subctx); } - subctx->seqs.push_back({ ggml_vk_begin_submission(device, *subctx->q) }); + subctx->seqs.push_back({ ggml_vk_begin_submission(device, *subctx->p) }); subctx->s = subctx->seqs[subctx->seqs.size() - 1].data(); } @@ -2512,8 +4259,8 @@ static void ggml_vk_buffer_write_nc_async(ggml_backend_vk_context * ctx, vk_cont GGML_ABORT("fatal error"); } // Check if src is pinned memory - vk_buffer buf; - size_t buf_offset; + vk_buffer buf = nullptr; + size_t buf_offset = 0; ggml_vk_host_get(ctx->device, tensor->data, buf, buf_offset); const uint64_t ne0 = tensor->ne[0]; @@ -2565,39 +4312,31 @@ static void ggml_vk_buffer_write_nc_async(ggml_backend_vk_context * ctx, vk_cont return; } - // Staging buffer required - vk_buffer staging = ctx->staging; - size_t staging_offset = ctx->staging_offset; - const size_t copy_size = ts*ne/bs; - if (ctx->staging->size < ctx->staging_offset + copy_size) { - if (sync_staging) { - // Create temporary larger buffer - ggml_vk_ensure_sync_staging_buffer(ctx->device, copy_size); - - staging = ctx->device->sync_staging; - staging_offset = 0; - } else { - GGML_ABORT("fatal error"); - } + if (!sync_staging) { + GGML_ABORT("Asynchronous write to non-pinned memory not supported"); } - VkBufferCopy buf_copy{ staging_offset, offset, copy_size }; + // Staging buffer required + vk_buffer& staging = ctx->device->sync_staging; + const uint64_t copy_size = ts*ne/bs; + ggml_vk_ensure_sync_staging_buffer(ctx->device, copy_size); + VkBufferCopy buf_copy{ 0, offset, copy_size }; ggml_vk_sync_buffers(subctx); - vkCmdCopyBuffer(subctx->s->buffer, staging->buffer, dst->buffer, 1, &buf_copy); + vkCmdCopyBuffer(subctx->s->buffer, (VkBuffer)staging->buffer, (VkBuffer)dst->buffer, 1, &buf_copy); for (uint64_t i3 = 0; i3 < ne3; i3++) { for (uint64_t i2 = 0; i2 < ne2; i2++) { // Find longest contiguous slice if (ne1*nb1 == dstnb2) { - deferred_memcpy((uint8_t *)staging->ptr + staging_offset + i3*dstnb3 + i2*dstnb2, (const uint8_t *) tensor->data + buf_offset + i3*nb3 + i2*nb2, dstnb2, &subctx->in_memcpys); + deferred_memcpy((uint8_t *)staging->ptr + i3*dstnb3 + i2*dstnb2, (const uint8_t *) tensor->data + buf_offset + i3*nb3 + i2*nb2, dstnb2, &subctx->in_memcpys); } else { for (uint64_t i1 = 0; i1 < ne1; i1++) { if (ne0*nb0/bs == dstnb1) { - deferred_memcpy((uint8_t *)staging->ptr + staging_offset + i3*dstnb3 + i2*dstnb2 + i1*dstnb1, (const uint8_t *) tensor->data + buf_offset + i3*nb3 + i2*nb2 + i1*nb1, dstnb1, &subctx->in_memcpys); + deferred_memcpy((uint8_t *)staging->ptr + i3*dstnb3 + i2*dstnb2 + i1*dstnb1, (const uint8_t *) tensor->data + buf_offset + i3*nb3 + i2*nb2 + i1*nb1, dstnb1, &subctx->in_memcpys); } else { const uint64_t s_off = buf_offset + i3*nb3 + i2*nb2 + i1*nb1; - const uint64_t d_off = staging_offset + i3*dstnb3 + i2*dstnb2 + i1*dstnb1; + const uint64_t d_off = i3*dstnb3 + i2*dstnb2 + i1*dstnb1; for (uint64_t i0 = 0; i0 < ne0; i0++) { deferred_memcpy((uint8_t *)staging->ptr + d_off + i0*dstnb0, (const uint8_t *) tensor->data + s_off + i0*nb0, dstnb0, &subctx->in_memcpys); } @@ -2608,7 +4347,7 @@ static void ggml_vk_buffer_write_nc_async(ggml_backend_vk_context * ctx, vk_cont } } -static void ggml_vk_buffer_write_2d_async(vk_context subctx, vk_buffer& dst, size_t offset, const void * src, size_t spitch, size_t width, size_t height, vk_buffer staging_buffer, size_t staging_offset, bool sync_staging = false) { +static void ggml_vk_buffer_write_2d_async(vk_context subctx, vk_buffer& dst, size_t offset, const void * src, size_t spitch, size_t width, size_t height, bool sync_staging = false) { VK_LOG_DEBUG("ggml_vk_buffer_write_2d_async(" << width << ", " << height << ")"); // Buffer is already mapped if(dst->memory_property_flags & vk::MemoryPropertyFlagBits::eHostVisible) { @@ -2617,7 +4356,7 @@ static void ggml_vk_buffer_write_2d_async(vk_context subctx, vk_buffer& dst, siz } // Check if src is pinned memory vk_buffer buf = nullptr; - size_t buf_offset; + size_t buf_offset = 0; ggml_vk_host_get(dst->device, src, buf, buf_offset); if (buf != nullptr) { @@ -2643,39 +4382,36 @@ static void ggml_vk_buffer_write_2d_async(vk_context subctx, vk_buffer& dst, siz } VK_LOG_DEBUG("STAGING"); - // Staging buffer required - const size_t copy_size = width*height; - if (staging_buffer == nullptr || staging_buffer->size < staging_offset + copy_size) { - if (sync_staging) { - ggml_vk_ensure_sync_staging_buffer(dst->device, copy_size); - - staging_buffer = dst->device->sync_staging; - staging_offset = 0; - } else { - GGML_ABORT("fatal error"); - } + if (!sync_staging) { + GGML_ABORT("Asynchronous write to non-pinned memory not supported"); } + // Staging buffer required + const size_t copy_size = width*height; + ggml_vk_ensure_sync_staging_buffer(dst->device, copy_size); + + vk_buffer& staging_buffer = dst->device->sync_staging; + VkBufferCopy buf_copy = { - staging_offset, + 0, offset, copy_size}; ggml_vk_sync_buffers(subctx); - vkCmdCopyBuffer(subctx->s->buffer, staging_buffer->buffer, dst->buffer, 1, &buf_copy); + vkCmdCopyBuffer(subctx->s->buffer, (VkBuffer)staging_buffer->buffer, (VkBuffer)dst->buffer, 1, &buf_copy); if (width == spitch) { - deferred_memcpy((uint8_t *)staging_buffer->ptr + staging_offset, src, width * height, &subctx->in_memcpys); + deferred_memcpy((uint8_t *)staging_buffer->ptr, src, width * height, &subctx->in_memcpys); } else { for (size_t i = 0; i < height; i++) { - deferred_memcpy((uint8_t *)staging_buffer->ptr + staging_offset + i * width, (const uint8_t *) src + i * spitch, width, &subctx->in_memcpys); + deferred_memcpy((uint8_t *)staging_buffer->ptr + i * width, (const uint8_t *) src + i * spitch, width, &subctx->in_memcpys); } } } -static void ggml_vk_buffer_write_async(vk_context subctx, vk_buffer& dst, size_t offset, const void * src, size_t size, vk_buffer staging_buffer, size_t staging_offset, bool sync_staging = false) { +static void ggml_vk_buffer_write_async(vk_context subctx, vk_buffer& dst, size_t offset, const void * src, size_t size, bool sync_staging = false) { VK_LOG_DEBUG("ggml_vk_buffer_write_async(" << size << ")"); - return ggml_vk_buffer_write_2d_async(subctx, dst, offset, src, size, size, 1, staging_buffer, staging_offset, sync_staging); + return ggml_vk_buffer_write_2d_async(subctx, dst, offset, src, size, size, 1, sync_staging); } static void ggml_vk_buffer_write_2d(vk_buffer& dst, size_t offset, const void * src, size_t spitch, size_t width, size_t height) { @@ -2688,9 +4424,11 @@ static void ggml_vk_buffer_write_2d(vk_buffer& dst, size_t offset, const void * memcpy((uint8_t *)dst->ptr + offset + i * width, (const uint8_t *) src + i * spitch, width); } } else { - vk_context subctx = ggml_vk_create_temporary_context(dst->device->transfer_queue); + std::lock_guard guard(dst->device->mutex); + + vk_context subctx = ggml_vk_create_temporary_context(dst->device->transfer_queue.cmd_pool); ggml_vk_ctx_begin(dst->device, subctx); - ggml_vk_buffer_write_2d_async(subctx, dst, offset, src, spitch, width, height, nullptr, 0, true); + ggml_vk_buffer_write_2d_async(subctx, dst, offset, src, spitch, width, height, true); ggml_vk_ctx_end(subctx); for (auto& cpy : subctx->in_memcpys) { @@ -2700,6 +4438,7 @@ static void ggml_vk_buffer_write_2d(vk_buffer& dst, size_t offset, const void * ggml_vk_submit(subctx, dst->device->fence); VK_CHECK(dst->device->device.waitForFences({ dst->device->fence }, true, UINT64_MAX), "vk_buffer_write_2d waitForFences"); dst->device->device.resetFences({ dst->device->fence }); + ggml_vk_queue_command_pools_cleanup(dst->device); } } @@ -2708,7 +4447,7 @@ static void ggml_vk_buffer_write(vk_buffer& dst, size_t offset, const void * src ggml_vk_buffer_write_2d(dst, offset, src, 0, size, 1); } -static void ggml_vk_buffer_read_2d_async(vk_context subctx, vk_buffer& src, size_t offset, void * dst, size_t spitch, size_t dpitch, size_t width, size_t height, vk_buffer staging_buffer, size_t staging_offset, bool sync_staging = false) { +static void ggml_vk_buffer_read_2d_async(vk_context subctx, vk_buffer& src, size_t offset, void * dst, size_t spitch, size_t dpitch, size_t width, size_t height, bool sync_staging = false) { VK_LOG_DEBUG("ggml_vk_buffer_read_2d_async(offset=" << offset << ", width=" << width << ", height=" << height << ")"); GGML_ASSERT(width > 0); GGML_ASSERT(height > 0); @@ -2718,7 +4457,7 @@ static void ggml_vk_buffer_read_2d_async(vk_context subctx, vk_buffer& src, size // Check if dst is pinned memory vk_buffer buf = nullptr; - size_t buf_offset; + size_t buf_offset = 0; ggml_vk_host_get(src->device, dst, buf, buf_offset); std::vector slices(1); @@ -2745,18 +4484,15 @@ static void ggml_vk_buffer_read_2d_async(vk_context subctx, vk_buffer& src, size } VK_LOG_DEBUG("STAGING"); + if (!sync_staging) { + GGML_ABORT("Asynchronous read from non-pinned memory not supported"); + } + // Fall back to staging buffer const size_t copy_size = dpitch * height; - if (staging_buffer == nullptr || staging_buffer->size < staging_offset + copy_size) { - if (sync_staging) { - // Create temporary larger buffer - ggml_vk_ensure_sync_staging_buffer(src->device, copy_size); + ggml_vk_ensure_sync_staging_buffer(src->device, copy_size); - staging_buffer = src->device->sync_staging; - } else { - GGML_ABORT("fatal error"); - } - } + vk_buffer& staging_buffer = src->device->sync_staging; ggml_vk_sync_buffers(subctx); subctx->s->buffer.copyBuffer(src->buffer, staging_buffer->buffer, slices); @@ -2764,25 +4500,32 @@ static void ggml_vk_buffer_read_2d_async(vk_context subctx, vk_buffer& src, size deferred_memcpy(dst, staging_buffer->ptr, copy_size, &subctx->out_memcpys); } -static void ggml_vk_buffer_read_async(vk_context subctx, vk_buffer& src, size_t offset, void * dst, size_t size, vk_buffer staging_buffer, size_t staging_offset, bool sync_staging = false) { - return ggml_vk_buffer_read_2d_async(subctx, src, offset, dst, size, size, size, 1, staging_buffer, staging_offset, sync_staging); +static void ggml_vk_buffer_read_async(vk_context subctx, vk_buffer& src, size_t offset, void * dst, size_t size, bool sync_staging = false) { + return ggml_vk_buffer_read_2d_async(subctx, src, offset, dst, size, size, size, 1, sync_staging); } static void ggml_vk_buffer_read(vk_buffer& src, size_t offset, void * dst, size_t size) { VK_LOG_DEBUG("ggml_vk_buffer_read(" << src->buffer << ", " << offset << ", " << size << ")"); - if(src->memory_property_flags & vk::MemoryPropertyFlagBits::eHostVisible) { + + // If the device is not an UMA device the memory is host-accessible through rebar. While writing + // through PCIe is sufficient fast reading back data from PCIe is slower than going through + // the HW device to host copy path. + if(src->memory_property_flags & vk::MemoryPropertyFlagBits::eHostVisible && src->device->uma) { GGML_ASSERT(src->memory_property_flags & vk::MemoryPropertyFlagBits::eHostCoherent); memcpy(dst, (uint8_t *) src->ptr + offset, size); } else { - vk_context subctx = ggml_vk_create_temporary_context(src->device->transfer_queue); + std::lock_guard guard(src->device->mutex); + + vk_context subctx = ggml_vk_create_temporary_context(src->device->transfer_queue.cmd_pool); ggml_vk_ctx_begin(src->device, subctx); - ggml_vk_buffer_read_async(subctx, src, offset, dst, size, nullptr, 0, true); + ggml_vk_buffer_read_async(subctx, src, offset, dst, size, true); ggml_vk_ctx_end(subctx); ggml_vk_submit(subctx, src->device->fence); VK_CHECK(src->device->device.waitForFences({ src->device->fence }, true, UINT64_MAX), "vk_buffer_read waitForFences"); src->device->device.resetFences({ src->device->fence }); + ggml_vk_queue_command_pools_cleanup(src->device); for (auto& cpy : subctx->out_memcpys) { memcpy(cpy.dst, cpy.src, cpy.n); @@ -2797,20 +4540,22 @@ static void ggml_vk_buffer_copy_async(vk_context& ctx, vk_buffer& dst, size_t ds VkBufferCopy bc{ src_offset, dst_offset, size }; - vkCmdCopyBuffer(ctx->s->buffer, src->buffer, dst->buffer, 1, &bc); + vkCmdCopyBuffer(ctx->s->buffer, (VkBuffer)src->buffer, (VkBuffer)dst->buffer, 1, &bc); } static void ggml_vk_buffer_copy(vk_buffer& dst, size_t dst_offset, vk_buffer& src, size_t src_offset, size_t size) { if (src->device == dst->device) { + std::lock_guard guard(src->device->mutex); VK_LOG_DEBUG("ggml_vk_buffer_copy(SINGLE_DEVICE, " << size << ")"); // Copy within the device - vk_context subctx = ggml_vk_create_temporary_context(src->device->transfer_queue); + vk_context subctx = ggml_vk_create_temporary_context(src->device->transfer_queue.cmd_pool); ggml_vk_ctx_begin(src->device, subctx); ggml_vk_buffer_copy_async(subctx, dst, dst_offset, src, src_offset, size); ggml_vk_ctx_end(subctx); ggml_vk_submit(subctx, src->device->fence); VK_CHECK(src->device->device.waitForFences({ src->device->fence }, true, UINT64_MAX), "vk_buffer_copy waitForFences"); src->device->device.resetFences({ src->device->fence }); + ggml_vk_queue_command_pools_cleanup(src->device); } else { VK_LOG_DEBUG("ggml_vk_buffer_copy(MULTI_DEVICE, " << size << ")"); // Copy device to device @@ -2826,10 +4571,17 @@ static void ggml_vk_buffer_copy(vk_buffer& dst, size_t dst_offset, vk_buffer& sr } } +static void ggml_vk_buffer_memset_async(vk_context& ctx, vk_buffer& dst, size_t offset, uint32_t c, size_t size) { + VK_LOG_DEBUG("ggml_vk_buffer_memset_async(" << offset << ", " << c << ", " << size << ")"); + + ctx->s->buffer.fillBuffer(dst->buffer, offset, size, c); +} + static void ggml_vk_buffer_memset(vk_buffer& dst, size_t offset, uint32_t c, size_t size) { VK_LOG_DEBUG("ggml_vk_buffer_memset(" << offset << ", " << c << ", " << size << ")"); - vk_context subctx = ggml_vk_create_temporary_context(dst->device->transfer_queue); + std::lock_guard guard(dst->device->mutex); + vk_context subctx = ggml_vk_create_temporary_context(dst->device->transfer_queue.cmd_pool); ggml_vk_ctx_begin(dst->device, subctx); subctx->s->buffer.fillBuffer(dst->buffer, offset, size, c); ggml_vk_ctx_end(subctx); @@ -2837,65 +4589,67 @@ static void ggml_vk_buffer_memset(vk_buffer& dst, size_t offset, uint32_t c, siz ggml_vk_submit(subctx, dst->device->fence); VK_CHECK(dst->device->device.waitForFences({ dst->device->fence }, true, UINT64_MAX), "vk_memset waitForFences"); dst->device->device.resetFences({ dst->device->fence }); + ggml_vk_queue_command_pools_cleanup(dst->device); } -static uint32_t ggml_vk_guess_split_k(int m, int n, int k) { +static uint32_t ggml_vk_guess_split_k(ggml_backend_vk_context * ctx, int m, int n, int k, const vk_pipeline& pipeline) { VK_LOG_DEBUG("ggml_vk_guess_split_k(" << m << ", " << n << ", " << k << ")"); - // if (k > 128 && (m < 128 || n < 128) && m > 2 && n > 2) { - // return 4; - // } - return 1; + uint32_t split_k = 1; + if (ctx->device->shader_core_count != 0 && m >= (int)pipeline->wg_denoms[0] && n >= (int)pipeline->wg_denoms[1]) { + // If k is 'large' and the SMs will fill less than halfway, use split_k. + uint32_t m_tiles = CEIL_DIV(m, pipeline->wg_denoms[0]); + uint32_t n_tiles = CEIL_DIV(n, pipeline->wg_denoms[1]); + if (k >= 2048 && m_tiles * n_tiles < ctx->device->shader_core_count / 2) { + split_k = ctx->device->shader_core_count / (m_tiles * n_tiles); + // Clamp to 2 or 4 + split_k = std::min(split_k, 4u); + if (split_k == 3) { + split_k = 2; + } + if (ctx->device->coopmat2) { + // coopmat2 shader expects splits to be aligned to 256 + while (split_k > 1 && ((k / split_k) % 256) != 0) { + split_k /= 2; + } + } + } + } - GGML_UNUSED(m); GGML_UNUSED(n); GGML_UNUSED(k); + return split_k; } -static vk_pipeline ggml_vk_guess_matmul_pipeline_amd(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, int m, int n, bool aligned) { - if (m <= 32 || n <= 32) { +static vk_pipeline ggml_vk_guess_matmul_pipeline(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, uint32_t m, uint32_t n, bool aligned, ggml_type src0_type, ggml_type src1_type) { + VK_LOG_DEBUG("ggml_vk_guess_matmul_pipeline(" << m << ", " << n << ", " << aligned << ", " << ggml_type_name(src0_type) << ", " << ggml_type_name(src1_type) << ")"); + + if (ctx->device->coopmat2) { + // Use large shader when the N dimension is greater than the medium shader's tile size + uint32_t crossover_large = mmp->m->wg_denoms[1]; + if ((ctx->device->mul_mat_l[src0_type] && (n > crossover_large)) || (!ctx->device->mul_mat_m[src0_type] && !ctx->device->mul_mat_s[src0_type])) { + return aligned ? mmp->a_l : mmp->l; + } + // Use medium shader when the N dimension is greater than the small shader's tile size + uint32_t crossover_medium = mmp->s->wg_denoms[1]; + if ((ctx->device->mul_mat_m[src0_type] && (n > crossover_medium)) || !ctx->device->mul_mat_s[src0_type]) { + return aligned ? mmp->a_m : mmp->m; + } return aligned ? mmp->a_s : mmp->s; } - return aligned ? mmp->a_m : mmp->m; - GGML_UNUSED(ctx); -} - -static vk_pipeline ggml_vk_guess_matmul_pipeline_apple(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, bool aligned) { - return aligned ? mmp->a_m : mmp->m; - - GGML_UNUSED(ctx); -} - -static vk_pipeline ggml_vk_guess_matmul_pipeline_intel(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, bool aligned) { - return aligned ? mmp->a_s : mmp->s; - - GGML_UNUSED(ctx); -} - -static vk_pipeline ggml_vk_guess_matmul_pipeline(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, int m, int n, bool aligned) { - VK_LOG_DEBUG("ggml_vk_guess_matmul_pipeline(" << m << ", " << n << ", " << aligned << ")"); - switch (ctx->device->vendor_id) { - case VK_VENDOR_ID_AMD: - return ggml_vk_guess_matmul_pipeline_amd(ctx, mmp, m, n, aligned); - case VK_VENDOR_ID_APPLE: - return ggml_vk_guess_matmul_pipeline_apple(ctx, mmp, aligned); - case VK_VENDOR_ID_INTEL: - return ggml_vk_guess_matmul_pipeline_intel(ctx, mmp, aligned); - default: - break; - } - - if (m <= 32 || n <= 32) { + if ((ctx->device->mul_mat_s[src0_type] && (m <= 32 || n <= 32)) || (!ctx->device->mul_mat_m[src0_type] && !ctx->device->mul_mat_l[src0_type])) { return aligned ? mmp->a_s : mmp->s; } - if (m <= 64 || n <= 64) { + if ((ctx->device->mul_mat_m[src0_type] && (m <= 64 || n <= 64)) || !ctx->device->mul_mat_l[src0_type]) { return aligned ? mmp->a_m : mmp->m; } return aligned ? mmp->a_l : mmp->l; + + GGML_UNUSED(src1_type); } -static uint32_t ggml_vk_guess_matmul_pipeline_align(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, int m, int n) { - VK_LOG_DEBUG("ggml_vk_guess_matmul_pipeline_align(" << m << ", " << n << ")"); - return ggml_vk_guess_matmul_pipeline(ctx, mmp, m, n, true)->align; +static uint32_t ggml_vk_guess_matmul_pipeline_align(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, int m, int n, ggml_type src0_type, ggml_type src1_type) { + VK_LOG_DEBUG("ggml_vk_guess_matmul_pipeline_align(" << m << ", " << n << ", " << ggml_type_name(src0_type) << ", " << ggml_type_name(src1_type) << ")"); + return ggml_vk_guess_matmul_pipeline(ctx, mmp, m, n, true, src0_type, src1_type)->align; } static void ggml_vk_matmul( @@ -2903,18 +4657,19 @@ static void ggml_vk_matmul( vk_subbuffer&& a, vk_subbuffer&& b, vk_subbuffer&& d, vk_subbuffer&& split_k_buffer, uint32_t m, uint32_t n, uint32_t k, uint32_t stride_a, uint32_t stride_b, uint32_t stride_d, uint32_t batch_stride_a, uint32_t batch_stride_b, uint32_t batch_stride_d, - uint32_t split_k, uint32_t batch, uint32_t ne02, uint32_t ne12, uint32_t broadcast2, uint32_t broadcast3) { - VK_LOG_DEBUG("ggml_vk_matmul(a: (" << a.buffer->buffer << ", " << a.offset << ", " << a.size << "), b: (" << b.buffer->buffer << ", " << b.offset << ", " << b.size << "), d: (" << d.buffer->buffer << ", " << d.offset << ", " << d.size << "), split_k: (" << (split_k_buffer.buffer != nullptr ? split_k_buffer.buffer->buffer : VK_NULL_HANDLE) << ", " << split_k_buffer.offset << ", " << split_k_buffer.size << "), m: " << m << ", n: " << n << ", k: " << k << ", stride_a: " << stride_a << ", stride_b: " << stride_b << ", stride_d: " << stride_d << ", batch_stride_a: " << batch_stride_a << ", batch_stride_b: " << batch_stride_b << ", batch_stride_d: " << batch_stride_d << ", split_k: " << split_k << ", batch: " << batch << ", ne02: " << ne02 << ", ne12: " << ne12 << ", broadcast2: " << broadcast2 << ", broadcast3: " << broadcast3 << ")"); + uint32_t split_k, uint32_t batch, uint32_t ne02, uint32_t ne12, uint32_t broadcast2, uint32_t broadcast3, + uint32_t padded_n) { + VK_LOG_DEBUG("ggml_vk_matmul(a: (" << a.buffer->buffer << ", " << a.offset << ", " << a.size << "), b: (" << b.buffer->buffer << ", " << b.offset << ", " << b.size << "), d: (" << d.buffer->buffer << ", " << d.offset << ", " << d.size << "), split_k: (" << (split_k_buffer.buffer != nullptr ? split_k_buffer.buffer->buffer : VK_NULL_HANDLE) << ", " << split_k_buffer.offset << ", " << split_k_buffer.size << "), m: " << m << ", n: " << n << ", k: " << k << ", stride_a: " << stride_a << ", stride_b: " << stride_b << ", stride_d: " << stride_d << ", batch_stride_a: " << batch_stride_a << ", batch_stride_b: " << batch_stride_b << ", batch_stride_d: " << batch_stride_d << ", split_k: " << split_k << ", batch: " << batch << ", ne02: " << ne02 << ", ne12: " << ne12 << ", broadcast2: " << broadcast2 << ", broadcast3: " << broadcast3 << ", padded_n: " << padded_n << ")"); ggml_vk_sync_buffers(subctx); if (split_k == 1) { - const vk_mat_mat_push_constants pc = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, k, ne02, ne12, broadcast2, broadcast3 }; + const vk_mat_mat_push_constants pc = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, k, ne02, ne12, broadcast2, broadcast3, padded_n }; ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, d }, sizeof(vk_mat_mat_push_constants), &pc, { m, n, batch }); return; } GGML_ASSERT(batch_stride_d == m * n); - const vk_mat_mat_push_constants pc1 = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, CEIL_DIV(k, split_k), ne02, ne12, broadcast2, broadcast3 }; + const vk_mat_mat_push_constants pc1 = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, CEIL_DIV(k, split_k), ne02, ne12, broadcast2, broadcast3, padded_n }; // Make sure enough workgroups get assigned for split k to work ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, split_k_buffer }, sizeof(vk_mat_mat_push_constants), &pc1, { (CEIL_DIV(m, pipeline->wg_denoms[0]) * pipeline->wg_denoms[0]) * split_k, n, batch }); ggml_vk_sync_buffers(subctx); @@ -2922,19 +4677,51 @@ static void ggml_vk_matmul( ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_matmul_split_k_reduce, { split_k_buffer, d }, pc2.size() * sizeof(uint32_t), pc2.data(), { m * n * batch, 1, 1 }); } +static vk_pipeline ggml_vk_guess_matmul_id_pipeline(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, uint32_t m, uint32_t n, bool aligned, ggml_type src0_type) { + VK_LOG_DEBUG("ggml_vk_guess_matmul_id_pipeline(" << m << ", " << n << ", " << aligned << ", " << ggml_type_name(src0_type) << ")"); + + if (ctx->device->coopmat2) { + // Use large shader when the N dimension is greater than the medium shader's tile size + uint32_t crossover_large = mmp->m->wg_denoms[1]; + if ((ctx->device->mul_mat_id_l[src0_type] && (n > crossover_large)) || (!ctx->device->mul_mat_id_m[src0_type] && !ctx->device->mul_mat_id_s[src0_type])) { + return aligned ? mmp->a_l : mmp->l; + } + // Use medium shader when the N dimension is greater than the small shader's tile size + uint32_t crossover_medium = mmp->s->wg_denoms[1]; + if ((ctx->device->mul_mat_id_m[src0_type] && (n > crossover_medium)) || !ctx->device->mul_mat_id_s[src0_type]) { + return aligned ? mmp->a_m : mmp->m; + } + return aligned ? mmp->a_s : mmp->s; + } + + if ((ctx->device->mul_mat_id_s[src0_type] && (m <= 32 || n <= 32)) || (!ctx->device->mul_mat_id_m[src0_type] && !ctx->device->mul_mat_id_l[src0_type])) { + return aligned ? mmp->a_s : mmp->s; + } + if ((ctx->device->mul_mat_id_m[src0_type] && (m <= 64 || n <= 64)) || !ctx->device->mul_mat_id_l[src0_type]) { + return aligned ? mmp->a_m : mmp->m; + } + return aligned ? mmp->a_l : mmp->l; +} + +static uint32_t ggml_vk_guess_matmul_id_pipeline_align(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, int m, int n, ggml_type src0_type) { + VK_LOG_DEBUG("ggml_vk_guess_matmul_pipeline_align(" << m << ", " << n << ", " << ggml_type_name(src0_type) << ")"); + return ggml_vk_guess_matmul_id_pipeline(ctx, mmp, m, n, true, src0_type)->align; +} + static void ggml_vk_matmul_id( ggml_backend_vk_context * ctx, vk_context& subctx, vk_pipeline& pipeline, vk_subbuffer&& a, vk_subbuffer&& b, vk_subbuffer&& d, vk_subbuffer&& ids, uint32_t m, uint32_t n, uint32_t k, uint32_t stride_a, uint32_t stride_b, uint32_t stride_d, uint32_t batch_stride_a, uint32_t batch_stride_b, uint32_t batch_stride_d, - uint32_t n_as, uint32_t nei0, uint32_t nei1, uint32_t nbi1, uint32_t ne11) { + uint32_t n_as, uint32_t nei0, uint32_t nei1, uint32_t nbi1, uint32_t ne11, + uint32_t padded_n) { VK_LOG_DEBUG("ggml_vk_matmul_id(a: (" << a.buffer->buffer << ", " << a.offset << ", " << a.size << "), b: (" << b.buffer->buffer << ", " << b.offset << ", " << b.size << "), d: (" << d.buffer->buffer << ", " << d.offset << ", " << d.size << "), ids: (" << ids.buffer->buffer << ", " << ids.offset << ", " << ids.size << "), " << "m: " << m << ", n: " << n << ", k: " << k << ", stride_a: " << stride_a << ", stride_b: " << stride_b << ", stride_d: " << stride_d << ", " << "batch_stride_a: " << batch_stride_a << ", batch_stride_b: " << batch_stride_b << ", batch_stride_d: " << batch_stride_d << ", " << "n_as: " << n_as << ", nei0: " << nei0 << ", nei1: " << nei1 << ", nbi1: " << nbi1 << ", ne11: " << ne11 << ")"); ggml_vk_sync_buffers(subctx); const vk_mat_mat_id_push_constants pc = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, - nei0, nei1, nbi1, ne11 }; + nei0, nei1, nbi1, ne11, padded_n }; ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, d, ids }, sizeof(vk_mat_mat_id_push_constants), &pc, { m, nei1, n_as }); } @@ -2945,18 +4732,96 @@ static bool ggml_vk_dim01_contiguous(const ggml_tensor * tensor) { tensor->nb[3] == tensor->nb[2]*tensor->ne[2]; } -static vk_pipeline ggml_vk_get_cpy_pipeline(ggml_backend_vk_context * ctx, ggml_type from, ggml_type to) { - if (from == GGML_TYPE_F32 && to == GGML_TYPE_F32) { - return ctx->device->pipeline_cpy_f32_f32; +static vk_pipeline ggml_vk_get_cpy_pipeline(ggml_backend_vk_context * ctx, const ggml_tensor * src, const ggml_tensor * dst, ggml_type to) { + + // Choose "contiguous copy" shader if src/dst are contiguous + bool contig = ggml_is_contiguous(src) && (!dst || ggml_is_contiguous(dst)); + + if (src->type == GGML_TYPE_F32 && to == GGML_TYPE_F32) { + if (contig) { + return ctx->device->pipeline_contig_cpy_f32_f32; + } else { + return ctx->device->pipeline_cpy_f32_f32; + } } - if (from == GGML_TYPE_F32 && to == GGML_TYPE_F16) { - return ctx->device->pipeline_cpy_f32_f16; + if (src->type == GGML_TYPE_F32 && to == GGML_TYPE_F16) { + if (contig) { + return ctx->device->pipeline_contig_cpy_f32_f16; + } else { + return ctx->device->pipeline_cpy_f32_f16; + } } - if (from == GGML_TYPE_F16 && to == GGML_TYPE_F16) { - return ctx->device->pipeline_cpy_f16_f16; + if (src->type == GGML_TYPE_F16 && to == GGML_TYPE_F16) { + if (contig) { + return ctx->device->pipeline_contig_cpy_f16_f16; + } else { + return ctx->device->pipeline_cpy_f16_f16; + } + } + if (src->type == GGML_TYPE_F16 && to == GGML_TYPE_F32) { + if (contig) { + return ctx->device->pipeline_contig_cpy_f16_f32; + } else { + return ctx->device->pipeline_cpy_f16_f32; + } + } + if (src->type == GGML_TYPE_F32 && to == GGML_TYPE_BF16) { + if (contig) { + return ctx->device->pipeline_contig_cpy_f32_bf16; + } else { + return ctx->device->pipeline_cpy_f32_bf16; + } + } + if (src->type == GGML_TYPE_F32) { + switch (to) { + case GGML_TYPE_Q4_0: + case GGML_TYPE_Q4_1: + case GGML_TYPE_Q5_0: + case GGML_TYPE_Q5_1: + case GGML_TYPE_Q8_0: + case GGML_TYPE_IQ4_NL: + return ctx->device->pipeline_cpy_f32_quant[to]; + default: + break; + } } - std::cerr << "Missing CPY op for types: " << ggml_type_name(from) << " " << ggml_type_name(to) << std::endl; + if (to == GGML_TYPE_F32) { + switch (src->type) { + case GGML_TYPE_Q4_0: + case GGML_TYPE_Q4_1: + case GGML_TYPE_Q5_0: + case GGML_TYPE_Q5_1: + case GGML_TYPE_Q8_0: + case GGML_TYPE_IQ4_NL: + return ctx->device->pipeline_cpy_quant_f32[src->type]; + default: + break; + } + } + + if (src->type == to) { + // Copy two or four bytes at a time, depending on block size. + // For quantized types, we scale by block size/type size. But + // this path is also used for bf16->bf16 for example, where the + // type size must be exactly 2 or 4. + GGML_ASSERT(ggml_is_quantized(to) || ggml_type_size(src->type) == 2 || ggml_type_size(src->type) == 4); + if ((ggml_type_size(src->type) % 4) == 0) { + if (contig) { + return ctx->device->pipeline_contig_cpy_f32_f32; + } else { + return ctx->device->pipeline_cpy_f32_f32; + } + } else { + if (contig) { + return ctx->device->pipeline_contig_cpy_f16_f16; + } else { + return ctx->device->pipeline_cpy_f16_f16; + } + } + } + + std::cerr << "Missing CPY op for types: " << ggml_type_name(src->type) << " " << ggml_type_name(to) << std::endl; GGML_ABORT("fatal error"); } @@ -2966,23 +4831,54 @@ static void ggml_vk_cpy_to_contiguous(ggml_backend_vk_context * ctx, vk_context& const int tensor_type_size = ggml_type_size(tensor->type); const uint32_t ne = ggml_nelements(tensor); + std::array elements; - const vk_op_unary_push_constants pc = { + if (ne > 262144) { + elements = { 512, 512, CEIL_DIV(ne, 262144) }; + } else if (ne > 512) { + elements = { 512, CEIL_DIV(ne, 512), 1 }; + } else { + elements = { ne, 1, 1 }; + } + + vk_op_unary_push_constants pc = { (uint32_t)ne, (uint32_t)tensor->ne[0], (uint32_t)tensor->ne[1], (uint32_t)tensor->ne[2], (uint32_t)tensor->ne[3], (uint32_t)tensor->nb[0] / tensor_type_size, (uint32_t)tensor->nb[1] / tensor_type_size, (uint32_t)tensor->nb[2] / tensor_type_size, (uint32_t)tensor->nb[3] / tensor_type_size, (uint32_t)tensor->ne[0], (uint32_t)tensor->ne[1], (uint32_t)tensor->ne[2], (uint32_t)tensor->ne[3], 1 , (uint32_t)tensor->ne[0] , (uint32_t)(tensor->ne[0] * tensor->ne[1]) , (uint32_t)(tensor->ne[0] * tensor->ne[1] * tensor->ne[2]), 0, 0.0f, 0.0f, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; + init_pushconst_fastdiv(pc); ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, sizeof(vk_op_unary_push_constants), &pc, { ne, 1, 1 }); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, sizeof(vk_op_unary_push_constants), &pc, elements); } -static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static vk_pipeline ggml_vk_get_quantize_pipeline(ggml_backend_vk_context * ctx, ggml_type type) { + switch(type) { + case GGML_TYPE_Q8_1: + return ctx->device->pipeline_quantize_q8_1; + default: + std::cerr << "Missing quantize pipeline for type: " << ggml_type_name(type) << std::endl; + GGML_ABORT("fatal error"); + } +} + +static void ggml_vk_quantize_q8_1(ggml_backend_vk_context * ctx, vk_context& subctx, vk_subbuffer&& in, vk_subbuffer&& out, uint32_t ne) { + VK_LOG_DEBUG("ggml_vk_quantize_q8_1(" << "buffer in size=" << in.buffer->size << ", buffer out size=" << out.buffer->size << ", " << ne << ")"); + + vk_pipeline pipeline = ggml_vk_get_quantize_pipeline(ctx, GGML_TYPE_Q8_1); + + ggml_vk_sync_buffers(subctx); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, sizeof(uint32_t), &ne, { ne, 1, 1 }); +} + +static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat_q_f16((" << src0 << ", name=" << src0->name << ", type=" << src0->type << ", ne0=" << src0->ne[0] << ", ne1=" << src0->ne[1] << ", ne2=" << src0->ne[2] << ", ne3=" << src0->ne[3] << ", nb0=" << src0->nb[0] << ", nb1=" << src0->nb[1] << ", nb2=" << src0->nb[2] << ", nb3=" << src0->nb[3]; std::cerr << "), (" << src1 << ", name=" << src1->name << ", type=" << src1->type << ", ne0=" << src1->ne[0] << ", ne1=" << src1->ne[1] << ", ne2=" << src1->ne[2] << ", ne3=" << src1->ne[3] << ", nb0=" << src1->nb[0] << ", nb1=" << src1->nb[1] << ", nb2=" << src1->nb[2] << ", nb3=" << src1->nb[3]; - std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3] << "),)"); - GGML_ASSERT(ggml_vk_dim01_contiguous(src0) || src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); // NOLINT + std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3]; + std::cerr << "), " << (dryrun ? "dryrun" : "") << ")"); + GGML_ASSERT(ggml_vk_dim01_contiguous(src0) || src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || src0->type == GGML_TYPE_BF16); // NOLINT GGML_ASSERT(ggml_vk_dim01_contiguous(src1) || src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16); // NOLINT const uint64_t ne00 = src0->ne[0]; @@ -3001,13 +4897,13 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub const uint64_t r2 = ne12 / ne02; const uint64_t r3 = ne13 / ne03; - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; - ggml_tensor_extra_gpu * extra_src1 = (ggml_tensor_extra_gpu *) src1->extra; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src0_buf_ctx = (ggml_backend_vk_buffer_context *)src0->buffer->context; + ggml_backend_vk_buffer_context * src1_buf_ctx = (ggml_backend_vk_buffer_context *)src1->buffer->context; - vk_buffer d_Qx; + vk_buffer d_Qx = nullptr; size_t qx_buf_offset = 0; - vk_buffer d_Qy; + vk_buffer d_Qy = nullptr; size_t qy_buf_offset = 0; bool src0_uma = false; @@ -3020,43 +4916,119 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub src1_uma = d_Qy != nullptr; } - const bool x_non_contig = !ggml_vk_dim01_contiguous(src0); - const bool y_non_contig = !ggml_vk_dim01_contiguous(src1); + // Reformat and convert to fp16 if non-contiguous, or for coopmat2 for better perf + const bool x_non_contig = (ctx->device->coopmat2 && src0->type == GGML_TYPE_F32) || + !ggml_vk_dim01_contiguous(src0); + const bool y_non_contig = (ctx->device->coopmat2 && src1->type == GGML_TYPE_F32) || + (src0->type == GGML_TYPE_BF16 && src1->type != GGML_TYPE_BF16) || + !ggml_vk_dim01_contiguous(src1); + + // If src0 is BF16, try to use a BF16 x BF16 multiply + ggml_type f16_type = src0->type == GGML_TYPE_BF16 ? GGML_TYPE_BF16 : GGML_TYPE_F16; const bool y_f32_kernel = src1->type == GGML_TYPE_F32 && !y_non_contig; - vk_matmul_pipeline mmp = ggml_vk_get_mul_mat_mat_pipeline(ctx, src0->type, y_non_contig ? GGML_TYPE_F16 : src1->type); + bool quantize_y = ctx->device->integer_dot_product && src1->type == GGML_TYPE_F32 && ggml_is_contiguous(src1) && (ne11 * ne10) % 4 == 0; - const bool qx_needs_dequant = mmp == nullptr || x_non_contig; - const bool qy_needs_dequant = (src1->type != GGML_TYPE_F16 && !y_f32_kernel) || y_non_contig; + // Check for mmq first + vk_matmul_pipeline mmp = quantize_y ? ggml_vk_get_mul_mat_mat_pipeline(ctx, src0->type, GGML_TYPE_Q8_1, (ggml_prec)dst->op_params[0]) : nullptr; if (mmp == nullptr) { + // Fall back to f16 dequant mul mat + mmp = ggml_vk_get_mul_mat_mat_pipeline(ctx, src0->type, y_non_contig ? f16_type : src1->type, (ggml_prec)dst->op_params[0]); + quantize_y = false; + } + + const bool qx_needs_dequant = mmp == nullptr || x_non_contig; + const bool qy_needs_dequant = !quantize_y && ((src1->type != f16_type && !y_f32_kernel) || y_non_contig); + + if (qx_needs_dequant) { // Fall back to dequant + f16 mulmat - mmp = ggml_vk_get_mul_mat_mat_pipeline(ctx, GGML_TYPE_F16, y_f32_kernel ? GGML_TYPE_F32 : GGML_TYPE_F16); + mmp = ggml_vk_get_mul_mat_mat_pipeline(ctx, f16_type, y_f32_kernel ? GGML_TYPE_F32 : f16_type, (ggml_prec)dst->op_params[0]); } // Not implemented GGML_ASSERT(y_non_contig || !qy_needs_dequant); // NOLINT + const uint32_t kpad = quantize_y ? 0 : ggml_vk_align_size(ne10, ggml_vk_guess_matmul_pipeline_align(ctx, mmp, ne01, ne11, qx_needs_dequant ? f16_type : src0->type, quantize_y ? GGML_TYPE_Q8_1 : (y_f32_kernel ? GGML_TYPE_F32 : src1->type))); + const bool aligned = !quantize_y && ne10 == kpad && ne01 > 8 && ne11 > 8; + + vk_pipeline pipeline = ggml_vk_guess_matmul_pipeline(ctx, mmp, ne01, ne11, aligned, qx_needs_dequant ? f16_type : src0->type, quantize_y ? GGML_TYPE_Q8_1 : (y_f32_kernel ? GGML_TYPE_F32 : src1->type)); + + // Reserve extra storage in the N dimension for the Y matrix, so we can avoid bounds-checking + uint32_t padded_n = qy_needs_dequant ? ROUNDUP_POW2(ne11, pipeline->wg_denoms[1]) : ne11; const int x_ne = ne01 * ne00; - const int y_ne = ne11 * ne10; + const int y_ne = padded_n * ne10; const int d_ne = ne11 * ne01; - const uint32_t kpad = ggml_vk_align_size(ne10, ggml_vk_guess_matmul_pipeline_align(ctx, mmp, ne01, ne11)); - const bool aligned = ne10 == kpad && ne01 > 8 && ne11 > 8; - - const uint32_t split_k = ggml_vk_guess_split_k(ne01, ne11, ne10); - - vk_pipeline pipeline = ggml_vk_guess_matmul_pipeline(ctx, mmp, ne01, ne11, aligned); + const uint32_t split_k = ggml_vk_guess_split_k(ctx, ne01, ne11, ne10, pipeline); const uint64_t qx_sz = ggml_type_size(src0->type) * x_ne / ggml_blck_size(src0->type); const uint64_t qy_sz = ggml_type_size(src1->type) * y_ne / ggml_blck_size(src1->type); const uint64_t x_sz = !qx_needs_dequant ? qx_sz : sizeof(ggml_fp16_t) * x_ne; - const uint64_t y_sz = y_f32_kernel ? sizeof(float) * y_ne : sizeof(ggml_fp16_t) * y_ne; + const uint64_t y_sz = quantize_y ? (y_ne * ggml_type_size(GGML_TYPE_Q8_1) / ggml_blck_size(GGML_TYPE_Q8_1)) : (y_f32_kernel ? sizeof(float) * y_ne : sizeof(ggml_fp16_t) * y_ne); const uint64_t d_sz = sizeof(float) * d_ne; - vk_buffer d_D = extra->buffer_gpu.lock(); - const uint64_t d_buf_offset = extra->offset + dst->view_offs; + vk_pipeline to_fp16_vk_0 = nullptr; + vk_pipeline to_fp16_vk_1 = nullptr; + vk_pipeline to_q8_1 = nullptr; + + if (x_non_contig) { + to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0, nullptr, f16_type); + } else { + to_fp16_vk_0 = ggml_vk_get_to_fp16(ctx, src0->type); + } + if (y_non_contig) { + to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1, nullptr, f16_type); + } else { + to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); + } + GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT + GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT + + if (quantize_y) { + to_q8_1 = ggml_vk_get_quantize_pipeline(ctx, GGML_TYPE_Q8_1); + } + + if (dryrun) { + const uint64_t x_sz_upd = x_sz * ne02 * ne03; + const uint64_t y_sz_upd = y_sz * ne12 * ne13; + const uint64_t split_k_size = split_k > 1 ? d_sz * ne12 * ne13 * split_k : 0; + if ( + (qx_needs_dequant && x_sz_upd > ctx->device->max_memory_allocation_size) || + (qy_needs_dequant && y_sz_upd > ctx->device->max_memory_allocation_size) || + (split_k > 1 && split_k_size > ctx->device->max_memory_allocation_size)) { + GGML_ABORT("Requested preallocation size is too large"); + } + if (qx_needs_dequant && ctx->prealloc_size_x < x_sz_upd) { + ctx->prealloc_size_x = x_sz_upd; + } + if ((qy_needs_dequant || quantize_y) && ctx->prealloc_size_y < y_sz_upd) { + ctx->prealloc_size_y = y_sz_upd; + } + if (split_k > 1 && ctx->prealloc_size_split_k < split_k_size) { + ctx->prealloc_size_split_k = split_k_size; + } + + // Request descriptor sets + ggml_pipeline_request_descriptor_sets(ctx, pipeline, 1); + if (qx_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_0, 1); + } + if (qy_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_1, 1); + } + if (quantize_y) { + ggml_pipeline_request_descriptor_sets(ctx, to_q8_1, 1); + } + if (split_k > 1) { + ggml_pipeline_request_descriptor_sets(ctx, ctx->device->pipeline_matmul_split_k_reduce, 1); + } + return; + } + + vk_buffer d_D = dst_buf_ctx->dev_buffer; + const uint64_t d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; GGML_ASSERT(d_D != nullptr); GGML_ASSERT(d_D->size >= d_buf_offset + d_sz * ne02 * ne03); vk_buffer d_X; @@ -3064,13 +5036,13 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub vk_buffer d_Y; uint64_t y_buf_offset = 0; if (!src0_uma) { - d_Qx = extra_src0->buffer_gpu.lock(); - qx_buf_offset = extra_src0->offset + src0->view_offs; + d_Qx = src0_buf_ctx->dev_buffer; + qx_buf_offset = vk_tensor_offset(src0) + src0->view_offs; GGML_ASSERT(d_Qx != nullptr); } if (!src1_uma) { - d_Qy = extra_src1->buffer_gpu.lock(); - qy_buf_offset = extra_src1->offset + src1->view_offs; + d_Qy = src1_buf_ctx->dev_buffer; + qy_buf_offset = vk_tensor_offset(src1) + src1->view_offs; GGML_ASSERT(d_Qy != nullptr); } if (qx_needs_dequant) { @@ -3083,41 +5055,16 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub } if (qy_needs_dequant) { d_Y = ctx->prealloc_y; - GGML_ASSERT(d_Y->size >= y_sz * ne02 * ne03); + GGML_ASSERT(d_Y->size >= y_sz * ne12 * ne13); + } else if (quantize_y) { + d_Y = ctx->prealloc_y; + GGML_ASSERT(d_Y->size >= y_ne * ggml_type_size(GGML_TYPE_Q8_1) / ggml_blck_size(GGML_TYPE_Q8_1)); } else { d_Y = d_Qy; y_buf_offset = qy_buf_offset; GGML_ASSERT(qy_sz == y_sz); } - vk_pipeline to_fp16_vk_0 = nullptr; - vk_pipeline to_fp16_vk_1 = nullptr; - - if (x_non_contig) { - to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0->type, GGML_TYPE_F16); - } else { - to_fp16_vk_0 = ggml_vk_get_to_fp16(ctx, src0->type); - } - if (y_non_contig) { - to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1->type, GGML_TYPE_F16); - } else { - to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); - } - GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT - GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT - - // Allocate descriptor sets - ggml_pipeline_allocate_descriptor_sets(ctx->device, pipeline, 1); - if (qx_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_0, 1); - } - if (qy_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_1, 1); - } - if (split_k > 1) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, ctx->device->pipeline_matmul_split_k_reduce, 1); - } - if (x_non_contig) { ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_0, src0, { d_Qx, qx_buf_offset, VK_WHOLE_SIZE }, { d_X, 0, VK_WHOLE_SIZE }); } else if (qx_needs_dequant) { @@ -3128,6 +5075,9 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub if (y_non_contig) { ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_1, src1, { d_Qy, qy_buf_offset, VK_WHOLE_SIZE }, { d_Y, 0, VK_WHOLE_SIZE }); } + if (quantize_y) { + ggml_vk_quantize_q8_1(ctx, subctx, { d_Qy, qy_buf_offset, VK_WHOLE_SIZE }, { d_Y, 0, VK_WHOLE_SIZE }, y_ne * ne12 * ne13); + } uint32_t stride_batch_x = ne00*ne01; uint32_t stride_batch_y = ne10*ne11; @@ -3136,7 +5086,7 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub stride_batch_x = src0->nb[0] / ggml_type_size(src0->type); } - if (!ggml_vk_dim01_contiguous(src1) && !qy_needs_dequant) { + if (!ggml_vk_dim01_contiguous(src1) && !qy_needs_dequant && !quantize_y) { stride_batch_y = src1->nb[0] / ggml_type_size(src1->type); } @@ -3147,15 +5097,16 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub { d_D, d_buf_offset, d_sz * ne12 * ne13 }, { ctx->prealloc_split_k, 0, d_sz * ne12 * ne13 * split_k }, ne01, ne11, ne10, ne10, ne10, ne01, stride_batch_x, stride_batch_y, ne20*ne21, - split_k, ne12*ne13, ne02, ne12, r2, r3 + split_k, ne12*ne13, ne02, ne12, r2, r3, padded_n ); // NOLINT } -static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat_vec_q_f16((" << src0 << ", name=" << src0->name << ", type=" << src0->type << ", ne0=" << src0->ne[0] << ", ne1=" << src0->ne[1] << ", ne2=" << src0->ne[2] << ", ne3=" << src0->ne[3] << ", nb0=" << src0->nb[0] << ", nb1=" << src0->nb[1] << ", nb2=" << src0->nb[2] << ", nb3=" << src0->nb[3]; std::cerr << "), (" << src1 << ", name=" << src1->name << ", type=" << src1->type << ", ne0=" << src1->ne[0] << ", ne1=" << src1->ne[1] << ", ne2=" << src1->ne[2] << ", ne3=" << src1->ne[3] << ", nb0=" << src1->nb[0] << ", nb1=" << src1->nb[1] << ", nb2=" << src1->nb[2] << ", nb3=" << src1->nb[3]; - std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3] << "),)"); - GGML_ASSERT(ggml_vk_dim01_contiguous(src0) || src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); // NOLINT + std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3]; + std::cerr << "), " << (dryrun ? "dryrun" : "") << "),)"); + GGML_ASSERT(ggml_vk_dim01_contiguous(src0) || src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || src0->type == GGML_TYPE_BF16); // NOLINT GGML_ASSERT(ggml_vk_dim01_contiguous(src1) || src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16); // NOLINT const uint64_t ne00 = src0->ne[0]; @@ -3168,8 +5119,6 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t ne12 = src1->ne[2]; const uint64_t ne13 = src1->ne[3]; - GGML_ASSERT(ne11 == 1); - const uint64_t ne20 = dst->ne[0]; const uint64_t ne21 = dst->ne[1]; const uint64_t ne22 = dst->ne[2]; @@ -3178,13 +5127,18 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t r2 = ne12 / ne02; const uint64_t r3 = ne13 / ne03; - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; - ggml_tensor_extra_gpu * extra_src1 = (ggml_tensor_extra_gpu *) src1->extra; + // batch_n indicates that we need to compute a few vector results, and this assumes + // ne12 and ne13 are 1. It overloads the batch_strides to hold the row strides. + GGML_ASSERT(ne11 == 1 || ne12 * ne13 == 1); + bool batch_n = ne11 > 1; - vk_buffer d_Qx; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src0_buf_ctx = (ggml_backend_vk_buffer_context *)src0->buffer->context; + ggml_backend_vk_buffer_context * src1_buf_ctx = (ggml_backend_vk_buffer_context *)src1->buffer->context; + + vk_buffer d_Qx = nullptr; size_t qx_buf_offset = 0; - vk_buffer d_Qy; + vk_buffer d_Qy = nullptr; size_t qy_buf_offset = 0; bool src0_uma = false; @@ -3218,21 +5172,62 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t y_sz = f16_f32_kernel ? sizeof(float) * y_ne : sizeof(ggml_fp16_t) * y_ne; const uint64_t d_sz = sizeof(float) * d_ne; - vk_buffer d_D = extra->buffer_gpu.lock(); - const uint64_t d_buf_offset = extra->offset + dst->view_offs; + vk_pipeline to_fp16_vk_0 = nullptr; + vk_pipeline to_fp16_vk_1 = nullptr; + if (x_non_contig) { + to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0, nullptr, src0->type); + } + if (y_non_contig) { + to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1, nullptr, src1->type); + } else { + to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); + } + vk_pipeline dmmv = ggml_vk_get_dequantize_mul_mat_vec(ctx, src0->type, src1->type, ne11); + GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT + GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT + GGML_ASSERT(dmmv != nullptr); + + if (dryrun) { + const uint64_t x_sz_upd = x_sz * ne02 * ne03; + const uint64_t y_sz_upd = y_sz * ne12 * ne13; + if ( + (qx_needs_dequant && x_sz_upd > ctx->device->max_memory_allocation_size) || + (qy_needs_dequant && y_sz_upd > ctx->device->max_memory_allocation_size)) { + GGML_ABORT("Requested preallocation size is too large"); + } + if (qx_needs_dequant && ctx->prealloc_size_x < x_sz_upd) { + ctx->prealloc_size_x = x_sz_upd; + } + if (qy_needs_dequant && ctx->prealloc_size_y < y_sz_upd) { + ctx->prealloc_size_y = y_sz_upd; + } + + // Request descriptor sets + if (qx_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_0, 1); + } + if (qy_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_1, 1); + } + ggml_pipeline_request_descriptor_sets(ctx, dmmv, 1); + return; + } + + vk_buffer d_D = dst_buf_ctx->dev_buffer; + const uint64_t d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; GGML_ASSERT(d_D != nullptr); vk_buffer d_X; uint64_t x_buf_offset = 0; vk_buffer d_Y; uint64_t y_buf_offset = 0; if(!src0_uma) { - d_Qx = extra_src0->buffer_gpu.lock(); - qx_buf_offset = extra_src0->offset + src0->view_offs; + d_Qx = src0_buf_ctx->dev_buffer; + qx_buf_offset = vk_tensor_offset(src0) + src0->view_offs; GGML_ASSERT(d_Qx != nullptr); } if(!src1_uma) { - d_Qy = extra_src1->buffer_gpu.lock(); - qy_buf_offset = extra_src1->offset + src1->view_offs; + d_Qy = src1_buf_ctx->dev_buffer; + qy_buf_offset = vk_tensor_offset(src1) + src1->view_offs; GGML_ASSERT(d_Qy != nullptr); } if (qx_needs_dequant) { @@ -3250,30 +5245,6 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& GGML_ASSERT(qy_sz == y_sz); } - vk_pipeline to_fp16_vk_0 = nullptr; - vk_pipeline to_fp16_vk_1 = nullptr; - if (x_non_contig) { - to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0->type, src0->type); - } - if (y_non_contig) { - to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1->type, src1->type); - } else { - to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); - } - vk_pipeline dmmv = ggml_vk_get_dequantize_mul_mat_vec(ctx, src0->type, src1->type); - GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT - GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT - GGML_ASSERT(dmmv != nullptr); - - // Allocate descriptor sets - if (qx_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_0, 1); - } - if (qy_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_1, y_non_contig ? 1 : ne12 * ne13); - } - ggml_pipeline_allocate_descriptor_sets(ctx->device, dmmv, ne12 * ne13); - if (x_non_contig) { GGML_ASSERT(x_sz == ggml_vk_align_size(ggml_type_size(src0->type) * x_ne, ctx->device->properties.limits.minStorageBufferOffsetAlignment)); ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_0, src0, { d_Qx, qx_buf_offset, VK_WHOLE_SIZE }, { d_X, 0, VK_WHOLE_SIZE }); @@ -3283,8 +5254,10 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_1, src1, { d_Qy, qy_buf_offset, VK_WHOLE_SIZE }, { d_Y, 0, VK_WHOLE_SIZE }); } - uint32_t stride_batch_x = ne00*ne01; - uint32_t stride_batch_y = ne10*ne11; + // For batch_n, the A matrix is the same for each batch, and B/D use the row stride as the batch stride + uint32_t stride_batch_x = batch_n ? 0 : ne00*ne01; + uint32_t stride_batch_y = batch_n ? ne10 : (ne10*ne11); + uint32_t stride_batch_d = batch_n ? ne20 : (ne20*ne21); if (!ggml_vk_dim01_contiguous(src0) && !qx_needs_dequant) { stride_batch_x = src0->nb[0] / ggml_type_size(src0->type); @@ -3301,13 +5274,13 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& if (ne01 > max_groups_x) { groups_z = 64; - groups_x /= groups_z; + groups_x = CEIL_DIV(groups_x, groups_z); } // compute const vk_mat_vec_push_constants pc = { (uint32_t)ne00, (uint32_t)ne10, (uint32_t)ne10, (uint32_t)ne01, - stride_batch_x, stride_batch_y, (uint32_t)(ne20*ne21), + stride_batch_x, stride_batch_y, stride_batch_d, (uint32_t)ne02, (uint32_t)ne12, (uint32_t)r2, (uint32_t)r3, }; ggml_vk_sync_buffers(subctx); @@ -3316,10 +5289,11 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& sizeof(vk_mat_vec_push_constants), &pc, { groups_x, (uint32_t)(ne12 * ne13), groups_z }); } -static void ggml_vk_mul_mat_vec_p021_f16_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_mul_mat_vec_p021_f16_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat_p021_f16_f32(" << src0 << ", name=" << src0->name << ", type=" << src0->type << ", ne0=" << src0->ne[0] << ", ne1=" << src0->ne[1] << ", ne2=" << src0->ne[2] << ", ne3=" << src0->ne[3] << ", nb0=" << src0->nb[0] << ", nb1=" << src0->nb[1] << ", nb2=" << src0->nb[2] << ", nb3=" << src0->nb[3]; std::cerr << "), (" << src1 << ", name=" << src1->name << ", type=" << src1->type << ", ne0=" << src1->ne[0] << ", ne1=" << src1->ne[1] << ", ne2=" << src1->ne[2] << ", ne3=" << src1->ne[3] << ", nb0=" << src1->nb[0] << ", nb1=" << src1->nb[1] << ", nb2=" << src1->nb[2] << ", nb3=" << src1->nb[3]; - std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3] << "),)"); + std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3]; + std::cerr << "), " << (dryrun ? "dryrun" : "") << ")"); GGML_ASSERT(ggml_is_permuted(src0) && ggml_is_permuted(src1)); GGML_ASSERT(src0->nb[0] <= src0->nb[1] && src0->nb[2] <= src0->nb[3]); // NOLINT GGML_ASSERT(src1->nb[0] <= src1->nb[1] && src1->nb[2] <= src1->nb[3]); // NOLINT @@ -3338,11 +5312,11 @@ static void ggml_vk_mul_mat_vec_p021_f16_f32(ggml_backend_vk_context * ctx, vk_c GGML_ASSERT(ne11 == 1); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; - ggml_tensor_extra_gpu * extra_src1 = (ggml_tensor_extra_gpu *) src1->extra; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src0_buf_ctx = (ggml_backend_vk_buffer_context *)src0->buffer->context; + ggml_backend_vk_buffer_context * src1_buf_ctx = (ggml_backend_vk_buffer_context *)src1->buffer->context; - vk_buffer d_Qy; + vk_buffer d_Qy = nullptr; size_t qy_buf_offset = 0; bool src1_uma = false; @@ -3360,20 +5334,29 @@ static void ggml_vk_mul_mat_vec_p021_f16_f32(ggml_backend_vk_context * ctx, vk_c const uint64_t qy_sz = ggml_type_size(src1->type) * y_ne / ggml_blck_size(src1->type); const uint64_t d_sz = sizeof(float) * d_ne; - vk_buffer d_D = extra->buffer_gpu.lock(); - const uint64_t d_buf_offset = extra->offset + dst->view_offs; - GGML_ASSERT(d_D != nullptr); - vk_buffer d_Qx = extra_src0->buffer_gpu.lock(); - const uint64_t qx_buf_offset = extra_src0->offset + src0->view_offs; - GGML_ASSERT(d_Qx != nullptr); - if (!src1_uma) { - d_Qy = extra_src1->buffer_gpu.lock(); - qy_buf_offset = extra_src1->offset + src1->view_offs; - GGML_ASSERT(d_Qx != nullptr); + // With grouped query attention there are > 1 Q matrices per K, V matrix. + uint32_t gqa_ratio = (uint32_t)ne12 / (uint32_t)ne02; + if (gqa_ratio > 8 || gqa_ratio == 0 || ne12 != ne02 * gqa_ratio) { + gqa_ratio = 1; } - // Allocate descriptor sets - ggml_pipeline_allocate_descriptor_sets(ctx->device, ctx->device->pipeline_mul_mat_vec_p021_f16_f32, 1); + if (dryrun) { + // Request descriptor sets + ggml_pipeline_request_descriptor_sets(ctx, ctx->device->pipeline_mul_mat_vec_p021_f16_f32[gqa_ratio - 1], 1); + return; + } + + vk_buffer d_D = dst_buf_ctx->dev_buffer; + const uint64_t d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; + GGML_ASSERT(d_D != nullptr); + vk_buffer d_Qx = src0_buf_ctx->dev_buffer; + const uint64_t qx_buf_offset = vk_tensor_offset(src0) + src0->view_offs; + GGML_ASSERT(d_Qx != nullptr); + if (!src1_uma) { + d_Qy = src1_buf_ctx->dev_buffer; + qy_buf_offset = vk_tensor_offset(src1) + src1->view_offs; + GGML_ASSERT(d_Qx != nullptr); + } const uint64_t qy_buffer_offset = (qy_buf_offset / ctx->device->properties.limits.minStorageBufferOffsetAlignment) * ctx->device->properties.limits.minStorageBufferOffsetAlignment; const uint64_t qy_shader_offset = qy_buf_offset - qy_buffer_offset; @@ -3383,14 +5366,22 @@ static void ggml_vk_mul_mat_vec_p021_f16_f32(ggml_backend_vk_context * ctx, vk_c // compute const std::array pc = { (uint32_t)ne00, (uint32_t)ne01, (uint32_t)ne02, (uint32_t)ne12, (uint32_t)(qy_shader_offset / ggml_type_size(src1->type)), (uint32_t)(d_shader_offset / ggml_type_size(dst->type)) }; + + uint32_t workgroups_z = (uint32_t)ne12; + // When gqa_ratio > 1, each invocation does multiple rows and we can launch fewer workgroups + if (gqa_ratio > 1) { + workgroups_z /= gqa_ratio; + } + ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_mul_mat_vec_p021_f16_f32, { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz }, vk_subbuffer{ d_Qy, qy_buffer_offset, qy_sz + qy_shader_offset }, vk_subbuffer{ d_D, d_buffer_offset, d_sz + d_shader_offset } }, 6 * sizeof(uint32_t), &pc, { 1, (uint32_t)ne01, (uint32_t)ne12 }); + ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_mul_mat_vec_p021_f16_f32[gqa_ratio - 1], { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz }, vk_subbuffer{ d_Qy, qy_buffer_offset, qy_sz + qy_shader_offset }, vk_subbuffer{ d_D, d_buffer_offset, d_sz + d_shader_offset } }, 6 * sizeof(uint32_t), &pc, { 1, (uint32_t)ne01, workgroups_z }); } -static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat_nc_f16_f32((" << src0 << ", name=" << src0->name << ", type=" << src0->type << ", ne0=" << src0->ne[0] << ", ne1=" << src0->ne[1] << ", ne2=" << src0->ne[2] << ", ne3=" << src0->ne[3] << ", nb0=" << src0->nb[0] << ", nb1=" << src0->nb[1] << ", nb2=" << src0->nb[2] << ", nb3=" << src0->nb[3]; std::cerr << "), (" << src1 << ", name=" << src1->name << ", type=" << src1->type << ", ne0=" << src1->ne[0] << ", ne1=" << src1->ne[1] << ", ne2=" << src1->ne[2] << ", ne3=" << src1->ne[3] << ", nb0=" << src1->nb[0] << ", nb1=" << src1->nb[1] << ", nb2=" << src1->nb[2] << ", nb3=" << src1->nb[3]; - std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3] << "),)"); + std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3]; + std::cerr << "), " << (dryrun ? "dryrun" : "") << ")"); GGML_ASSERT(!ggml_is_transposed(src0)); GGML_ASSERT(!ggml_is_transposed(src1)); GGML_ASSERT(!ggml_is_permuted(src0)); @@ -3405,6 +5396,8 @@ static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_con const uint64_t nb01 = src0->nb[1]; const uint64_t nb02 = src0->nb[2]; + const uint64_t nb12 = src1->nb[2]; + // const uint64_t ne10 = src1->ne[0]; const uint64_t ne11 = src1->ne[1]; const uint64_t ne12 = src1->ne[2]; @@ -3412,9 +5405,9 @@ static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_con GGML_ASSERT(ne11 == 1); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; - ggml_tensor_extra_gpu * extra_src1 = (ggml_tensor_extra_gpu *) src1->extra; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src0_buf_ctx = (ggml_backend_vk_buffer_context *)src0->buffer->context; + ggml_backend_vk_buffer_context * src1_buf_ctx = (ggml_backend_vk_buffer_context *)src1->buffer->context; vk_buffer d_Qy = nullptr; size_t qy_buf_offset = 0; @@ -3430,25 +5423,29 @@ static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_con const uint32_t row_stride_x = nb01 / sizeof(ggml_fp16_t); const uint32_t channel_stride_x = nb02 / sizeof(ggml_fp16_t); + const uint32_t channel_stride_y = nb12 / sizeof(float); const uint64_t qx_sz = ggml_nbytes(src0); const uint64_t qy_sz = ggml_nbytes(src1); const uint64_t d_sz = sizeof(float) * d_ne; - vk_buffer d_D = extra->buffer_gpu.lock(); - const uint64_t d_buf_offset = extra->offset + dst->view_offs; - GGML_ASSERT(d_D != nullptr); - vk_buffer d_Qx = extra_src0->buffer_gpu.lock(); - const uint64_t qx_buf_offset = extra_src0->offset + src0->view_offs; - GGML_ASSERT(d_Qx != nullptr); - if (!src1_uma) { - d_Qy = extra_src1->buffer_gpu.lock(); - qy_buf_offset = extra_src1->offset + src1->view_offs; - GGML_ASSERT(d_Qx != nullptr); + if (dryrun) { + // Request descriptor sets + ggml_pipeline_request_descriptor_sets(ctx, ctx->device->pipeline_mul_mat_vec_nc_f16_f32, 1); + return; } - // Allocate descriptor sets - ggml_pipeline_allocate_descriptor_sets(ctx->device, ctx->device->pipeline_mul_mat_vec_nc_f16_f32, 1); + vk_buffer d_D = dst_buf_ctx->dev_buffer; + const uint64_t d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; + GGML_ASSERT(d_D != nullptr); + vk_buffer d_Qx = src0_buf_ctx->dev_buffer; + const uint64_t qx_buf_offset = vk_tensor_offset(src0) + src0->view_offs; + GGML_ASSERT(d_Qx != nullptr); + if (!src1_uma) { + d_Qy = src1_buf_ctx->dev_buffer; + qy_buf_offset = vk_tensor_offset(src1) + src1->view_offs; + GGML_ASSERT(d_Qx != nullptr); + } const uint64_t qy_buffer_offset = (qy_buf_offset / ctx->device->properties.limits.minStorageBufferOffsetAlignment) * ctx->device->properties.limits.minStorageBufferOffsetAlignment; const uint64_t qy_shader_offset = qy_buf_offset - qy_buffer_offset; @@ -3457,26 +5454,39 @@ static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_con const uint64_t d_shader_offset = d_buf_offset - d_buffer_offset; // compute - const std::array pc = { (uint32_t)ne00, (uint32_t)ne01, row_stride_x, channel_stride_x, (uint32_t)(ne12 / ne02), (uint32_t)(qy_shader_offset / ggml_type_size(src1->type)), (uint32_t)(d_shader_offset / ggml_type_size(dst->type)) }; + const std::array pc = { (uint32_t)ne00, (uint32_t)ne01, row_stride_x, channel_stride_x, channel_stride_y, (uint32_t)(ne12 / ne02), (uint32_t)ne12, (uint32_t)(qy_shader_offset / ggml_type_size(src1->type)), (uint32_t)(d_shader_offset / ggml_type_size(dst->type)) }; ggml_vk_sync_buffers(subctx); ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_mul_mat_vec_nc_f16_f32, { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz }, vk_subbuffer{ d_Qy, qy_buffer_offset, qy_sz + qy_shader_offset }, vk_subbuffer{ d_D, d_buffer_offset, d_sz + d_shader_offset } }, 7 * sizeof(uint32_t), &pc, { 1, (uint32_t)ne01, (uint32_t)ne12 }); } -static void ggml_vk_mul_mat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_mul_mat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat(" << src0 << ", " << src1 << ", " << dst << ")"); - if (src0->type == GGML_TYPE_F16 && ggml_is_permuted(src0) && ggml_is_permuted(src1) && dst->ne[1] == 1) { - ggml_vk_mul_mat_vec_p021_f16_f32(ctx, subctx, src0, src1, dst); - } else if (src0->type == GGML_TYPE_F16 && !ggml_is_contiguous(src0) && !ggml_is_transposed(src1) && dst->ne[1] == 1) { - ggml_vk_mul_mat_vec_nc_f16_f32(ctx, subctx, src0, src1, dst); - } else if (dst->ne[1] == 1 && (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || ggml_is_quantized(src0->type))) { - ggml_vk_mul_mat_vec_q_f16(ctx, subctx, src0, src1, dst); + if (src0->type == GGML_TYPE_F16 && ggml_is_permuted(src0) && ggml_is_permuted(src1) && dst->ne[1] == 1 && + // detect 0213 permutation, and batch size of 1 + src0->nb[0] <= src0->nb[2] && + src0->nb[2] <= src0->nb[1] && + src0->nb[1] <= src0->nb[3] && + src1->nb[0] <= src1->nb[2] && + src1->nb[2] <= src1->nb[1] && + src1->nb[1] <= src1->nb[3] && + src0->ne[3] == 1 && + src1->ne[3] == 1) { + ggml_vk_mul_mat_vec_p021_f16_f32(ctx, subctx, src0, src1, dst, dryrun); + } else if (src0->type == GGML_TYPE_F16 && !ggml_is_contiguous(src0) && !ggml_is_transposed(src1) && dst->ne[1] == 1 && + !ggml_is_permuted(src0) && !ggml_is_permuted(src1)) { + ggml_vk_mul_mat_vec_nc_f16_f32(ctx, subctx, src0, src1, dst, dryrun); + // mul_mat_vec supports batching ne12*ne13 when ne11==1, or treating ne11 as the batch size (up to four) + // when ne12 and ne13 are one. + } else if ((dst->ne[1] == 1 || (dst->ne[1] <= mul_mat_vec_max_cols && src1->ne[2] * src1->ne[3] == 1)) && + (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || src0->type == GGML_TYPE_BF16 || ggml_is_quantized(src0->type))) { + ggml_vk_mul_mat_vec_q_f16(ctx, subctx, src0, src1, dst, dryrun); } else { - ggml_vk_mul_mat_q_f16(ctx, subctx, src0, src1, dst); + ggml_vk_mul_mat_q_f16(ctx, subctx, src0, src1, dst, dryrun); } } -static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst) { +static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat_id_q_f16((" << src0 << ", name=" << src0->name << ", type=" << src0->type << ", ne0=" << src0->ne[0] << ", ne1=" << src0->ne[1] << ", ne2=" << src0->ne[2] << ", ne3=" << src0->ne[3] << ", nb0=" << src0->nb[0] << ", nb1=" << src0->nb[1] << ", nb2=" << src0->nb[2] << ", nb3=" << src0->nb[3]; std::cerr << "), (" << src1 << ", name=" << src1->name << ", type=" << src1->type << ", ne0=" << src1->ne[0] << ", ne1=" << src1->ne[1] << ", ne2=" << src1->ne[2] << ", ne3=" << src1->ne[3] << ", nb0=" << src1->nb[0] << ", nb1=" << src1->nb[1] << ", nb2=" << src1->nb[2] << ", nb3=" << src1->nb[3]; std::cerr << "), (" << ids << ", name=" << ids->name << ", type=" << ids->type << ", ne0=" << ids->ne[0] << ", ne1=" << ids->ne[1] << ", ne2=" << ids->ne[2] << ", ne3=" << ids->ne[3] << ", nb0=" << ids->nb[0] << ", nb1=" << ids->nb[1] << ", nb2=" << ids->nb[2] << ", nb3=" << ids->nb[3]; @@ -3496,7 +5506,7 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t nei0 = ids->ne[0]; const uint64_t nei1 = ids->ne[1]; - GGML_ASSERT(nei0 * nei1 <= 3072); + GGML_ASSERT(nei0 * nei1 <= 4096); const uint32_t nbi1 = ids->nb[1]; const uint32_t nbi2 = ids->nb[2]; @@ -3508,16 +5518,16 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t n_as = ne02; - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; - ggml_tensor_extra_gpu * extra_src1 = (ggml_tensor_extra_gpu *) src1->extra; - ggml_tensor_extra_gpu * extra_ids = (ggml_tensor_extra_gpu *) ids->extra; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src0_buf_ctx = (ggml_backend_vk_buffer_context *)src0->buffer->context; + ggml_backend_vk_buffer_context * src1_buf_ctx = (ggml_backend_vk_buffer_context *)src1->buffer->context; + ggml_backend_vk_buffer_context * ids_buf_ctx = (ggml_backend_vk_buffer_context *)ids->buffer->context; - vk_buffer d_Qx; + vk_buffer d_Qx = nullptr; size_t qx_buf_offset = 0; - vk_buffer d_Qy; + vk_buffer d_Qy = nullptr; size_t qy_buf_offset = 0; - vk_buffer d_ids; + vk_buffer d_ids = nullptr; size_t ids_buf_offset = 0; bool src0_uma = false; @@ -3533,31 +5543,41 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& ids_uma = d_ids != nullptr; } - const bool x_non_contig = !ggml_vk_dim01_contiguous(src0); - const bool y_non_contig = !ggml_vk_dim01_contiguous(src1); + // Reformat and convert to fp16 if non-contiguous, or for coopmat2 for better perf + const bool x_non_contig = (ctx->device->coopmat2 && src0->type == GGML_TYPE_F32) || + !ggml_vk_dim01_contiguous(src0); + const bool y_non_contig = (ctx->device->coopmat2 && src1->type == GGML_TYPE_F32) || + (src0->type == GGML_TYPE_BF16 && src1->type != GGML_TYPE_BF16) || + !ggml_vk_dim01_contiguous(src1); + + // If src0 is BF16, try to use a BF16 x BF16 multiply + ggml_type f16_type = src0->type == GGML_TYPE_BF16 ? GGML_TYPE_BF16 : GGML_TYPE_F16; const bool y_f32_kernel = src1->type == GGML_TYPE_F32 && !y_non_contig; - vk_matmul_pipeline mmp = ggml_vk_get_mul_mat_mat_id_pipeline(ctx, src0->type, y_non_contig ? GGML_TYPE_F16 : src1->type); + vk_matmul_pipeline mmp = ggml_vk_get_mul_mat_mat_id_pipeline(ctx, src0->type, y_non_contig ? f16_type : src1->type, (ggml_prec)dst->op_params[0]); const bool qx_needs_dequant = mmp == nullptr || x_non_contig; - const bool qy_needs_dequant = (src1->type != GGML_TYPE_F16 && !y_f32_kernel) || y_non_contig; + const bool qy_needs_dequant = (src1->type != f16_type && !y_f32_kernel) || y_non_contig; - if (mmp == nullptr) { - GGML_ABORT("fatal error"); + if (qx_needs_dequant) { + // Fall back to dequant + f16 mulmat + mmp = ggml_vk_get_mul_mat_mat_id_pipeline(ctx, f16_type, y_f32_kernel ? GGML_TYPE_F32 : f16_type, (ggml_prec)dst->op_params[0]); } // Not implemented GGML_ASSERT(y_non_contig || !qy_needs_dequant); // NOLINT - const uint64_t x_ne = ne01 * ne00; - const uint64_t y_ne = ne11 * ne10; - const uint64_t d_ne = ne21 * ne20; - - const uint32_t kpad = ggml_vk_align_size(ne10, ggml_vk_guess_matmul_pipeline_align(ctx, mmp, ne01, nei1)); + const uint32_t kpad = ggml_vk_align_size(ne10, ggml_vk_guess_matmul_id_pipeline_align(ctx, mmp, ne01, nei1, qx_needs_dequant ? f16_type : src0->type)); const bool aligned = ne10 == kpad && ne01 > 8 && nei1 > 8; - vk_pipeline pipeline = ggml_vk_guess_matmul_pipeline(ctx, mmp, ne01, nei1, aligned); + vk_pipeline pipeline = ggml_vk_guess_matmul_id_pipeline(ctx, mmp, ne01, nei1, aligned, qx_needs_dequant ? f16_type : src0->type); + + // Reserve extra storage in the N dimension for the Y matrix, so we can avoid bounds-checking + uint32_t padded_n = qy_needs_dequant ? ROUNDUP_POW2(ne11, pipeline->wg_denoms[1]) :ne11; + const uint64_t x_ne = ne01 * ne00; + const uint64_t y_ne = padded_n * ne10; + const uint64_t d_ne = ne21 * ne20; const uint64_t qx_sz = ggml_type_size(src0->type) * x_ne / ggml_blck_size(src0->type); const uint64_t qy_sz = ggml_type_size(src1->type) * y_ne / ggml_blck_size(src1->type); @@ -3566,26 +5586,68 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t ids_sz = nbi2; const uint64_t d_sz = sizeof(float) * d_ne; - vk_buffer d_D = extra->buffer_gpu.lock(); - const uint64_t d_buf_offset = extra->offset + dst->view_offs; + vk_pipeline to_fp16_vk_0 = nullptr; + vk_pipeline to_fp16_vk_1 = nullptr; + + if (x_non_contig) { + to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0, nullptr, f16_type); + } else { + to_fp16_vk_0 = ggml_vk_get_to_fp16(ctx, src0->type); + } + if (y_non_contig) { + to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1, nullptr, f16_type); + } else { + to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); + } + GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT + GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT + + if (dryrun) { + const uint64_t x_sz_upd = x_sz * ne02 * ne03; + const uint64_t y_sz_upd = y_sz * ne12 * ne13; + if ( + (qx_needs_dequant && x_sz_upd > ctx->device->max_memory_allocation_size) || + (qy_needs_dequant && y_sz_upd > ctx->device->max_memory_allocation_size)) { + GGML_ABORT("Requested preallocation size is too large"); + } + if (qx_needs_dequant && ctx->prealloc_size_x < x_sz_upd) { + ctx->prealloc_size_x = x_sz_upd; + } + if (qy_needs_dequant && ctx->prealloc_size_y < y_sz_upd) { + ctx->prealloc_size_y = y_sz_upd; + } + + // Request descriptor sets + ggml_pipeline_request_descriptor_sets(ctx, pipeline, 1); + if (qx_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_0, 1); + } + if (qy_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_1, 1); + } + return; + } + + vk_buffer d_D = dst_buf_ctx->dev_buffer; + const uint64_t d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; GGML_ASSERT(d_D != nullptr); vk_buffer d_X; uint64_t x_buf_offset = 0; vk_buffer d_Y; uint64_t y_buf_offset = 0; if (!src0_uma) { - d_Qx = extra_src0->buffer_gpu.lock(); - qx_buf_offset = extra_src0->offset + src0->view_offs; + d_Qx = src0_buf_ctx->dev_buffer; + qx_buf_offset = vk_tensor_offset(src0) + src0->view_offs; GGML_ASSERT(d_Qx != nullptr); } if (!src1_uma) { - d_Qy = extra_src1->buffer_gpu.lock(); - qy_buf_offset = extra_src1->offset + src1->view_offs; + d_Qy = src1_buf_ctx->dev_buffer; + qy_buf_offset = vk_tensor_offset(src1) + src1->view_offs; GGML_ASSERT(d_Qy != nullptr); } if (!ids_uma) { - d_ids = extra_ids->buffer_gpu.lock(); - ids_buf_offset = extra_ids->offset + ids->view_offs; + d_ids = ids_buf_ctx->dev_buffer; + ids_buf_offset = vk_tensor_offset(ids) + ids->view_offs; GGML_ASSERT(d_ids != nullptr); } if (qx_needs_dequant) { @@ -3598,38 +5660,13 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& } if (qy_needs_dequant) { d_Y = ctx->prealloc_y; - GGML_ASSERT(d_Y->size >= y_sz * ne02 * ne03); + GGML_ASSERT(d_Y->size >= y_sz * ne12 * ne13); } else { d_Y = d_Qy; y_buf_offset = qy_buf_offset; GGML_ASSERT(qy_sz == y_sz); } - vk_pipeline to_fp16_vk_0 = nullptr; - vk_pipeline to_fp16_vk_1 = nullptr; - - if (x_non_contig) { - to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0->type, GGML_TYPE_F16); - } else { - to_fp16_vk_0 = ggml_vk_get_to_fp16(ctx, src0->type); - } - if (y_non_contig) { - to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1->type, GGML_TYPE_F16); - } else { - to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); - } - GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT - GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT - - // Allocate descriptor sets - ggml_pipeline_allocate_descriptor_sets(ctx->device, pipeline, 1); - if (qx_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_0, 1); - } - if (qy_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_1, 1); - } - if (x_non_contig) { ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_0, src0, { d_Qx, qx_buf_offset, VK_WHOLE_SIZE }, { d_X, 0, VK_WHOLE_SIZE }); } else if (qx_needs_dequant) { @@ -3660,16 +5697,17 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& { d_D, d_buf_offset, d_sz * ne22 * ne23 }, { d_ids, ids_buf_offset, ids_sz }, ne01, ne21, ne10, ne10, ne10, ne01, stride_batch_x, stride_batch_y, ne20*ne21, - n_as, nei0, nei1, nbi1 / ggml_type_size(ids->type), ne11 + n_as, nei0, nei1, nbi1 / ggml_type_size(ids->type), ne11, padded_n ); // NOLINT } -static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst) { +static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat_vec_id_q_f16((" << src0 << ", name=" << src0->name << ", type=" << src0->type << ", ne0=" << src0->ne[0] << ", ne1=" << src0->ne[1] << ", ne2=" << src0->ne[2] << ", ne3=" << src0->ne[3] << ", nb0=" << src0->nb[0] << ", nb1=" << src0->nb[1] << ", nb2=" << src0->nb[2] << ", nb3=" << src0->nb[3]; std::cerr << "), (" << src1 << ", name=" << src1->name << ", type=" << src1->type << ", ne0=" << src1->ne[0] << ", ne1=" << src1->ne[1] << ", ne2=" << src1->ne[2] << ", ne3=" << src1->ne[3] << ", nb0=" << src1->nb[0] << ", nb1=" << src1->nb[1] << ", nb2=" << src1->nb[2] << ", nb3=" << src1->nb[3]; std::cerr << "), (" << ids << ", name=" << ids->name << ", type=" << ids->type << ", ne0=" << ids->ne[0] << ", ne1=" << ids->ne[1] << ", ne2=" << ids->ne[2] << ", ne3=" << ids->ne[3] << ", nb0=" << ids->nb[0] << ", nb1=" << ids->nb[1] << ", nb2=" << ids->nb[2] << ", nb3=" << ids->nb[3]; - std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3] << "),)"); - GGML_ASSERT(ggml_vk_dim01_contiguous(src0) || src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); // NOLINT + std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3]; + std::cerr << "), " << (dryrun ? "dryrun" : "") << ")"); + GGML_ASSERT(ggml_vk_dim01_contiguous(src0) || src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || src0->type == GGML_TYPE_BF16); // NOLINT GGML_ASSERT(ggml_vk_dim01_contiguous(src1) || src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16); // NOLINT GGML_ASSERT(ids->type == GGML_TYPE_I32); @@ -3695,16 +5733,16 @@ static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_conte const uint64_t ne22 = dst->ne[2]; const uint64_t ne23 = dst->ne[3]; - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; - ggml_tensor_extra_gpu * extra_src1 = (ggml_tensor_extra_gpu *) src1->extra; - ggml_tensor_extra_gpu * extra_ids = (ggml_tensor_extra_gpu *) ids->extra; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src0_buf_ctx = (ggml_backend_vk_buffer_context *)src0->buffer->context; + ggml_backend_vk_buffer_context * src1_buf_ctx = (ggml_backend_vk_buffer_context *)src1->buffer->context; + ggml_backend_vk_buffer_context * ids_buf_ctx = (ggml_backend_vk_buffer_context *)ids->buffer->context; - vk_buffer d_Qx; + vk_buffer d_Qx = nullptr; size_t qx_buf_offset = 0; - vk_buffer d_Qy; + vk_buffer d_Qy = nullptr; size_t qy_buf_offset = 0; - vk_buffer d_ids; + vk_buffer d_ids = nullptr; size_t ids_buf_offset = 0; bool src0_uma = false; @@ -3742,26 +5780,67 @@ static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_conte const uint64_t ids_sz = nbi2; const uint64_t d_sz = sizeof(float) * d_ne; - vk_buffer d_D = extra->buffer_gpu.lock(); - const uint64_t d_buf_offset = extra->offset + dst->view_offs; + vk_pipeline to_fp16_vk_0 = nullptr; + vk_pipeline to_fp16_vk_1 = nullptr; + if (x_non_contig) { + to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0, nullptr, src0->type); + } + if (y_non_contig) { + to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1, nullptr, src1->type); + } else { + to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); + } + vk_pipeline dmmv = ggml_vk_get_dequantize_mul_mat_vec_id(ctx, src0->type, src1->type); + GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT + GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT + GGML_ASSERT(dmmv != nullptr); + + if (dryrun) { + const uint64_t x_sz_upd = x_sz * ne02 * ne03; + const uint64_t y_sz_upd = y_sz * ne12 * ne13; + if ( + (qx_needs_dequant && x_sz_upd > ctx->device->max_memory_allocation_size) || + (qy_needs_dequant && y_sz_upd > ctx->device->max_memory_allocation_size)) { + GGML_ABORT("Requested preallocation size is too large"); + } + if (qx_needs_dequant && ctx->prealloc_size_x < x_sz_upd) { + ctx->prealloc_size_x = x_sz_upd; + } + if (qy_needs_dequant && ctx->prealloc_size_y < y_sz_upd) { + ctx->prealloc_size_y = y_sz_upd; + } + + // Request descriptor sets + if (qx_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_0, 1); + } + if (qy_needs_dequant) { + ggml_pipeline_request_descriptor_sets(ctx, to_fp16_vk_1, 1); + } + ggml_pipeline_request_descriptor_sets(ctx, dmmv, 1); + return; + } + + vk_buffer d_D = dst_buf_ctx->dev_buffer; + const uint64_t d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; GGML_ASSERT(d_D != nullptr); vk_buffer d_X; uint64_t x_buf_offset = 0; vk_buffer d_Y; uint64_t y_buf_offset = 0; if(!src0_uma) { - d_Qx = extra_src0->buffer_gpu.lock(); - qx_buf_offset = extra_src0->offset + src0->view_offs; + d_Qx = src0_buf_ctx->dev_buffer; + qx_buf_offset = vk_tensor_offset(src0) + src0->view_offs; GGML_ASSERT(d_Qx != nullptr); } if(!src1_uma) { - d_Qy = extra_src1->buffer_gpu.lock(); - qy_buf_offset = extra_src1->offset + src1->view_offs; + d_Qy = src1_buf_ctx->dev_buffer; + qy_buf_offset = vk_tensor_offset(src1) + src1->view_offs; GGML_ASSERT(d_Qy != nullptr); } if(!ids_uma) { - d_ids = extra_ids->buffer_gpu.lock(); - ids_buf_offset = extra_ids->offset + ids->view_offs; + d_ids = ids_buf_ctx->dev_buffer; + ids_buf_offset = vk_tensor_offset(ids) + ids->view_offs; GGML_ASSERT(d_ids != nullptr); } if (qx_needs_dequant) { @@ -3779,30 +5858,6 @@ static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_conte GGML_ASSERT(qy_sz == y_sz); } - vk_pipeline to_fp16_vk_0 = nullptr; - vk_pipeline to_fp16_vk_1 = nullptr; - if (x_non_contig) { - to_fp16_vk_0 = ggml_vk_get_cpy_pipeline(ctx, src0->type, src0->type); - } - if (y_non_contig) { - to_fp16_vk_1 = ggml_vk_get_cpy_pipeline(ctx, src1->type, src1->type); - } else { - to_fp16_vk_1 = ggml_vk_get_to_fp16(ctx, src1->type); - } - vk_pipeline dmmv = ggml_vk_get_dequantize_mul_mat_vec_id(ctx, src0->type, src1->type); - GGML_ASSERT(!qx_needs_dequant || to_fp16_vk_0 != nullptr); // NOLINT - GGML_ASSERT(!qy_needs_dequant || to_fp16_vk_1 != nullptr); // NOLINT - GGML_ASSERT(dmmv != nullptr); - - // Allocate descriptor sets - if (qx_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_0, 1); - } - if (qy_needs_dequant) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, to_fp16_vk_1, y_non_contig ? 1 : ne12 * ne13); - } - ggml_pipeline_allocate_descriptor_sets(ctx->device, dmmv, ne12 * ne13); - if (x_non_contig) { GGML_ASSERT(x_sz == ggml_vk_align_size(ggml_type_size(src0->type) * x_ne, ctx->device->properties.limits.minStorageBufferOffsetAlignment)); ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_0, src0, { d_Qx, qx_buf_offset, VK_WHOLE_SIZE }, { d_X, 0, VK_WHOLE_SIZE }); @@ -3825,7 +5880,7 @@ static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_conte if (ne01 > max_groups_x) { groups_z = 64; - groups_x /= groups_z; + groups_x = CEIL_DIV(groups_x, groups_z); } // compute @@ -3841,85 +5896,376 @@ static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_conte sizeof(vk_mat_vec_id_push_constants), &pc, { groups_x, (uint32_t)nei0, groups_z }); } -static void ggml_vk_mul_mat_id(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst) { +static void ggml_vk_mul_mat_id(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_mul_mat_id(" << src0 << ", " << src1 << ", " << src2 << ", " << dst << ")"); if (src2->ne[1] == 1 && (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || ggml_is_quantized(src0->type))) { - ggml_vk_mul_mat_vec_id_q_f16(ctx, subctx, src0, src1, src2, dst); + ggml_vk_mul_mat_vec_id_q_f16(ctx, subctx, src0, src1, src2, dst, dryrun); } else { - ggml_vk_mul_mat_id_q_f16(ctx, subctx, src0, src1, src2, dst); + ggml_vk_mul_mat_id_q_f16(ctx, subctx, src0, src1, src2, dst, dryrun); } } -static void ggml_vk_op_repeat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { - VK_LOG_DEBUG("ggml_vk_op_repeat(" << src0 << ", " << src1 << ", " << dst << ")"); - const uint64_t ne0 = dst->ne[0]; - const uint64_t ne1 = dst->ne[1]; - const uint64_t ne2 = dst->ne[2]; - const uint64_t ne3 = dst->ne[3]; +static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, const uint32_t D, bool f32acc) { + // Needs to be kept up to date on shader changes + const uint32_t wg_size = scalar_flash_attention_workgroup_size; + const uint32_t Br = scalar_flash_attention_num_large_rows; + const uint32_t Bc = scalar_flash_attention_Bc; - const uint64_t ne00 = src0->ne[0]; - const uint64_t ne01 = src0->ne[1]; - const uint64_t ne02 = src0->ne[2]; - const uint64_t ne03 = src0->ne[3]; + const uint32_t acctype = f32acc ? 4 : 2; + const uint32_t f16vec4 = 8; - const uint64_t nb0 = dst->nb[0]; - const uint64_t nb1 = dst->nb[1]; - const uint64_t nb2 = dst->nb[2]; - const uint64_t nb3 = dst->nb[3]; + const uint32_t tmpsh = wg_size * sizeof(float); + const uint32_t tmpshv4 = wg_size * 4 * acctype; - const uint64_t nb00 = src0->nb[0]; - const uint64_t nb01 = src0->nb[1]; - const uint64_t nb02 = src0->nb[2]; - const uint64_t nb03 = src0->nb[3]; + const uint32_t Qf = Br * (D / 4 + 2) * f16vec4; - // guaranteed to be an integer due to the check in ggml_can_repeat - const uint64_t nr0 = ne0/ne00; - const uint64_t nr1 = ne1/ne01; - const uint64_t nr2 = ne2/ne02; - const uint64_t nr3 = ne3/ne03; + const uint32_t sfshstride = (D <= 128) ? (Br + 8) : Br; + const uint32_t sfsh = Bc * sfshstride * acctype; - // TODO: support for transposed / permuted tensors - GGML_ASSERT(nb0 == sizeof(float)); - GGML_ASSERT(nb00 == sizeof(float)); + const uint32_t kshstride = D / 4 + 2; + const uint32_t ksh = Bc * kshstride * f16vec4; - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; + const uint32_t slope = Br * sizeof(float); - const vk_buffer src_buf = extra_src0->buffer_gpu.lock(); - const uint64_t src_offset = extra_src0->offset + src0->view_offs; - vk_buffer dst_buf = extra->buffer_gpu.lock(); - const uint64_t dst_offset = extra->offset + dst->view_offs; + const uint32_t total_size = tmpsh + tmpshv4 + Qf + sfsh + ksh + slope; + const bool supported = total_size <= device->properties.limits.maxComputeSharedMemorySize; - std::vector copies; + VK_LOG_DEBUG("ggml_vk_flash_attn_coopmat_shmem_support(D=" << D << ", f32acc=" << f32acc << ", total_size=" << total_size << ", supported=" << supported); - for (uint64_t i3 = 0; i3 < nr3; i3++) { - for (uint64_t k3 = 0; k3 < ne03; k3++) { - for (uint64_t i2 = 0; i2 < nr2; i2++) { - for (uint64_t k2 = 0; k2 < ne02; k2++) { - for (uint64_t i1 = 0; i1 < nr1; i1++) { - for (uint64_t k1 = 0; k1 < ne01; k1++) { - for (uint64_t i0 = 0; i0 < nr0; i0++) { - copies.push_back({ - src_offset + ( k3)*nb03 + ( k2)*nb02 + ( k1)*nb01, - dst_offset + (i3*ne03 + k3)*nb3 + (i2*ne02 + k2)*nb2 + (i1*ne01 + k1)*nb1 + (i0*ne00)*nb0, - ne00*nb0, - }); - } - } - } - } - } + return supported; +} + +static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * q, const ggml_tensor * k, const ggml_tensor * v, const ggml_tensor * mask, ggml_tensor * dst, bool dryrun = false) { + VK_LOG_DEBUG("ggml_vk_flash_attn((" << q << ", name=" << q->name << ", type=" << q->type << ", ne0=" << q->ne[0] << ", ne1=" << q->ne[1] << ", ne2=" << q->ne[2] << ", ne3=" << q->ne[3] << ", nb0=" << q->nb[0] << ", nb1=" << q->nb[1] << ", nb2=" << q->nb[2] << ", nb3=" << q->nb[3]; + std::cerr << "), (" << k << ", name=" << k->name << ", type=" << k->type << ", ne0=" << k->ne[0] << ", ne1=" << k->ne[1] << ", ne2=" << k->ne[2] << ", ne3=" << k->ne[3] << ", nb0=" << k->nb[0] << ", nb1=" << k->nb[1] << ", nb2=" << k->nb[2] << ", nb3=" << k->nb[3]; + std::cerr << "), (" << v << ", name=" << v->name << ", type=" << v->type << ", ne0=" << v->ne[0] << ", ne1=" << v->ne[1] << ", ne2=" << v->ne[2] << ", ne3=" << v->ne[3] << ", nb0=" << v->nb[0] << ", nb1=" << v->nb[1] << ", nb2=" << v->nb[2] << ", nb3=" << v->nb[3]; + std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3]; + std::cerr << "), " << (dryrun ? "dryrun" : "") << ")"); + + GGML_TENSOR_LOCALS(int64_t, neq, q, ne) + GGML_TENSOR_LOCALS(size_t, nbq, q, nb) + GGML_TENSOR_LOCALS(int64_t, nek, k, ne) + GGML_TENSOR_LOCALS(size_t, nbk, k, nb) + GGML_TENSOR_LOCALS(int64_t, nev, v, ne) + GGML_TENSOR_LOCALS(size_t, nbv, v, nb) + GGML_TENSOR_LOCALS(int64_t, ne, dst, ne) + GGML_TENSOR_LOCALS(size_t, nb, dst, nb) + + const uint32_t nem1 = mask ? mask->ne[1] : 0; + const uint32_t nbm1 = mask ? mask->nb[1] : 0; + + const uint32_t D = neq0; + uint32_t N = neq1; + const uint32_t KV = nek1; + + GGML_ASSERT(ne0 == D); + GGML_ASSERT(ne2 == N); + + // input tensor rows must be contiguous + GGML_ASSERT(nbq0 == ggml_type_size(q->type)); + GGML_ASSERT(nbk0 == ggml_type_size(k->type)); + GGML_ASSERT(nbv0 == ggml_type_size(v->type)); + + GGML_ASSERT(neq0 == D); + GGML_ASSERT(nek0 == D); + GGML_ASSERT(nev0 == D); + + GGML_ASSERT(neq1 == N); + GGML_ASSERT(nev0 == D); + + GGML_ASSERT(nev1 == nek1); + + // dst cannot be transposed or permuted + GGML_ASSERT(nb0 == sizeof(float)); + GGML_ASSERT(nb0 <= nb1); + GGML_ASSERT(nb1 <= nb2); + GGML_ASSERT(nb2 <= nb3); + + assert(dst->type == GGML_TYPE_F32); + assert(q->type == GGML_TYPE_F32); + assert(k->type == v->type); + + FaCodePath path = ctx->device->coopmat2 ? FA_COOPMAT2 : + ctx->device->coopmat1_fa_support ? FA_COOPMAT1 : FA_SCALAR; + + if (path == FA_COOPMAT1) { + const bool coopmat_shape_supported = (dst->op_params[3] == GGML_PREC_F32 && ctx->device->coopmat_support_16x16x16_f32acc) || + (dst->op_params[3] != GGML_PREC_F32 && ctx->device->coopmat_support_16x16x16_f16acc); + + const bool coopmat_shmem_supported = ggml_vk_flash_attn_coopmat_shmem_support(ctx->device, D, dst->op_params[3] == GGML_PREC_F32); + + if (!coopmat_shape_supported || !coopmat_shmem_supported) { + path = FA_SCALAR; } } + uint32_t gqa_ratio = 1; + uint32_t qk_ratio = neq2 / nek2; + uint32_t workgroups_x = (uint32_t)neq1; + uint32_t workgroups_y = (uint32_t)neq2; + uint32_t workgroups_z = (uint32_t)neq3; + + // For scalar/coopmat1 FA, we can use the "large" size to accommodate qga. + // For coopmat2 FA, we always use the small size (which is still pretty large for gqa). + uint32_t max_gqa; + switch (path) { + case FA_SCALAR: + case FA_COOPMAT1: + // We may switch from coopmat1 to scalar, so use the scalar limit for both + max_gqa = scalar_flash_attention_num_large_rows; + break; + case FA_COOPMAT2: + max_gqa = get_fa_num_small_rows(FA_COOPMAT2); + break; + default: + GGML_ASSERT(0); + } + + if (N == 1 && qk_ratio > 1 && qk_ratio <= max_gqa && + qk_ratio * nek2 == neq2 && nek2 == nev2 && neq3 == 1 && nek3 == 1 && nev3 == 1) { + // grouped query attention - make the N dimension equal to gqa_ratio, reduce + // workgroups proportionally in y dimension. The shader will detect gqa_ratio > 1 + // and change addressing calculations to index Q's dimension 2. + gqa_ratio = qk_ratio; + N = gqa_ratio; + workgroups_y /= N; + } + + vk_pipeline *pipelines; + bool small_rows = N <= get_fa_num_small_rows(path); + + // coopmat1 does not actually support "small rows" (it needs 16 rows). + // So use scalar instead. + if (small_rows && path == FA_COOPMAT1) { + path = FA_SCALAR; + } + + // scalar is faster than coopmat2 when N==1 + if (N == 1 && path == FA_COOPMAT2) { + path = FA_SCALAR; + } + + bool f32acc = path == FA_SCALAR || dst->op_params[3] == GGML_PREC_F32; + + switch (path) { + case FA_SCALAR: + switch (D) { + case 64: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D64[k->type][f32acc][small_rows][0]; break; + case 80: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D80[k->type][f32acc][small_rows][0]; break; + case 96: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D96[k->type][f32acc][small_rows][0]; break; + case 112: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D112[k->type][f32acc][small_rows][0]; break; + case 128: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D128[k->type][f32acc][small_rows][0]; break; + case 256: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D256[k->type][f32acc][small_rows][0]; break; + default: + GGML_ASSERT(!"unsupported D value"); + return; + } + break; + case FA_COOPMAT1: + switch (D) { + case 64: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D64_cm1[k->type][f32acc][small_rows][0]; break; + case 80: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D80_cm1[k->type][f32acc][small_rows][0]; break; + case 96: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D96_cm1[k->type][f32acc][small_rows][0]; break; + case 112: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D112_cm1[k->type][f32acc][small_rows][0]; break; + case 128: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D128_cm1[k->type][f32acc][small_rows][0]; break; + case 256: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D256_cm1[k->type][f32acc][small_rows][0]; break; + default: + GGML_ASSERT(!"unsupported D value"); + return; + } + break; + case FA_COOPMAT2: + switch (D) { + case 64: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D64_cm2[k->type][f32acc][small_rows][0]; break; + case 80: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D80_cm2[k->type][f32acc][small_rows][0]; break; + case 96: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D96_cm2[k->type][f32acc][small_rows][0]; break; + case 112: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D112_cm2[k->type][f32acc][small_rows][0]; break; + case 128: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D128_cm2[k->type][f32acc][small_rows][0]; break; + case 256: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D256_cm2[k->type][f32acc][small_rows][0]; break; + default: + GGML_ASSERT(!"unsupported D value"); + return; + } + break; + default: + GGML_ASSERT(0); + } + assert(pipelines); + + const uint32_t q_stride = (uint32_t)(nbq1 / ggml_type_size(q->type)); + const uint32_t k_stride = (uint32_t)(nbk1 / ggml_type_size(k->type)); + const uint32_t v_stride = (uint32_t)(nbv1 / ggml_type_size(v->type)); + + bool aligned = (KV % pipelines[1]->align) == 0 && + // the "aligned" shader variant will forcibly align strides, for performance + (q_stride & 7) == 0 && (k_stride & 7) == 0 && (v_stride & 7) == 0; + + // mask dim1 is padded to 64, we rely on this to avoid clamping mask loads + GGML_ASSERT((nem1 % GGML_KQ_MASK_PAD) == 0); + + vk_pipeline pipeline = pipelines[aligned]; + assert(pipeline); + + uint32_t split_kv = KV; + uint32_t split_k = 1; + + // Use a placeholder core count if one isn't available. split_k is a big help for perf. + const uint32_t shader_core_count = ctx->device->shader_core_count ? ctx->device->shader_core_count : 16; + + // Try to use split_k when KV is large enough to be worth the overhead + if (workgroups_x == 1 && shader_core_count > 0 && KV >= 512) { + // Try to run two workgroups per SM. + split_k = ctx->device->shader_core_count * 2 / workgroups_y; + if (split_k > 1) { + // Try to evenly split KV into split_k chunks, but it needs to be a multiple + // of "align", so recompute split_k based on that. + split_kv = ROUNDUP_POW2(KV / split_k, pipelines[1]->align); + split_k = CEIL_DIV(KV, split_kv); + workgroups_x = split_k; + } + } + + // Reserve space for split_k temporaries. For each split, we need to store the O matrix (D x ne1) + // and the per-row m and L values (ne1 rows). + const uint64_t split_k_size = split_k > 1 ? (D * ne1 * sizeof(float) + ne1 * sizeof(float) * 2) * split_k : 0; + if (split_k_size > ctx->device->max_memory_allocation_size) { + GGML_ABORT("Requested preallocation size is too large"); + } + if (ctx->prealloc_size_split_k < split_k_size) { + ctx->prealloc_size_split_k = split_k_size; + } + + if (dryrun) { + // Request descriptor sets + ggml_pipeline_request_descriptor_sets(ctx, pipeline, 1); + if (split_k > 1) { + ggml_pipeline_request_descriptor_sets(ctx, ctx->device->pipeline_flash_attn_split_k_reduce, 1); + } + return; + } + + float scale = 1.0f; + float max_bias = 0.0f; + float logit_softcap = 0.0f; + + memcpy(&scale, (const float *) dst->op_params + 0, sizeof(float)); + memcpy(&max_bias, (const float *) dst->op_params + 1, sizeof(float)); + memcpy(&logit_softcap, (const float *) dst->op_params + 2, sizeof(float)); + + if (logit_softcap != 0) { + scale /= logit_softcap; + } + + const uint32_t n_head_kv = neq2; + const uint32_t n_head_log2 = 1u << (uint32_t) floorf(log2f((float) n_head_kv)); + const float m0 = powf(2.0f, -(max_bias ) / n_head_log2); + const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2); + + vk_buffer d_Q = nullptr, d_K = nullptr, d_V = nullptr, d_D = nullptr, d_M = nullptr; + size_t q_buf_offset = 0, k_buf_offset = 0, v_buf_offset = 0, d_buf_offset = 0, m_buf_offset = 0; + + bool Q_uma = false, K_uma = false, V_uma = false, D_uma = false, M_uma = false; + + if (ctx->device->uma) { + ggml_vk_host_get(ctx->device, q->data, d_Q, q_buf_offset); + ggml_vk_host_get(ctx->device, k->data, d_K, k_buf_offset); + ggml_vk_host_get(ctx->device, v->data, d_V, v_buf_offset); + ggml_vk_host_get(ctx->device, dst->data, d_D, d_buf_offset); + Q_uma = d_Q != nullptr; + K_uma = d_K != nullptr; + V_uma = d_V != nullptr; + D_uma = d_D != nullptr; + if (mask) { + ggml_vk_host_get(ctx->device, mask->data, d_M, m_buf_offset); + M_uma = d_M != nullptr; + } + } + + + ggml_backend_vk_buffer_context * d_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * q_buf_ctx = (ggml_backend_vk_buffer_context *)q->buffer->context; + ggml_backend_vk_buffer_context * k_buf_ctx = (ggml_backend_vk_buffer_context *)k->buffer->context; + ggml_backend_vk_buffer_context * v_buf_ctx = (ggml_backend_vk_buffer_context *)v->buffer->context; + + if (!Q_uma) { + d_Q = q_buf_ctx->dev_buffer; + q_buf_offset = vk_tensor_offset(q) + q->view_offs; + } + if (!K_uma) { + d_K = k_buf_ctx->dev_buffer; + k_buf_offset = vk_tensor_offset(k) + k->view_offs; + } + if (!V_uma) { + d_V = v_buf_ctx->dev_buffer; + v_buf_offset = vk_tensor_offset(v) + v->view_offs; + } + if (!D_uma) { + d_D = d_buf_ctx->dev_buffer; + d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; + } + + if (!M_uma) { + d_M = d_Q; + m_buf_offset = q_buf_offset; + if (mask) { + ggml_backend_vk_buffer_context * m_buf_ctx = (ggml_backend_vk_buffer_context*)mask->buffer->context; + d_M = m_buf_ctx->dev_buffer; + m_buf_offset = vk_tensor_offset(mask) + mask->view_offs; + } + } + + const vk_flash_attn_push_constants pc = { N, KV, + (uint32_t)ne1, (uint32_t)ne2, (uint32_t)ne3, + (uint32_t)neq2, (uint32_t)neq3, + (uint32_t)nek2, (uint32_t)nek3, + (uint32_t)nev2, (uint32_t)nev3, + nem1, + q_stride, (uint32_t)nbq2, (uint32_t)nbq3, + k_stride, (uint32_t)nbk2, (uint32_t)nbk3, + v_stride, (uint32_t)nbv2, (uint32_t)nbv3, + nbm1, + scale, max_bias, logit_softcap, + mask != nullptr, n_head_log2, m0, m1, + gqa_ratio, split_kv, split_k }; + ggml_vk_sync_buffers(subctx); - subctx->s->buffer.copyBuffer(src_buf->buffer, dst_buf->buffer, copies); - GGML_UNUSED(ctx); - GGML_UNUSED(src1); + if (split_k > 1) { + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, + { + vk_subbuffer{d_Q, q_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{d_K, k_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{d_V, v_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{d_M, m_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{ctx->prealloc_split_k, 0, VK_WHOLE_SIZE}, + }, + // We only use split_k when group query attention is enabled, which means + // there's no more than one tile of rows (i.e. workgroups_x would have been + // one). We reuse workgroups_x to mean the number of splits, so we need to + // cancel out the divide by wg_denoms[0]. + sizeof(vk_flash_attn_push_constants), &pc, { workgroups_x * pipeline->wg_denoms[0], workgroups_y, workgroups_z }); + + ggml_vk_sync_buffers(subctx); + const std::array pc2 = { D, (uint32_t)ne1, split_k }; + ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_flash_attn_split_k_reduce, + { + vk_subbuffer{ctx->prealloc_split_k, 0, VK_WHOLE_SIZE}, + vk_subbuffer{d_D, d_buf_offset, VK_WHOLE_SIZE}, + }, + pc2.size() * uint32_t{sizeof(uint32_t)}, pc2.data(), { (uint32_t)ne1, 1, 1 }); + } else { + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, + { + vk_subbuffer{d_Q, q_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{d_K, k_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{d_V, v_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{d_M, m_buf_offset, VK_WHOLE_SIZE}, + vk_subbuffer{d_D, d_buf_offset, VK_WHOLE_SIZE}, + }, + sizeof(vk_flash_attn_push_constants), &pc, { workgroups_x, workgroups_y, workgroups_z }); + } } - static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst, ggml_op op) { switch (op) { case GGML_OP_GET_ROWS: @@ -3932,21 +6278,37 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const } return nullptr; case GGML_OP_ADD: - if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_add_f32; - } - if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F16) { - return ctx->device->pipeline_add_f16_f32_f16; - } - return nullptr; + case GGML_OP_SUB: case GGML_OP_MUL: - if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_mul_f32; - } - return nullptr; case GGML_OP_DIV: - if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_div_f32; + if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || + (src1->type != GGML_TYPE_F32 && src1->type != GGML_TYPE_F16) || + (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16)) { + return nullptr; + } + switch (op) { + case GGML_OP_ADD: + { + auto pipelines = ggml_are_same_shape(src0, src1) ? ctx->device->pipeline_add_norepeat : ctx->device->pipeline_add; + return pipelines[src0->type == GGML_TYPE_F16][src1->type == GGML_TYPE_F16][dst->type == GGML_TYPE_F16]; + } + case GGML_OP_SUB: + { + auto pipelines = ggml_are_same_shape(src0, src1) ? ctx->device->pipeline_sub_norepeat : ctx->device->pipeline_sub; + return pipelines[src0->type == GGML_TYPE_F16][src1->type == GGML_TYPE_F16][dst->type == GGML_TYPE_F16]; + } + case GGML_OP_MUL: + { + auto pipelines = ggml_are_same_shape(src0, src1) ? ctx->device->pipeline_mul_norepeat : ctx->device->pipeline_mul; + return pipelines[src0->type == GGML_TYPE_F16][src1->type == GGML_TYPE_F16][dst->type == GGML_TYPE_F16]; + } + case GGML_OP_DIV: + { + auto pipelines = ggml_are_same_shape(src0, src1) ? ctx->device->pipeline_div_norepeat : ctx->device->pipeline_div; + return pipelines[src0->type == GGML_TYPE_F16][src1->type == GGML_TYPE_F16][dst->type == GGML_TYPE_F16]; + } + default: + break; } return nullptr; case GGML_OP_CONCAT: @@ -3985,10 +6347,25 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_pad_f32; } return nullptr; + case GGML_OP_REPEAT: + if (ggml_type_size(src0->type) == sizeof(float) && ggml_type_size(dst->type) == sizeof(float)) { + return ctx->device->pipeline_repeat_f32; + } + return nullptr; + case GGML_OP_REPEAT_BACK: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_repeat_back_f32; + } + return nullptr; case GGML_OP_CPY: case GGML_OP_CONT: case GGML_OP_DUP: - return ggml_vk_get_cpy_pipeline(ctx, src0->type, dst->type); + return ggml_vk_get_cpy_pipeline(ctx, src0, dst, dst->type); + case GGML_OP_SILU_BACK: + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_silu_back_f32; + } + return nullptr; case GGML_OP_NORM: if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_norm_f32; @@ -4004,33 +6381,31 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_rms_norm_f32; } return nullptr; + case GGML_OP_RMS_NORM_BACK: + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_rms_norm_back_f32; + } + return nullptr; case GGML_OP_UNARY: + if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || + (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16) || + (src0->type != dst->type)) { + return nullptr; + } + switch (ggml_get_unary_op(dst)) { case GGML_UNARY_OP_SILU: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_silu_f32; - } - break; + return ctx->device->pipeline_silu[dst->type == GGML_TYPE_F16]; case GGML_UNARY_OP_GELU: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_gelu_f32; - } - break; + return ctx->device->pipeline_gelu[dst->type == GGML_TYPE_F16]; case GGML_UNARY_OP_GELU_QUICK: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_gelu_quick_f32; - } - break; + return ctx->device->pipeline_gelu_quick[dst->type == GGML_TYPE_F16]; case GGML_UNARY_OP_RELU: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_relu_f32; - } - break; + return ctx->device->pipeline_relu[dst->type == GGML_TYPE_F16]; case GGML_UNARY_OP_TANH: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_tanh_f32; - } - break; + return ctx->device->pipeline_tanh[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_SIGMOID: + return ctx->device->pipeline_sigmoid[dst->type == GGML_TYPE_F16]; default: break; } @@ -4044,13 +6419,19 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const GGML_ASSERT(!src1 || src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16); if (src0->type == GGML_TYPE_F32 && (src1 == nullptr || src1->type == GGML_TYPE_F32) && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_soft_max_f32; + return src0->ne[0] > 1024 ? ctx->device->pipeline_soft_max_f32_wg512 : ctx->device->pipeline_soft_max_f32; } if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_soft_max_f32_f16; + return src0->ne[0] > 1024 ? ctx->device->pipeline_soft_max_f32_f16_wg512 : ctx->device->pipeline_soft_max_f32_f16; + } + return nullptr; + case GGML_OP_SOFT_MAX_BACK: + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_soft_max_back_f32; } return nullptr; case GGML_OP_ROPE: + case GGML_OP_ROPE_BACK: { const int mode = ((const int32_t *) dst->op_params)[2]; const bool is_neox = mode & 2; @@ -4077,11 +6458,17 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_argsort_f32; } return nullptr; + case GGML_OP_SUM: case GGML_OP_SUM_ROWS: if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_sum_rows_f32; } return nullptr; + case GGML_OP_ARGMAX: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_I32) { + return ctx->device->pipeline_argmax_f32; + } + return nullptr; case GGML_OP_IM2COL: if (src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_im2col_f32; @@ -4095,6 +6482,16 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_timestep_embedding_f32; } return nullptr; + case GGML_OP_CONV_TRANSPOSE_1D: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_conv_transpose_1d_f32; + } + return nullptr; + case GGML_OP_POOL_2D: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_pool2d_f32; + } + return nullptr; case GGML_OP_LEAKY_RELU: if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_leaky_relu_f32; @@ -4107,36 +6504,83 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const GGML_UNUSED(src2); } -static ggml_vk_func_t ggml_vk_op_get_func(ggml_op op) { - switch(op) { - case GGML_OP_REPEAT: - return ggml_vk_op_repeat; - default: - return nullptr; - } -} - static bool ggml_vk_op_supports_incontiguous(ggml_op op) { switch (op) { case GGML_OP_CPY: case GGML_OP_GET_ROWS: case GGML_OP_ADD: + case GGML_OP_SUB: case GGML_OP_MUL: case GGML_OP_DIV: case GGML_OP_CONCAT: case GGML_OP_UPSCALE: - case GGML_OP_SCALE: case GGML_OP_SQR: case GGML_OP_CLAMP: case GGML_OP_PAD: + case GGML_OP_REPEAT: + case GGML_OP_REPEAT_BACK: + case GGML_OP_ROPE: + case GGML_OP_RMS_NORM: + case GGML_OP_IM2COL: return true; default: return false; } } +static uint32_t get_misalign_bytes(ggml_backend_vk_context * ctx, const ggml_tensor * t) +{ + return ((vk_tensor_offset(t) + t->view_offs) & (ctx->device->properties.limits.minStorageBufferOffsetAlignment - 1));; +} + +template void init_pushconst_tensor_offsets(ggml_backend_vk_context * ctx, T &p, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst) { + GGML_UNUSED(p); + GGML_UNUSED(src0); + GGML_UNUSED(src1); + GGML_UNUSED(src2); + GGML_UNUSED(dst); + static_assert(!std::is_const::value, "unexpected type"); + GGML_ASSERT(!src0 || get_misalign_bytes(ctx, src0) == 0); + GGML_ASSERT(!src1 || get_misalign_bytes(ctx, src1) == 0); + GGML_ASSERT(!src2 || get_misalign_bytes(ctx, src2) == 0); + GGML_ASSERT(!dst || get_misalign_bytes(ctx, dst) == 0); +} + +template <> void init_pushconst_tensor_offsets(ggml_backend_vk_context * ctx, vk_op_unary_push_constants &p, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst) { + const uint32_t a_offset = get_misalign_bytes(ctx, src0) / ggml_type_size(src0->type); + const uint32_t d_offset = get_misalign_bytes(ctx, dst) / ggml_type_size(dst->type); + + p.misalign_offsets = (a_offset << 16) | d_offset; + + GGML_UNUSED(src1); + GGML_UNUSED(src2); +} + +template <> void init_pushconst_tensor_offsets(ggml_backend_vk_context * ctx, vk_op_binary_push_constants &p, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst) { + const uint32_t a_offset = get_misalign_bytes(ctx, src0) / ggml_type_size(src0->type); + const uint32_t b_offset = get_misalign_bytes(ctx, src1) / ggml_type_size(src1->type); + const uint32_t d_offset = get_misalign_bytes(ctx, dst) / ggml_type_size(dst->type); + + GGML_ASSERT(dst->op != GGML_OP_GET_ROWS || (a_offset == 0 && b_offset == 0 && d_offset == 0)); + + p.misalign_offsets = (a_offset << 16) | (b_offset << 8) | d_offset; + + GGML_UNUSED(src2); +} + +template <> void init_pushconst_tensor_offsets(ggml_backend_vk_context * ctx, vk_op_upscale_push_constants &p, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst) { + const uint32_t a_offset = get_misalign_bytes(ctx, src0) / ggml_type_size(src0->type); + const uint32_t d_offset = get_misalign_bytes(ctx, dst) / ggml_type_size(dst->type); + + p.a_offset = a_offset; + p.d_offset = d_offset; + + GGML_UNUSED(src1); + GGML_UNUSED(src2); +} + template -static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst, ggml_op op, const PC&& pc) { +static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst, ggml_op op, PC&& pc, bool dryrun = false) { VK_LOG_DEBUG("ggml_vk_op_f32((" << src0 << ", name=" << src0->name << ", type=" << src0->type << ", ne0=" << src0->ne[0] << ", ne1=" << src0->ne[1] << ", ne2=" << src0->ne[2] << ", ne3=" << src0->ne[3] << ", nb0=" << src0->nb[0] << ", nb1=" << src0->nb[1] << ", nb2=" << src0->nb[2] << ", nb3=" << src0->nb[3]; if (src1 != nullptr) { std::cerr << "), (" << src1 << ", name=" << src1->name << ", type=" << src1->type << ", ne0=" << src1->ne[0] << ", ne1=" << src1->ne[1] << ", ne2=" << src1->ne[2] << ", ne3=" << src1->ne[3] << ", nb0=" << src1->nb[0] << ", nb1=" << src1->nb[1] << ", nb2=" << src1->nb[2] << ", nb3=" << src1->nb[3]; @@ -4144,10 +6588,11 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co if (src2 != nullptr) { std::cerr << "), (" << src2 << ", name=" << src2->name << ", type=" << src2->type << ", ne0=" << src2->ne[0] << ", ne1=" << src2->ne[1] << ", ne2=" << src2->ne[2] << ", ne3=" << src2->ne[3] << ", nb0=" << src2->nb[0] << ", nb1=" << src2->nb[1] << ", nb2=" << src2->nb[2] << ", nb3=" << src2->nb[3]; } - std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3] << "), " << ggml_op_name(op) << ")"); - GGML_ASSERT(op == GGML_OP_GET_ROWS || (!ggml_is_quantized(src0->type) && (src1 == nullptr || !ggml_is_quantized(src1->type)))); // NOLINT + std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3]; + std::cerr << "), " << ggml_op_name(op) << ", " << (dryrun ? "dryrun" : "") << ")"); + GGML_ASSERT(op == GGML_OP_GET_ROWS || op == GGML_OP_CPY || (!ggml_is_quantized(src0->type) && (src1 == nullptr || !ggml_is_quantized(src1->type)))); // NOLINT GGML_ASSERT(ggml_vk_op_supports_incontiguous(op) || ggml_vk_dim01_contiguous(src0)); // NOLINT - GGML_ASSERT(dst->extra != nullptr); + GGML_ASSERT(dst->buffer != nullptr); const uint64_t ne00 = src0->ne[0]; const uint64_t ne01 = src0->ne[1]; const uint64_t ne02 = src0->ne[2]; @@ -4175,30 +6620,30 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co const uint64_t ned3 = dst->ne[3]; const uint64_t ned = ned0 * ned1; + init_pushconst_fastdiv(pc); + vk_pipeline pipeline = ggml_vk_op_get_pipeline(ctx, src0, src1, src2, dst, op); - ggml_vk_func_t op_func; if (pipeline == nullptr) { - op_func = ggml_vk_op_get_func(op); - if (op_func == nullptr) { - std::cerr << "ggml_vulkan: Error: Missing op: " << ggml_op_name(op) << " for " << ggml_type_name(src0->type); - if (src1 != nullptr) { - std::cerr << " and " << ggml_type_name(src1->type); - } - std::cerr << " to " << ggml_type_name(dst->type) << std::endl; - GGML_ABORT("fatal error"); + std::cerr << "ggml_vulkan: Error: Missing op: " << ggml_op_name(op) << " for " << ggml_type_name(src0->type); + if (src1 != nullptr) { + std::cerr << " and " << ggml_type_name(src1->type); } + std::cerr << " to " << ggml_type_name(dst->type) << std::endl; + GGML_ABORT("fatal error"); + } - op_func(ctx, subctx, src0, src1, dst); + if (dryrun) { + ggml_pipeline_request_descriptor_sets(ctx, pipeline, 1); return; } const bool op_supports_incontiguous = ggml_vk_op_supports_incontiguous(op); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; - ggml_tensor_extra_gpu * extra_src0 = (ggml_tensor_extra_gpu *) src0->extra; - ggml_tensor_extra_gpu * extra_src1 = use_src1 ? (ggml_tensor_extra_gpu *) src1->extra : nullptr; - ggml_tensor_extra_gpu * extra_src2 = use_src2 ? (ggml_tensor_extra_gpu *) src2->extra : nullptr; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src0_buf_ctx = (ggml_backend_vk_buffer_context *)src0->buffer->context; + ggml_backend_vk_buffer_context * src1_buf_ctx = use_src1 ? (ggml_backend_vk_buffer_context *)src1->buffer->context : nullptr; + ggml_backend_vk_buffer_context * src2_buf_ctx = use_src2 ? (ggml_backend_vk_buffer_context *)src2->buffer->context : nullptr; vk_buffer d_X = nullptr; size_t x_buf_offset = 0; @@ -4229,7 +6674,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co uint64_t z_sz = use_src2 ? ggml_type_size(src2->type) * ne2 : 0; uint64_t d_sz = ggml_type_size(dst->type) * ned; - vk_buffer d_D = extra->buffer_gpu.lock(); + vk_buffer d_D = dst_buf_ctx->dev_buffer; // Workaround for tiny tensor inputs on ROPE if (op == GGML_OP_ROPE && use_src1 && y_sz > d_D->size) { @@ -4237,23 +6682,28 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co } GGML_ASSERT(d_D != nullptr); - uint64_t d_buf_offset = ((extra->offset + dst->view_offs) / ctx->device->properties.limits.minStorageBufferOffsetAlignment) * ctx->device->properties.limits.minStorageBufferOffsetAlignment; - GGML_ASSERT(d_buf_offset == extra->offset || op == GGML_OP_CPY); // NOLINT + uint64_t d_buf_offset = vk_tensor_offset(dst) + dst->view_offs; if(!src0_uma) { - d_X = extra_src0->buffer_gpu.lock(); - x_buf_offset = extra_src0->offset + src0->view_offs; + d_X = src0_buf_ctx->dev_buffer; + x_buf_offset = vk_tensor_offset(src0) + src0->view_offs; GGML_ASSERT(d_X != nullptr); } if (use_src1 && !src1_uma) { - d_Y = extra_src1->buffer_gpu.lock(); - y_buf_offset = extra_src1->offset + src1->view_offs; + d_Y = src1_buf_ctx->dev_buffer; + y_buf_offset = vk_tensor_offset(src1) + src1->view_offs; GGML_ASSERT(d_Y != nullptr); } if (use_src2 && !src2_uma) { - d_Z = extra_src2->buffer_gpu.lock(); - z_buf_offset = extra_src2->offset + src2->view_offs; + d_Z = src2_buf_ctx->dev_buffer; + z_buf_offset = vk_tensor_offset(src2) + src2->view_offs; GGML_ASSERT(d_Z != nullptr); } + // Compute misalignment offset for descriptors and store it in in push constants, then align the descriptor offsets. + init_pushconst_tensor_offsets(ctx, pc, src0, src1, src2, dst); + x_buf_offset &= ~(ctx->device->properties.limits.minStorageBufferOffsetAlignment - 1); + y_buf_offset &= ~(ctx->device->properties.limits.minStorageBufferOffsetAlignment - 1); + z_buf_offset &= ~(ctx->device->properties.limits.minStorageBufferOffsetAlignment - 1); + d_buf_offset &= ~(ctx->device->properties.limits.minStorageBufferOffsetAlignment - 1); if (op_supports_incontiguous) { x_sz = ggml_nbytes(src0); @@ -4278,188 +6728,175 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co std::array elements; // Single call if dimension 2 is contiguous - if (op_supports_incontiguous || (ggml_is_contiguous(src0) && (src1 == nullptr || ggml_is_contiguous(src1)))) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, pipeline, 1); + GGML_ASSERT(op_supports_incontiguous || (ggml_is_contiguous(src0) && (src1 == nullptr || ggml_is_contiguous(src1)))); - switch (op) { - case GGML_OP_NORM: - case GGML_OP_RMS_NORM: - case GGML_OP_SOFT_MAX: - case GGML_OP_SUM_ROWS: - { - const uint32_t nr = ggml_nrows(src0); - if (nr > 262144) { - elements = { 512, 512, CEIL_DIV(nr, 262144) }; - } else if (nr > 512) { - elements = { 512, CEIL_DIV(nr, 512), 1 }; - } else { - elements = { nr, 1, 1 }; - } - } break; - case GGML_OP_GROUP_NORM: - { - const uint32_t num_groups = dst->op_params[0]; - elements = { num_groups * (uint32_t)src0->ne[3], 1, 1 }; - } break; - case GGML_OP_DIAG_MASK_INF: - case GGML_OP_ROPE: - elements = { (uint32_t)ggml_nrows(src0), (uint32_t)ne00, 1 }; - break; - case GGML_OP_GET_ROWS: - elements = { (uint32_t)ne00, (uint32_t)ne10, (uint32_t)(ne11 * ne12) }; - break; - case GGML_OP_ARGSORT: - elements = { (uint32_t)ne00, (uint32_t)ggml_nrows(src0), 1 }; - break; - case GGML_OP_IM2COL: - { - const bool is_2D = dst->op_params[6] == 1; - - const uint32_t IC = src1->ne[is_2D ? 2 : 1]; - - const uint32_t KH = is_2D ? src0->ne[1] : 1; - const uint32_t KW = src0->ne[0]; - - const uint32_t OH = is_2D ? dst->ne[2] : 1; - const uint32_t OW = dst->ne[1]; - - const uint32_t batch = src1->ne[3]; - - elements = { OW * KW * KH, OH, batch * IC }; - } break; - case GGML_OP_TIMESTEP_EMBEDDING: - { - const uint32_t dim = dst->op_params[0]; - uint32_t half_ceil = (dim + 1) / 2; - elements = { half_ceil, (uint32_t)src0->ne[0], 1 }; - } break; - case GGML_OP_ADD: - case GGML_OP_DIV: - case GGML_OP_MUL: - case GGML_OP_SCALE: - case GGML_OP_SQR: - case GGML_OP_CLAMP: - case GGML_OP_PAD: - case GGML_OP_CPY: - case GGML_OP_CONCAT: - case GGML_OP_UPSCALE: - case GGML_OP_UNARY: - { - const uint32_t ne = ggml_nelements(dst); - if (ne > 262144) { - elements = { 512, 512, CEIL_DIV(ne, 262144) }; - } else if (ne > 512) { - elements = { 512, CEIL_DIV(ne, 512), 1 }; - } else { - elements = { ne, 1, 1 }; - } - } break; - default: - elements = { (uint32_t)ggml_nelements(src0), 1, 1 }; - break; - } - - if (!op_supports_incontiguous) { - if (x_sz != VK_WHOLE_SIZE) { - x_sz *= ne02 * ne03; - } - if (use_src1 && y_sz != VK_WHOLE_SIZE) { - y_sz *= ne12 * ne13; - } - if (use_src2 && z_sz != VK_WHOLE_SIZE) { - z_sz *= ne22 * ne23; - } - if (d_sz != VK_WHOLE_SIZE) { - d_sz *= ned2 * ned3; - } - } - - if (op == GGML_OP_SOFT_MAX) { - // Empty src1 is possible in soft_max, but the shader needs a buffer - vk_subbuffer subbuf_y; - if (use_src1) { - subbuf_y = { d_Y, y_buf_offset, y_sz }; + switch (op) { + case GGML_OP_NORM: + case GGML_OP_RMS_NORM_BACK: + case GGML_OP_SOFT_MAX: + case GGML_OP_SOFT_MAX_BACK: + case GGML_OP_SUM_ROWS: + case GGML_OP_ARGMAX: + { + const uint32_t nr = ggml_nrows(src0); + if (nr > 262144) { + elements = { 512, 512, CEIL_DIV(nr, 262144) }; + } else if (nr > 512) { + elements = { 512, CEIL_DIV(nr, 512), 1 }; } else { - subbuf_y = { d_X, 0, x_sz }; + elements = { nr, 1, 1 }; } + } break; + case GGML_OP_RMS_NORM: + elements = { (uint32_t)ne01, (uint32_t)ne02, (uint32_t)ne03 }; + break; - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, subbuf_y, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); - } else if (op == GGML_OP_ROPE) { - // Empty src2 is possible in rope, but the shader needs a buffer - vk_subbuffer subbuf_z; - if (use_src2) { - subbuf_z = { d_Z, z_buf_offset, z_sz }; + case GGML_OP_SUM: + // We use GGML_OP_SUM_ROWS with 1 row. + elements = { 1, 1, 1 }; + break; + case GGML_OP_GROUP_NORM: + { + const uint32_t num_groups = dst->op_params[0]; + elements = { num_groups * (uint32_t)src0->ne[3], 1, 1 }; + } break; + case GGML_OP_DIAG_MASK_INF: + case GGML_OP_ROPE: + case GGML_OP_ROPE_BACK: + elements = { (uint32_t)ggml_nrows(src0), (uint32_t)ne00, 1 }; + break; + case GGML_OP_GET_ROWS: + elements = { (uint32_t)ne00, (uint32_t)ne10, (uint32_t)(ne11 * ne12) }; + break; + case GGML_OP_ARGSORT: + elements = { (uint32_t)ne00, (uint32_t)ggml_nrows(src0), 1 }; + break; + case GGML_OP_IM2COL: + { + const bool is_2D = dst->op_params[6] == 1; + + const uint32_t IC = src1->ne[is_2D ? 2 : 1]; + + const uint32_t KH = is_2D ? src0->ne[1] : 1; + const uint32_t KW = src0->ne[0]; + + const uint32_t OH = is_2D ? dst->ne[2] : 1; + const uint32_t OW = dst->ne[1]; + + const uint32_t batch = src1->ne[is_2D ? 3 : 2]; + + elements = { OW * KW * KH, OH, batch * IC }; + } break; + case GGML_OP_TIMESTEP_EMBEDDING: + { + const uint32_t dim = dst->op_params[0]; + uint32_t half_ceil = (dim + 1) / 2; + elements = { half_ceil, (uint32_t)src0->ne[0], 1 }; + } break; + case GGML_OP_CONV_TRANSPOSE_1D: + { + elements = {uint32_t(src0->ne[1]), 1, 1}; // parallelize in {Cout, 1, 1} + } break; + case GGML_OP_POOL_2D: + { + const uint32_t N = dst->ne[3]; + const uint32_t OC = dst->ne[2]; + const uint32_t OH = dst->ne[1]; + const uint32_t OW = dst->ne[0]; + elements = { N * OC * OH * OW, 1, 1}; + } break; + case GGML_OP_ADD: + case GGML_OP_SUB: + case GGML_OP_DIV: + case GGML_OP_MUL: + case GGML_OP_SCALE: + case GGML_OP_SQR: + case GGML_OP_CLAMP: + case GGML_OP_PAD: + case GGML_OP_REPEAT: + case GGML_OP_REPEAT_BACK: + case GGML_OP_CPY: + case GGML_OP_CONCAT: + case GGML_OP_UPSCALE: + case GGML_OP_UNARY: + { + uint32_t ne = ggml_nelements(dst); + if (op == GGML_OP_CPY && ggml_is_quantized(src0->type) && ggml_is_quantized(dst->type)) { + // Convert from number of logical elements to 2- or 4-byte units. + ne /= ggml_blck_size(src0->type); + if ((ggml_type_size(src0->type) % 4) == 0) { + ne *= ggml_type_size(src0->type) / 4; + } else { + ne *= ggml_type_size(src0->type) / 2; + } + } + if (ne > 262144) { + elements = { 512, 512, CEIL_DIV(ne, 262144) }; + } else if (ne > 512) { + elements = { 512, CEIL_DIV(ne, 512), 1 }; } else { - subbuf_z = { d_X, 0, x_sz }; + elements = { ne, 1, 1 }; } + } break; + default: + elements = { (uint32_t)ggml_nelements(src0), 1, 1 }; + break; + } - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, subbuf_z, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); - } else if (op == GGML_OP_IM2COL) { - // im2col uses only src1 and dst buffers - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); - } else if (use_src2) { - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_Z, z_buf_offset, z_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); - } else if (use_src1) { - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + if (!op_supports_incontiguous) { + if (x_sz != VK_WHOLE_SIZE) { + x_sz *= ne02 * ne03; + } + if (use_src1 && y_sz != VK_WHOLE_SIZE) { + y_sz *= ne12 * ne13; + } + if (use_src2 && z_sz != VK_WHOLE_SIZE) { + z_sz *= ne22 * ne23; + } + if (d_sz != VK_WHOLE_SIZE) { + d_sz *= ned2 * ned3; + } + } + + if (op == GGML_OP_SOFT_MAX) { + // Empty src1 is possible in soft_max, but the shader needs a buffer + vk_subbuffer subbuf_y; + if (use_src1) { + subbuf_y = { d_Y, y_buf_offset, y_sz }; } else { - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + subbuf_y = { d_X, 0, x_sz }; } + + ggml_vk_sync_buffers(subctx); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, subbuf_y, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + } else if (op == GGML_OP_ROPE || op == GGML_OP_ROPE_BACK) { + // Empty src2 is possible in rope, but the shader needs a buffer + vk_subbuffer subbuf_z; + if (use_src2) { + subbuf_z = { d_Z, z_buf_offset, z_sz }; + } else { + subbuf_z = { d_X, 0, x_sz }; + } + + ggml_vk_sync_buffers(subctx); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, subbuf_z, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + } else if (op == GGML_OP_IM2COL) { + // im2col uses only src1 and dst buffers + ggml_vk_sync_buffers(subctx); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + } else if (use_src2) { + ggml_vk_sync_buffers(subctx); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_Z, z_buf_offset, z_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + } else if (use_src1) { + ggml_vk_sync_buffers(subctx); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); } else { - GGML_ASSERT(op != GGML_OP_SOFT_MAX); - GGML_ASSERT(op != GGML_OP_ARGSORT); - GGML_ASSERT(!use_src2); - - ggml_pipeline_allocate_descriptor_sets(ctx->device, pipeline, ne02 * ne03); - - switch (op) { - case GGML_OP_NORM: - case GGML_OP_GROUP_NORM: - case GGML_OP_RMS_NORM: - elements = { (uint32_t)ne01, 1, 1 }; - break; - case GGML_OP_DIAG_MASK_INF: - case GGML_OP_ROPE: - elements = { (uint32_t)ne01, (uint32_t)ne00, 1 }; - break; - case GGML_OP_GET_ROWS: - elements = { (uint32_t)ne00, (uint32_t)ne10, (uint32_t)(ne11 * ne12) }; - break; - default: - elements = { (uint32_t)ne0, 1, 1 }; - break; - } - - for (uint64_t i03 = 0; i03 < ne03; i03++) { - for (uint64_t i02 = 0; i02 < ne02; i02++) { - const uint32_t it_idx0 = (i03 * ne02 + i02); - const uint32_t it_idx1 = use_src1 ? ((i03 % ne13) * ne12 + (i02 % ne12)) : 0; - const uint32_t x_offset = x_sz * it_idx0; - const uint32_t y_offset = y_sz * it_idx1; - const uint32_t d_offset = d_sz * it_idx0; - - if (use_src1) { - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset + x_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset + y_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset + d_offset, d_sz } }, sizeof(PC), &pc, elements); - } else { - ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset + x_offset, x_sz }, vk_subbuffer{ d_D, d_buf_offset + d_offset, d_sz } }, sizeof(PC), &pc, elements); - } - } - } + ggml_vk_sync_buffers(subctx); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); } } -static void ggml_vk_repeat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_REPEAT, {}); -} - -static void ggml_vk_get_rows(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_get_rows(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t src1_type_size = ggml_type_size(src1->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4471,10 +6908,30 @@ static void ggml_vk_get_rows(ggml_backend_vk_context * ctx, vk_context& subctx, (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, 0.0f, 0.0f, 0, - }); + }, dryrun); } -static void ggml_vk_add(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_acc(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t src1_type_size = ggml_type_size(src1->type); + const uint32_t dst_type_size = ggml_type_size(dst->type); + + int nb1 = dst->op_params[0] / 4; // 4 bytes of float32 + int nb2 = dst->op_params[1] / 4; // 4 bytes of float32 + // int nb3 = dst->op_params[2] / 4; // 4 bytes of float32 - unused + int offset = dst->op_params[3] / 4; // offset in bytes + + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_ACC, { + (uint32_t)ggml_nelements(src0), + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2],(uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)nb1, (uint32_t)nb2, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t)src1->ne[0], (uint32_t)src1->ne[1], (uint32_t)src1->ne[2],(uint32_t)src1->ne[3], (uint32_t)src1->nb[0] / src1_type_size, (uint32_t)src1->nb[1] / src1_type_size, (uint32_t)src1->nb[2] / src1_type_size, (uint32_t)src1->nb[3] / src1_type_size, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t)nb1, (uint32_t)nb2, (uint32_t) dst->nb[3] / dst_type_size, + 0, + 0.0f, 0.0f, offset, + }, dryrun); +} + +static void ggml_vk_add(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t src1_type_size = ggml_type_size(src1->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4486,10 +6943,25 @@ static void ggml_vk_add(ggml_backend_vk_context * ctx, vk_context& subctx, const (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, 0.0f, 0.0f, 0, - }); + }, dryrun); } -static void ggml_vk_mul(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_sub(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t src1_type_size = ggml_type_size(src1->type); + const uint32_t dst_type_size = ggml_type_size(dst->type); + + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_SUB, { + (uint32_t)ggml_nelements(src0), + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2],(uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t)src1->ne[0], (uint32_t)src1->ne[1], (uint32_t)src1->ne[2],(uint32_t)src1->ne[3], (uint32_t)src1->nb[0] / src1_type_size, (uint32_t)src1->nb[1] / src1_type_size, (uint32_t)src1->nb[2] / src1_type_size, (uint32_t)src1->nb[3] / src1_type_size, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, + 0, + 0.0f, 0.0f, 0, + }, dryrun); +} + +static void ggml_vk_mul(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t src1_type_size = ggml_type_size(src1->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4501,10 +6973,10 @@ static void ggml_vk_mul(ggml_backend_vk_context * ctx, vk_context& subctx, const (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, 0.0f, 0.0f, 0, - }); + }, dryrun); } -static void ggml_vk_div(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_div(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t src1_type_size = ggml_type_size(src1->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4516,10 +6988,11 @@ static void ggml_vk_div(ggml_backend_vk_context * ctx, vk_context& subctx, const (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, 0.0f, 0.0f, 0, - }); + }, dryrun); } -static void ggml_vk_concat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { + +static void ggml_vk_concat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { int * op_params = (int *)dst->op_params; const uint32_t src0_type_size = ggml_type_size(src0->type); @@ -4533,10 +7006,10 @@ static void ggml_vk_concat(ggml_backend_vk_context * ctx, vk_context& subctx, co (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, 0.0f, 0.0f, op_params[0], - }); + }, dryrun); } -static void ggml_vk_upscale(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_upscale(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const float sf0 = (float)dst->ne[0] / src0->ne[0]; @@ -4545,14 +7018,14 @@ static void ggml_vk_upscale(ggml_backend_vk_context * ctx, vk_context& subctx, c const float sf3 = (float)dst->ne[3] / src0->ne[3]; ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_UPSCALE, { - (uint32_t)ggml_nelements(dst), 0, + (uint32_t)ggml_nelements(dst), 0, 0, (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, (uint32_t)dst->ne[0], (uint32_t)dst->ne[1], (uint32_t)dst->ne[2],(uint32_t)dst->ne[3], sf0, sf1, sf2, sf3, - }); + }, dryrun); } -static void ggml_vk_scale(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_scale(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { float * op_params = (float *)dst->op_params; const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4562,11 +7035,12 @@ static void ggml_vk_scale(ggml_backend_vk_context * ctx, vk_context& subctx, con (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, - op_params[0], 0.0f - }); + op_params[0], 0.0f, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); } -static void ggml_vk_sqr(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_sqr(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4576,10 +7050,12 @@ static void ggml_vk_sqr(ggml_backend_vk_context * ctx, vk_context& subctx, const (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, 0.0f, 0.0f, - }); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); } -static void ggml_vk_clamp(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { + +static void ggml_vk_clamp(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { float * op_params = (float *)dst->op_params; const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4590,10 +7066,11 @@ static void ggml_vk_clamp(ggml_backend_vk_context * ctx, vk_context& subctx, con (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, op_params[0], op_params[1], - }); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); } -static void ggml_vk_pad(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_pad(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t dst_type_size = ggml_type_size(dst->type); @@ -4603,55 +7080,114 @@ static void ggml_vk_pad(ggml_backend_vk_context * ctx, vk_context& subctx, const (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, 0.0f, 0.0f, - }); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); } -static void ggml_vk_cpy(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) dst->extra; +static void ggml_vk_repeat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); const uint32_t dst_type_size = ggml_type_size(dst->type); - const uint32_t d_offset = ((extra->offset + dst->view_offs) % ctx->device->properties.limits.minStorageBufferOffsetAlignment) / dst_type_size; + + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_REPEAT, { + (uint32_t)ggml_nelements(dst), + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, + 0, + 0.0f, 0.0f, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); +} + +static void ggml_vk_repeat_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t dst_type_size = ggml_type_size(dst->type); + + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_REPEAT_BACK, { + (uint32_t)ggml_nelements(dst), + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, + 0, + 0.0f, 0.0f, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); +} + +static void ggml_vk_cpy(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t dst_type_size = ggml_type_size(dst->type); + + uint32_t ne = (uint32_t)ggml_nelements(src0); + if (ggml_is_quantized(src0->type) && ggml_is_quantized(dst->type)) { + // Convert from number of logical elements to 2- or 4-byte units. + ne /= ggml_blck_size(src0->type); + if ((ggml_type_size(src0->type) % 4) == 0) { + ne *= ggml_type_size(src0->type) / 4; + } else { + ne *= ggml_type_size(src0->type) / 2; + } + } ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_CPY, { + ne, + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, + 0, + 0.0f, 0.0f, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); +} + +static void ggml_vk_silu_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_SILU_BACK, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); +} + +static void ggml_vk_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + float * op_params = (float *)dst->op_params; + + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_NORM, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }, dryrun); +} + +static void ggml_vk_group_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + const int * int_op_params = (const int *)dst->op_params; + const float * float_op_params = (const float *)dst->op_params; + + const uint32_t num_groups = int_op_params[0]; + const float eps = float_op_params[1]; + const uint32_t group_size = src0->ne[0] * src0->ne[1] * ((src0->ne[2] + num_groups - 1) / num_groups); + + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_GROUP_NORM, { group_size, 0, eps, 0.0f }, dryrun); +} + +static void ggml_vk_rms_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + float * op_params = (float *)dst->op_params; + const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t dst_type_size = ggml_type_size(dst->type); + + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_RMS_NORM, { (uint32_t)ggml_nelements(src0), (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, - d_offset, - 0.0f, 0.0f, - }); + 0, + op_params[0], 0.0f, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, dryrun); } -static void ggml_vk_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_rms_norm_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { float * op_params = (float *)dst->op_params; - - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_NORM, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }); + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_RMS_NORM_BACK, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }, dryrun); } -static void ggml_vk_group_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { - int * op_params = (int *)dst->op_params; - - uint32_t num_groups = op_params[0]; - uint32_t group_size = src0->ne[0] * src0->ne[1] * ((src0->ne[2] + num_groups - 1) / num_groups); - static const float eps = 1e-6f; - - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_GROUP_NORM, { group_size, 0, eps, 0.0f }); +static void ggml_vk_unary(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); } -static void ggml_vk_rms_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { - float * op_params = (float *)dst->op_params; - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_RMS_NORM, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }); -} - -static void ggml_vk_unary(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }); -} - -static void ggml_vk_diag_mask_inf(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_diag_mask_inf(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { int32_t * op_params = (int32_t *)dst->op_params; - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_DIAG_MASK_INF, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0] }); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_DIAG_MASK_INF, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0] }, dryrun); } -static void ggml_vk_soft_max(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_soft_max(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { float * op_params = (float *)dst->op_params; float scale = op_params[0]; @@ -4673,12 +7209,18 @@ static void ggml_vk_soft_max(ggml_backend_vk_context * ctx, vk_context& subctx, scale, max_bias, m0, m1, n_head_log2, - }); + nrows_x, + }, dryrun); } -static void ggml_vk_rope(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst) { +static void ggml_vk_soft_max_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + float * op_params = (float *)dst->op_params; + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_SOFT_MAX_BACK, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], op_params[1] }, dryrun); +} + +static void ggml_vk_rope(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst, bool backprop, bool dryrun = false) { const int n_dims = ((int32_t *) dst->op_params)[1]; - // const int mode = ((int32_t *) dst->op_params)[2]; + const int mode = ((int32_t *) dst->op_params)[2]; // const int n_ctx = ((int32_t *) dst->op_params)[3]; const int n_ctx_orig = ((int32_t *) dst->op_params)[4]; const float freq_base = ((float *) dst->op_params)[5]; @@ -4687,20 +7229,28 @@ static void ggml_vk_rope(ggml_backend_vk_context * ctx, vk_context& subctx, cons const float attn_factor = ((float *) dst->op_params)[8]; const float beta_fast = ((float *) dst->op_params)[9]; const float beta_slow = ((float *) dst->op_params)[10]; + int sections[4] {}; + if (mode & 8) { + memcpy(sections, (int32_t *) dst->op_params + 11, sizeof(int)*4); + } float corr_dims[2]; ggml_rope_yarn_corr_dims(n_dims, n_ctx_orig, freq_base, beta_fast, beta_slow, corr_dims); const float theta_scale = powf(freq_base, -2.0f/n_dims); + uint32_t s1 = src0->nb[1] / ggml_type_size(src0->type); + uint32_t s2 = src0->nb[2] / ggml_type_size(src0->type); + ggml_vk_op_f32(ctx, subctx, src0, src1, src2, dst, GGML_OP_ROPE, { (uint32_t)src0->ne[0], (uint32_t)n_dims, freq_scale, (uint32_t)src0->ne[1], freq_base, ext_factor, attn_factor, {corr_dims[0], corr_dims[1]}, theta_scale, - src2 != nullptr, - }); + src2 != nullptr, (uint32_t)src0->ne[2], s1, s2, + sections[0], sections[1], sections[2], sections[3], backprop + }, dryrun); } -static void ggml_vk_argsort(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_argsort(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { int32_t * op_params = (int32_t *)dst->op_params; uint32_t ncols = src0->ne[0]; @@ -4716,14 +7266,22 @@ static void ggml_vk_argsort(ggml_backend_vk_context * ctx, vk_context& subctx, c ncols, ncols_pad, op_params[0], - }); + }, dryrun); } -static void ggml_vk_sum_rows(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SUM_ROWS, { (uint32_t)src0->ne[0], 0, 0.0f, 0.0f }); +static void ggml_vk_sum(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SUM, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); } -static void ggml_vk_im2col(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) { +static void ggml_vk_sum_rows(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SUM_ROWS, { (uint32_t)src0->ne[0], 0, 0.0f, 0.0f }, dryrun); +} + +static void ggml_vk_argmax(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_ARGMAX, { (uint32_t)src0->ne[0], 0, 0.0f, 0.0f }, dryrun); +} + +static void ggml_vk_im2col(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { const int32_t s0 = dst->op_params[0]; const int32_t s1 = dst->op_params[1]; const int32_t p0 = dst->op_params[2]; @@ -4744,7 +7302,7 @@ static void ggml_vk_im2col(ggml_backend_vk_context * ctx, vk_context& subctx, co const uint32_t OW = dst->ne[1]; const uint32_t offset_delta = src1->nb[is_2D ? 2 : 1] / 4; // nb is byte offset, src is type float32 - const uint32_t batch_offset = src1->nb[3] / 4; // nb is byte offset, src is type float32 + const uint32_t batch_offset = src1->nb[is_2D ? 3 : 2] / 4; // nb is byte offset, src is type float32 const uint32_t pelements = OW * KW * KH; @@ -4754,22 +7312,82 @@ static void ggml_vk_im2col(ggml_backend_vk_context * ctx, vk_context& subctx, co pelements, IC * KH * KW, s0, s1, p0, p1, d0, d1, - }); + }, dryrun); } -static void ggml_vk_timestep_embedding(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_timestep_embedding(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const uint32_t dim = dst->op_params[0]; const uint32_t max_period = dst->op_params[1]; const uint32_t nb1 = dst->nb[1] / ggml_type_size(dst->type); ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_TIMESTEP_EMBEDDING, { nb1, dim, max_period, - }); + }, dryrun); } -static void ggml_vk_leaky_relu(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) { +static void ggml_vk_conv_transpose_1d(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + // src0: (K, Cout, Cin, 1) -- kernel + // src1: (L, Cin, 1, 1) -- input + // dst: (*, Cout, 1, 1) + + GGML_ASSERT(src0->type == GGML_TYPE_F32); + GGML_ASSERT(src1->type == GGML_TYPE_F32); + GGML_ASSERT( dst->type == GGML_TYPE_F32); + + GGML_TENSOR_BINARY_OP_LOCALS + + GGML_ASSERT(nb00 == sizeof(float)); + GGML_ASSERT(nb10 == sizeof(float)); + + const int32_t s0 = dst->op_params[0]; + + vk_op_conv_transpose_1d_push_constants p{}; + p.Cout = static_cast(ne01); + p.Cin = static_cast(ne02); + p.K = static_cast(ne00); + p.L = static_cast(ne10); + p.KL = static_cast(ne0); + p.nb01 = static_cast(nb01 / nb00); + p.nb02 = static_cast(nb02 / nb00); + p.nb11 = static_cast(nb11 / nb10); + p.nb1 = static_cast(nb1 / nb0); + p.s0 = static_cast(s0); + + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_CONV_TRANSPOSE_1D, std::move(p), dryrun); +} + +static void ggml_vk_pool_2d(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + uint32_t op = static_cast(dst->op_params[0]); + const int32_t k1 = dst->op_params[1]; + const int32_t k0 = dst->op_params[2]; + const int32_t s1 = dst->op_params[3]; + const int32_t s0 = dst->op_params[4]; + const int32_t p1 = dst->op_params[5]; + const int32_t p0 = dst->op_params[6]; + + const uint32_t IH = src0->ne[1]; + const uint32_t IW = src0->ne[0]; + + const uint32_t N = dst->ne[3]; + + const uint32_t OC = dst->ne[2]; + const uint32_t OH = dst->ne[1]; + const uint32_t OW = dst->ne[0]; + + const uint32_t parallel_elements = N * OC * OH * OW; + + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_POOL_2D, { + IW, IH, OW, OH, OC, + parallel_elements, + op, + k0, k1, s0, s1, p0, p1, + }, dryrun); +} + + +static void ggml_vk_leaky_relu(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const float * op_params = (const float *)dst->op_params; - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_LEAKY_RELU, { (uint32_t)ggml_nelements(src0), 0, op_params[0], 0.0f }); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_LEAKY_RELU, { (uint32_t)ggml_nelements(src0), 0, op_params[0], 0.0f }, dryrun); } #ifdef GGML_VULKAN_RUN_TESTS @@ -4823,10 +7441,10 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t p = ctx->device->pipeline_matmul_f32_f16->a_s; shname = "F32_F16_ALIGNED_S"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16_f32->a_s; + p = ctx->device->pipeline_matmul_f16_f32.f32acc->a_s; shname = "F16_F32_ALIGNED_S"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16->a_s; + p = ctx->device->pipeline_matmul_f16.f32acc->a_s; shname = "F16_ALIGNED_S"; } else { GGML_ABORT("fatal error"); @@ -4839,10 +7457,10 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t p = ctx->device->pipeline_matmul_f32_f16->a_m; shname = "F32_F16_ALIGNED_M"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16_f32->a_m; + p = ctx->device->pipeline_matmul_f16_f32.f32acc->a_m; shname = "F16_F32_ALIGNED_M"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16->a_m; + p = ctx->device->pipeline_matmul_f16.f32acc->a_m; shname = "F16_ALIGNED_M"; } else { GGML_ABORT("fatal error"); @@ -4855,10 +7473,10 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t p = ctx->device->pipeline_matmul_f32_f16->a_l; shname = "F32_F16_ALIGNED_L"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16_f32->a_l; + p = ctx->device->pipeline_matmul_f16_f32.f32acc->a_l; shname = "F16_F32_ALIGNED_L"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16->a_l; + p = ctx->device->pipeline_matmul_f16.f32acc->a_l; shname = "F16_ALIGNED_L"; } else { GGML_ABORT("fatal error"); @@ -4878,10 +7496,10 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t p = ctx->device->pipeline_matmul_f32_f16->s; shname = "F32_F16_S"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16_f32->s; + p = ctx->device->pipeline_matmul_f16_f32.f32acc->s; shname = "F16_F32_S"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16->s; + p = ctx->device->pipeline_matmul_f16.f32acc->s; shname = "F16_S"; } } else if (shader_size == 1) { @@ -4892,10 +7510,10 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t p = ctx->device->pipeline_matmul_f32_f16->m; shname = "F32_F16_M"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16_f32->m; + p = ctx->device->pipeline_matmul_f16_f32.f32acc->m; shname = "F16_F32_M"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16->m; + p = ctx->device->pipeline_matmul_f16.f32acc->m; shname = "F16_M"; } } else if (shader_size == 2) { @@ -4906,18 +7524,18 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t p = ctx->device->pipeline_matmul_f32_f16->l; shname = "F32_F16_L"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16_f32->l; + p = ctx->device->pipeline_matmul_f16_f32.f32acc->l; shname = "F16_F32_L"; } else if (std::is_same() && std::is_same()) { - p = ctx->device->pipeline_matmul_f16->l; + p = ctx->device->pipeline_matmul_f16.f32acc->l; shname = "F16_L"; } } } - ggml_pipeline_allocate_descriptor_sets(ctx->device, p, num_it); + ggml_pipeline_request_descriptor_sets(ctx, p, num_it); if (split_k > 1) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, ctx->device->pipeline_matmul_split_k_reduce, num_it); + ggml_pipeline_request_descriptor_sets(ctx, ctx->device->pipeline_matmul_split_k_reduce, num_it); if (ctx->prealloc_split_k == nullptr || ctx->prealloc_split_k->size < sizeof(float) * d_ne * split_k) { // Resize buffer @@ -4928,6 +7546,12 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t } } + if (ctx->device->need_compiles) { + ggml_vk_load_shaders(ctx->device); + } + + ggml_pipeline_allocate_descriptor_sets(ctx); + vk_buffer d_X = ggml_vk_create_buffer_check(ctx->device, sizeof(X_TYPE) * x_ne, vk::MemoryPropertyFlagBits::eDeviceLocal); vk_buffer d_Y = ggml_vk_create_buffer_check(ctx->device, sizeof(Y_TYPE) * y_ne, vk::MemoryPropertyFlagBits::eDeviceLocal); vk_buffer d_D = ggml_vk_create_buffer_check(ctx->device, sizeof(float) * d_ne, vk::MemoryPropertyFlagBits::eDeviceLocal); @@ -4939,19 +7563,27 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t for (size_t i = 0; i < x_ne; i++) { if (std::is_same()) { x[i] = (rand() / (float)RAND_MAX) * 2.0f - 1.0f; + // x[i] = 1.0f; + // x[i] = i + 1; + // x[i] = (i % k == i / k) ? 1.0f : 0.0f; } else if (std::is_same()) { x[i] = ggml_fp32_to_fp16((rand() / (float)RAND_MAX) * 2.0f - 1.0f); + // x[i] = ggml_fp32_to_fp16(1.0f); + // x[i] = ggml_fp32_to_fp16(i + 1); + // x[i] = ggml_fp32_to_fp16((i % k == i / k) ? 1.0f : 0.0f); } else { GGML_ABORT("fatal error"); } } for (size_t i = 0; i < y_ne; i++) { if (std::is_same()) { - // y[i] = (rand() / (float)RAND_MAX) * 2.0f - 1.0f; - y[i] = (i % k == i / k) ? 1.0f : 0.0f; + y[i] = (rand() / (float)RAND_MAX) * 2.0f - 1.0f; + // y[i] = (i % k == i / k) ? 1.0f : 0.0f; + // y[i] = i + 1; } else if (std::is_same()) { - // y[i] = ggml_fp32_to_fp16((rand() / (float)RAND_MAX) * 2.0f - 1.0f); - y[i] = ggml_fp32_to_fp16((i % k == i / k) ? 1.0f : 0.0f); + y[i] = ggml_fp32_to_fp16((rand() / (float)RAND_MAX) * 2.0f - 1.0f); + // y[i] = ggml_fp32_to_fp16((i % k == i / k) ? 1.0f : 0.0f); + // y[i] = ggml_fp32_to_fp16(i + 1); } else { GGML_ABORT("fatal error"); } @@ -4960,22 +7592,23 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t ggml_vk_buffer_write(d_X, 0, x, sizeof(X_TYPE) * k * m * batch); ggml_vk_buffer_write(d_Y, 0, y, sizeof(Y_TYPE) * k * n * batch); - vk_context subctx = ggml_vk_create_context(ctx, ctx->device->compute_queue); + vk_context subctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); + ggml_vk_ctx_begin(ctx->device, subctx); for (size_t i = 0; i < num_it; i++) { - ggml_vk_ctx_begin(ctx->device, subctx); ggml_vk_matmul( ctx, subctx, p, ggml_vk_subbuffer(d_X), ggml_vk_subbuffer(d_Y), ggml_vk_subbuffer(d_D), ggml_vk_subbuffer(ctx->prealloc_split_k), m, n, k, k, k, m, k*m, k*n, m*n, - split_k, batch, batch, batch, 1, 1 + split_k, batch, batch, batch, 1, 1, n ); - ggml_vk_ctx_end(subctx); } + ggml_vk_ctx_end(subctx); auto begin = std::chrono::high_resolution_clock::now(); ggml_vk_submit(subctx, ctx->fence); VK_CHECK(ctx->device->device.waitForFences({ ctx->fence }, true, UINT64_MAX), "ggml_vk_test_matmul waitForFences"); ctx->device->device.resetFences({ ctx->fence }); + ggml_vk_queue_command_pools_cleanup(ctx->device); auto end = std::chrono::high_resolution_clock::now(); double time = std::chrono::duration_cast(end-begin).count() / 1000.0; @@ -5035,7 +7668,7 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t double err = std::fabs(d[i] - d_chk[i]); avg_err += err; - if (err > 0.05f && first_err_n == -1) { + if ((err > 0.05f || std::isnan(err)) && first_err_n == -1) { first_err_b = i / (m * n); first_err_n = (i % (m * n)) / m; first_err_m = (i % (m * n)) % m; @@ -5044,14 +7677,14 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t avg_err /= m * n; - std::cerr << "TEST " << shname << " m=" << m << " n=" << n << " k=" << k << " batch=" << batch << " split_k=" << split_k << " matmul " << time / num_it << "ms avg_err=" << avg_err << std::endl; + double tflops = 2.0*m*n*k*batch*num_it / (time / 1000.0) / (1000.0*1000.0*1000.0*1000.0); - if (avg_err > 0.1) { + std::cerr << "TEST " << shname << " m=" << m << " n=" << n << " k=" << k << " batch=" << batch << " split_k=" << split_k << " matmul " << time / num_it << "ms " << tflops << " TFLOPS avg_err=" << avg_err << std::endl; + + if (avg_err > 0.1 || std::isnan(avg_err)) { std::cerr << "m = " << first_err_m << " n = " << first_err_n << " b = " << first_err_b << std::endl; std::cerr << "Actual result: " << std::endl << std::endl; ggml_vk_print_matrix_area(d, GGML_TYPE_F32, m, n, first_err_m, first_err_n, first_err_b); - std::cerr << std::endl; - ggml_vk_print_matrix_area(d, GGML_TYPE_F32, m, n, first_err_m, first_err_n + 15, first_err_b); std::cerr << "Expected result: " << std::endl << std::endl; ggml_vk_print_matrix_area(d_chk, GGML_TYPE_F32, m, n, first_err_m, first_err_n, first_err_b); @@ -5077,16 +7710,13 @@ static void ggml_vk_test_matmul(ggml_backend_vk_context * ctx, size_t m, size_t free(d_chk); - ggml_vk_queue_cleanup(ctx->device, ctx->device->transfer_queue); - ggml_vk_queue_cleanup(ctx->device, ctx->device->compute_queue); + ggml_vk_command_pool_cleanup(ctx->device, ctx->compute_cmd_pool); + ggml_vk_command_pool_cleanup(ctx->device, ctx->transfer_cmd_pool); ggml_vk_destroy_buffer(d_X); ggml_vk_destroy_buffer(d_Y); ggml_vk_destroy_buffer(d_D); - ggml_pipeline_cleanup(p); - ggml_pipeline_cleanup(ctx->device->pipeline_matmul_split_k_reduce); - free(x); free(y); free(d); @@ -5164,14 +7794,20 @@ static void ggml_vk_test_dequant(ggml_backend_vk_context * ctx, size_t ne, ggml_ ggml_vk_quantize_data(x, qx, ne, quant); ggml_vk_dequantize_data(qx, x_ref, ne, quant); - ggml_pipeline_allocate_descriptor_sets(ctx->device, p, 1); + ggml_pipeline_request_descriptor_sets(ctx, p, 1); + + if (ctx->device->need_compiles) { + ggml_vk_load_shaders(ctx->device); + } + + ggml_pipeline_allocate_descriptor_sets(ctx); ggml_vk_buffer_write(qx_buf, 0, qx, qx_sz); - vk_context subctx = ggml_vk_create_context(ctx, ctx->device->compute_queue); + vk_context subctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); ggml_vk_ctx_begin(ctx->device, subctx); const std::vector pc = { 1, (uint32_t)ne, (uint32_t)ne, (uint32_t)ne, (uint32_t)ne }; - ggml_vk_dispatch_pipeline(ctx, subctx, p, { { qx_buf, 0, qx_sz }, { x_buf, 0, x_sz_f16 } }, pc.size() * sizeof(int), pc.data(), { (uint32_t)ne, 1, 1}); + ggml_vk_dispatch_pipeline(ctx, subctx, p, { vk_subbuffer{ qx_buf, 0, qx_sz }, vk_subbuffer{ x_buf, 0, x_sz_f16 } }, pc.size() * sizeof(int), pc.data(), { (uint32_t)ne, 1, 1}); ggml_vk_ctx_end(subctx); auto begin = std::chrono::high_resolution_clock::now(); @@ -5179,6 +7815,7 @@ static void ggml_vk_test_dequant(ggml_backend_vk_context * ctx, size_t ne, ggml_ ggml_vk_submit(subctx, ctx->fence); VK_CHECK(ctx->device->device.waitForFences({ ctx->fence }, true, UINT64_MAX), "ggml_vk_test_dequant waitForFences"); ctx->device->device.resetFences({ ctx->fence }); + ggml_vk_queue_command_pools_cleanup(ctx->device); auto end = std::chrono::high_resolution_clock::now(); @@ -5223,71 +7860,204 @@ static void ggml_vk_test_dequant(ggml_backend_vk_context * ctx, size_t ne, ggml_ free(x_chk); } -static void ggml_vk_test_dequant_matmul(ggml_backend_vk_context * ctx, size_t m, size_t n, size_t k, size_t batch, size_t num_it, size_t split_k, size_t shader_size, ggml_type quant) { +// This does not work without ggml q8_1 quantization support +// +// typedef uint16_t ggml_half; +// typedef uint32_t ggml_half2; +// +// #define QK8_1 32 +// typedef struct { +// union { +// struct { +// ggml_half d; // delta +// ggml_half s; // d * sum(qs[i]) +// } GGML_COMMON_AGGR_S; +// ggml_half2 ds; +// } GGML_COMMON_AGGR_U; +// int8_t qs[QK8_1]; // quants +// } block_q8_1; +// +// static void ggml_vk_test_quantize(ggml_backend_vk_context * ctx, size_t ne, ggml_type quant) { +// VK_LOG_DEBUG("ggml_vk_test_quantize(" << ne << ")"); +// GGML_ASSERT(quant == GGML_TYPE_Q8_1); +// +// const size_t x_sz = sizeof(float) * ne; +// const size_t qx_sz = ne * ggml_type_size(quant)/ggml_blck_size(quant); +// float * x = (float *) malloc(x_sz); +// block_q8_1 * qx = (block_q8_1 *)malloc(qx_sz); +// block_q8_1 * qx_res = (block_q8_1 *)malloc(qx_sz); +// vk_buffer x_buf = ggml_vk_create_buffer_check(ctx->device, x_sz, vk::MemoryPropertyFlagBits::eDeviceLocal); +// vk_buffer qx_buf = ggml_vk_create_buffer_check(ctx->device, qx_sz, vk::MemoryPropertyFlagBits::eDeviceLocal); +// +// for (size_t i = 0; i < ne; i++) { +// x[i] = rand() / (float)RAND_MAX; +// } +// +// vk_pipeline p = ggml_vk_get_quantize_pipeline(ctx, quant); +// +// ggml_pipeline_request_descriptor_sets(ctx, p, 1); +// +// if (ctx->device->need_compiles) { +// ggml_vk_load_shaders(ctx->device); +// } +// +// ggml_pipeline_allocate_descriptor_sets(ctx); +// +// ggml_vk_buffer_write(x_buf, 0, x, x_sz); +// +// vk_context subctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); +// ggml_vk_ctx_begin(ctx->device, subctx); +// ggml_vk_quantize_q8_1(ctx, subctx, ggml_vk_subbuffer(x_buf), ggml_vk_subbuffer(qx_buf), ne); +// ggml_vk_ctx_end(subctx); +// +// auto begin = std::chrono::high_resolution_clock::now(); +// +// ggml_vk_submit(subctx, ctx->fence); +// VK_CHECK(ctx->device->device.waitForFences({ ctx->fence }, true, UINT64_MAX), "ggml_vk_test_quantize waitForFences"); +// ctx->device->device.resetFences({ ctx->fence }); +// ggml_vk_queue_command_pools_cleanup(ctx->device); +// +// auto end = std::chrono::high_resolution_clock::now(); +// +// double ms_quant = std::chrono::duration_cast(end-begin).count() / 1000.0; +// ggml_vk_buffer_read(qx_buf, 0, qx, qx_sz); +// +// ggml_vk_quantize_data(x, qx_res, ne, quant); +// +// int first_err = -1; +// +// for (size_t i = 0; i < ne / 32; i++) { +// double error = std::fabs(ggml_fp16_to_fp32(qx_res[i].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.d) - ggml_fp16_to_fp32(qx[i].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.d)); +// +// if (first_err < 0 && error > 0.1) { +// first_err = i; +// } +// +// error = std::fabs(ggml_fp16_to_fp32(qx_res[i].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.s) - ggml_fp16_to_fp32(qx[i].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.s)); +// +// if (first_err < 0 && error > 0.1) { +// first_err = i; +// } +// +// for (size_t j = 0; j < 32; j++) { +// uint64_t error = std::abs(qx_res[i].qs[j] - qx[i].qs[j]); +// +// if (first_err < 0 && error > 1) { +// first_err = i; +// } +// } +// } +// +// std::cerr << "TEST QUANTIZE " << ggml_type_name(quant) << " time=" << ms_quant << "ms " << (first_err == -1 ? "CORRECT" : "INCORRECT") << std::endl; +// +// if (first_err != -1) { +// std::cerr << "first_error = " << first_err << std::endl; +// std::cerr << "Actual result: " << std::endl << std::endl; +// std::cout << "d=" << ggml_fp16_to_fp32(qx[first_err].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.d) << " s=" << ggml_fp16_to_fp32(qx[first_err].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.s) << " "; +// for (size_t j = 0; j < 32; j++) { +// std::cout << " qs" << j << "=" << (uint32_t)qx[first_err].qs[j] << " "; +// } +// std::cerr << std::endl << std::endl << "Expected result: " << std::endl << std::endl; +// std::cout << "d=" << ggml_fp16_to_fp32(qx_res[first_err].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.d) << " s=" << ggml_fp16_to_fp32(qx_res[first_err].GGML_COMMON_AGGR_U.GGML_COMMON_AGGR_S.s) << " "; +// for (size_t j = 0; j < 32; j++) { +// std::cout << " qs" << j << "=" << (uint32_t)qx_res[first_err].qs[j] << " "; +// } +// std::cerr << std::endl; +// } +// +// ggml_vk_destroy_buffer(x_buf); +// ggml_vk_destroy_buffer(qx_buf); +// +// free(x); +// free(qx); +// free(qx_res); +// } + +static void ggml_vk_test_dequant_matmul(ggml_backend_vk_context * ctx, size_t m, size_t n, size_t k, size_t batch, size_t num_it, size_t split_k, size_t shader_size, ggml_type quant, bool mmq = false) { VK_LOG_DEBUG("ggml_vk_test_dequant_matmul(" << m << ", " << n << ", " << k << ", " << batch << ", " << num_it << ", " << split_k << ", " << ggml_type_name(quant) << ")"); const size_t x_ne = m * k * batch; const size_t y_ne = k * n * batch; const size_t d_ne = m * n * batch; + vk_matmul_pipeline2 * pipelines; + + if (mmq) { + pipelines = ctx->device->pipeline_dequant_mul_mat_mat_q8_1; + } else { + pipelines = ctx->device->pipeline_dequant_mul_mat_mat; + } + + const bool fp16acc = ctx->device->fp16; + vk_pipeline p; std::string shname; if (shader_size == 0) { - p = ctx->device->pipeline_dequant_mul_mat_mat[quant]->a_s; + p = fp16acc ? pipelines[quant].f16acc->a_s : pipelines[quant].f32acc->a_s; shname = std::string(ggml_type_name(quant)) + "_ALIGNED_S"; } else if (shader_size == 1) { - p = ctx->device->pipeline_dequant_mul_mat_mat[quant]->a_m; + p = fp16acc ? pipelines[quant].f16acc->a_m : pipelines[quant].f32acc->a_m; shname = std::string(ggml_type_name(quant)) + "_ALIGNED_M"; } else if (shader_size == 2) { - p = ctx->device->pipeline_dequant_mul_mat_mat[quant]->a_l; + p = fp16acc ? pipelines[quant].f16acc->a_l : pipelines[quant].f32acc->a_l; shname = std::string(ggml_type_name(quant)) + "_ALIGNED_L"; } else { GGML_ASSERT(0); } - const size_t kpad = ggml_vk_align_size(k, p->align); + const size_t kpad = mmq ? 0 : ggml_vk_align_size(k, p->align); - if (k != kpad) { + if (mmq || k != kpad) { if (shader_size == 0) { - p = ctx->device->pipeline_dequant_mul_mat_mat[quant]->s; + p = fp16acc ? pipelines[quant].f16acc->s : pipelines[quant].f32acc->s; shname = std::string(ggml_type_name(quant)) + "_S"; } else if (shader_size == 1) { - p = ctx->device->pipeline_dequant_mul_mat_mat[quant]->m; + p = fp16acc ? pipelines[quant].f16acc->m : pipelines[quant].f32acc->m; shname = std::string(ggml_type_name(quant)) + "_M"; } else if (shader_size == 2) { - p = ctx->device->pipeline_dequant_mul_mat_mat[quant]->l; + p = fp16acc ? pipelines[quant].f16acc->l : pipelines[quant].f32acc->l; shname = std::string(ggml_type_name(quant)) + "_L"; } else { GGML_ASSERT(0); } } + if (p == nullptr) { + std::cerr << "error: no pipeline for ggml_vk_test_dequant_matmul " << ggml_type_name(quant) << std::endl; + return; + } + const size_t x_sz = sizeof(float) * x_ne; const size_t y_sz = sizeof(float) * y_ne; const size_t qx_sz = x_ne * ggml_type_size(quant)/ggml_blck_size(quant); + const size_t qy_sz = mmq ? y_ne * ggml_type_size(GGML_TYPE_Q8_1)/ggml_blck_size(GGML_TYPE_Q8_1) : y_sz; const size_t d_sz = sizeof(float) * d_ne; float * x = (float *) malloc(x_sz); float * y = (float *) malloc(y_sz); void * qx = malloc(qx_sz); vk_buffer qx_buf = ggml_vk_create_buffer_check(ctx->device, qx_sz, vk::MemoryPropertyFlagBits::eDeviceLocal); vk_buffer y_buf = ggml_vk_create_buffer_check(ctx->device, y_sz, vk::MemoryPropertyFlagBits::eDeviceLocal); + vk_buffer qy_buf = ggml_vk_create_buffer_check(ctx->device, qy_sz, vk::MemoryPropertyFlagBits::eDeviceLocal); vk_buffer d_buf = ggml_vk_create_buffer_check(ctx->device, d_sz, vk::MemoryPropertyFlagBits::eDeviceLocal); float * d = (float *) malloc(d_sz); float * d_chk = (float *) malloc(d_sz); for (size_t i = 0; i < x_ne; i++) { x[i] = (rand() / (float)RAND_MAX) * 2.0f - 1.0f; + // x[i] = (i % k == i / k) ? 1.0f : 0.0f; + // x[i] = i % k; } ggml_vk_quantize_data(x, qx, x_ne, quant); for (size_t i = 0; i < y_ne; i++) { - // y[i] = rand() / (float)RAND_MAX; - y[i] = (i % k == i / k) ? 1.0f : 0.0f; + y[i] = (rand() / (float)RAND_MAX) * 2.0f - 1.0f; + // y[i] = (i % k == i / k) ? 1.0f : 0.0f; + // y[i] = i % k; } - ggml_pipeline_allocate_descriptor_sets(ctx->device, p, num_it); + ggml_pipeline_request_descriptor_sets(ctx, p, num_it); if (split_k > 1) { - ggml_pipeline_allocate_descriptor_sets(ctx->device, ctx->device->pipeline_matmul_split_k_reduce, num_it); + ggml_pipeline_request_descriptor_sets(ctx, ctx->device->pipeline_matmul_split_k_reduce, num_it); if (ctx->prealloc_split_k == nullptr || ctx->prealloc_split_k->size < sizeof(float) * d_ne * split_k) { // Resize buffer @@ -5297,27 +8067,49 @@ static void ggml_vk_test_dequant_matmul(ggml_backend_vk_context * ctx, size_t m, ctx->prealloc_split_k = ggml_vk_create_buffer_check(ctx->device, sizeof(float) * d_ne * split_k, vk::MemoryPropertyFlagBits::eDeviceLocal); } } + if (mmq) { + ggml_pipeline_request_descriptor_sets(ctx, ctx->device->pipeline_quantize_q8_1, num_it); + } + + if (ctx->device->need_compiles) { + ggml_vk_load_shaders(ctx->device); + } + + ggml_pipeline_allocate_descriptor_sets(ctx); ggml_vk_buffer_write(qx_buf, 0, qx, qx_sz); ggml_vk_buffer_write(y_buf, 0, y, y_sz); - vk_context subctx = ggml_vk_create_context(ctx, ctx->device->compute_queue); - for (size_t i = 0; i < num_it; i++) { - ggml_vk_ctx_begin(ctx->device, subctx); - ggml_vk_matmul( - ctx, subctx, p, ggml_vk_subbuffer(qx_buf), ggml_vk_subbuffer(y_buf), ggml_vk_subbuffer(d_buf), ggml_vk_subbuffer(ctx->prealloc_split_k), - m, n, k, - k, k, m, k*m, k*n, m*n, - split_k, batch, batch, batch, 1, 1 - ); - ggml_vk_ctx_end(subctx); + vk_context subctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); + ggml_vk_ctx_begin(ctx->device, subctx); + if (mmq) { + for (size_t i = 0; i < num_it; i++) { + ggml_vk_quantize_q8_1(ctx, subctx, { y_buf, 0, y_sz }, { qy_buf, 0, qy_sz }, y_ne); + ggml_vk_matmul( + ctx, subctx, p, { qx_buf, 0, qx_sz }, { qy_buf, 0, qy_sz }, { d_buf, 0, d_sz }, { ctx->prealloc_split_k, 0, ctx->prealloc_size_split_k }, + m, n, k, + k, k, m, k*m, k*n, m*n, + split_k, batch, batch, batch, 1, 1, n + ); + } + } else { + for (size_t i = 0; i < num_it; i++) { + ggml_vk_matmul( + ctx, subctx, p, { qx_buf, 0, qx_sz }, { y_buf, 0, y_sz }, { d_buf, 0, d_sz }, { ctx->prealloc_split_k, 0, ctx->prealloc_size_split_k }, + m, n, k, + k, k, m, k*m, k*n, m*n, + split_k, batch, batch, batch, 1, 1, n + ); + } } + ggml_vk_ctx_end(subctx); auto begin = std::chrono::high_resolution_clock::now(); ggml_vk_submit(subctx, ctx->fence); VK_CHECK(ctx->device->device.waitForFences({ ctx->fence }, true, UINT64_MAX), "ggml_vk_test_dequant waitForFences"); ctx->device->device.resetFences({ ctx->fence }); + ggml_vk_queue_command_pools_cleanup(ctx->device); auto end = std::chrono::high_resolution_clock::now(); @@ -5365,7 +8157,13 @@ static void ggml_vk_test_dequant_matmul(ggml_backend_vk_context * ctx, size_t m, avg_err /= m * n; - std::cerr << "TEST MMQ " << shname << " m=" << m << " n=" << n << " k=" << k << " batch=" << batch << " split_k=" << split_k << " matmul " << time_ms / num_it << "ms avg_err=" << avg_err << std::endl; + double tflops = 2.0*m*n*k*batch*num_it / (time_ms / 1000.0) / (1000.0*1000.0*1000.0*1000.0); + + std::cerr << "TEST dequant matmul " << shname; + if (mmq) { + std::cerr << " mmq"; + } + std::cerr << " m=" << m << " n=" << n << " k=" << k << " batch=" << batch << " split_k=" << split_k << " matmul " << time_ms / num_it << "ms " << tflops << " TFLOPS avg_err=" << avg_err << std::endl; if (avg_err > 0.01 || std::isnan(avg_err)) { std::cerr << "m = " << first_err_m << " n = " << first_err_n << " b = " << first_err_b << std::endl; @@ -5375,6 +8173,12 @@ static void ggml_vk_test_dequant_matmul(ggml_backend_vk_context * ctx, size_t m, std::cerr << "Expected result: " << std::endl << std::endl; ggml_vk_print_matrix_area(d_chk, GGML_TYPE_F32, m, n, first_err_m, first_err_n, first_err_b); + std::cerr << "src0: " << std::endl << std::endl; + ggml_vk_print_matrix_area(x, GGML_TYPE_F32, k, m, first_err_m, first_err_n, first_err_b); + std::cerr << std::endl; + std::cerr << "src1: " << std::endl << std::endl; + ggml_vk_print_matrix_area(y, GGML_TYPE_F32, k, n, first_err_m, first_err_n, first_err_b); + if (split_k > 1) { float * split_k_buf = (float *) malloc(sizeof(float) * d_ne * split_k); ggml_vk_buffer_read(ctx->prealloc_split_k, 0, split_k_buf, sizeof(float) * d_ne * split_k); @@ -5397,6 +8201,7 @@ static void ggml_vk_test_dequant_matmul(ggml_backend_vk_context * ctx, size_t m, ggml_vk_destroy_buffer(qx_buf); ggml_vk_destroy_buffer(y_buf); + ggml_vk_destroy_buffer(qy_buf); ggml_vk_destroy_buffer(d_buf); free(x); @@ -5407,247 +8212,15 @@ static void ggml_vk_test_dequant_matmul(ggml_backend_vk_context * ctx, size_t m, } #endif -static ggml_tensor_extra_gpu * ggml_vk_tensor_create_extra(ggml_tensor * tensor) { - VK_LOG_DEBUG("ggml_vk_create_extra(" << tensor << " (" << tensor->name << ", " << ggml_op_name(tensor->op) << "))"); - ggml_tensor_extra_gpu * extra = new ggml_tensor_extra_gpu; - extra->reset(); - tensor->extra = extra; - return extra; -} - -static void ggml_vk_preallocate_buffers_graph(ggml_backend_vk_context * ctx, ggml_tensor * node){ - VK_LOG_DEBUG("ggml_vk_preallocate_buffers_graph(" << node << ")"); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) node->extra; - - if (extra == nullptr) { - return; - } - - ggml_tensor * src0 = node->src[0]; - ggml_tensor * src1 = node->src[1]; - - const bool use_src0 = src0 != nullptr; - const int64_t ne00 = use_src0 ? src0->ne[0] : 0; - const int64_t ne01 = use_src0 ? src0->ne[1] : 0; - const int64_t ne02 = use_src0 ? src0->ne[2] : 0; - const int64_t ne03 = use_src0 ? src0->ne[3] : 0; - const bool use_src1 = src1 != nullptr && node->op != GGML_OP_CPY && node->op != GGML_OP_CONT && node->op != GGML_OP_DUP; - const int64_t ne10 = use_src1 ? src1->ne[0] : 0; - const int64_t ne11 = use_src1 ? src1->ne[1] : 0; - const int64_t ne12 = use_src1 ? src1->ne[2] : 0; - const int64_t ne13 = use_src1 ? src1->ne[3] : 0; - const int64_t ne20 = node->ne[0]; - const int64_t ne21 = node->ne[1]; - const int64_t ne22 = node->ne[2]; - const int64_t ne23 = node->ne[3]; - - const ggml_type src0_type = (use_src0 && src0->type == GGML_TYPE_F32) ? src0->type : GGML_TYPE_F16; - const ggml_type src1_type = (use_src1 && src1->type == GGML_TYPE_F32) ? src1->type : GGML_TYPE_F16; - - const bool x_non_contig = use_src0 && !ggml_vk_dim01_contiguous(src0); - const bool y_non_contig = use_src1 && !ggml_vk_dim01_contiguous(src1); - - const bool y_f32_kernel = use_src1 && src1->type == GGML_TYPE_F32 && !y_non_contig; - - bool mmp = (use_src0 && use_src1 && (node->op == GGML_OP_MUL_MAT || node->op == GGML_OP_MUL_MAT_ID)) ? ggml_vk_get_mul_mat_mat_pipeline(ctx, src0->type, y_non_contig ? GGML_TYPE_F16 : src1->type) != nullptr : false; - - const bool qx_needs_dequant = use_src0 && (!mmp || x_non_contig); - const bool qy_needs_dequant = use_src1 && ((src1->type != GGML_TYPE_F16 && !y_f32_kernel) || y_non_contig); - - int split_k; - if (node->op == GGML_OP_MUL_MAT || node->op == GGML_OP_MUL_MAT_ID) { - split_k = ggml_vk_guess_split_k(ne01, ne11, ne10); - } else { - split_k = 1; - } - const uint32_t x_ne = ne00 * ne01; - const uint32_t y_ne = ne10 * ne11; - const uint32_t d_ne = ne20 * ne21; - - const uint64_t x_sz = (use_src0 && qx_needs_dequant) ? ggml_vk_align_size(sizeof(src0_type) * x_ne, ctx->device->properties.limits.minStorageBufferOffsetAlignment) * ne02 * ne03 : 0; - const uint64_t y_sz = (use_src1 && qy_needs_dequant) ? ggml_vk_align_size(sizeof(src1_type) * y_ne, ctx->device->properties.limits.minStorageBufferOffsetAlignment) * ne12 * ne13 : 0; - uint64_t d_sz = ggml_vk_align_size(ggml_type_size(node->type) * d_ne, ctx->device->properties.limits.minStorageBufferOffsetAlignment) * ne22 * ne23; - const uint64_t split_k_size = split_k > 1 ? d_sz * 4 : 0; - - if (extra->buffer_gpu.expired()) { - // Workaround for CPU backend BLAS matmul calls - extra->buffer_gpu = ggml_vk_create_buffer_temp(ctx, d_sz); - } - - switch (node->op) { - case GGML_OP_REPEAT: - case GGML_OP_GET_ROWS: - case GGML_OP_RESHAPE: - case GGML_OP_VIEW: - case GGML_OP_PERMUTE: - case GGML_OP_TRANSPOSE: - case GGML_OP_ADD: - case GGML_OP_SCALE: - case GGML_OP_SQR: - case GGML_OP_CLAMP: - case GGML_OP_PAD: - case GGML_OP_CPY: - case GGML_OP_CONT: - case GGML_OP_DUP: - case GGML_OP_MUL: - case GGML_OP_DIV: - case GGML_OP_CONCAT: - case GGML_OP_UPSCALE: - case GGML_OP_NORM: - case GGML_OP_GROUP_NORM: - case GGML_OP_RMS_NORM: - case GGML_OP_DIAG_MASK_INF: - case GGML_OP_SOFT_MAX: - case GGML_OP_ROPE: - case GGML_OP_ARGSORT: - case GGML_OP_SUM_ROWS: - case GGML_OP_IM2COL: - case GGML_OP_TIMESTEP_EMBEDDING: - case GGML_OP_LEAKY_RELU: - break; - case GGML_OP_UNARY: - switch (ggml_get_unary_op(node)) { - case GGML_UNARY_OP_SILU: - case GGML_UNARY_OP_GELU: - case GGML_UNARY_OP_GELU_QUICK: - case GGML_UNARY_OP_RELU: - case GGML_UNARY_OP_TANH: - break; - default: - return; - } - break; - case GGML_OP_MUL_MAT: - case GGML_OP_MUL_MAT_ID: - if ( - x_sz > ctx->device->max_memory_allocation_size || - y_sz > ctx->device->max_memory_allocation_size || - d_sz > ctx->device->max_memory_allocation_size || - split_k_size > ctx->device->max_memory_allocation_size) { - GGML_ABORT("Requested preallocation size is too large"); - } - if (ctx->prealloc_size_x < x_sz) { - ctx->prealloc_size_x = x_sz; - } - if (ctx->prealloc_size_y < y_sz) { - ctx->prealloc_size_y = y_sz; - } - if (ctx->prealloc_size_split_k < split_k_size) { - ctx->prealloc_size_split_k = split_k_size; - } - if (ctx->staging_size < x_sz + y_sz) { - ctx->staging_size = x_sz + y_sz; - } - break; - default: - return; - } -} - static void ggml_vk_preallocate_buffers(ggml_backend_vk_context * ctx) { #if defined(GGML_VULKAN_RUN_TESTS) - ctx->staging = ggml_vk_create_buffer_check(ctx->device, 100ul * 1024ul * 1024ul, - vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostCached, - vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_F32); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q4_0); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q4_1); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q5_0); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q5_1); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q8_0); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q2_K); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q3_K); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q4_K); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q5_K); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_Q6_K); - ggml_vk_test_dequant(ctx, 7680, GGML_TYPE_IQ4_NL); - - ggml_vk_test_matmul(ctx, 512, 512, 100, 32, 100, 1, 2); - - ggml_vk_test_matmul(ctx, 128, 512, 512, 2, 100, 1, 0); - ggml_vk_test_matmul(ctx, 128, 512, 512, 2, 100, 1, 1); - ggml_vk_test_matmul(ctx, 128, 512, 512, 2, 100, 1, 2); - // ggml_vk_test_matmul(ctx, 128, 512, 512, 2, 100, 4, 0); - // ggml_vk_test_matmul(ctx, 128, 512, 512, 2, 100, 4, 1); - // ggml_vk_test_matmul(ctx, 128, 512, 512, 2, 100, 4, 2); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q4_0); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q4_0); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q4_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q4_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q4_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q4_0); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q4_1); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q4_1); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q4_1); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q4_1); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q4_1); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q4_1); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q5_0); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q5_0); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q5_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q5_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q5_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q5_0); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q5_1); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q5_1); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q5_1); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q5_1); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q5_1); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q5_1); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q8_0); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q8_0); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q8_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q8_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q8_0); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q8_0); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q2_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q2_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q2_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q2_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q2_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q2_K); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q3_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q3_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q3_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q3_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q3_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q3_K); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q4_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q4_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q4_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q4_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q4_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q4_K); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q5_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q5_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q5_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q5_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q5_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q5_K); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_Q6_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_Q6_K); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_Q6_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 0, GGML_TYPE_Q6_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 1, GGML_TYPE_Q6_K); - // ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 4, 2, GGML_TYPE_Q6_K); - - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 0, GGML_TYPE_IQ4_NL); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 1, GGML_TYPE_IQ4_NL); - ggml_vk_test_dequant_matmul(ctx, 128, 512, 512, 2, 100, 1, 2, GGML_TYPE_IQ4_NL); - - std::cerr << std::endl; - const std::vector vals { + 512, 512, 128, + 128, 512, 512, + 4096, 512, 4096, + 11008, 512, 4096, + 4096, 512, 11008, + 32000, 512, 4096, 8, 8, 8, 100, 46, 576, 623, 111, 128, @@ -5660,25 +8233,70 @@ static void ggml_vk_preallocate_buffers(ggml_backend_vk_context * ctx) { 49, 49, 128, 128, 49, 49, 4096, 49, 4096, - 11008, 49, 4096, - 4096, 49, 11008, - 32000, 49, 4096, - 512, 512, 128, - 128, 512, 512, - 4096, 512, 4096, - 11008, 512, 4096, - 4096, 512, 11008, - 32000, 512, 4096, }; - const size_t num_it = 1; + const size_t num_it = 100; + + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 0, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 1, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 2, GGML_TYPE_Q4_0); + + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 0, GGML_TYPE_Q4_0, true); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 1, GGML_TYPE_Q4_0, true); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 2, GGML_TYPE_Q4_0, true); + + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 0, GGML_TYPE_Q8_0); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 1, GGML_TYPE_Q8_0); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 2, GGML_TYPE_Q8_0); + + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 0, GGML_TYPE_Q8_0, true); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 1, GGML_TYPE_Q8_0, true); + ggml_vk_test_dequant_matmul(ctx, 4096, 512, 4096, 2, num_it, 1, 2, GGML_TYPE_Q8_0, true); + + abort(); + for (size_t i = 0; i < vals.size(); i += 3) { ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 0); ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 1); ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 2); - // ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 0); - // ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 1); - // ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 2); - std::cerr << std::endl; + std::cerr << '\n'; + ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 0); + ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 1); + ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 2); + std::cerr << '\n'; + ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 0); + ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 1); + ggml_vk_test_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 2); + std::cerr << '\n' << std::endl; + + if (vals[i + 2] % 32 == 0) { + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 0, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 1, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 2, GGML_TYPE_Q4_0); + std::cerr << '\n'; + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 0, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 1, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 2, GGML_TYPE_Q4_0); + std::cerr << '\n'; + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 0, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 1, GGML_TYPE_Q4_0); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 2, GGML_TYPE_Q4_0); + std::cerr << '\n' << std::endl; + } + + if (vals[i + 2] % 256 == 0) { + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 0, GGML_TYPE_Q4_K); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 1, GGML_TYPE_Q4_K); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 1, 2, GGML_TYPE_Q4_K); + std::cerr << '\n'; + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 0, GGML_TYPE_Q4_K); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 1, GGML_TYPE_Q4_K); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 2, 2, GGML_TYPE_Q4_K); + std::cerr << '\n'; + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 0, GGML_TYPE_Q4_K); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 1, GGML_TYPE_Q4_K); + ggml_vk_test_dequant_matmul(ctx, vals[i], vals[i + 1], vals[i + 2], 2, num_it, 4, 2, GGML_TYPE_Q4_K); + std::cerr << '\n' << std::endl; + } } GGML_ABORT("fatal error"); @@ -5708,32 +8326,24 @@ static void ggml_vk_preallocate_buffers(ggml_backend_vk_context * ctx) { } ctx->prealloc_split_k = ggml_vk_create_buffer_device(ctx->device, ctx->prealloc_size_split_k); } - if (ctx->staging == nullptr || (ctx->staging_size > 0 && ctx->staging->size < ctx->staging_size)) { - VK_LOG_MEMORY("ggml_vk_preallocate_buffers(staging_size: " << ctx->staging_size << ")"); - // Resize buffer - if (ctx->staging != nullptr) { - ggml_vk_destroy_buffer(ctx->staging); - } - ctx->staging = ggml_vk_create_buffer_check(ctx->device, ctx->staging_size, - vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostCached, - vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); - } } -static void ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * node, int node_idx, bool last_node){ - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) node->extra; +static bool ggml_vk_compute_forward(ggml_backend_vk_context* ctx, ggml_tensor* tensor, int tensor_idx, bool use_fence, bool almost_ready); - if (ggml_is_empty(node) || extra == nullptr) { - return; +// Returns true if node has enqueued work into the queue, false otherwise +// If submit is true the current all operations queued so far are being submitted to Vulkan to overlap cmdlist creation and GPU execution. +static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * node, int node_idx, ggml_tensor *node_begin, int node_idx_begin, bool dryrun, bool last_node, bool almost_ready, bool submit){ + if (ggml_is_empty(node) || !node->buffer) { + return false; } VK_LOG_DEBUG("ggml_vk_build_graph(" << node << ", " << ggml_op_name(node->op) << ")"); ctx->semaphore_idx = 0; - ctx->staging_offset = 0; const ggml_tensor * src0 = node->src[0]; const ggml_tensor * src1 = node->src[1]; const ggml_tensor * src2 = node->src[2]; + const ggml_tensor * src3 = node->src[3]; switch (node->op) { // Return on empty ops to avoid generating a compute_ctx and setting exit_tensor @@ -5742,7 +8352,7 @@ static void ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_PERMUTE: case GGML_OP_TRANSPOSE: case GGML_OP_NONE: - return; + return false; case GGML_OP_UNARY: switch (ggml_get_unary_op(node)) { case GGML_UNARY_OP_SILU: @@ -5750,14 +8360,17 @@ static void ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: + case GGML_UNARY_OP_SIGMOID: break; default: - return; + return false; } break; case GGML_OP_REPEAT: + case GGML_OP_REPEAT_BACK: case GGML_OP_GET_ROWS: case GGML_OP_ADD: + case GGML_OP_SUB: case GGML_OP_MUL: case GGML_OP_DIV: case GGML_OP_CONCAT: @@ -5769,97 +8382,177 @@ static void ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_CPY: case GGML_OP_CONT: case GGML_OP_DUP: + case GGML_OP_SILU_BACK: case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: + case GGML_OP_RMS_NORM_BACK: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: + case GGML_OP_SOFT_MAX_BACK: case GGML_OP_ROPE: + case GGML_OP_ROPE_BACK: case GGML_OP_MUL_MAT: case GGML_OP_MUL_MAT_ID: case GGML_OP_ARGSORT: + case GGML_OP_SUM: case GGML_OP_SUM_ROWS: + case GGML_OP_ARGMAX: case GGML_OP_IM2COL: case GGML_OP_TIMESTEP_EMBEDDING: + case GGML_OP_CONV_TRANSPOSE_1D: + case GGML_OP_POOL_2D: case GGML_OP_LEAKY_RELU: + case GGML_OP_FLASH_ATTN_EXT: break; default: std::cerr << "ggml_vulkan: Error: Missing op: " << ggml_op_name(node->op) << std::endl; GGML_ABORT("fatal error"); - return; + return false; } vk_context compute_ctx; - if (ctx->compute_ctx.expired()) { - compute_ctx = ggml_vk_create_context(ctx, ctx->device->compute_queue); - ctx->compute_ctx = compute_ctx; - ggml_vk_ctx_begin(ctx->device, compute_ctx); + if (!dryrun) { + if (ctx->compute_ctx.expired()) { + compute_ctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); + ctx->compute_ctx = compute_ctx; + ggml_vk_ctx_begin(ctx->device, compute_ctx); + } else { + compute_ctx = ctx->compute_ctx.lock(); + } } else { - compute_ctx = ctx->compute_ctx.lock(); + switch (node->op) { + case GGML_OP_REPEAT: + case GGML_OP_REPEAT_BACK: + case GGML_OP_ACC: + case GGML_OP_GET_ROWS: + case GGML_OP_ADD: + case GGML_OP_SUB: + case GGML_OP_MUL: + case GGML_OP_DIV: + case GGML_OP_CONCAT: + case GGML_OP_UPSCALE: + case GGML_OP_SCALE: + case GGML_OP_SQR: + case GGML_OP_CLAMP: + case GGML_OP_PAD: + case GGML_OP_CPY: + case GGML_OP_CONT: + case GGML_OP_DUP: + case GGML_OP_SILU_BACK: + case GGML_OP_NORM: + case GGML_OP_GROUP_NORM: + case GGML_OP_RMS_NORM: + case GGML_OP_RMS_NORM_BACK: + case GGML_OP_UNARY: + case GGML_OP_DIAG_MASK_INF: + case GGML_OP_SOFT_MAX: + case GGML_OP_SOFT_MAX_BACK: + case GGML_OP_ROPE: + case GGML_OP_ROPE_BACK: + case GGML_OP_ARGSORT: + case GGML_OP_SUM: + case GGML_OP_SUM_ROWS: + case GGML_OP_ARGMAX: + case GGML_OP_IM2COL: + case GGML_OP_TIMESTEP_EMBEDDING: + case GGML_OP_CONV_TRANSPOSE_1D: + case GGML_OP_POOL_2D: + case GGML_OP_LEAKY_RELU: + { + // These operations all go through ggml_vk_op_f32, so short-circuit and + // do the only thing needed for the dryrun. + vk_pipeline pipeline = ggml_vk_op_get_pipeline(ctx, src0, src1, src2, node, node->op); + ggml_pipeline_request_descriptor_sets(ctx, pipeline, 1); + return false; + } + default: + break; + } } switch (node->op) { case GGML_OP_REPEAT: - ggml_vk_repeat(ctx, compute_ctx, src0, node); + ggml_vk_repeat(ctx, compute_ctx, src0, node, dryrun); + + break; + case GGML_OP_REPEAT_BACK: + ggml_vk_repeat_back(ctx, compute_ctx, src0, node, dryrun); + + break; + case GGML_OP_ACC: + ggml_vk_acc(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_GET_ROWS: - ggml_vk_get_rows(ctx, compute_ctx, src0, src1, node); + ggml_vk_get_rows(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_ADD: - ggml_vk_add(ctx, compute_ctx, src0, src1, node); + ggml_vk_add(ctx, compute_ctx, src0, src1, node, dryrun); + + break; + case GGML_OP_SUB: + ggml_vk_sub(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_MUL: - ggml_vk_mul(ctx, compute_ctx, src0, src1, node); + ggml_vk_mul(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_DIV: - ggml_vk_div(ctx, compute_ctx, src0, src1, node); + ggml_vk_div(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_CONCAT: - ggml_vk_concat(ctx, compute_ctx, src0, src1, node); + ggml_vk_concat(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_UPSCALE: - ggml_vk_upscale(ctx, compute_ctx, src0, node); + ggml_vk_upscale(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_SCALE: - ggml_vk_scale(ctx, compute_ctx, src0, node); + ggml_vk_scale(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_SQR: - ggml_vk_sqr(ctx, compute_ctx, src0, node); + ggml_vk_sqr(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_CLAMP: - ggml_vk_clamp(ctx, compute_ctx, src0, node); + ggml_vk_clamp(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_PAD: - ggml_vk_pad(ctx, compute_ctx, src0, node); + ggml_vk_pad(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_CPY: case GGML_OP_CONT: case GGML_OP_DUP: - ggml_vk_cpy(ctx, compute_ctx, src0, node); + ggml_vk_cpy(ctx, compute_ctx, src0, node, dryrun); + + break; + case GGML_OP_SILU_BACK: + ggml_vk_silu_back(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_NORM: - ggml_vk_norm(ctx, compute_ctx, src0, node); + ggml_vk_norm(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_GROUP_NORM: - ggml_vk_group_norm(ctx, compute_ctx, src0, node); + ggml_vk_group_norm(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_RMS_NORM: - ggml_vk_rms_norm(ctx, compute_ctx, src0, node); + ggml_vk_rms_norm(ctx, compute_ctx, src0, node, dryrun); + + break; + case GGML_OP_RMS_NORM_BACK: + ggml_vk_rms_norm_back(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_UNARY: @@ -5869,77 +8562,132 @@ static void ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: - ggml_vk_unary(ctx, compute_ctx, src0, node); + case GGML_UNARY_OP_SIGMOID: + ggml_vk_unary(ctx, compute_ctx, src0, node, dryrun); break; default: - return; + return false; } break; case GGML_OP_DIAG_MASK_INF: - ggml_vk_diag_mask_inf(ctx, compute_ctx, src0, node); + ggml_vk_diag_mask_inf(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_SOFT_MAX: - ggml_vk_soft_max(ctx, compute_ctx, src0, src1, node); + ggml_vk_soft_max(ctx, compute_ctx, src0, src1, node, dryrun); + + break; + case GGML_OP_SOFT_MAX_BACK: + ggml_vk_soft_max_back(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_ROPE: - ggml_vk_rope(ctx, compute_ctx, src0, src1, src2, node); + ggml_vk_rope(ctx, compute_ctx, src0, src1, src2, node, false, dryrun); + + break; + case GGML_OP_ROPE_BACK: + ggml_vk_rope(ctx, compute_ctx, src0, src1, src2, node, true, dryrun); break; case GGML_OP_ARGSORT: - ggml_vk_argsort(ctx, compute_ctx, src0, node); + ggml_vk_argsort(ctx, compute_ctx, src0, node, dryrun); + + break; + case GGML_OP_SUM: + ggml_vk_sum(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_SUM_ROWS: - ggml_vk_sum_rows(ctx, compute_ctx, src0, node); + ggml_vk_sum_rows(ctx, compute_ctx, src0, node, dryrun); + + break; + case GGML_OP_ARGMAX: + ggml_vk_argmax(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_IM2COL: - ggml_vk_im2col(ctx, compute_ctx, src0, src1, node); + ggml_vk_im2col(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_TIMESTEP_EMBEDDING: - ggml_vk_timestep_embedding(ctx, compute_ctx, src0, node); + ggml_vk_timestep_embedding(ctx, compute_ctx, src0, node, dryrun); + + break; + case GGML_OP_CONV_TRANSPOSE_1D: + ggml_vk_conv_transpose_1d(ctx, compute_ctx, src0, src1, node, dryrun); + + break; + case GGML_OP_POOL_2D: + ggml_vk_pool_2d(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_LEAKY_RELU: - ggml_vk_leaky_relu(ctx, compute_ctx, src0, node); + ggml_vk_leaky_relu(ctx, compute_ctx, src0, node, dryrun); break; case GGML_OP_MUL_MAT: - ggml_vk_mul_mat(ctx, compute_ctx, src0, src1, node); + ggml_vk_mul_mat(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_MUL_MAT_ID: - ggml_vk_mul_mat_id(ctx, compute_ctx, src0, src1, src2, node); + ggml_vk_mul_mat_id(ctx, compute_ctx, src0, src1, src2, node, dryrun); + + break; + + case GGML_OP_FLASH_ATTN_EXT: + ggml_vk_flash_attn(ctx, compute_ctx, src0, src1, src2, src3, node, dryrun); break; default: - return; + return false; + } + + if (dryrun) { + return false; } ctx->tensor_ctxs[node_idx] = compute_ctx; -#ifdef GGML_VULKAN_CHECK_RESULTS +#if defined(GGML_VULKAN_CHECK_RESULTS) // Force context reset on each node so that each tensor ends up in its own context // and can be run and compared to its CPU equivalent separately last_node = true; #endif - if (last_node) { + if (submit || last_node) { ggml_vk_ctx_end(compute_ctx); - compute_ctx->exit_tensor_idx = node_idx; + + // TODO probably it'd be better to pass a exit_node flag to ggml_vk_compute_forward + if (last_node) { + compute_ctx->exit_tensor_idx = node_idx_begin; + } + else { + compute_ctx->exit_tensor_idx = -1; + } + ctx->compute_ctx.reset(); + + bool ok = ggml_vk_compute_forward(ctx, node_begin, node_idx_begin, false, almost_ready); + if (!ok) { + if (node->op == GGML_OP_UNARY) { + std::cerr << __func__ << ": error: op not supported UNARY " << node->name << " (" << ggml_unary_op_name(static_cast(node->op_params[0])) << ")" << std::endl; + } + else { + std::cerr << __func__ << ": error: op not supported " << node->name << " (" << ggml_op_name(node->op) << ")" << std::endl; + } + } + } + return true; } -static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * tensor, int tensor_idx){ - ggml_tensor_extra_gpu * extra = nullptr; +static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * tensor, int tensor_idx, bool use_fence = true, bool almost_ready = false) { + ggml_backend_buffer * buf = nullptr; switch (tensor->op) { case GGML_OP_ADD: case GGML_OP_GET_ROWS: + case GGML_OP_SUB: case GGML_OP_MUL: case GGML_OP_DIV: case GGML_OP_CONCAT: @@ -5951,24 +8699,33 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * case GGML_OP_CPY: case GGML_OP_CONT: case GGML_OP_DUP: + case GGML_OP_SILU_BACK: case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: + case GGML_OP_RMS_NORM_BACK: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: + case GGML_OP_SOFT_MAX_BACK: case GGML_OP_ROPE: + case GGML_OP_ROPE_BACK: case GGML_OP_RESHAPE: case GGML_OP_VIEW: case GGML_OP_PERMUTE: case GGML_OP_TRANSPOSE: case GGML_OP_NONE: case GGML_OP_ARGSORT: + case GGML_OP_SUM: case GGML_OP_SUM_ROWS: + case GGML_OP_ARGMAX: case GGML_OP_IM2COL: case GGML_OP_TIMESTEP_EMBEDDING: + case GGML_OP_CONV_TRANSPOSE_1D: + case GGML_OP_POOL_2D: case GGML_OP_LEAKY_RELU: case GGML_OP_REPEAT: - extra = (ggml_tensor_extra_gpu *) tensor->extra; + case GGML_OP_REPEAT_BACK: + buf = tensor->buffer; break; case GGML_OP_UNARY: @@ -5978,7 +8735,8 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: - extra = (ggml_tensor_extra_gpu *) tensor->extra; + case GGML_UNARY_OP_SIGMOID: + buf = tensor->buffer; break; default: return false; @@ -5986,39 +8744,55 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * break; case GGML_OP_MUL_MAT: case GGML_OP_MUL_MAT_ID: - extra = (ggml_tensor_extra_gpu *) tensor->extra; + case GGML_OP_FLASH_ATTN_EXT: + buf = tensor->buffer; break; default: return false; } - if (extra == nullptr) { + if (buf == nullptr) { return false; } VK_LOG_DEBUG("ggml_vk_compute_forward(" << tensor << ", name=" << tensor->name << ", op=" << ggml_op_name(tensor->op) << ", type=" << tensor->type << ", ne0=" << tensor->ne[0] << ", ne1=" << tensor->ne[1] << ", ne2=" << tensor->ne[2] << ", ne3=" << tensor->ne[3] << ", nb0=" << tensor->nb[0] << ", nb1=" << tensor->nb[1] << ", nb2=" << tensor->nb[2] << ", nb3=" << tensor->nb[3] << ", view_src=" << tensor->view_src << ", view_offs=" << tensor->view_offs << ")"); -#ifdef GGML_VULKAN_CHECK_RESULTS - ggml_vk_check_results_0(tensor); -#endif - vk_context subctx = ctx->tensor_ctxs[tensor_idx].lock(); + // always wait for the GPU work to be done for the last submit + if (tensor_idx == subctx->exit_tensor_idx) { + use_fence = true; + } + // Only run if ctx hasn't been submitted yet if (!subctx->seqs.empty()) { +#ifdef GGML_VULKAN_CHECK_RESULTS + ggml_vk_check_results_0(tensor); + use_fence = true; +#endif + // Do staging buffer copies for (auto& cpy : subctx->in_memcpys) { memcpy(cpy.dst, cpy.src, cpy.n); } - ggml_vk_submit(subctx, ctx->fence); + if (almost_ready && !ctx->almost_ready_fence_pending && !use_fence) { + ggml_vk_submit(subctx, ctx->almost_ready_fence); + ctx->almost_ready_fence_pending = true; + } else { + ggml_vk_submit(subctx, use_fence ? ctx->fence : vk::Fence{}); + } + + if (use_fence) { + ggml_vk_wait_for_fence(ctx); + } +#ifdef GGML_VULKAN_CHECK_RESULTS + ggml_vk_check_results_1(tensor); +#endif } if (tensor_idx == subctx->exit_tensor_idx) { - VK_CHECK(ctx->device->device.waitForFences({ ctx->fence }, true, UINT64_MAX), "ggml_vk_compute_forward waitForFences"); - ctx->device->device.resetFences({ ctx->fence }); - // Do staging buffer copies for (auto& cpy : subctx->out_memcpys) { memcpy(cpy.dst, cpy.src, cpy.n); @@ -6038,17 +8812,8 @@ static void ggml_vk_graph_cleanup(ggml_backend_vk_context * ctx) { } ctx->gc.temp_buffers.clear(); - for (auto& pipeline : ctx->device->pipelines) { - if (pipeline.expired()) { - continue; - } - - vk_pipeline pl = pipeline.lock(); - ggml_pipeline_cleanup(pl); - } - - ggml_vk_queue_cleanup(ctx->device, ctx->device->compute_queue); - ggml_vk_queue_cleanup(ctx->device, ctx->device->transfer_queue); + ggml_vk_command_pool_cleanup(ctx->device, ctx->compute_cmd_pool); + ggml_vk_command_pool_cleanup(ctx->device, ctx->transfer_cmd_pool); for (size_t i = 0; i < ctx->gc.semaphores.size(); i++) { ctx->device->device.destroySemaphore({ ctx->gc.semaphores[i].s }); @@ -6067,10 +8832,10 @@ static void ggml_vk_graph_cleanup(ggml_backend_vk_context * ctx) { ctx->device->device.resetEvent(event); } - ctx->staging_offset = 0; - ctx->tensor_ctxs.clear(); ctx->gc.contexts.clear(); + ctx->pipeline_descriptor_set_requirements = 0; + ctx->descriptor_set_idx = 0; } // Clean up on backend free @@ -6081,7 +8846,6 @@ static void ggml_vk_cleanup(ggml_backend_vk_context * ctx) { ggml_vk_destroy_buffer(ctx->prealloc_x); ggml_vk_destroy_buffer(ctx->prealloc_y); ggml_vk_destroy_buffer(ctx->prealloc_split_k); - ggml_vk_destroy_buffer(ctx->staging); for (auto& buffer : ctx->buffer_pool) { ggml_vk_destroy_buffer(buffer); @@ -6090,7 +8854,6 @@ static void ggml_vk_cleanup(ggml_backend_vk_context * ctx) { ctx->prealloc_size_x = 0; ctx->prealloc_size_y = 0; ctx->prealloc_size_split_k = 0; - ctx->staging_size = 0; for (auto& event : ctx->gc.events) { ctx->device->device.destroyEvent(event); @@ -6098,6 +8861,16 @@ static void ggml_vk_cleanup(ggml_backend_vk_context * ctx) { ctx->gc.events.clear(); ctx->device->device.destroyFence(ctx->fence); + ctx->device->device.destroyFence(ctx->almost_ready_fence); + + for (auto& pool : ctx->descriptor_pools) { + ctx->device->device.destroyDescriptorPool(pool); + } + ctx->descriptor_pools.clear(); + ctx->descriptor_sets.clear(); + + ctx->compute_cmd_pool.destroy(ctx->device->device); + ctx->transfer_cmd_pool.destroy(ctx->device->device); } GGML_CALL static int ggml_vk_get_device_count() { @@ -6123,42 +8896,6 @@ GGML_CALL static void ggml_vk_get_device_description(int device, char * descript // device backend -static void * const vk_ptr_base = (void *)(uintptr_t) 0x1000; // NOLINT - -struct ggml_backend_vk_buffer_context { - vk_device_ref device; - vk_buffer dev_buffer; - ggml_tensor_extra_gpu * temp_tensor_extras = nullptr; - size_t temp_tensor_extra_index = 0; - std::string name; - - ggml_backend_vk_buffer_context(vk_device_ref device, vk_buffer&& dev_buffer, std::string& name) : - device(device), - dev_buffer(dev_buffer), - name(name) { - } - - ~ggml_backend_vk_buffer_context() { - ggml_vk_destroy_buffer(dev_buffer); - if (temp_tensor_extras != nullptr) { - delete[] temp_tensor_extras; - } - } - - ggml_tensor_extra_gpu * ggml_vk_alloc_temp_tensor_extra() { - if (temp_tensor_extras == nullptr) { - temp_tensor_extras = new ggml_tensor_extra_gpu[GGML_VK_MAX_NODES]; - } - - size_t alloc_index = temp_tensor_extra_index; - temp_tensor_extra_index = (temp_tensor_extra_index + 1) % GGML_VK_MAX_NODES; - ggml_tensor_extra_gpu * extra = &temp_tensor_extras[alloc_index]; - extra->reset(); - - return extra; - } -}; - GGML_CALL static const char * ggml_backend_vk_buffer_get_name(ggml_backend_buffer_t buffer) { ggml_backend_vk_buffer_context * ctx = (ggml_backend_vk_buffer_context *)buffer->context; return ctx->name.c_str(); @@ -6183,51 +8920,46 @@ GGML_CALL static void * ggml_backend_vk_buffer_get_base(ggml_backend_buffer_t bu GGML_CALL static void ggml_backend_vk_buffer_init_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor) { VK_LOG_DEBUG("ggml_backend_vk_buffer_init_tensor(" << buffer << " (" << buffer->context << "), " << tensor << ")"); - ggml_backend_vk_buffer_context * ctx = (ggml_backend_vk_buffer_context *)buffer->context; - if (tensor->view_src != nullptr) { GGML_ASSERT(tensor->view_src->buffer->buft == buffer->buft); - GGML_ASSERT(tensor->view_src->extra != nullptr); - tensor->extra = tensor->view_src->extra; - } else { - ggml_tensor_extra_gpu * extra = ctx->ggml_vk_alloc_temp_tensor_extra(); - extra->buffer_gpu = ctx->dev_buffer; - extra->offset = (uint8_t *) tensor->data - (uint8_t *) vk_ptr_base; - tensor->extra = extra; } } -GGML_CALL static void ggml_backend_vk_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, const void * data, size_t offset, size_t size) { +static void ggml_backend_vk_buffer_memset_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, uint8_t value, size_t offset, size_t size) { + VK_LOG_DEBUG("ggml_backend_vk_buffer_memset_tensor(" << buffer << ", " << tensor << ", " << value << ", " << offset << ", " << size << ")"); + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)buffer->context; + vk_buffer buf = buf_ctx->dev_buffer; + + uint32_t val32 = (uint32_t)value * 0x01010101; + ggml_vk_buffer_memset(buf, vk_tensor_offset(tensor) + tensor->view_offs + offset, val32, size); +} + +static void ggml_backend_vk_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, const void * data, size_t offset, size_t size) { VK_LOG_DEBUG("ggml_backend_vk_buffer_set_tensor(" << buffer << ", " << tensor << ", " << data << ", " << offset << ", " << size << ")"); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) tensor->extra; + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)buffer->context; + vk_buffer buf = buf_ctx->dev_buffer; - vk_buffer buf = extra->buffer_gpu.lock(); - - ggml_vk_buffer_write(buf, extra->offset + tensor->view_offs + offset, data, size); - - GGML_UNUSED(buffer); + ggml_vk_buffer_write(buf, vk_tensor_offset(tensor) + tensor->view_offs + offset, data, size); } GGML_CALL static void ggml_backend_vk_buffer_get_tensor(ggml_backend_buffer_t buffer, const ggml_tensor * tensor, void * data, size_t offset, size_t size) { VK_LOG_DEBUG("ggml_backend_vk_buffer_get_tensor(" << buffer << ", " << tensor << ", " << data << ", " << offset << ", " << size << ")"); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) tensor->extra; + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)buffer->context; - vk_buffer buf = extra->buffer_gpu.lock(); + vk_buffer buf = buf_ctx->dev_buffer; - ggml_vk_buffer_read(buf, extra->offset + tensor->view_offs + offset, data, size); - - GGML_UNUSED(buffer); + ggml_vk_buffer_read(buf, vk_tensor_offset(tensor) + tensor->view_offs + offset, data, size); } GGML_CALL static bool ggml_backend_vk_buffer_cpy_tensor(ggml_backend_buffer_t buffer, const ggml_tensor * src, ggml_tensor * dst) { if (ggml_backend_buffer_is_vk(src->buffer)) { - ggml_tensor_extra_gpu * src_extra = (ggml_tensor_extra_gpu *) src->extra; - ggml_tensor_extra_gpu * dst_extra = (ggml_tensor_extra_gpu *) dst->extra; + ggml_backend_vk_buffer_context * src_buf_ctx = (ggml_backend_vk_buffer_context *)src->buffer->context; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; - vk_buffer src_buf = src_extra->buffer_gpu.lock(); - vk_buffer dst_buf = dst_extra->buffer_gpu.lock(); + vk_buffer src_buf = src_buf_ctx->dev_buffer; + vk_buffer dst_buf = dst_buf_ctx->dev_buffer; - ggml_vk_buffer_copy(dst_buf, dst_extra->offset + dst->view_offs, src_buf, src_extra->offset + src->view_offs, ggml_nbytes(src)); + ggml_vk_buffer_copy(dst_buf, vk_tensor_offset(dst) + dst->view_offs, src_buf, vk_tensor_offset(src) + src->view_offs, ggml_nbytes(src)); return true; } @@ -6247,6 +8979,7 @@ static ggml_backend_buffer_i ggml_backend_vk_buffer_interface = { /* .free_buffer = */ ggml_backend_vk_buffer_free_buffer, /* .get_base = */ ggml_backend_vk_buffer_get_base, /* .init_tensor = */ ggml_backend_vk_buffer_init_tensor, + /* .memset_tensor = */ ggml_backend_vk_buffer_memset_tensor, /* .set_tensor = */ ggml_backend_vk_buffer_set_tensor, /* .get_tensor = */ ggml_backend_vk_buffer_get_tensor, /* .cpy_tensor = */ ggml_backend_vk_buffer_cpy_tensor, @@ -6284,7 +9017,7 @@ GGML_CALL static size_t ggml_backend_vk_buffer_type_get_alignment(ggml_backend_b GGML_CALL static size_t ggml_backend_vk_buffer_type_get_max_size(ggml_backend_buffer_type_t buft) { ggml_backend_vk_buffer_type_context * ctx = (ggml_backend_vk_buffer_type_context *) buft->context; - return ctx->device->max_memory_allocation_size; + return ctx->device->suballocation_block_size; } GGML_CALL static size_t ggml_backend_vk_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor) { @@ -6330,8 +9063,7 @@ GGML_CALL static ggml_backend_buffer_t ggml_backend_vk_host_buffer_type_alloc_bu try { ptr = ggml_vk_host_malloc(vk_instance.devices[0], size); } catch (vk::SystemError& e) { - std::cerr << "ggml_vulkan: Failed to allocate pinned memory." << std::endl; - std::cerr << "ggml_vulkan: " << e.what() << std::endl; + GGML_LOG_WARN("ggml_vulkan: Failed to allocate pinned memory (%s)\n", e.what()); // fallback to cpu buffer return ggml_backend_buft_alloc_buffer(ggml_backend_cpu_buffer_type(), size); } @@ -6352,6 +9084,12 @@ GGML_CALL static size_t ggml_backend_vk_host_buffer_type_get_alignment(ggml_back UNUSED(buft); } +static size_t ggml_backend_vk_host_buffer_type_get_max_size(ggml_backend_buffer_type_t buft) { + return vk_instance.devices[0]->suballocation_block_size; + + UNUSED(buft); +} + // Should be changed to return device-specific host buffer type // but that probably requires changes in llama.cpp GGML_CALL ggml_backend_buffer_type_t ggml_backend_vk_host_buffer_type() { @@ -6360,7 +9098,7 @@ GGML_CALL ggml_backend_buffer_type_t ggml_backend_vk_host_buffer_type() { /* .get_name = */ ggml_backend_vk_host_buffer_type_name, /* .alloc_buffer = */ ggml_backend_vk_host_buffer_type_alloc_buffer, /* .get_alignment = */ ggml_backend_vk_host_buffer_type_get_alignment, - /* .get_max_size = */ NULL, // defaults to SIZE_MAX + /* .get_max_size = */ ggml_backend_vk_host_buffer_type_get_max_size, /* .get_alloc_size = */ ggml_backend_cpu_buffer_type()->iface.get_alloc_size, /* .is_host = */ ggml_backend_cpu_buffer_type()->iface.is_host, }, @@ -6404,22 +9142,22 @@ GGML_CALL static void ggml_backend_vk_set_tensor_async(ggml_backend_t backend, g ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; GGML_ASSERT((tensor->buffer->buft == ggml_backend_vk_get_default_buffer_type(backend) || tensor->buffer->buft == ggml_backend_vk_host_buffer_type()) && "unsupported buffer type"); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) tensor->extra; + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)tensor->buffer->context; vk_context transfer_ctx; if (ctx->transfer_ctx.expired()) { // Initialize new transfer context - transfer_ctx = ggml_vk_create_context(ctx, ctx->device->transfer_queue); + transfer_ctx = ggml_vk_create_context(ctx, ctx->transfer_cmd_pool); ctx->transfer_ctx = transfer_ctx; ggml_vk_ctx_begin(ctx->device, transfer_ctx); } else { transfer_ctx = ctx->transfer_ctx.lock(); } - vk_buffer buf = extra->buffer_gpu.lock(); + vk_buffer buf = buf_ctx->dev_buffer; - ggml_vk_buffer_write_async(transfer_ctx, buf, extra->offset + tensor->view_offs + offset, data, size, ctx->staging, ctx->staging_offset); + ggml_vk_buffer_write_async(transfer_ctx, buf, vk_tensor_offset(tensor) + tensor->view_offs + offset, data, size); } GGML_CALL static void ggml_backend_vk_get_tensor_async(ggml_backend_t backend, const ggml_tensor * tensor, void * data, size_t offset, size_t size) { @@ -6427,46 +9165,46 @@ GGML_CALL static void ggml_backend_vk_get_tensor_async(ggml_backend_t backend, c ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; GGML_ASSERT((tensor->buffer->buft == ggml_backend_vk_get_default_buffer_type(backend) || tensor->buffer->buft == ggml_backend_vk_host_buffer_type()) && "unsupported buffer type"); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) tensor->extra; + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)tensor->buffer->context; vk_context transfer_ctx; if (ctx->transfer_ctx.expired()) { // Initialize new transfer context - transfer_ctx = ggml_vk_create_context(ctx, ctx->device->transfer_queue); + transfer_ctx = ggml_vk_create_context(ctx, ctx->transfer_cmd_pool); ctx->transfer_ctx = transfer_ctx; ggml_vk_ctx_begin(ctx->device, transfer_ctx); } else { transfer_ctx = ctx->transfer_ctx.lock(); } - vk_buffer buf = extra->buffer_gpu.lock(); + vk_buffer buf = buf_ctx->dev_buffer; - ggml_vk_buffer_read_async(transfer_ctx, buf, extra->offset + tensor->view_offs + offset, data, size, ctx->staging, ctx->staging_offset); + ggml_vk_buffer_read_async(transfer_ctx, buf, vk_tensor_offset(tensor) + tensor->view_offs + offset, data, size); } GGML_CALL static bool ggml_backend_vk_cpy_tensor_async(ggml_backend_t backend, const ggml_tensor * src, ggml_tensor * dst) { VK_LOG_DEBUG("ggml_backend_vk_cpy_tensor_async()"); ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; if ((dst->buffer->buft == ggml_backend_vk_get_default_buffer_type(backend) || dst->buffer->buft == ggml_backend_vk_host_buffer_type()) && ggml_backend_buffer_is_vk(src->buffer)) { - ggml_tensor_extra_gpu * src_extra = (ggml_tensor_extra_gpu *) src->extra; - ggml_tensor_extra_gpu * dst_extra = (ggml_tensor_extra_gpu *) dst->extra; + ggml_backend_vk_buffer_context * src_buf_ctx = (ggml_backend_vk_buffer_context *)src->buffer->context; + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; vk_context transfer_ctx; if (ctx->transfer_ctx.expired()) { // Initialize new transfer context - transfer_ctx = ggml_vk_create_context(ctx, ctx->device->transfer_queue); + transfer_ctx = ggml_vk_create_context(ctx, ctx->transfer_cmd_pool); ctx->transfer_ctx = transfer_ctx; ggml_vk_ctx_begin(ctx->device, transfer_ctx); } else { transfer_ctx = ctx->transfer_ctx.lock(); } - vk_buffer src_buf = src_extra->buffer_gpu.lock(); - vk_buffer dst_buf = dst_extra->buffer_gpu.lock(); + vk_buffer src_buf = src_buf_ctx->dev_buffer; + vk_buffer dst_buf = dst_buf_ctx->dev_buffer; - ggml_vk_buffer_copy_async(transfer_ctx, dst_buf, dst_extra->offset + dst->view_offs, src_buf, src_extra->offset + src->view_offs, ggml_nbytes(src)); + ggml_vk_buffer_copy_async(transfer_ctx, dst_buf, vk_tensor_offset(dst) + dst->view_offs, src_buf, vk_tensor_offset(src) + src->view_offs, ggml_nbytes(src)); return true; } @@ -6489,8 +9227,7 @@ GGML_CALL static void ggml_backend_vk_synchronize(ggml_backend_t backend) { } ggml_vk_submit(transfer_ctx, ctx->fence); - VK_CHECK(ctx->device->device.waitForFences({ ctx->fence }, true, UINT64_MAX), "ggml_backend_vk_synchronize waitForFences"); - ctx->device->device.resetFences({ ctx->fence }); + ggml_vk_wait_for_fence(ctx); for (auto& cpy : transfer_ctx->out_memcpys) { memcpy(cpy.dst, cpy.src, cpy.n); @@ -6507,10 +9244,25 @@ GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backen VK_LOG_DEBUG("ggml_backend_vk_graph_compute(" << cgraph->n_nodes << " nodes)"); ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; + if (vk_instance.debug_utils_support) { + vk::DebugUtilsLabelEXT dul = {}; + dul.pLabelName = "ggml_backend_vk_graph_compute"; + dul.color = std::array{1.0f, 1.0f, 1.0f, 1.0f}; + vk_instance.pfn_vkQueueBeginDebugUtilsLabelEXT(ctx->device->compute_queue.queue, reinterpret_cast(&dul)); + } + + uint64_t total_mat_mul_bytes = 0; for (int i = 0; i < cgraph->n_nodes; i++) { - ggml_vk_preallocate_buffers_graph(ctx, cgraph->nodes[i]); + ggml_vk_build_graph(ctx, cgraph->nodes[i], i, nullptr, 0, true, false, false, false); + if (cgraph->nodes[i]->op == GGML_OP_MUL_MAT || cgraph->nodes[i]->op == GGML_OP_MUL_MAT_ID) { + total_mat_mul_bytes += ggml_nbytes(cgraph->nodes[i]->src[0]); + } + } + if (ctx->device->need_compiles) { + ggml_vk_load_shaders(ctx->device); } ggml_vk_preallocate_buffers(ctx); + ggml_pipeline_allocate_descriptor_sets(ctx); int last_node = cgraph->n_nodes - 1; @@ -6522,31 +9274,111 @@ GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backen // Reserve tensor context space for all nodes ctx->tensor_ctxs.resize(cgraph->n_nodes); - for (int i = 0; i < cgraph->n_nodes; i++) { - ggml_vk_build_graph(ctx, cgraph->nodes[i], i, i == last_node); + bool first_node_in_batch = true; // true if next node will be first node in a batch + int submit_node_idx = 0; // index to first node in a batch + + vk_context compute_ctx; + if (vk_perf_logger_enabled) { + // allocate/resize the query pool + if (ctx->device->num_queries < cgraph->n_nodes + 1) { + if (ctx->device->query_pool) { + ctx->device->device.destroyQueryPool(ctx->device->query_pool); + } + vk::QueryPoolCreateInfo query_create_info; + query_create_info.queryType = vk::QueryType::eTimestamp; + query_create_info.queryCount = cgraph->n_nodes + 100; + ctx->device->query_pool = ctx->device->device.createQueryPool(query_create_info); + ctx->device->num_queries = query_create_info.queryCount; + } + + ctx->device->device.resetQueryPool(ctx->device->query_pool, 0, cgraph->n_nodes+1); + + GGML_ASSERT(ctx->compute_ctx.expired()); + compute_ctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); + ctx->compute_ctx = compute_ctx; + ggml_vk_ctx_begin(ctx->device, compute_ctx); + compute_ctx->s->buffer.writeTimestamp(vk::PipelineStageFlagBits::eAllCommands, ctx->device->query_pool, 0); } + // Submit after enough work has accumulated, to overlap CPU cmdbuffer generation with GPU execution. + // Estimate the amount of matmul work by looking at the weight matrix size, and submit every 100MB + // (and scaled down based on model size, so smaller models submit earlier). + // Also submit at least every 100 nodes, in case there are workloads without as much matmul. + int nodes_per_submit = 100; + int submitted_nodes = 0; + int submit_count = 0; + uint64_t mul_mat_bytes = 0; + uint64_t mul_mat_bytes_per_submit = std::min(uint64_t(100*1000*1000), total_mat_mul_bytes / 40u); for (int i = 0; i < cgraph->n_nodes; i++) { - ggml_tensor * node = cgraph->nodes[i]; - - if (ggml_vk_is_empty(node)) { - continue; + if (first_node_in_batch) { + submit_node_idx = i; } - bool ok = ggml_vk_compute_forward(ctx, node, i); - if (!ok) { - if (node->op == GGML_OP_UNARY) { - std::cerr << __func__ << ": error: op not supported UNARY " << node->name << " (" << ggml_unary_op_name(static_cast(node->op_params[0])) << ")" << std::endl; + if (cgraph->nodes[i]->op == GGML_OP_MUL_MAT || cgraph->nodes[i]->op == GGML_OP_MUL_MAT_ID) { + mul_mat_bytes += ggml_nbytes(cgraph->nodes[i]->src[0]); + } + + // Signal the almost_ready fence when the graph is mostly complete (< 20% remaining) + bool almost_ready = (cgraph->n_nodes - i) < cgraph->n_nodes / 5; + bool submit = (submitted_nodes >= nodes_per_submit) || + (mul_mat_bytes >= mul_mat_bytes_per_submit) || + (i == last_node) || + (almost_ready && !ctx->almost_ready_fence_pending); + + bool enqueued = ggml_vk_build_graph(ctx, cgraph->nodes[i], i, cgraph->nodes[submit_node_idx], submit_node_idx, false, i == last_node, almost_ready, submit); + + if (vk_perf_logger_enabled) { + if (ctx->compute_ctx.expired()) { + compute_ctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); + ctx->compute_ctx = compute_ctx; + ggml_vk_ctx_begin(ctx->device, compute_ctx); } else { - std::cerr << __func__ << ": error: op not supported " << node->name << " (" << ggml_op_name(node->op) << ")" << std::endl; + compute_ctx = ctx->compute_ctx.lock(); + } + compute_ctx->s->buffer.writeTimestamp(vk::PipelineStageFlagBits::eAllCommands, ctx->device->query_pool, i+1); + } + + if (enqueued) { + ++submitted_nodes; + +#ifndef GGML_VULKAN_CHECK_RESULTS + if (first_node_in_batch) { + first_node_in_batch = false; + } +#endif + } + + if (submit && enqueued) { + first_node_in_batch = true; + submitted_nodes = 0; + mul_mat_bytes = 0; + if (submit_count < 3) { + mul_mat_bytes_per_submit *= 2; + } + submit_count++; + } + } + + if (vk_perf_logger_enabled) { + // End the command buffer and submit/wait + GGML_ASSERT(!ctx->compute_ctx.expired()); + compute_ctx = ctx->compute_ctx.lock(); + ggml_vk_ctx_end(compute_ctx); + + ggml_vk_submit(compute_ctx, ctx->device->fence); + VK_CHECK(ctx->device->device.waitForFences({ ctx->device->fence }, true, UINT64_MAX), "GGML_VULKAN_PERF waitForFences"); + ctx->device->device.resetFences({ ctx->device->fence }); + + // Get the results and pass them to the logger + std::vector timestamps(cgraph->n_nodes + 1); + VK_CHECK(ctx->device->device.getQueryPoolResults(ctx->device->query_pool, 0, cgraph->n_nodes + 1, (cgraph->n_nodes + 1)*sizeof(uint64_t), timestamps.data(), sizeof(uint64_t), vk::QueryResultFlagBits::e64 | vk::QueryResultFlagBits::eWait), "get timestamp results"); + for (int i = 0; i < cgraph->n_nodes; i++) { + if (!ggml_vk_is_empty(cgraph->nodes[i])) { + ctx->device->perf_logger->log_timing(cgraph->nodes[i], uint64_t((timestamps[i+1] - timestamps[i]) * ctx->device->properties.limits.timestampPeriod)); } } -#ifdef GGML_VULKAN_CHECK_RESULTS - else { - ggml_vk_check_results_1(node); - } -#endif - GGML_ASSERT(ok); + + ctx->device->perf_logger->print_timings(); } ggml_vk_graph_cleanup(ctx); @@ -6567,7 +9399,11 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const case GGML_UNARY_OP_SILU: case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: - return ggml_is_contiguous(op->src[0]); + case GGML_UNARY_OP_SIGMOID: + return ggml_is_contiguous(op->src[0]) && + (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) && + (op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16) && + (op->src[0]->type == op->type); default: return false; } @@ -6575,9 +9411,17 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const case GGML_OP_MUL_MAT: case GGML_OP_MUL_MAT_ID: { - switch (op->src[0]->type) { + ggml_type src0_type = op->src[0]->type; + ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; + const vk_device& device = ctx->device; + if (op->op == GGML_OP_MUL_MAT_ID && !device->mul_mat_id_s[src0_type] && !device->mul_mat_id_m[src0_type] && !device->mul_mat_id_l[src0_type]) { + // If there's not enough shared memory for row_ids and the result tile, fallback to CPU + return false; + } + switch (src0_type) { case GGML_TYPE_F32: case GGML_TYPE_F16: + case GGML_TYPE_BF16: case GGML_TYPE_Q4_0: case GGML_TYPE_Q4_1: case GGML_TYPE_Q5_0: @@ -6588,6 +9432,14 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const case GGML_TYPE_Q4_K: case GGML_TYPE_Q5_K: case GGML_TYPE_Q6_K: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: break; default: @@ -6605,13 +9457,136 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const if (a->ne[3] != b->ne[3]) { return false; } + if (!(ggml_vk_dim01_contiguous(op->src[0]) || op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16 || op->src[0]->type == GGML_TYPE_BF16) || + !(ggml_vk_dim01_contiguous(op->src[1]) || op->src[1]->type == GGML_TYPE_F32 || op->src[1]->type == GGML_TYPE_F16)) { + return false; + } + if (op->src[0]->type == GGML_TYPE_BF16 && op->src[1]->type == GGML_TYPE_F16) { + // We currently don't have a bf16 x f16 shader, or an fp16->bf16 copy shader. + // So don't support this combination for now. + return false; + } + return true; } break; + case GGML_OP_FLASH_ATTN_EXT: + { + ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; + bool coopmat2 = ctx->device->coopmat2; + switch (op->src[0]->ne[0]) { + case 64: + case 80: + case 96: + case 112: + case 128: + case 256: + break; + default: + return false; + } + if (op->src[0]->type != GGML_TYPE_F32) { + return false; + } + if (op->type != GGML_TYPE_F32) { + return false; + } + if (op->src[3] && op->src[3]->type != GGML_TYPE_F16) { + return false; + } + // It's straightforward to support different K/V dequant, but would + // significantly increase the number of pipelines + if (op->src[1]->type != op->src[2]->type) { + return false; + } + switch (op->src[1]->type) { + case GGML_TYPE_F16: + case GGML_TYPE_Q4_0: + case GGML_TYPE_Q8_0: + // supported in scalar and coopmat2 paths + break; + case GGML_TYPE_Q4_1: + case GGML_TYPE_Q5_0: + case GGML_TYPE_Q5_1: + // K dequants currently disabled because D dimension is rounded up to 256 and runs inefficiently + //case GGML_TYPE_Q2_K: + //case GGML_TYPE_Q3_K: + //case GGML_TYPE_Q4_K: + //case GGML_TYPE_Q5_K: + //case GGML_TYPE_Q6_K: + //case GGML_TYPE_IQ1_S: + //case GGML_TYPE_IQ1_M: + //case GGML_TYPE_IQ2_XXS: + //case GGML_TYPE_IQ2_XS: + //case GGML_TYPE_IQ2_S: + //case GGML_TYPE_IQ3_XXS: + //case GGML_TYPE_IQ3_S: + //case GGML_TYPE_IQ4_XS: + case GGML_TYPE_IQ4_NL: + // currently supported only in coopmat2 path + if (!coopmat2) { + return false; + } + break; + default: + return false; + } + if (!coopmat2 && !ctx->device->subgroup_shuffle) { + // scalar FA uses subgroupShuffle + return false; + } + return true; + } case GGML_OP_GET_ROWS: { switch (op->src[0]->type) { case GGML_TYPE_F32: case GGML_TYPE_F16: + case GGML_TYPE_BF16: + case GGML_TYPE_Q4_0: + case GGML_TYPE_Q4_1: + case GGML_TYPE_Q5_0: + case GGML_TYPE_Q5_1: + case GGML_TYPE_Q8_0: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ4_XS: + case GGML_TYPE_IQ4_NL: + return true; + default: + return false; + } + } break; + case GGML_OP_CONT: + case GGML_OP_CPY: + case GGML_OP_DUP: + { + ggml_type src0_type = op->src[0]->type; + ggml_type src1_type = op->src[1] != nullptr ? op->src[1]->type : src0_type; + + if (src0_type == GGML_TYPE_F32) { + switch (src1_type) { + case GGML_TYPE_F32: + case GGML_TYPE_F16: + case GGML_TYPE_BF16: + case GGML_TYPE_Q4_0: + case GGML_TYPE_Q4_1: + case GGML_TYPE_Q5_0: + case GGML_TYPE_Q5_1: + case GGML_TYPE_Q8_0: + case GGML_TYPE_IQ4_NL: + return true; + default: + break; + } + } + if (src1_type == GGML_TYPE_F32) { + switch (src0_type) { + case GGML_TYPE_F16: case GGML_TYPE_Q4_0: case GGML_TYPE_Q4_1: case GGML_TYPE_Q5_0: @@ -6620,58 +9595,70 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const case GGML_TYPE_IQ4_NL: return true; default: - return false; - } - } break; - case GGML_OP_CPY: - case GGML_OP_DUP: - { - ggml_type src0_type = op->src[0]->type; - ggml_type src1_type = op->src[1] != nullptr ? op->src[1]->type : src0_type; - if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F32) { - return true; - } - if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F16) { - return true; + break; + } } + if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) { return true; } + + // We can handle copying from a type to the same type if it's + // contiguous (memcpy). We use f16 or f32 shaders to do the copy, + // so the type/block size must be a multiple of 4. + if (src0_type == src1_type && + ggml_is_contiguous(op->src[0]) && ggml_is_contiguous(op) && + (ggml_type_size(src0_type) % 2) == 0) { + return true; + } return false; } break; case GGML_OP_REPEAT: - { - ggml_type src0_type = op->src[0]->type; - return src0_type != GGML_TYPE_I32 && src0_type != GGML_TYPE_I16; - } break; + return ggml_type_size(op->type) == sizeof(float) && ggml_type_size(op->src[0]->type) == sizeof(float); + case GGML_OP_REPEAT_BACK: + return op->type == GGML_TYPE_F32 && op->src[0]->type == GGML_TYPE_F32; case GGML_OP_ROPE: - return ggml_is_contiguous(op->src[0]); + case GGML_OP_ROPE_BACK: case GGML_OP_NONE: case GGML_OP_RESHAPE: case GGML_OP_VIEW: case GGML_OP_PERMUTE: case GGML_OP_TRANSPOSE: + case GGML_OP_RMS_NORM: + return true; case GGML_OP_NORM: case GGML_OP_GROUP_NORM: - case GGML_OP_RMS_NORM: + return ggml_is_contiguous(op->src[0]); case GGML_OP_ADD: + case GGML_OP_SUB: case GGML_OP_MUL: case GGML_OP_DIV: + return (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) && + (op->src[1]->type == GGML_TYPE_F32 || op->src[1]->type == GGML_TYPE_F16) && + (op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16); + case GGML_OP_SILU_BACK: + case GGML_OP_RMS_NORM_BACK: + case GGML_OP_SQR: + 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_SQR: - case GGML_OP_CLAMP: case GGML_OP_PAD: - case GGML_OP_CONT: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: + case GGML_OP_SOFT_MAX_BACK: case GGML_OP_ARGSORT: + case GGML_OP_SUM: case GGML_OP_SUM_ROWS: + case GGML_OP_ARGMAX: case GGML_OP_IM2COL: case GGML_OP_TIMESTEP_EMBEDDING: case GGML_OP_LEAKY_RELU: return true; + case GGML_OP_CONV_TRANSPOSE_1D: + return op->src[0]->type == GGML_TYPE_F32 && op->src[1]->type == GGML_TYPE_F32; default: return false; } @@ -6828,6 +9815,39 @@ static bool ggml_vk_instance_portability_enumeration_ext_available(const std::ve UNUSED(instance_extensions); } +// Extension availability +static bool ggml_vk_instance_debug_utils_ext_available( + const std::vector & instance_extensions) { + // Check for portability enumeration extension for MoltenVK support + for (const auto & properties : instance_extensions) { + if (strcmp("VK_EXT_debug_utils", properties.extensionName) == 0) { + return true; + } + } + + std::cerr << "ggml_vulkan: WARNING: Instance extension VK_EXT_debug_utils not found." << std::endl; + return false; + + UNUSED(instance_extensions); +} + +static bool ggml_vk_khr_cooperative_matrix_support(const vk::PhysicalDeviceProperties& props, const vk::PhysicalDeviceDriverProperties& driver_props, vk_device_architecture arch) { + switch (props.vendorID) { + case VK_VENDOR_ID_INTEL: + // Only allowing Xe2 GPU at the moment since Xe2 GPU can gain significant performance boost, + // while some older hardware (ex. Arc A770) has performance regressions + return arch == vk_device_architecture::INTEL_XE2; + case VK_VENDOR_ID_AMD: + if (driver_props.driverID == vk::DriverId::eAmdProprietary || driver_props.driverID == vk::DriverId::eAmdOpenSource) { + // Workaround for AMD proprietary driver reporting support on all GPUs + return arch == vk_device_architecture::AMD_RDNA3; + } + return true; + default: + return true; + } +} + // checks #ifdef GGML_VULKAN_CHECK_RESULTS @@ -6894,10 +9914,10 @@ static void ggml_vk_print_tensor(const ggml_tensor * tensor, const char * name) const size_t tensor_size = ggml_nbytes(tensor); tensor_data = malloc(tensor_size); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) tensor->extra; + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)tensor->buffer->context; - vk_buffer buffer_gpu = extra->buffer_gpu.lock(); - ggml_vk_buffer_read(buffer_gpu, extra->offset + tensor->view_offs, tensor_data, tensor_size); + vk_buffer buffer_gpu = buf_ctx->dev_buffer; + ggml_vk_buffer_read(buffer_gpu, vk_tensor_offset(tensor) + tensor->view_offs, tensor_data, tensor_size); } std::cerr << "TENSOR CHECK " << name << " (" << tensor->name << "): " << ggml_op_name(tensor->op) << std::endl; @@ -6937,7 +9957,6 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { ggml_tensor * src0 = tensor->src[0]; ggml_tensor * src1 = tensor->src[1]; - ggml_tensor * src2 = tensor->src[2]; struct ggml_init_params iparams = { /*.mem_size =*/ 2ul*1024ul*1024ul*1024ul, @@ -6947,183 +9966,121 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { struct ggml_context * ggml_ctx = ggml_init(iparams); - struct ggml_tensor * src0_clone = nullptr; - struct ggml_tensor * src1_clone = nullptr; - struct ggml_tensor * src2_clone = nullptr; + std::array src_clone = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; + std::array src_size = {0, 0, 0, 0, 0, 0}; + std::array src_buffer = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; + const char * srci_name[6] = {"src0", "src1", "src2", "src3", "src4", "src5"}; + struct ggml_tensor * tensor_clone = nullptr; - size_t src0_size; - size_t src1_size; - size_t src2_size; + for (int i = 0; i < 6; i++) { + ggml_tensor * srci = tensor->src[i]; + if (srci == nullptr) { + continue; + } + ggml_tensor * srci_clone = ggml_dup_tensor(ggml_ctx, srci); + size_t srci_size = ggml_nbytes(srci); - void * src0_buffer = nullptr; - void * src1_buffer = nullptr; - void * src2_buffer = nullptr; + src_clone[i] = srci_clone; + src_size[i] = ggml_nbytes(srci); + src_buffer[i] = malloc(srci_size); - if (src0 != nullptr) { - src0_clone = ggml_dup_tensor(ggml_ctx, src0); - - src0_size = ggml_nbytes(src0); - - src0_buffer = malloc(src0_size); - src0_clone->data = src0_buffer; - if (ggml_backend_buffer_is_host(src0->buffer)) { - memcpy(src0_clone->data, src0->data, src0_size); - memcpy(src0_clone->nb, src0->nb, sizeof(size_t) * GGML_MAX_DIMS); - } else if (ggml_backend_buffer_is_vk(src0->buffer)) { - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) src0->extra; - vk_buffer buffer_gpu = extra->buffer_gpu.lock(); - uint64_t offset = extra->offset + src0->view_offs; - if (!ggml_is_contiguous(src0) && ggml_vk_dim01_contiguous(src0)) { - for (int i3 = 0; i3 < src0->ne[3]; i3++) { - for (int i2 = 0; i2 < src0->ne[2]; i2++) { - const int idx = i3*src0->ne[2] + i2; - ggml_vk_buffer_read(buffer_gpu, offset + idx * src0->nb[2], ((char *)src0_clone->data + idx * src0_clone->nb[2]), src0->ne[1] * src0->nb[1]); + srci_clone->data = src_buffer[i]; + if (ggml_backend_buffer_is_host(srci->buffer)) { + memcpy(srci_clone->data, srci->data, srci_size); + memcpy(srci_clone->nb, srci->nb, sizeof(size_t) * GGML_MAX_DIMS); + } else if (ggml_backend_buffer_is_vk(srci->buffer)) { + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)srci->buffer->context; + vk_buffer& buffer_gpu = buf_ctx->dev_buffer; + uint64_t offset = vk_tensor_offset(srci) + srci->view_offs; + if (!ggml_is_contiguous(srci) && ggml_vk_dim01_contiguous(srci)) { + for (int i3 = 0; i3 < srci->ne[3]; i3++) { + for (int i2 = 0; i2 < srci->ne[2]; i2++) { + const int idx = i3*srci->ne[2] + i2; + ggml_vk_buffer_read(buffer_gpu, offset + idx * srci->nb[2], ((char *)srci_clone->data + idx * srci_clone->nb[2]), srci->ne[1] * srci->nb[1]); } } - src0_clone->nb[0] = src0->nb[0]; - src0_clone->nb[1] = src0->nb[1]; + srci_clone->nb[0] = srci->nb[0]; + srci_clone->nb[1] = srci->nb[1]; for (int i = 2; i < GGML_MAX_DIMS; i++) { - src0_clone->nb[i] = src0_clone->nb[i - 1]*src0_clone->ne[i - 1]; + srci_clone->nb[i] = srci_clone->nb[i - 1]*srci_clone->ne[i - 1]; } } else { - if (offset + src0_size >= buffer_gpu->size) { - src0_size = buffer_gpu->size - offset; + if (offset + srci_size >= buffer_gpu->size) { + srci_size = buffer_gpu->size - offset; } - ggml_vk_buffer_read(buffer_gpu, offset, src0_clone->data, src0_size); - memcpy(src0_clone->nb, src0->nb, sizeof(size_t) * GGML_MAX_DIMS); + ggml_vk_buffer_read(buffer_gpu, offset, srci_clone->data, srci_size); + memcpy(srci_clone->nb, srci->nb, sizeof(size_t) * GGML_MAX_DIMS); } } else { GGML_ABORT("fatal error"); } if (vk_output_tensor > 0 && vk_output_tensor == check_counter) { - ggml_vk_print_tensor(src0, "src0"); - } - } - if (src1 != nullptr) { - src1_clone = ggml_dup_tensor(ggml_ctx, src1); - - src1_size = ggml_nbytes(src1); - - src1_buffer = malloc(src1_size); - src1_clone->data = src1_buffer; - if (ggml_backend_buffer_is_host(src1->buffer)) { - memcpy(src1_clone->data, src1->data, src1_size); - memcpy(src1_clone->nb, src1->nb, sizeof(size_t) * GGML_MAX_DIMS); - } else if (ggml_backend_buffer_is_vk(src1->buffer)) { - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) src1->extra; - vk_buffer buffer_gpu = extra->buffer_gpu.lock(); - uint64_t offset = extra->offset + src1->view_offs; - if (!ggml_is_contiguous(src1) && ggml_vk_dim01_contiguous(src1)) { - for (int i3 = 0; i3 < src1->ne[3]; i3++) { - for (int i2 = 0; i2 < src1->ne[2]; i2++) { - const int idx = i3*src1->ne[2] + i2; - ggml_vk_buffer_read(buffer_gpu, offset + idx * src1->nb[2], ((char *)src1_clone->data + idx * src1_clone->nb[2]), src1->ne[1] * src1->nb[1]); - } - } - - src1_clone->nb[0] = src1->nb[0]; - src1_clone->nb[1] = src1->nb[1]; - for (int i = 2; i < GGML_MAX_DIMS; i++) { - src1_clone->nb[i] = src1_clone->nb[i - 1]*src1_clone->ne[i - 1]; - } - } else { - if (offset + src1_size >= buffer_gpu->size) { - src1_size = buffer_gpu->size - offset; - } - ggml_vk_buffer_read(buffer_gpu, offset, src1_clone->data, src1_size); - memcpy(src1_clone->nb, src1->nb, sizeof(size_t) * GGML_MAX_DIMS); - } - } else { - GGML_ABORT("fatal error"); - } - - if (vk_output_tensor > 0 && vk_output_tensor == check_counter) { - ggml_vk_print_tensor(src1, "src1"); - } - } - if (src2 != nullptr) { - src2_clone = ggml_dup_tensor(ggml_ctx, src2); - - src2_size = ggml_nbytes(src2); - - src2_buffer = malloc(src2_size); - src2_clone->data = src2_buffer; - if (ggml_backend_buffer_is_host(src2->buffer)) { - memcpy(src2_clone->data, src2->data, src2_size); - memcpy(src2_clone->nb, src2->nb, sizeof(size_t) * GGML_MAX_DIMS); - } else if (ggml_backend_buffer_is_vk(src2->buffer)) { - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) src2->extra; - vk_buffer buffer_gpu = extra->buffer_gpu.lock(); - uint64_t offset = extra->offset + src2->view_offs; - if (!ggml_is_contiguous(src2) && ggml_vk_dim01_contiguous(src2)) { - for (int i3 = 0; i3 < src2->ne[3]; i3++) { - for (int i2 = 0; i2 < src2->ne[2]; i2++) { - const int idx = i3*src2->ne[2] + i2; - ggml_vk_buffer_read(buffer_gpu, offset + idx * src2->nb[2], ((char *)src2_clone->data + idx * src2_clone->nb[2]), src2->ne[1] * src2->nb[1]); - } - } - - src2_clone->nb[0] = src2->nb[0]; - src2_clone->nb[1] = src2->nb[1]; - for (int i = 2; i < GGML_MAX_DIMS; i++) { - src2_clone->nb[i] = src2_clone->nb[i - 1]*src2_clone->ne[i - 1]; - } - } else { - if (offset + src2_size >= buffer_gpu->size) { - src2_size = buffer_gpu->size - offset; - } - ggml_vk_buffer_read(buffer_gpu, offset, src2_clone->data, src2_size); - memcpy(src2_clone->nb, src2->nb, sizeof(size_t) * GGML_MAX_DIMS); - } - } else { - GGML_ABORT("fatal error"); - } - - if (vk_output_tensor > 0 && vk_output_tensor == check_counter) { - ggml_vk_print_tensor(src2, "src2"); + ggml_vk_print_tensor(srci, srci_name[i]); } } - if (tensor->op == GGML_OP_MUL_MAT) { - tensor_clone = ggml_mul_mat(ggml_ctx, src0_clone, src1_clone); + if (tensor->op == GGML_OP_FLASH_ATTN_EXT) { + const float * params = (const float *)tensor->op_params; + tensor_clone = ggml_flash_attn_ext(ggml_ctx, src_clone[0], src_clone[1], src_clone[2], src_clone[3], params[0], params[1], params[2]); + } else if (tensor->op == GGML_OP_MUL_MAT) { + tensor_clone = ggml_mul_mat(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_MUL_MAT_ID) { - tensor_clone = ggml_mul_mat_id(ggml_ctx, src0_clone, src1_clone, src2_clone); + tensor_clone = ggml_mul_mat_id(ggml_ctx, src_clone[0], src_clone[1], src_clone[2]); + } else if (tensor->op == GGML_OP_SUB) { + tensor_clone = ggml_sub(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_MUL) { - tensor_clone = ggml_mul(ggml_ctx, src0_clone, src1_clone); + tensor_clone = ggml_mul(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_DIV) { - tensor_clone = ggml_div(ggml_ctx, src0_clone, src1_clone); + tensor_clone = ggml_div(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_CONCAT) { - tensor_clone = ggml_concat(ggml_ctx, src0_clone, src1_clone, *(int *)tensor->op_params); + tensor_clone = ggml_concat(ggml_ctx, src_clone[0], src_clone[1], *(int *)tensor->op_params); } else if (tensor->op == GGML_OP_UPSCALE) { - tensor_clone = ggml_upscale_ext(ggml_ctx, src0_clone, tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); + tensor_clone = ggml_upscale_ext(ggml_ctx, src_clone[0], tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); } else if (tensor->op == GGML_OP_SCALE) { - tensor_clone = ggml_scale(ggml_ctx, src0_clone, ((float *)tensor->op_params)[0]); + const float * params = (const float *)tensor->op_params; + tensor_clone = ggml_scale(ggml_ctx, src_clone[0], params[0]); } else if (tensor->op == GGML_OP_SQR) { - tensor_clone = ggml_sqr(ggml_ctx, src0_clone); - } else if (tensor->op == GGML_OP_CLAMP) { - tensor_clone = ggml_clamp(ggml_ctx, src0_clone, ((float *)tensor->op_params)[0], ((float *)tensor->op_params)[1]); + tensor_clone = ggml_sqr(ggml_ctx, src_clone[0]); + } else if (tensor->op == GGML_OP_CLAMP) { + const float * params = (const float *)tensor->op_params; + tensor_clone = ggml_clamp(ggml_ctx, src_clone[0], params[0], params[1]); } else if (tensor->op == GGML_OP_PAD) { - tensor_clone = ggml_pad(ggml_ctx, src0_clone, tensor->ne[0] - src0_clone->ne[0], tensor->ne[1] - src0_clone->ne[1], tensor->ne[2] - src0_clone->ne[2], tensor->ne[3] - src0_clone->ne[3]); + tensor_clone = ggml_pad(ggml_ctx, src_clone[0], tensor->ne[0] - src_clone[0]->ne[0], tensor->ne[1] - src_clone[0]->ne[1], tensor->ne[2] - src_clone[0]->ne[2], tensor->ne[3] - src_clone[0]->ne[3]); + } else if (tensor->op == GGML_OP_REPEAT) { + tensor_clone = ggml_repeat(ggml_ctx, src_clone[0], tensor); + } else if (tensor->op == GGML_OP_REPEAT_BACK) { + tensor_clone = ggml_repeat_back(ggml_ctx, src_clone[0], tensor); } else if (tensor->op == GGML_OP_ADD) { - tensor_clone = ggml_add(ggml_ctx, src0_clone, src1_clone); + tensor_clone = ggml_add(ggml_ctx, src_clone[0], src_clone[1]); + } else if (tensor->op == GGML_OP_ACC) { + tensor_clone = ggml_acc(ggml_ctx, src_clone[0], src_clone[1], tensor->op_params[0], tensor->op_params[1], tensor->op_params[2], tensor->op_params[3]); } else if (tensor->op == GGML_OP_NORM) { - tensor_clone = ggml_norm(ggml_ctx, src0_clone, *(float *)tensor->op_params); + tensor_clone = ggml_norm(ggml_ctx, src_clone[0], *(float *)tensor->op_params); } else if (tensor->op == GGML_OP_GROUP_NORM) { - tensor_clone = ggml_group_norm(ggml_ctx, src0_clone, *(int *)tensor->op_params); + const float * float_params = (const float *)tensor->op_params; + tensor_clone = ggml_group_norm(ggml_ctx, src_clone[0], tensor->op_params[0], float_params[1]); } else if (tensor->op == GGML_OP_RMS_NORM) { - tensor_clone = ggml_rms_norm(ggml_ctx, src0_clone, *(float *)tensor->op_params); + tensor_clone = ggml_rms_norm(ggml_ctx, src_clone[0], *(float *)tensor->op_params); + } else if (tensor->op == GGML_OP_RMS_NORM_BACK) { + const float eps = ((float *) tensor->op_params)[0]; + tensor_clone = ggml_rms_norm_back(ggml_ctx, src_clone[0], src_clone[1], eps); + } else if (tensor->op == GGML_OP_SILU_BACK) { + tensor_clone = ggml_silu_back(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_SOFT_MAX) { if (src1 != nullptr) { - tensor_clone = ggml_soft_max_ext(ggml_ctx, src0_clone, src1_clone, ((float *)tensor->op_params)[0], ((float *)tensor->op_params)[1]); + const float * params = (const float *)tensor->op_params; + tensor_clone = ggml_soft_max_ext(ggml_ctx, src_clone[0], src_clone[1], params[0], params[1]); } else { - tensor_clone = ggml_soft_max(ggml_ctx, src0_clone); + tensor_clone = ggml_soft_max(ggml_ctx, src_clone[0]); } + } else if (tensor->op == GGML_OP_SOFT_MAX_BACK) { + tensor_clone = ggml_soft_max_ext_back(ggml_ctx, src_clone[0], src_clone[1], ((float *)tensor->op_params)[0], ((float *)tensor->op_params)[1]); } else if (tensor->op == GGML_OP_DIAG_MASK_INF) { - tensor_clone = ggml_diag_mask_inf(ggml_ctx, src0_clone, *(int *)tensor->op_params); - } else if (tensor->op == GGML_OP_ROPE) { + tensor_clone = ggml_diag_mask_inf(ggml_ctx, src_clone[0], tensor->op_params[0]); + } else if (tensor->op == GGML_OP_ROPE || tensor->op == GGML_OP_ROPE_BACK) { const int n_dims = ((int32_t *) tensor->op_params)[1]; const int mode = ((int32_t *) tensor->op_params)[2]; //const int n_ctx_ggml = ((int32_t *) tensor->op_params)[3]; @@ -7134,23 +10091,39 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { const float attn_factor = ((float *) tensor->op_params)[8]; const float beta_fast = ((float *) tensor->op_params)[9]; const float beta_slow = ((float *) tensor->op_params)[10]; - tensor_clone = ggml_rope_ext(ggml_ctx, src0_clone, src1_clone, src2_clone, n_dims, mode, n_ctx_orig_ggml, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow); + if (mode & GGML_ROPE_TYPE_MROPE) { + int32_t *sections = ((int32_t *) tensor->op_params) + 11; + if (tensor->op == GGML_OP_ROPE) { + tensor_clone = ggml_rope_multi(ggml_ctx, src_clone[0], src_clone[1], src_clone[2], n_dims, sections, mode, n_ctx_orig_ggml, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow); + } else { + tensor_clone = ggml_rope_multi_back(ggml_ctx, src_clone[0], src_clone[1], src_clone[2], n_dims, sections, mode, n_ctx_orig_ggml, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow); + } + } else { + if (tensor->op == GGML_OP_ROPE) { + tensor_clone = ggml_rope_ext(ggml_ctx, src_clone[0], src_clone[1], src_clone[2], n_dims, mode, n_ctx_orig_ggml, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow); + } else { + tensor_clone = ggml_rope_ext_back(ggml_ctx, src_clone[0], src_clone[1], src_clone[2], n_dims, mode, n_ctx_orig_ggml, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow); + } + } } else if (tensor->op == GGML_OP_UNARY) { switch (ggml_get_unary_op(tensor)) { case GGML_UNARY_OP_SILU: - tensor_clone = ggml_silu(ggml_ctx, src0_clone); + tensor_clone = ggml_silu(ggml_ctx, src_clone[0]); break; case GGML_UNARY_OP_GELU: - tensor_clone = ggml_gelu(ggml_ctx, src0_clone); + tensor_clone = ggml_gelu(ggml_ctx, src_clone[0]); break; case GGML_UNARY_OP_GELU_QUICK: - tensor_clone = ggml_gelu_quick(ggml_ctx, src0_clone); + tensor_clone = ggml_gelu_quick(ggml_ctx, src_clone[0]); break; case GGML_UNARY_OP_RELU: - tensor_clone = ggml_relu(ggml_ctx, src0_clone); + tensor_clone = ggml_relu(ggml_ctx, src_clone[0]); break; case GGML_UNARY_OP_TANH: - tensor_clone = ggml_tanh(ggml_ctx, src0_clone); + tensor_clone = ggml_tanh(ggml_ctx, src_clone[0]); + break; + case GGML_UNARY_OP_SIGMOID: + tensor_clone = ggml_sigmoid(ggml_ctx, src_clone[0]); break; default: std::cerr << "Missing vk_check_results OP: " << ggml_op_name(tensor->op) << std::endl; @@ -7158,29 +10131,33 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { } } else if (tensor->op == GGML_OP_CPY || tensor->op == GGML_OP_DUP) { if (src1 == nullptr) { - tensor_clone = ggml_dup(ggml_ctx, src0_clone); + tensor_clone = ggml_dup(ggml_ctx, src_clone[0]); tensor_clone->type = tensor->type; } else { - tensor_clone = ggml_cpy(ggml_ctx, src0_clone, src1_clone); + tensor_clone = ggml_cpy(ggml_ctx, src_clone[0], src_clone[1]); } } else if (tensor->op == GGML_OP_CONT) { - tensor_clone = ggml_cont_4d(ggml_ctx, src0_clone, tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); + tensor_clone = ggml_cont_4d(ggml_ctx, src_clone[0], tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); } else if (tensor->op == GGML_OP_RESHAPE) { - tensor_clone = ggml_reshape_4d(ggml_ctx, src0_clone, tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); + tensor_clone = ggml_reshape_4d(ggml_ctx, src_clone[0], tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); } else if (tensor->op == GGML_OP_VIEW) { - tensor_clone = ggml_view_4d(ggml_ctx, src0_clone, tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3], tensor->nb[1], tensor->nb[2], tensor->nb[3], ((int32_t *) tensor->op_params)[0]); + tensor_clone = ggml_view_4d(ggml_ctx, src_clone[0], tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3], tensor->nb[1], tensor->nb[2], tensor->nb[3], ((int32_t *) tensor->op_params)[0]); } else if (tensor->op == GGML_OP_PERMUTE) { int32_t * params = (int32_t *)tensor->op_params; - tensor_clone = ggml_permute(ggml_ctx, src0_clone, params[0], params[1], params[2], params[3]); + tensor_clone = ggml_permute(ggml_ctx, src_clone[0], params[0], params[1], params[2], params[3]); } else if (tensor->op == GGML_OP_TRANSPOSE) { - tensor_clone = ggml_transpose(ggml_ctx, src0_clone); + tensor_clone = ggml_transpose(ggml_ctx, src_clone[0]); } else if (tensor->op == GGML_OP_GET_ROWS) { - tensor_clone = ggml_get_rows(ggml_ctx, src0_clone, src1_clone); + tensor_clone = ggml_get_rows(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_ARGSORT) { - tensor_clone = ggml_argsort(ggml_ctx, src0_clone, (ggml_sort_order) *(int *)tensor->op_params); + tensor_clone = ggml_argsort(ggml_ctx, src_clone[0], (ggml_sort_order) *(int *)tensor->op_params); + } else if (tensor->op == GGML_OP_SUM) { + tensor_clone = ggml_sum(ggml_ctx, src_clone[0]); } else if (tensor->op == GGML_OP_SUM_ROWS) { - tensor_clone = ggml_sum_rows(ggml_ctx, src0_clone); - } else if (tensor->op == GGML_OP_IM2COL) { + tensor_clone = ggml_sum_rows(ggml_ctx, src_clone[0]); + } else if (tensor->op == GGML_OP_ARGMAX) { + tensor_clone = ggml_argmax(ggml_ctx, src_clone[0]); + } else if (tensor->op == GGML_OP_IM2COL) { const int32_t s0 = tensor->op_params[0]; const int32_t s1 = tensor->op_params[1]; const int32_t p0 = tensor->op_params[2]; @@ -7189,15 +10166,31 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { const int32_t d1 = tensor->op_params[5]; const bool is_2D = tensor->op_params[6] == 1; - tensor_clone = ggml_im2col(ggml_ctx, src0_clone, src1_clone, s0, s1, p0, p1, d0, d1, is_2D, tensor->type); + tensor_clone = ggml_im2col(ggml_ctx, src_clone[0], src_clone[1], s0, s1, p0, p1, d0, d1, is_2D, tensor->type); } else if (tensor->op == GGML_OP_TIMESTEP_EMBEDDING) { const int32_t dim = tensor->op_params[0]; const int32_t max_period = tensor->op_params[1]; - tensor_clone = ggml_timestep_embedding(ggml_ctx, src0_clone, dim, max_period); + tensor_clone = ggml_timestep_embedding(ggml_ctx, src_clone[0], dim, max_period); + } else if (tensor->op == GGML_OP_CONV_TRANSPOSE_1D){ + const int32_t s0 = tensor->op_params[0]; + const int32_t p0 = tensor->op_params[1]; + const int32_t d0 = tensor->op_params[2]; + tensor_clone = ggml_conv_transpose_1d(ggml_ctx, src_clone[0], src_clone[1], s0, p0, d0); + } else if (tensor->op == GGML_OP_POOL_2D) { + enum ggml_op_pool op = static_cast(tensor->op_params[0]); + const int32_t k0 = tensor->op_params[1]; + const int32_t k1 = tensor->op_params[2]; + const int32_t s0 = tensor->op_params[3]; + const int32_t s1 = tensor->op_params[4]; + const int32_t p0 = tensor->op_params[5]; + const int32_t p1 = tensor->op_params[6]; + + tensor_clone = ggml_pool_2d(ggml_ctx, src_clone[0], op, k0, k1, s0, s1, p0, p1); } else if (tensor->op == GGML_OP_LEAKY_RELU) { const float * op_params = (const float *)tensor->op_params; - tensor_clone = ggml_leaky_relu(ggml_ctx, src0_clone, op_params[0], false); - } else { + tensor_clone = ggml_leaky_relu(ggml_ctx, src_clone[0], op_params[0], false); + } + else { std::cerr << "Missing vk_check_results OP: " << ggml_op_name(tensor->op) << std::endl; GGML_ABORT("fatal error"); } @@ -7217,11 +10210,10 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { memcpy(comp_result, tensor_clone->data, comp_size); memcpy(comp_nb, tensor_clone->nb, sizeof(size_t) * GGML_MAX_DIMS); - if (src0 != nullptr) { - free(src0_buffer); - } - if (src1 != nullptr) { - free(src1_buffer); + for (int i = 0; i < 6; i++) { + if (src_buffer[i] != nullptr) { + free(src_buffer[i]); + } } ggml_free(ggml_ctx); @@ -7242,6 +10234,7 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { ggml_tensor * src0 = tensor->src[0]; ggml_tensor * src1 = tensor->src[1]; ggml_tensor * src2 = tensor->src[2]; + ggml_tensor * src3 = tensor->src[3]; void * tensor_data = tensor->data; @@ -7249,14 +10242,15 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { size_t tensor_size = ggml_nbytes(tensor); tensor_data = malloc(tensor_size); - ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) tensor->extra; + ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)tensor->buffer->context; - vk_buffer buffer_gpu = extra->buffer_gpu.lock(); - if (extra->offset + tensor->view_offs + tensor_size >= buffer_gpu->size) { - tensor_size = buffer_gpu->size - (extra->offset + tensor->view_offs); + vk_buffer& buffer_gpu = buf_ctx->dev_buffer; + uint64_t offset = vk_tensor_offset(tensor) + tensor->view_offs; + if (offset + tensor_size >= buffer_gpu->size) { + tensor_size = buffer_gpu->size - offset; } - ggml_vk_buffer_read(buffer_gpu, extra->offset + tensor->view_offs, tensor_data, tensor_size); + ggml_vk_buffer_read(buffer_gpu, offset, tensor_data, tensor_size); } float first_error_result = -1.0f; @@ -7283,6 +10277,9 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { } else if (tensor->type == GGML_TYPE_I32) { correct = *(int32_t *) ((char *) comp_result + i3*comp_nb[3] + i2*comp_nb[2] + i1*comp_nb[1] + i0*comp_nb[0]); result = *(int32_t *) ((char *) tensor_data + i3*tensor->nb[3] + i2*tensor->nb[2] + i1*tensor->nb[1] + i0*tensor->nb[0]); + } else if (tensor->type == GGML_TYPE_I64) { + correct = *(int64_t *) ((char *) comp_result + i3*comp_nb[3] + i2*comp_nb[2] + i1*comp_nb[1] + i0*comp_nb[0]); + result = *(int64_t *) ((char *) tensor_data + i3*tensor->nb[3] + i2*tensor->nb[2] + i1*tensor->nb[1] + i0*tensor->nb[0]); } else { std::cerr << "Results check not implemented for type " << ggml_type_name(tensor->type) << std::endl; } @@ -7303,6 +10300,9 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { if (src2 != nullptr) { std::cerr << "src2=" << src2 << " src2->name=" << src2->name << " op=" << ggml_op_name(src2->op) << " type=" << ggml_type_name(src2->type) << " ne0=" << src2->ne[0] << " nb0=" << src2->nb[0] << " ne1=" << src2->ne[1] << " nb1=" << src2->nb[1] << " ne2=" << src2->ne[2] << " nb2=" << src2->nb[2] << " ne3=" << src2->ne[3] << " nb3=" << src2->nb[3] << " offset=" << src2->view_offs << std::endl; } + if (src3 != nullptr) { + std::cerr << "src3=" << src3 << " src3->name=" << src3->name << " op=" << ggml_op_name(src3->op) << " type=" << ggml_type_name(src3->type) << " ne0=" << src3->ne[0] << " nb0=" << src3->nb[0] << " ne1=" << src3->ne[1] << " nb1=" << src3->nb[1] << " ne2=" << src3->ne[2] << " nb2=" << src3->nb[2] << " ne3=" << src3->ne[3] << " nb3=" << src3->nb[3] << " offset=" << src3->view_offs << std::endl; + } std::cerr << "First error: result=" << first_error_result << " correct=" << first_error_correct << " i3=" << first_error[3] << " i2=" << first_error[2] << " i1=" << first_error[1] << " i0=" << first_error[0] << std::endl; std::cerr << std::endl << "Result:" << std::endl; ggml_vk_print_tensor_area(tensor, tensor_data, i0, i1, i2, i3); @@ -7313,7 +10313,8 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { ggml_vk_print_graph_origin(tensor, done); GGML_ABORT("fatal error"); } - if (first_error[0] == -1 && std::fabs(correct - result) > 0.1f) { + const double denom = std::fabs(correct) > 1.0f ? (std::fabs(correct) > 1e-8 ? std::fabs(correct) : 1e-8) : 1.0f; + if (first_error[0] == -1 && std::fabs(correct - result) / denom > 0.5) { first_error[0] = i0; first_error[1] = i1; first_error[2] = i2; @@ -7325,7 +10326,7 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { // Special case, value is infinite, avoid NaN result in avg_err // NaN also appears in results, if both are nan error is 0 if (!std::isinf(correct) && !std::isinf(result) && !std::isnan(correct) && !std::isnan(result)) { - avg_err += std::fabs(correct - result); + avg_err += std::fabs(correct - result) / denom; } counter++; } @@ -7347,6 +10348,9 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { if (src2 != nullptr) { std::cerr << "src2=" << src2 << " op=" << ggml_op_name(src2->op) << " type=" << ggml_type_name(src2->type) << " ne0=" << src2->ne[0] << " nb0=" << src2->nb[0] << " ne1=" << src2->ne[1] << " nb1=" << src2->nb[1] << " ne2=" << src2->ne[2] << " nb2=" << src2->nb[2] << " ne3=" << src2->ne[3] << " nb3=" << src2->nb[3] << " offset=" << src2->view_offs << std::endl; } + if (src3 != nullptr) { + std::cerr << "src3=" << src3 << " op=" << ggml_op_name(src3->op) << " type=" << ggml_type_name(src3->type) << " ne0=" << src3->ne[0] << " nb0=" << src3->nb[0] << " ne1=" << src3->ne[1] << " nb1=" << src3->nb[1] << " ne2=" << src3->ne[2] << " nb2=" << src3->nb[2] << " ne3=" << src3->ne[3] << " nb3=" << src3->nb[3] << " offset=" << src3->view_offs << std::endl; + } std::cerr << "First error: result=" << first_error_result << " correct=" << first_error_correct << " i3=" << first_error[3] << " i2=" << first_error[2] << " i1=" << first_error[1] << " i0=" << first_error[0] << std::endl; std::cerr << std::endl << "Result:" << std::endl; ggml_vk_print_tensor_area(tensor, tensor_data, 5, 5, 0, 0); @@ -7357,7 +10361,7 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { ggml_vk_print_graph_origin(tensor, done); } - if (avg_err > 0.05 || std::isnan(avg_err)) { + if (avg_err > 0.5 || std::isnan(avg_err)) { std::cerr << "ERROR: avg_err=" << avg_err << " in " << ggml_op_name(tensor->op) << " (check " << check_counter << ")" << std::endl; std::cerr << "tensor=" << tensor << " tensor->name=" << tensor->name << " tensor->type: " << ggml_type_name(tensor->type) << " ne0=" << tensor->ne[0] << " nb0=" << tensor->nb[0] << " ne1=" << tensor->ne[1] << " nb1=" << tensor->nb[1] << " ne2=" << tensor->ne[2] << " nb2=" << tensor->nb[2] << " ne3=" << tensor->ne[3] << " nb3=" << tensor->nb[3] << " offset=" << tensor->view_offs << std::endl; if (src0 != nullptr) { @@ -7369,6 +10373,9 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { if (src2 != nullptr) { std::cerr << "src2=" << src2 << " op=" << ggml_op_name(src2->op) << " type=" << ggml_type_name(src2->type) << " ne0=" << src2->ne[0] << " nb0=" << src2->nb[0] << " ne1=" << src2->ne[1] << " nb1=" << src2->nb[1] << " ne2=" << src2->ne[2] << " nb2=" << src2->nb[2] << " ne3=" << src2->ne[3] << " nb3=" << src2->nb[3] << " offset=" << src2->view_offs << std::endl; } + if (src3 != nullptr) { + std::cerr << "src3=" << src3 << " op=" << ggml_op_name(src3->op) << " type=" << ggml_type_name(src3->type) << " ne0=" << src3->ne[0] << " nb0=" << src3->nb[0] << " ne1=" << src3->ne[1] << " nb1=" << src3->nb[1] << " ne2=" << src3->ne[2] << " nb2=" << src3->nb[2] << " ne3=" << src3->ne[3] << " nb3=" << src3->nb[3] << " offset=" << src3->view_offs << std::endl; + } std::cerr << "First error: result=" << first_error_result << " correct=" << first_error_correct << " i3=" << first_error[3] << " i2=" << first_error[2] << " i1=" << first_error[1] << " i0=" << first_error[0] << std::endl; std::cerr << std::endl << "Result:" << std::endl; ggml_vk_print_tensor_area(tensor, tensor_data, first_error[0], first_error[1], first_error[2], first_error[3]); diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index d06f6553..97b5bff7 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -6310,6 +6310,7 @@ struct ggml_tensor * ggml_argmax( return result; } + // ggml_repeat struct ggml_tensor * ggml_repeat( diff --git a/ggml/src/vulkan-shaders/CMakeLists.txt b/ggml/src/vulkan-shaders/CMakeLists.txt index 10075db3..a22ea817 100644 --- a/ggml/src/vulkan-shaders/CMakeLists.txt +++ b/ggml/src/vulkan-shaders/CMakeLists.txt @@ -1,5 +1,29 @@ +cmake_minimum_required(VERSION 3.19) +project("vulkan-shaders-gen" C CXX) + find_package (Threads REQUIRED) +if (GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + add_compile_definitions(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + message(STATUS "Enabling coopmat glslc support") +endif() +if (GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + add_compile_definitions(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + message(STATUS "Enabling coopmat2 glslc support") +endif() +if (GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + add_compile_definitions(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + message(STATUS "Enabling dot glslc support") +endif() +if (GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + add_compile_definitions(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + message(STATUS "Enabling bfloat16 glslc support") +endif() +if (GGML_VULKAN_SHADER_DEBUG_INFO) + add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO) + message(STATUS "Enabling shader debug info") +endif() + set(TARGET vulkan-shaders-gen) add_executable(${TARGET} vulkan-shaders-gen.cpp) install(TARGETS ${TARGET} RUNTIME) diff --git a/ggml/src/vulkan-shaders/acc.comp b/ggml/src/vulkan-shaders/acc.comp new file mode 100644 index 00000000..d896f1ef --- /dev/null +++ b/ggml/src/vulkan-shaders/acc.comp @@ -0,0 +1,29 @@ +#version 450 + +#include "types.comp" +#include "generic_binary_head.comp" + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +void main() { + const uint idx = gl_GlobalInvocationID.x; + if (idx >= p.ne) { + return; + } + + const uint offset = p.param3; + const uint src1_i = idx - offset; + const uint oz = src1_i / p.nb02; + const uint oy = (src1_i - (oz * p.nb02)) / p.nb01; + const uint ox = src1_i % p.nb01; + + uint i00, i01, i02, i03; + get_indices(idx, i00, i01, i02, i03); + + if (ox < p.ne10 && oy < p.ne11 && oz < p.ne12) { + data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) + FLOAT_TYPE(data_b[get_boffset() + ox + oy * p.ne10 + oz * p.ne10 * p.ne11])); + } else { + data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)])); + } +} + diff --git a/ggml/src/vulkan-shaders/add.comp b/ggml/src/vulkan-shaders/add.comp index 3974845d..2b4085c4 100644 --- a/ggml/src/vulkan-shaders/add.comp +++ b/ggml/src/vulkan-shaders/add.comp @@ -1,14 +1,29 @@ #version 450 +#extension GL_EXT_shader_16bit_storage : require + #include "types.comp" #include "generic_binary_head.comp" +const uint num_threads = 256; + +layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in; + void main() { - const uint idx = get_idx(); + uint idx = get_idx(); - if (idx >= p.ne) { - return; + // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation + const uint num_iter = 2; + + [[unroll]] for (uint i = 0; i < num_iter; ++i) { + if (idx >= p.ne) { + continue; + } + uint i00, i01, i02, i03; + get_indices(idx, i00, i01, i02, i03); + + data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) + FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)])); + + idx += num_threads; } - - data_d[p.d_offset + dst_idx(idx)] = D_TYPE(FLOAT_TYPE(data_a[src0_idx(idx)]) + FLOAT_TYPE(data_b[src1_idx(idx)])); } diff --git a/ggml/src/vulkan-shaders/argmax.comp b/ggml/src/vulkan-shaders/argmax.comp new file mode 100644 index 00000000..eaf4da34 --- /dev/null +++ b/ggml/src/vulkan-shaders/argmax.comp @@ -0,0 +1,51 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; + +layout (constant_id = 0) const uint BLOCK_SIZE = 32; + +shared FLOAT_TYPE tmpmax[BLOCK_SIZE]; +shared uint tmp[BLOCK_SIZE]; + +void main() { + const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x; + const uint col = gl_LocalInvocationID.x; + + if (col >= p.KX) { + return; + } + A_TYPE amax = data_a[row*p.KX + col]; + tmp[col] = col; + + for (uint i = col + BLOCK_SIZE; i < p.KX; i += BLOCK_SIZE) { + A_TYPE val = data_a[row*p.KX + i]; + if (val > amax) { + amax = val; + tmp[col] = i; + } + } + tmpmax[col] = amax; + + barrier(); + [[unroll]] for (int s = int(BLOCK_SIZE) / 2; s > 0; s >>= 1) { + if (col < s && col + s < p.KX) { + if (tmpmax[col] < tmpmax[col + s]) { + tmpmax[col] = tmpmax[col + s]; + tmp[col] = tmp[col + s]; + } + } + barrier(); + } + + if (col == 0) { + data_d[row] = D_TYPE(tmp[0]); + } +} diff --git a/ggml/src/vulkan-shaders/argsort.comp b/ggml/src/vulkan-shaders/argsort.comp index e55414b0..d4fa45b1 100644 --- a/ggml/src/vulkan-shaders/argsort.comp +++ b/ggml/src/vulkan-shaders/argsort.comp @@ -29,20 +29,18 @@ void main() { const int col = int(gl_LocalInvocationID.x); const uint row = gl_WorkGroupID.y; - if (col >= p.ncols_pad) { - return; - } - const uint row_offset = row * p.ncols; // initialize indices - dst_row[col] = col; + if (col < p.ncols_pad) { + dst_row[col] = col; + } barrier(); for (uint k = 2; k <= p.ncols_pad; k *= 2) { for (uint j = k / 2; j > 0; j /= 2) { const uint ixj = col ^ j; - if (ixj > col) { + if (col < p.ncols_pad && ixj > col) { if ((col & k) == 0) { if (dst_row[col] >= p.ncols || (dst_row[ixj] < p.ncols && (p.order == ASC ? diff --git a/ggml/src/vulkan-shaders/clamp.comp b/ggml/src/vulkan-shaders/clamp.comp index 7071302a..1e5cb8da 100644 --- a/ggml/src/vulkan-shaders/clamp.comp +++ b/ggml/src/vulkan-shaders/clamp.comp @@ -3,6 +3,8 @@ #include "types.comp" #include "generic_unary_head.comp" +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + void main() { const uint idx = get_idx(); @@ -10,6 +12,6 @@ void main() { return; } - const FLOAT_TYPE val = FLOAT_TYPE(data_a[src0_idx(idx)]); - data_d[p.d_offset + dst_idx(idx)] = D_TYPE(val < p.param1 ? p.param1 : (val > p.param2 ? p.param2 : val)); + const FLOAT_TYPE val = FLOAT_TYPE(data_a[get_aoffset() + src0_idx(idx)]); + data_d[get_doffset() + dst_idx(idx)] = D_TYPE(val < p.param1 ? p.param1 : (val > p.param2 ? p.param2 : val)); } diff --git a/ggml/src/vulkan-shaders/concat.comp b/ggml/src/vulkan-shaders/concat.comp index 08ab5514..9ee2f1fa 100644 --- a/ggml/src/vulkan-shaders/concat.comp +++ b/ggml/src/vulkan-shaders/concat.comp @@ -3,6 +3,8 @@ #include "types.comp" #include "generic_binary_head.comp" +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + void main() { const uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; const int dim = p.param3; @@ -28,8 +30,12 @@ void main() { const bool is_src0 = i0 < p.ne00 && i1 < p.ne01 && i2 < p.ne02 && i3 < p.ne03; #ifndef OPTIMIZATION_ERROR_WORKAROUND - data_d[p.d_offset + dst_idx] = D_TYPE(is_src0 ? data_a[src0_idx] : data_b[src1_idx]); + data_d[get_doffset() + dst_idx] = D_TYPE(is_src0 ? data_a[get_aoffset() + src0_idx] : data_b[get_boffset() + src1_idx]); #else - data_d[p.d_offset + dst_idx] = is_src0 ? data_a[src0_idx] : data_b[src1_idx]; + if (is_src0) { + data_d[get_doffset() + dst_idx] = data_a[get_aoffset() + src0_idx]; + } else { + data_d[get_doffset() + dst_idx] = data_b[get_boffset() + src1_idx]; + } #endif } diff --git a/ggml/src/vulkan-shaders/contig_copy.comp b/ggml/src/vulkan-shaders/contig_copy.comp new file mode 100644 index 00000000..6567a8c5 --- /dev/null +++ b/ggml/src/vulkan-shaders/contig_copy.comp @@ -0,0 +1,49 @@ +#version 450 + +#include "types.comp" +#include "generic_unary_head.comp" + +#extension GL_EXT_control_flow_attributes : require + +const uint num_threads = 128; + +layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in; + +void main() { + uint idx = get_idx(); + + // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation + const uint num_iter = 4; + + // fast path for when all four iterations are in-bounds + if (idx + (num_iter-1)*num_threads < p.ne) { + [[unroll]] for (uint i = 0; i < num_iter; ++i) { + +#if defined(DATA_D_BF16) + float f = float(data_a[get_aoffset() + idx]); + data_d[get_doffset() + idx] = D_TYPE(fp32_to_bf16(f)); +#elif !defined(OPTIMIZATION_ERROR_WORKAROUND) + data_d[get_doffset() + idx] = D_TYPE(data_a[get_aoffset() + idx]); +#else + data_d[get_doffset() + idx] = data_a[get_aoffset() + idx]; +#endif + idx += num_threads; + } + } else { + [[unroll]] for (uint i = 0; i < num_iter; ++i) { + if (idx >= p.ne) { + continue; + } + +#if defined(DATA_D_BF16) + float f = float(data_a[get_aoffset() + idx]); + data_d[get_doffset() + idx] = D_TYPE(fp32_to_bf16(f)); +#elif !defined(OPTIMIZATION_ERROR_WORKAROUND) + data_d[get_doffset() + idx] = D_TYPE(data_a[get_aoffset() + idx]); +#else + data_d[get_doffset() + idx] = data_a[get_aoffset() + idx]; +#endif + idx += num_threads; + } + } +} diff --git a/ggml/src/vulkan-shaders/conv_transpose_1d.comp b/ggml/src/vulkan-shaders/conv_transpose_1d.comp new file mode 100644 index 00000000..b17b4e83 --- /dev/null +++ b/ggml/src/vulkan-shaders/conv_transpose_1d.comp @@ -0,0 +1,98 @@ +#version 450 + +#include "types.comp" + +layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; // src0 - kernel: [K, Cout, Cin] +layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; // src1 - input: [L, Cin] +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; // dst - result [KL, Cout] + +layout(local_size_x = 128 , local_size_y = 1, local_size_z = 1) in; + +layout (push_constant) uniform parameter { + uint32_t Cout; + uint32_t Cin; + uint32_t K; + uint32_t L; + uint32_t KL; + + uint32_t nb01; + uint32_t nb02; + uint32_t nb11; + uint32_t nb1; + + int32_t s0; +} p; + + +uint32_t Cout_idx = gl_WorkGroupID.x; +const uint32_t bs = gl_WorkGroupSize.x; +uint32_t tid = gl_LocalInvocationID.x; +// Code is more straightforward if we assume it is bs*s0+K instead of (bs-1)*s0+K. +uint32_t tmp_len = bs*p.s0+p.K; +shared D_TYPE tmp[4096]; + +uint splitWork(uint workSize){ + return (bs + workSize -1) / bs; +} + +void main(){ + for(uint32_t i = 0; i < splitWork(tmp_len); i++){ + uint32_t idx = i*bs+tid; + if(idx < tmp_len){ + tmp[idx] = 0.0; + } + } + + uint32_t L_blocks = splitWork(p.L); + for(uint32_t L_block_id = 0; L_block_id < L_blocks; L_block_id++){ + if(L_block_id > 0){ + barrier(); + // Shift values in tmp to the current processing window + for(int i = 0; i < splitWork(tmp_len); i++){ + uint32_t idx = i*bs+tid; + if(idx >= bs*p.s0 && idx < tmp_len){ + tmp[idx-bs*p.s0] = tmp[idx]; + tmp[idx] = 0.0; + }else if(idx >= p.K && idx < bs*p.s0){ + tmp[idx] = 0.0; + } + } + } + barrier(); + + // Save contributions of the block to tmp + uint32_t L_idx = L_block_id*bs + tid; + for(uint32_t K_idx = 0; K_idx < p.K; K_idx++){ + D_TYPE dp = 0.0; + for(uint32_t Cin_idx = 0; Cin_idx < p.Cin; Cin_idx++){ + A_TYPE elemKrn = data_a[K_idx + Cout_idx * p.nb01 + Cin_idx * p.nb02]; + if(L_idx < p.L){ + B_TYPE elemInp = data_b[L_idx + Cin_idx*p.nb11]; + dp = fma(elemKrn, elemInp, dp); + } + } + tmp[tid*p.s0 + K_idx] += dp; + barrier(); + } + + // Save the computed values except the last block that can have different size + uint32_t KLb_idx = L_block_id*bs*p.s0; + if(L_block_id < L_blocks-1){ + for(uint32_t s0_idx = 0; s0_idx < p.s0; s0_idx++){ + uint32_t sh_idx = p.s0*tid+s0_idx; + uint32_t KL_idx = KLb_idx+sh_idx; + if(KL_idx < p.KL){ + data_d[KL_idx + Cout_idx*p.nb1] = tmp[sh_idx]; + } + } + } + } + + for(uint32_t i = 0; i < splitWork(tmp_len); i++){ + uint32_t idx = i*bs+tid; + uint32_t KL_idx = (L_blocks-1)*bs*p.s0+idx; + if(KL_idx < p.KL){ + data_d[KL_idx + Cout_idx*p.nb1] = tmp[idx]; + } + } +} diff --git a/ggml/src/vulkan-shaders/copy.comp b/ggml/src/vulkan-shaders/copy.comp index c26917c0..f476a2e3 100644 --- a/ggml/src/vulkan-shaders/copy.comp +++ b/ggml/src/vulkan-shaders/copy.comp @@ -3,6 +3,8 @@ #include "types.comp" #include "generic_unary_head.comp" +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + void main() { const uint idx = get_idx(); @@ -10,9 +12,12 @@ void main() { return; } -#ifndef OPTIMIZATION_ERROR_WORKAROUND - data_d[p.d_offset + dst_idx(idx)] = D_TYPE(data_a[src0_idx(idx)]); +#if defined(DATA_D_BF16) + float f = float(data_a[get_aoffset() + src0_idx(idx)]); + data_d[get_doffset() + dst_idx(idx)] = D_TYPE(fp32_to_bf16(f)); +#elif !defined(OPTIMIZATION_ERROR_WORKAROUND) + data_d[get_doffset() + dst_idx(idx)] = D_TYPE(data_a[get_aoffset() + src0_idx(idx)]); #else - data_d[p.d_offset + dst_idx(idx)] = data_a[src0_idx(idx)]; + data_d[get_doffset() + dst_idx(idx)] = data_a[get_aoffset() + src0_idx(idx)]; #endif } diff --git a/ggml/src/vulkan-shaders/copy_from_quant.comp b/ggml/src/vulkan-shaders/copy_from_quant.comp new file mode 100644 index 00000000..dbc7daa3 --- /dev/null +++ b/ggml/src/vulkan-shaders/copy_from_quant.comp @@ -0,0 +1,51 @@ +#version 450 + +#include "types.comp" +#include "generic_unary_head.comp" +#include "dequant_funcs.comp" + +#if defined(DATA_A_IQ4_NL) +// 16 invocations needed for init_iq4nl_shmem +layout(local_size_x = 16, local_size_y = 1, local_size_z = 1) in; +#else +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; +#endif + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); + if (gl_LocalInvocationIndex.x != 0) { + return; + } +#endif + + const uint idx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * QUANT_K; + + if (idx >= p.ne) { + return; + } + + uint dst_idx = get_doffset() + dst_idx(idx); + uint src_idx = src0_idx_quant(idx, QUANT_K); + + const uint a_offset = 0; + const uint ib = src_idx; + const vec2 dm = get_dm(ib, a_offset); + + [[unroll]] for (int j = 0; j < QUANT_K; j += 4) { + vec4 v = dequantize4(ib, j / QUANT_R, a_offset); + v = v * dm.x + vec4(dm.y); + +#if QUANT_R == 2 + data_d[dst_idx + j/2 + 0] = v[0]; + data_d[dst_idx + j/2 + QUANT_K/2 + 0] = v[1]; + data_d[dst_idx + j/2 + 1] = v[2]; + data_d[dst_idx + j/2 + QUANT_K/2 + 1] = v[3]; +#else + data_d[dst_idx + j + 0] = v[0]; + data_d[dst_idx + j + 1] = v[1]; + data_d[dst_idx + j + 2] = v[2]; + data_d[dst_idx + j + 3] = v[3]; +#endif + } +} diff --git a/ggml/src/vulkan-shaders/copy_to_quant.comp b/ggml/src/vulkan-shaders/copy_to_quant.comp new file mode 100644 index 00000000..9c76437d --- /dev/null +++ b/ggml/src/vulkan-shaders/copy_to_quant.comp @@ -0,0 +1,242 @@ +#version 450 + +#if RTE16 +#extension GL_EXT_spirv_intrinsics : enable +spirv_execution_mode(capabilities = [4467], 4462, 16); // RoundingModeRTE, 16 bits +#endif // RTE16 + +#include "types.comp" +#include "generic_unary_head.comp" + +#if defined(DATA_A_IQ4_NL) +// 16 invocations needed for init_iq4nl_shmem +layout(local_size_x = 16, local_size_y = 1, local_size_z = 1) in; +#else +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; +#endif + +layout (binding = 0) readonly buffer S {float data_s[];}; +layout (binding = 1) writeonly buffer Q {A_TYPE data_q[];}; + +#if defined(DATA_A_Q4_0) +void quantize(uint dst_idx, uint src_idx) +{ + float amax = 0.0; + float vmax = 0.0; + + [[unroll]] for (int j = 0; j < QUANT_K_Q4_0; ++j) { + const float v = data_s[src_idx + j]; + if (amax < abs(v)) { + amax = abs(v); + vmax = v; + } + } + + const float d = vmax / -8; + const float id = (d != 0.0) ? 1.0/d : 0.0; + + data_q[dst_idx].d = float16_t(d); + + [[unroll]] for (int j = 0; j < QUANT_K_Q4_0/2; ++j) { + const float x0 = data_s[src_idx + 0 + j]*id; + const float x1 = data_s[src_idx + QUANT_K_Q4_0/2 + j]*id; + + const uint xi0 = min(15, int(x0 + 8.5)); + const uint xi1 = min(15, int(x1 + 8.5)); + + data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4)); + } +} +#endif + +#if defined(DATA_A_Q4_1) +void quantize(uint dst_idx, uint src_idx) +{ + float vmin = 1.0/0.0; + float vmax = -vmin; + + [[unroll]] for (int j = 0; j < QUANT_K_Q4_1; ++j) { + const float v = data_s[src_idx + j]; + + if (v < vmin) vmin = v; + if (v > vmax) vmax = v; + } + + const float d = (vmax - vmin) / ((1 << 4) - 1); + const float id = (d != 0.0) ? 1.0/d : 0.0; + + data_q[dst_idx].d = float16_t(d); + data_q[dst_idx].m = float16_t(vmin); + + [[unroll]] for (int j = 0; j < QUANT_K_Q4_1/2; ++j) { + const float x0 = (data_s[src_idx + 0 + j] - vmin)*id; + const float x1 = (data_s[src_idx + QUANT_K_Q4_1/2 + j] - vmin)*id; + + const uint xi0 = min(15, int(x0 + 0.5)); + const uint xi1 = min(15, int(x1 + 0.5)); + + data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4)); + } +} +#endif + +#if defined(DATA_A_Q5_0) +void quantize(uint dst_idx, uint src_idx) +{ + float amax = 0.0; + float vmax = 0.0; + + [[unroll]] for (int j = 0; j < QUANT_K_Q5_0; ++j) { + const float v = data_s[src_idx + j]; + if (amax < abs(v)) { + amax = abs(v); + vmax = v; + } + } + + const float d = vmax / -16; + const float id = (d != 0.0) ? 1.0/d : 0.0; + + data_q[dst_idx].d = float16_t(d); + + uint32_t qh = 0; + [[unroll]] for (int j = 0; j < QUANT_K_Q5_0/2; ++j) { + const float x0 = data_s[src_idx + 0 + j]*id; + const float x1 = data_s[src_idx + QUANT_K_Q5_0/2 + j]*id; + + const uint xi0 = min(31, int(x0 + 16.5)); + const uint xi1 = min(31, int(x1 + 16.5)); + + data_q[dst_idx].qs[j] = uint8_t((xi0 & 0xf) | ((xi1 & 0xf) << 4)); + qh |= ((xi0 & 0x10u) >> 4) << (j + 0); + qh |= ((xi1 & 0x10u) >> 4) << (j + QUANT_K_Q5_0/2); + } + data_q[dst_idx].qh[0] = uint16_t(qh & 0xFFFF); + data_q[dst_idx].qh[1] = uint16_t(qh >> 16); +} +#endif + +#if defined(DATA_A_Q5_1) +void quantize(uint dst_idx, uint src_idx) +{ + float min = data_s[src_idx + 0]; + float max = min; + + [[unroll]] for (int j = 1; j < QUANT_K_Q5_1; ++j) { + const float v = data_s[src_idx + j]; + min = v < min ? v : min; + max = v > max ? v : max; + } + + const float d = (max - min) / 31; + const float id = (d != 0) ? 1.0/d : 0.0; + + data_q[dst_idx].d = float16_t(d); + data_q[dst_idx].m = float16_t(min); + + uint32_t qh = 0; + [[unroll]] for (int j = 0; j < QUANT_K_Q5_1/2; ++j) { + const float x0 = (data_s[src_idx + 0 + j] - min)*id; + const float x1 = (data_s[src_idx + QUANT_K_Q5_1/2 + j] - min)*id; + + const uint xi0 = uint(x0 + 0.5); + const uint xi1 = uint(x1 + 0.5); + + data_q[dst_idx].qs[j] = uint8_t((xi0 & 0xf) | ((xi1 & 0xf) << 4)); + qh |= ((xi0 & 0x10u) >> 4) << (j + 0); + qh |= ((xi1 & 0x10u) >> 4) << (j + QUANT_K_Q5_1/2); + } + data_q[dst_idx].qh = qh; +} +#endif + +#if defined(DATA_A_Q8_0) +void quantize(uint dst_idx, uint src_idx) +{ + float amax = 0.0; // absolute max + + [[unroll]] for (int j = 0; j < QUANT_K_Q8_0; j++) { + const float v = data_s[src_idx + j]; + amax = max(amax, abs(v)); + } + + const float d = amax / ((1 << 7) - 1); + const float id = (d != 0.0) ? 1.0/d : 0.0; + + data_q[dst_idx].d = float16_t(d); + + [[unroll]] for (int j = 0; j < QUANT_K_Q8_0; ++j) { + const float x0 = data_s[src_idx + j]*id; + + data_q[dst_idx].qs[j] = int8_t(round(x0)); + } +} +#endif + +#if defined(DATA_A_IQ4_NL) +uint best_index(float x) { + if (x <= kvalues_iq4nl[0]) return 0; + if (x >= kvalues_iq4nl[15]) return 15; + int ml = 0, mu = 15; + while (mu-ml > 1) { + int mav = (ml+mu)/2; + if (x < kvalues_iq4nl[mav]) mu = mav; else ml = mav; + } + return x - kvalues_iq4nl[mu-1] < kvalues_iq4nl[mu] - x ? mu-1 : mu; +} + +void quantize(uint dst_idx, uint src_idx) +{ + float amax = 0.0; + float vmax = 0.0; + + [[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL; ++j) { + const float v = data_s[src_idx + j]; + if (amax < abs(v)) { + amax = abs(v); + vmax = v; + } + } + + float d = vmax / kvalues_iq4nl[0]; + const float id = (d != 0.0) ? 1.0/d : 0.0; + + float sumqx = 0, sumq2 = 0; + [[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL/2; ++j) { + const float x0 = data_s[src_idx + 0 + j]*id; + const float x1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*id; + const uint xi0 = best_index(x0); + const uint xi1 = best_index(x1); + data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4)); + const float v0 = kvalues_iq4nl[xi0]; + const float v1 = kvalues_iq4nl[xi1]; + const float w0 = data_s[src_idx + 0 + j]*data_s[src_idx + 0 + j]; + const float w1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*data_s[src_idx + QUANT_K_IQ4_NL/2 + j]; + sumqx += w0*v0*data_s[src_idx + j] + w1*v1*data_s[src_idx + QUANT_K_IQ4_NL/2 + j]; + sumq2 += w0*v0*v0 + w1*v1*v1; + } + + data_q[dst_idx].d = float16_t(sumq2 > 0 ? sumqx/sumq2 : d); + +} +#endif + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); + if (gl_LocalInvocationIndex.x != 0) { + return; + } +#endif + + const uint idx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * QUANT_K; + + if (idx >= p.ne) { + return; + } + + uint dst_idx = dst_idx_quant(idx, QUANT_K); + uint src_idx = get_aoffset() + src0_idx(idx); + + quantize(dst_idx, src_idx); +} diff --git a/ggml/src/vulkan-shaders/cos.comp b/ggml/src/vulkan-shaders/cos.comp new file mode 100644 index 00000000..0b8d02f5 --- /dev/null +++ b/ggml/src/vulkan-shaders/cos.comp @@ -0,0 +1,17 @@ +#version 450 + +#include "types.comp" +#include "generic_unary_head.comp" + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +void main() { + const uint idx = get_idx(); + + if (idx >= p.ne) { + return; + } + + const FLOAT_TYPE val = FLOAT_TYPE(data_a[get_aoffset() + src0_idx(idx)]); + data_d[get_doffset() + dst_idx(idx)] = D_TYPE(cos(val)); +} diff --git a/ggml/src/vulkan-shaders/count_equal.comp b/ggml/src/vulkan-shaders/count_equal.comp new file mode 100644 index 00000000..d9345497 --- /dev/null +++ b/ggml/src/vulkan-shaders/count_equal.comp @@ -0,0 +1,31 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable + +#include "types.comp" +#include "generic_head.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) readonly buffer Y {B_TYPE data_b[];}; +layout (binding = 2) buffer D {D_TYPE data_d[];}; + +const uint CHUNK_SIZE = 512; + +void main() { + const uint base = gl_WorkGroupID.x * CHUNK_SIZE; + const uint col = gl_LocalInvocationID.x; + + uint count = 0; + [[unroll]] + for (uint i = 0; i < CHUNK_SIZE; i += gl_WorkGroupSize.x) { + const uint idx = base + i + col; + if (idx >= p.KX) { + break; + } + count += uint(data_a[idx] == data_b[idx]); + } + + atomicAdd(data_d[0], D_TYPE(count)); +} diff --git a/ggml/src/vulkan-shaders/dequant_funcs.comp b/ggml/src/vulkan-shaders/dequant_funcs.comp index d5b98973..0d9739d4 100644 --- a/ggml/src/vulkan-shaders/dequant_funcs.comp +++ b/ggml/src/vulkan-shaders/dequant_funcs.comp @@ -2,6 +2,15 @@ #extension GL_EXT_shader_explicit_arithmetic_types_int8 : require #endif +#include "types.comp" + +#if defined(A_TYPE_PACKED16) +layout (binding = 0) readonly buffer A_PACKED16 {A_TYPE_PACKED16 data_a_packed16[];}; +#endif +#if defined(A_TYPE_PACKED32) +layout (binding = 0) readonly buffer A_PACKED32 {A_TYPE_PACKED32 data_a_packed32[];}; +#endif + #if defined(DATA_A_F32) vec2 dequantize(uint ib, uint iqs, uint a_offset) { return vec2(data_a[a_offset + ib], data_a[a_offset + ib + 1]); @@ -14,55 +23,440 @@ vec2 dequantize(uint ib, uint iqs, uint a_offset) { } #endif +#if defined(DATA_A_BF16) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + return vec2(bf16_to_fp32(data_a[a_offset + ib]), bf16_to_fp32(data_a[a_offset + ib + 1])); +} +#endif + #if defined(DATA_A_Q4_0) vec2 dequantize(uint ib, uint iqs, uint a_offset) { - const float d = float(data_a[a_offset + ib].d); const uint vui = uint(data_a[a_offset + ib].qs[iqs]); - return (vec2(vui & 0xF, vui >> 4) - 8.0f) * d; + return (vec2(vui & 0xF, vui >> 4) - 8.0f); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]); + return (vec4(vui & 0xF, (vui >> 4) & 0xF, (vui >> 8) & 0xF, vui >> 12) - 8.0f); } #endif #if defined(DATA_A_Q4_1) vec2 dequantize(uint ib, uint iqs, uint a_offset) { - const float d = float(data_a[a_offset + ib].d); - const float m = float(data_a[a_offset + ib].m); const uint vui = uint(data_a[a_offset + ib].qs[iqs]); - return vec2(vui & 0xF, vui >> 4) * d + m; + return vec2(vui & 0xF, vui >> 4); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]); + return vec4(vui & 0xF, (vui >> 4) & 0xF, (vui >> 8) & 0xF, vui >> 12); } #endif #if defined(DATA_A_Q5_0) vec2 dequantize(uint ib, uint iqs, uint a_offset) { - const float d = float(data_a[a_offset + ib].d); const uint uint_qh = uint(data_a[a_offset + ib].qh[1]) << 16 | data_a[a_offset + ib].qh[0]; const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10); const uint vui = uint(data_a[a_offset + ib].qs[iqs]); - return (vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y) - 16.0f) * d; + return (vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y) - 16.0f); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint uint_qh = uint(data_a_packed16[a_offset + ib].qh[1]) << 16 | data_a_packed16[a_offset + ib].qh[0]; + const ivec2 qh0 = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10); + const ivec2 qh1 = ivec2(((uint_qh >> (iqs + 1)) << 4) & 0x10, (uint_qh >> (iqs + 13)) & 0x10); + const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]); + return (vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y) - 16.0f); } #endif #if defined(DATA_A_Q5_1) vec2 dequantize(uint ib, uint iqs, uint a_offset) { - const float d = float(data_a[a_offset + ib].d); - const float m = float(data_a[a_offset + ib].m); const uint uint_qh = data_a[a_offset + ib].qh; const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10); const uint vui = uint(data_a[a_offset + ib].qs[iqs]); - return vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y) * d + m; + return vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint uint_qh = data_a_packed16[a_offset + ib].qh; + const ivec2 qh0 = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10); + const ivec2 qh1 = ivec2(((uint_qh >> (iqs + 1)) << 4) & 0x10, (uint_qh >> (iqs + 13)) & 0x10); + const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]); + return vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y); } #endif #if defined(DATA_A_Q8_0) vec2 dequantize(uint ib, uint iqs, uint a_offset) { - const float d = float(data_a[a_offset + ib].d); - return vec2(int(data_a[a_offset + ib].qs[iqs]), int(data_a[a_offset + ib].qs[iqs + 1])) * d; + return vec2(int(data_a[a_offset + ib].qs[iqs]), int(data_a[a_offset + ib].qs[iqs + 1])); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const i8vec2 v0 = unpack8(int32_t(data_a_packed16[a_offset + ib].qs[iqs/2])).xy; // vec4 used due to #12147 + const i8vec2 v1 = unpack8(int32_t(data_a_packed16[a_offset + ib].qs[iqs/2 + 1])).xy; + return vec4(v0.x, v0.y, v1.x, v1.y); +} +#endif + +#if defined(DATA_A_IQ1_S) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint ib8 = iqs / 8; + const int i8 = int(iqs % 8); + const uint qh = data_a[a_offset + ib].qh[ib32]; + const uint qs = data_a[a_offset + ib].qs[ib8]; + const float dl = float(2 * bitfieldExtract(qh, 12, 3) + 1); + const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; + const uint idxhi = bitfieldExtract(qh, 3 * int(ib8 & 3), 3); + const int16_t grid = int16_t(iq1s_grid[qs | (idxhi << 8)]); + // Signed bitfield extract. + const ivec2 gvec = ivec2( + bitfieldExtract(grid, 2 * (i8), 2), + bitfieldExtract(grid, 2 * (i8 + 1), 2) + ); + return dl * (vec2(gvec) + delta); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint ib8 = iqs / 8; + const int i8 = int(iqs % 8); + const uint qh = data_a[a_offset + ib].qh[ib32]; + const uint qs = data_a[a_offset + ib].qs[ib8]; + const float dl = 2 * bitfieldExtract(qh, 12, 3) + 1; + const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; + const int16_t grid = int16_t(iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)]); + // Signed bitfield extract. + const ivec4 gvec = ivec4( + bitfieldExtract(grid, 2 * (i8), 2), + bitfieldExtract(grid, 2 * (i8 + 1), 2), + bitfieldExtract(grid, 2 * (i8 + 2), 2), + bitfieldExtract(grid, 2 * (i8 + 3), 2) + ); + return dl * (vec4(gvec) + delta); +} +#endif + +#if defined(DATA_A_IQ1_M) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint ib8 = iqs / 8; + const uint ib16 = iqs / 16; + const int i8 = int(iqs % 8); + const uint sc = data_a[a_offset + ib].scales[iqs / 64]; + const uint qs = data_a[a_offset + ib].qs[ib8]; + const uint qh = data_a[a_offset + ib].qh[ib16] >> (4 * (ib8 & 1)); + const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1; + const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA; + const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]); + // Signed bitfield extract. + const ivec2 gvec = ivec2( + bitfieldExtract(grid, 2 * (i8), 2), + bitfieldExtract(grid, 2 * (i8 + 1), 2) + ); + return dl * (vec2(gvec) + delta); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint ib8 = iqs / 8; + const uint ib16 = iqs / 16; + const int i8 = int(iqs % 8); + const uint sc = data_a[a_offset + ib].scales[iqs / 64]; + const uint qs = data_a[a_offset + ib].qs[ib8]; + const uint qh = data_a[a_offset + ib].qh[ib16] >> (4 * (ib8 & 1)); + const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1; + const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA; + const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]); + // Signed bitfield extract. + const ivec4 gvec = ivec4( + bitfieldExtract(grid, 2 * (i8), 2), + bitfieldExtract(grid, 2 * (i8 + 1), 2), + bitfieldExtract(grid, 2 * (i8 + 2), 2), + bitfieldExtract(grid, 2 * (i8 + 3), 2) + ); + return dl * (vec4(gvec) + delta); +} +#endif + +#if defined(DATA_A_IQ2_XXS) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint ib8 = (iqs / 8) % 4; + const uint qs = data_a[a_offset + ib].qs[8 * ib32 + ib8]; + // Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale) + const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[4 * ib32 + 2], + data_a_packed16[a_offset + ib].qs[4 * ib32 + 3])); + const float db = 0.25 * (0.5 + (signs >> 28)); + const uint sign7 = bitfieldExtract(signs, 7 * int(ib8), 7); + // Add parity bit + const uint sign8 = sign7 | (bitCount(sign7) << 7); + const uint sign = sign8 >> (iqs % 8); + const u8vec4 grid = unpack8(iq2xxs_grid[qs][(iqs % 8) / 4] >> (8 * (iqs % 4))); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + return db * vec2( + grid.x * (sign0 ? -1.0 : 1.0), + grid.y * (sign1 ? -1.0 : 1.0) + ); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint ib8 = (iqs / 8) % 4; + const uint qs = data_a[a_offset + ib].qs[8 * ib32 + ib8]; + // Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale) + const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[4 * ib32 + 2], + data_a_packed16[a_offset + ib].qs[4 * ib32 + 3])); + const float db = 0.25 * (0.5 + (signs >> 28)); + const uint sign7 = bitfieldExtract(signs, 7 * int(ib8), 7); + // Add parity bit + const uint sign8 = sign7 | (bitCount(sign7) << 7); + const uint sign = sign8 >> (iqs % 8); + const u8vec4 grid = unpack8(iq2xxs_grid[qs][(iqs % 8) / 4] >> (8 * (iqs % 4))); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + bool sign2 = (sign & 4) != 0; + bool sign3 = (sign & 8) != 0; + return db * vec4( + grid.x * (sign0 ? -1.0 : 1.0), + grid.y * (sign1 ? -1.0 : 1.0), + grid.z * (sign2 ? -1.0 : 1.0), + grid.w * (sign3 ? -1.0 : 1.0) + ); +} +#endif + +#if defined(DATA_A_IQ2_XS) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint scale = (data_a[a_offset + ib].scales[iqs / 32] >> (4 * ((iqs / 16) & 1))) & 0xf; + const uint qs = data_a[a_offset + ib].qs[iqs / 8]; + const float db = 0.25 * (0.5 + scale); + const uint sign7 = qs >> 9; + // Add parity bit + const uint sign8 = sign7 | (bitCount(sign7) << 7); + const uint sign = sign8 >> (iqs % 8); + const u8vec4 grid = unpack8(iq2xs_grid[qs & 511][(iqs % 8) / 4] >> (8 * (iqs % 4))); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + return db * vec2( + grid.x * (sign0 ? -1.0 : 1.0), + grid.y * (sign1 ? -1.0 : 1.0) + ); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint scale = (data_a[a_offset + ib].scales[iqs / 32] >> (4 * ((iqs / 16) & 1))) & 0xf; + const uint qs = data_a[a_offset + ib].qs[iqs / 8]; + const float db = 0.25 * (0.5 + scale); + const uint sign7 = qs >> 9; + // Add parity bit + const uint sign8 = sign7 | (bitCount(sign7) << 7); + const uint sign = sign8 >> (iqs % 8); + const u8vec4 grid = unpack8(iq2xs_grid[qs & 511][(iqs % 8) / 4] >> (8 * (iqs % 4))); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + bool sign2 = (sign & 4) != 0; + bool sign3 = (sign & 8) != 0; + return db * vec4( + grid.x * (sign0 ? -1.0 : 1.0), + grid.y * (sign1 ? -1.0 : 1.0), + grid.z * (sign2 ? -1.0 : 1.0), + grid.w * (sign3 ? -1.0 : 1.0) + ); +} +#endif + +#if defined(DATA_A_IQ2_S) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint ib8 = iqs / 8; + + const uint scale = (data_a[a_offset + ib].scales[ib32] >> (4 * ((iqs / 16) & 1))) & 0xf; + const uint qs = data_a[a_offset + ib].qs[ib8]; + const uint qh = data_a[a_offset + ib].qh[ib32]; + const uint qhshift = 2 * (ib8 % 4); + const uint sign = data_a[a_offset + ib].qs[QUANT_K / 8 + ib8] >> (iqs % 8); + + const float db = 0.25 * (0.5 + scale); + const u8vec4 grid = unpack8(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(iqs % 8) / 4]); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + return db * vec2( + grid[iqs % 4] * (sign0 ? -1.0 : 1.0), + grid[(iqs % 4) + 1] * (sign1 ? -1.0 : 1.0) + ); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint ib8 = iqs / 8; + + const uint scale = (data_a[a_offset + ib].scales[ib32] >> (4 * ((iqs / 16) & 1))) & 0xf; + const uint qs = data_a[a_offset + ib].qs[ib8]; + const uint qh = data_a[a_offset + ib].qh[ib32]; + const uint qhshift = 2 * (ib8 % 4); + const uint sign = data_a[a_offset + ib].qs[QUANT_K / 8 + ib8] >> (iqs % 8); + + const float db = 0.25 * (0.5 + scale); + const u8vec4 grid = unpack8(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(iqs % 8) / 4]); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + bool sign2 = (sign & 4) != 0; + bool sign3 = (sign & 8) != 0; + return db * vec4( + grid.x * (sign0 ? -1.0 : 1.0), + grid.y * (sign1 ? -1.0 : 1.0), + grid.z * (sign2 ? -1.0 : 1.0), + grid.w * (sign3 ? -1.0 : 1.0) + ); +} +#endif + +#if defined(DATA_A_IQ3_XXS) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint ib4 = iqs / 4; + const uint ib32 = iqs / 32; + const uint is = QUANT_K / 4 + 4 * ib32; + const uint qs = data_a[a_offset + ib].qs[ib4]; + // Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale) + const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[is / 2], + data_a_packed16[a_offset + ib].qs[is / 2 + 1])); + const float db = 0.5 * (0.5 + (signs >> 28)); + const uint sign7 = bitfieldExtract(signs, 7 * (int(ib4 / 2) % 4), 7); + // Add parity bit + const uint sign8 = sign7 | (bitCount(sign7) << 7); + const uint sign = sign8 >> (iqs % 8); + const u8vec4 grid = unpack8(iq3xxs_grid[qs] >> (8 * (iqs % 4))); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + return db * vec2( + grid.x * (sign0 ? -1.0 : 1.0), + grid.y * (sign1 ? -1.0 : 1.0) + ); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint ib4 = iqs / 4; + const uint ib32 = iqs / 32; + const uint is = QUANT_K / 4 + 4 * ib32; + const uint qs = data_a[a_offset + ib].qs[ib4]; + const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[is / 2], + data_a_packed16[a_offset + ib].qs[is / 2 + 1])); + const float db = 0.5 * (0.5 + (signs >> 28)); + const uint sign7 = bitfieldExtract(signs, 7 * (int(ib4 / 2) % 4), 7); + // Add parity bit + const uint sign8 = sign7 | (bitCount(sign7) << 7); + const uint sign = sign8 >> (iqs % 8); + const u8vec4 grid = unpack8(iq3xxs_grid[qs]); + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + bool sign2 = (sign & 4) != 0; + bool sign3 = (sign & 8) != 0; + return db * vec4( + grid.x * (sign0 ? -1.0 : 1.0), + grid.y * (sign1 ? -1.0 : 1.0), + grid.z * (sign2 ? -1.0 : 1.0), + grid.w * (sign3 ? -1.0 : 1.0) + ); +} +#endif + +#if defined(DATA_A_IQ3_S) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint qs = data_a[a_offset + ib].qs[iqs / 4]; + const uint qh = data_a[a_offset + ib].qh[iqs / 32]; + const uint sign = data_a[a_offset + ib].signs[iqs / 8] >> (iqs % 8); + const uint scale = data_a[a_offset + ib].scales[iqs / 64]; + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + const float db = 1 + 2 * ((scale >> (4 * ((iqs / 32) & 1))) & 0xf); + const uint32_t grid = iq3s_grid[qs | ((qh << (8 - ((iqs / 4) % 8))) & 256)] >> (8 * (iqs % 4)); + return db * vec2( + int(grid & 0xFF) * (sign0 ? -1.0 : 1.0), + int((grid >> 8) & 0xFF) * (sign1 ? -1.0 : 1.0) + ); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint ib4 = iqs / 4; + const uint ib32 = iqs / 32; + const uint qs = data_a[a_offset + ib].qs[ib4]; + const uint qh = data_a[a_offset + ib].qh[ib32]; + const uint sign = data_a[a_offset + ib].signs[iqs / 8] >> (iqs % 8); + const uint scale = data_a[a_offset + ib].scales[ib32 / 2]; + bool sign0 = (sign & 1) != 0; + bool sign1 = (sign & 2) != 0; + bool sign2 = (sign & 4) != 0; + bool sign3 = (sign & 8) != 0; + const float db = 1 + 2 * ((scale >> (4 * (ib32 & 1))) & 0xf); + const uint32_t grid = iq3s_grid[qs | ((qh << (8 - ib4 % 8)) & 256)] >> (8 * (iqs % 4)); + return db * vec4( + int(grid & 0xFF) * (sign0 ? -1.0 : 1.0), + int((grid >> 8) & 0xFF) * (sign1 ? -1.0 : 1.0), + int((grid >> 16) & 0xFF) * (sign2 ? -1.0 : 1.0), + int((grid >> 24) & 0xFF) * (sign3 ? -1.0 : 1.0) + ); +} +#endif + +#if defined(DATA_A_IQ4_XS) +vec2 dequantize(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint iq = 16 * ib32 + (iqs % 16); + + const uint sl = (data_a[a_offset + ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF; + const uint sh = (data_a[a_offset + ib].scales_h >> (2 * ib32)) & 3; + const uint qshift = (iqs & 16) >> 2; + u8vec2 qs = u8vec2(data_a[a_offset + ib].qs[iq], data_a[a_offset + ib].qs[iq + 1]); + qs = (qs >> qshift) & uint8_t(0xF); + + const float dl = float(int(sl | (sh << 4)) - 32); + return dl * vec2(kvalues_iq4nl[qs.x], kvalues_iq4nl[qs.y]); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint ib32 = iqs / 32; + const uint iq = 16 * ib32 + (iqs % 16); + + const uint sl = (data_a[a_offset + ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF; + const uint sh = (data_a[a_offset + ib].scales_h >> (2 * ib32)) & 3; + const uint qshift = (iqs & 16) >> 2; + u8vec4 qs = u8vec4( + data_a[a_offset + ib].qs[iq + 0], + data_a[a_offset + ib].qs[iq + 1], + data_a[a_offset + ib].qs[iq + 2], + data_a[a_offset + ib].qs[iq + 3] + ); + qs = (qs >> qshift) & uint8_t(0xF); + + const float dl = float(int(sl | (sh << 4)) - 32); + return dl * vec4( + kvalues_iq4nl[qs.x], kvalues_iq4nl[qs.y], + kvalues_iq4nl[qs.z], kvalues_iq4nl[qs.w]); } #endif #if defined(DATA_A_IQ4_NL) vec2 dequantize(uint ib, uint iqs, uint a_offset) { - const float d = float(data_a[a_offset + ib].d); const uint vui = uint(data_a[a_offset + ib].qs[iqs]); - return vec2(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[vui >> 4]) * d; + return vec2(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[vui >> 4]); +} +vec4 dequantize4(uint ib, uint iqs, uint a_offset) { + const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]); + return vec4(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[(vui >> 4) & 0xF], kvalues_iq4nl[(vui >> 8) & 0xF], kvalues_iq4nl[vui >> 12]); +} +#endif + +#if defined(DATA_A_F32) || defined(DATA_A_F16) || defined(DATA_A_BF16) +vec2 get_dm(uint ib, uint a_offset) { + return vec2(0, 0); +} +#endif + +#if defined(DATA_A_IQ1_M) +vec2 get_dm(uint ib, uint a_offset) { + const uint16_t[4] scales = data_a[a_offset + ib].scales; + const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12; + const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x); + return vec2(d, 0); +} +#endif + +#if defined(DATA_A_Q4_0) || defined(DATA_A_Q5_0) || defined(DATA_A_Q8_0) || defined(DATA_A_IQ1_S) || defined(DATA_A_IQ2_XXS) || defined(DATA_A_IQ2_XS) || defined(DATA_A_IQ2_S) || defined(DATA_A_IQ3_XXS) || defined(DATA_A_IQ3_S) || defined(DATA_A_IQ4_XS) || defined(DATA_A_IQ4_NL) +vec2 get_dm(uint ib, uint a_offset) { + return vec2(float(data_a[a_offset + ib].d), 0); +} +#endif + +#if defined(DATA_A_Q4_1) || defined(DATA_A_Q5_1) +vec2 get_dm(uint ib, uint a_offset) { + return vec2(float(data_a[a_offset + ib].d), float(data_a[a_offset + ib].m)); } #endif diff --git a/ggml/src/vulkan-shaders/dequant_funcs_cm2.comp b/ggml/src/vulkan-shaders/dequant_funcs_cm2.comp new file mode 100644 index 00000000..9cb7da2d --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_funcs_cm2.comp @@ -0,0 +1,699 @@ + +#include "types.comp" + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ4_0 { + block_q4_0_packed16 block; +}; + +float16_t dequantFuncQ4_0(const in decodeBufQ4_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + const uint shift = (idx & 0x10) >> 2; + uint32_t qs = uint32_t(bl.block.qs[(idx & 0xE) >> 1]); + qs >>= shift; + qs &= 0x0F0F; + qs = unpack8(qs)[idx & 1]; + float16_t ret = (float16_t(qs) - float16_t(8)) * d; + return ret; +} + +layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ4_1 { + block_q4_1 block; +}; + +float16_t dequantFuncQ4_1(const in decodeBufQ4_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const float16_t m = bl.block.m; + const uint idx = coordInBlock[1]; + const uint iqs = idx & 0xF; + const uint shift = (idx & 0x10) >> 2; + uint32_t qs = bl.block.qs[iqs]; + qs >>= shift; + qs &= 0xF; + float16_t ret = float16_t(qs) * d + m; + return ret; +} + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ5_0 { + block_q5_0 block; +}; + +float16_t dequantFuncQ5_0(const in decodeBufQ5_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + const uint iqs = idx & 0xF; + + const uint uint_qh = uint(bl.block.qh[1]) << 16 | bl.block.qh[0]; + const uint qh = ((uint_qh >> idx) << 4) & 0x10; + + const uint shift = (idx & 0x10) >> 2; + uint32_t qs = bl.block.qs[iqs]; + qs >>= shift; + qs &= 0xF; + + float16_t ret = (float16_t(qs | qh) - float16_t(16)) * d; + return ret; +} + +layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufQ5_1 { + block_q5_1 block; +}; + +float16_t dequantFuncQ5_1(const in decodeBufQ5_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const float16_t m = bl.block.m; + const uint idx = coordInBlock[1]; + const uint iqs = idx & 0xF; + + const uint uint_qh = bl.block.qh; + const uint qh = ((uint_qh >> idx) << 4) & 0x10; + + const uint shift = (idx & 0x10) >> 2; + uint32_t qs = bl.block.qs[iqs]; + qs >>= shift; + qs &= 0xF; + + float16_t ret = float16_t(qs | qh) * d + m; + return ret; +} + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ8_0 { + block_q8_0_packed16 block; +}; + +float16_t dequantFuncQ8_0(const in decodeBufQ8_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + const uint iqs = idx; + + // Load 16b and select the byte for this element + int32_t qs = unpack8(bl.block.qs[(iqs & 0x1E) >> 1])[iqs & 1]; + float16_t ret = float16_t(qs) * d; + return ret; +} + +layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ2_K { + block_q2_K block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ2_K_packed16 { + block_q2_K_packed16 block; +}; + +float16_t dequantFuncQ2_K(const in decodeBufQ2_K bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + decodeBufQ2_K_packed16 bl16 = decodeBufQ2_K_packed16(bl); + const f16vec2 d = bl.block.d; + const uint idx = coordInBlock[1]; + + const uint scalesi = (idx & 0xF0) >> 4; // 0..15 + const uint qsshift = (idx & 0x60) >> 4; // 0,2,4,6 + + uint qs = uint32_t(bl16.block.qs[((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1)]); + qs = (qs >> qsshift) & 0x0303; + qs = unpack8(qs)[idx & 1]; + + const uint scales = bl.block.scales[scalesi]; + float16_t ret = d.x * float16_t(scales & 0xF) * float16_t(qs) - d.y * float16_t(scales >> 4); + return ret; +} + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ3_K { + block_q3_K block; +}; + +float16_t dequantFuncQ3_K(const in decodeBufQ3_K bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const uint idx = coordInBlock[1]; + const uint iqs = idx; + + const uint n = iqs / 128; // 0,1 + const uint qsi = n * 32 + (iqs % 32); // 0..63 + const uint hmi = (iqs % 32); // 0..31 + const uint j = (iqs % 128) / 8; // 0..15 + const uint is = iqs / 16; // 0..15 + const uint halfsplit = ((iqs % 128) / 32); // 0,1,2,3 + const uint qsshift = halfsplit * 2; // 0,2,4,6 + const uint m = 1 << (4 * n + halfsplit); // 1,2,4,8,16,32,64,128 + + uint32_t scaleidx0 = (is < 8) ? is : (is-8); + uint32_t scaleidx0shift = (is < 8) ? 0 : 4; + uint32_t scaleidx1 = is + 8 - (is/4)*4; + uint32_t scaleidx1shift = (is/4)*2; + + const int8_t us = int8_t(((bl.block.scales[scaleidx0] >> scaleidx0shift) & 0xF) | (((bl.block.scales[scaleidx1] >> scaleidx1shift) & 3) << 4)); + + const float16_t dl = bl.block.d * float16_t(us - 32); + + float16_t ret = dl * float16_t(int8_t((bl.block.qs[qsi ] >> qsshift) & 3) - (((bl.block.hmask[hmi ] & m) != 0) ? 0 : 4)); + + return ret; +} + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K { + block_q4_K block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed16 { + block_q4_K_packed16 block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed128 { + block_q4_K_packed128 block; +}; + +#if defined(IS_MUL_MM2) + +// For Q4_K and Q5_K in the mat-mul shader, we decode a tile's worth of scales +// into shared memory and then process the whole tile using those scales. +// There is a fetch function that loads into private variables and then a store +// function that stores into shared memory. +// Q4_K and Q5_K have the same encoding of scales, so everything is shared except +// the part that fetches from the structure (which has a different block layout). +#if defined(DATA_A_Q4_K) || defined(DATA_A_Q5_K) +const uint shAscales_stride = (BM + 2); +// 1 scale per 32 elements -> 8 scales per block, per row +shared vec2 shAscales[8 * shAscales_stride]; +uvec4 row_v; +#endif + +#if defined(DATA_A_Q4_K) +layout (binding = 0) readonly buffer A_Q4_K_128 {block_q4_K_packed128 data_a_q4_k_packed128[];}; + +void fetch_scalesQ4_K(uint ir_BM, uint pos_a, uint stride_a, uint block_k, uint tid, bool in_bounds) +{ + uint tids_per_row = BLOCK_SIZE / BM; + uint is_per_tid = 8 / tids_per_row; + uint is_start = is_per_tid * (tid % tids_per_row); + uint tid_row = tid / tids_per_row; + + uint row = ir_BM + tid_row; + uint block_index = pos_a + row * stride_a + (block_k / QUANT_K); + if (in_bounds || row < p.M) { + row_v = data_a_q4_k_packed128[block_index].q4k[0]; + } +} +#endif +#if defined(DATA_A_Q5_K) +layout (binding = 0) readonly buffer A_Q5_K_128 {block_q5_K_packed128 data_a_q5_k_packed128[];}; + +void fetch_scalesQ5_K(uint ir_BM, uint pos_a, uint stride_a, uint block_k, uint tid, bool in_bounds) +{ + uint tids_per_row = BLOCK_SIZE / BM; + uint is_per_tid = 8 / tids_per_row; + uint is_start = is_per_tid * (tid % tids_per_row); + uint tid_row = tid / tids_per_row; + + uint row = ir_BM + tid_row; + uint block_index = pos_a + row * stride_a + (block_k / QUANT_K); + if (in_bounds || row < p.M) { + row_v = data_a_q5_k_packed128[block_index].q5k[0]; + } +} +#endif + +#if defined(DATA_A_Q4_K) || defined(DATA_A_Q5_K) +void store_scalesQ4_K(uint tid) +{ + barrier(); + + uint tids_per_row = BLOCK_SIZE / BM; + uint is_per_tid = 8 / tids_per_row; + uint is_start = is_per_tid * (tid % tids_per_row); + uint tid_row = tid / tids_per_row; + + [[unroll]] for (uint idx = 0; idx < is_per_tid; ++idx) { + uint is = idx + is_start; + uvec4 v = row_v; + const vec2 loadd = vec2(unpackFloat2x16(v.x)); + + uint32_t sc; + uint32_t mbyte; + + uint32_t scale0 = v.y; + uint32_t scale4 = v.z; + uint32_t scale8 = v.w; + + uint32_t sc_lo = scale0; + uint32_t mb_lo = scale4; + uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2); + uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2); + + sc = is < 4 ? sc_lo : sc_hi; + mbyte = is < 4 ? mb_lo : mb_hi; + sc = sc >> (8 * (is & 3)); + mbyte = mbyte >> (8 * (is & 3)); + sc &= 0x3F; + mbyte &= 0x3F; + + const float d = loadd.x * float(sc); + const float m = loadd.y * float(mbyte); + shAscales[is * shAscales_stride + tid_row] = vec2(d,m); + } + + barrier(); +} +#endif + +#endif + +float16_t dequantFuncQ4_K(const in decodeBufQ4_K bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + decodeBufQ4_K_packed16 bl16 = decodeBufQ4_K_packed16(bl); + decodeBufQ4_K_packed128 bl128 = decodeBufQ4_K_packed128(bl); + const uint idx = coordInBlock[1]; + + const uint b = (idx & 0x20) >> 5; // 0,1 + const uint is = (idx & 0xE0) >> 5; // 0..7 + +#if defined(IS_MUL_MM2) && defined(DATA_A_Q4_K) + vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)]; + float d = v.x; + float m = v.y; +#else + uvec4 v = bl128.block.q4k[0]; + const vec2 loadd = vec2(unpackFloat2x16(v.x)); + + uint32_t sc; + uint32_t mbyte; + + uint32_t scale0 = v.y; + uint32_t scale4 = v.z; + uint32_t scale8 = v.w; + + uint32_t sc_lo = scale0; + uint32_t mb_lo = scale4; + uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2); + uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2); + + sc = is < 4 ? sc_lo : sc_hi; + mbyte = is < 4 ? mb_lo : mb_hi; + sc = sc >> (8 * (is & 3)); + mbyte = mbyte >> (8 * (is & 3)); + sc &= 0x3F; + mbyte &= 0x3F; + + const float d = loadd.x * float(sc); + const float m = loadd.y * float(mbyte); +#endif + + uint qs = uint32_t(bl16.block.qs[((idx & 0xC0) >> 2) + ((idx & 0x1E) >> 1)]); + qs = (qs >> (b * 4 + 8 * (idx & 1))) & 0xF; + + float ret = d * float(qs) - m; + + return float16_t(ret); +} + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K { + block_q5_K block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed16 { + block_q5_K_packed16 block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed128 { + block_q5_K_packed128 block; +}; + +float16_t dequantFuncQ5_K(const in decodeBufQ5_K bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + decodeBufQ5_K_packed16 bl16 = decodeBufQ5_K_packed16(bl); + decodeBufQ5_K_packed128 bl128 = decodeBufQ5_K_packed128(bl); + const uint idx = coordInBlock[1]; + + const uint b = (idx & 0x20) >> 5; // 0,1 + const uint is = (idx & 0xE0) >> 5; // 0..7 + +#if defined(IS_MUL_MM2) && defined(DATA_A_Q5_K) + vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)]; + float d = v.x; + float m = v.y; +#else + uvec4 v = bl128.block.q5k[0]; + + const f16vec2 loadd = unpackFloat2x16(v.x); + + uint32_t sc; + uint32_t mbyte; + + uint32_t scale0 = v.y; + uint32_t scale4 = v.z; + uint32_t scale8 = v.w; + + uint32_t sc_lo = scale0; + uint32_t mb_lo = scale4; + uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2); + uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2); + + sc = is < 4 ? sc_lo : sc_hi; + mbyte = is < 4 ? mb_lo : mb_hi; + sc = sc >> (8 * (is & 3)); + mbyte = mbyte >> (8 * (is & 3)); + sc &= 0x3F; + mbyte &= 0x3F; + + const float16_t d = loadd.x * float16_t(sc); + const float16_t m = loadd.y * float16_t(mbyte); +#endif + + uint qh = uint32_t(bl16.block.qh[(idx & 0x1E) >> 1]); + qh = ((qh >> is) & 0x101) << 4; + + uint qs = uint32_t(bl16.block.qs[((idx & 0xC0) >> 2) + ((idx & 0x1E) >> 1)]); + qs = (qs >> (b * 4)) & 0x0F0F; + qs = unpack8(qs | qh)[idx & 1]; + + float ret = d * float(qs) - m; + + return float16_t(ret); +} + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ6_K { + block_q6_K block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ6_K_packed16 { + block_q6_K_packed16 block; +}; + +float16_t dequantFuncQ6_K(const in decodeBufQ6_K bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + decodeBufQ6_K_packed16 bl16 = decodeBufQ6_K_packed16(bl); + const uint idx = coordInBlock[1]; + + const uint b = (idx & 0x40) >> 6; // 0,1 + const uint qhshift = (idx & 0x60) >> 4; // 0,2,4,6 + const uint is = (idx & 0xF0) >> 4; // 0..15 + + const float16_t dscale = bl.block.d * float16_t(bl.block.scales[is]); + + uint ql = uint32_t(bl16.block.ql[((idx & 0x80) >> 2) + ((idx & 0x3E) >> 1)]); + ql = (ql >> (b * 4)) & 0x0F0F; + + uint qh = uint32_t(bl16.block.qh[((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1)]); + qh = ((qh >> qhshift) & 0x0303) << 4; + + int q = unpack8(ql | qh)[idx & 1]; + + float16_t ret = dscale * float16_t(q - 32); + + return ret; +} + +#if defined(DATA_A_IQ1_S) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ1_S { + block_iq1_s block; +}; + +float16_t dequantFuncIQ1_S(const in decodeBufIQ1_S bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + + const uint ib32 = (idx & 0xE0) >> 5; + const uint ib8 = (idx & 0xF8) >> 3; + + const uint qh = bl.block.qh[ib32]; + const uint qs = bl.block.qs[ib8]; + const float dl = d * float(2 * bitfieldExtract(qh, 12, 3) + 1); + const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; + const uint grid = iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)]; + + float16_t ret = float16_t(dl) * (float16_t(bitfieldExtract(int(grid), 2 * int(idx % 8), 2)) + float16_t(delta)); + return ret; +} +#endif + +#if defined(DATA_A_IQ1_M) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ1_M { + block_iq1_m block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufIQ1_M_packed64 { + block_iq1_m_packed64 block; +}; + +float16_t dequantFuncIQ1_M(const in decodeBufIQ1_M bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + decodeBufIQ1_M_packed64 bl64 = decodeBufIQ1_M_packed64(bl); + const uint idx = coordInBlock[1]; + + uvec2 scales = unpack32(bl64.block.scales); + const float16_t d = uint16BitsToHalf(uint16_t(((scales.x & 0xF000) >> 12) | ((scales.x & 0xF0000000) >> 24) | ((scales.y & 0xF000) >> 4) | ((scales.y & 0xF0000000) >> 16))); + + const uint ib8 = (idx & 0xF8) >> 3; + const uint ib16 = (idx & 0xF0) >> 4; + const int i8 = int(idx % 8); + const uint sc = bl.block.scales[ib8 / 8]; + const uint qs = bl.block.qs[ib8]; + const uint qh = bl.block.qh[ib16] >> (4 * (ib8 & 1)); + const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1; + const float delta = ((qh & 8) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; + const uint grid = iq1s_grid[qs | ((qh & 7) << 8)]; + + float16_t ret = d * float16_t(dl) * (float16_t(bitfieldExtract(int(grid), 2 * i8, 2)) + float16_t(delta)); + return ret; +} +#endif + +#if defined(DATA_A_IQ2_XXS) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XXS { + block_iq2_xxs block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XXS_packed16 { + block_iq2_xxs_packed16 block; +}; + +float16_t dequantFuncIQ2_XXS(const in decodeBufIQ2_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + decodeBufIQ2_XXS_packed16 bl16 = decodeBufIQ2_XXS_packed16(bl); + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + + const uint ib32 = (idx & 0xE0) >> 5; // 0..7 + const uint ib8 = (idx & 0x18) >> 3; // 0..3 + const uint iqs = 8 * ib32 + ib8; + + const uint qs = bl.block.qs[iqs]; + const uint signscale = pack32(u16vec2(bl16.block.qs[4*ib32+2], bl16.block.qs[4*ib32+3])); + + const float dscale = float(bl.block.d) * 0.25 * (0.5 + float(signscale >> 28)); + uint sign = bitfieldExtract(signscale, 7 * int(ib8), 7); + sign |= bitCount(sign) << 7; + + uint g2 = iq2xxs_grid[qs][(idx & 4) >> 2]; + g2 >>= (idx & 2) * 8; + const vec2 g = vec2(unpack8(g2)); + + vec2 ret = dscale * g * ((sign & (1 << (idx & 7))) != 0 ? -1.0hf : 1.0hf); + return float16_t(ret[idx & 1]); +} +#endif + +#if defined(DATA_A_IQ2_XS) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XS { + block_iq2_xs block; +}; + +float16_t dequantFuncIQ2_XS(const in decodeBufIQ2_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + + const uint is = (idx & 0xE0) >> 5; // 0..8 + const uint sshift = (idx & 0x10) >> 2; // 0,4 + const uint iqs = (idx & 0xF8) >> 3; // 0..63 + + const uint16_t qs = bl.block.qs[iqs]; + const float dscale = float(bl.block.d) * 0.25 * (0.5 + float((bl.block.scales[is] >> sshift) & 0xF)); + + uint sign = uint(qs >> 9); + sign |= bitCount(sign) << 7; + uint g2 = iq2xs_grid[qs & 0x1FF][(idx & 4) >> 2]; + g2 >>= (idx & 2) * 8; + const vec2 g = vec2(unpack8(g2)); + + vec2 ret = dscale * g * ((sign & (1 << (idx & 7))) != 0 ? -1.0hf : 1.0hf); + return float16_t(ret[idx & 1]); +} +#endif + +#if defined(DATA_A_IQ2_S) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_S { + block_iq2_s block; +}; + +float16_t dequantFuncIQ2_S(const in decodeBufIQ2_S bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + uint idx = coordInBlock[1]; + + const uint ib32 = (idx & 0xE0) >> 5; // 0..7 + const uint ib8 = (idx & 0xF8) >> 3; // 0..31 + const uint qhshift = 2 * (ib8 % 4); + + const uint scale = (bl.block.scales[ib32] >> ((idx & 0x10) >> 2)) & 0xf; + const uint qs = bl.block.qs[ib8]; + const uint qh = bl.block.qh[ib32]; + const uint sign = bl.block.qs[QUANT_K / 8 + ib8] >> (idx & 0x6); + + const float d = float(bl.block.d); + const float db = d * 0.25 * (0.5 + scale); + const ivec2 sign01 = 1 - (2 & ivec2(sign << 1, sign)); + uint g2 = iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(idx & 4) >> 2]; + g2 >>= (idx & 2) * 8; + const vec2 v = db * vec2(sign01) * vec2(unpack8(g2)); + return float16_t(v[idx & 1]); +} +#endif + +#if defined(DATA_A_IQ3_XXS) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_XXS { + block_iq3_xxs block; +}; + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_XXS_packed16 { + block_iq3_xxs_packed16 block; +}; + +float16_t dequantFuncIQ3_XXS(const in decodeBufIQ3_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + decodeBufIQ3_XXS_packed16 bl16 = decodeBufIQ3_XXS_packed16(bl); + uint idx = coordInBlock[1]; + + const uint iqs = (idx & 0xFC) >> 2; // 0..63 + const uint is = QUANT_K / 4 + ((idx & 0xE0) >> 3);// 8 values + + const float d = float(bl.block.d); + const uint qs = bl.block.qs[iqs]; + const uint signs = pack32(u16vec2( + bl16.block.qs[is/2+0], + bl16.block.qs[is/2+1] + )); + const float db = d * 0.5 * (0.5 + (signs >> 28)); + const uint32_t sign7 = bitfieldExtract(signs, 7 * (int(iqs / 2) % 4), 7); + const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (idx & 0x6); + const ivec2 sign01 = ivec2(1 - (2 & ivec2(sign << 1, sign))); + const uint grid = iq3xxs_grid[qs] >> (16 * ((idx & 2) >> 1)); + const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); + return float16_t(v[idx & 1]); +} +#endif + +#if defined(DATA_A_IQ3_S) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_S { + block_iq3_s block; +}; + +float16_t dequantFuncIQ3_S(const in decodeBufIQ3_S bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + uint idx = coordInBlock[1]; + + const uint iqs = (idx & 0xFC) >> 2; // 0..63 + const uint iqh = (idx & 0xE0) >> 5; + + const float d = float(bl.block.d); + const uint qs = bl.block.qs[iqs]; + const uint qh = bl.block.qh[iqh]; + const int8_t sign = int8_t(bl.block.signs[iqs / 2] >> (idx & 0x6)); + const uint scale = bl.block.scales[iqs / 16]; + const ivec2 sign01 = ivec2(1 - (2 & ivec2(sign << 1, sign))); + const float db = d * (1 + 2 * ((scale >> (4 * (iqh & 1))) & 0xf)); + const uint32_t grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)] >> ((idx & 2) << 3); + const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); + + return float16_t(v[idx & 1]); +} +#endif + +#if defined(DATA_A_IQ4_XS) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_XS { + block_iq4_xs block; +}; + +float16_t dequantFuncIQ4_XS(const in decodeBufIQ4_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + + const uint ib32 = (idx & 0xE0) >> 5; // 0..7 + + const uint sl = (bl.block.scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF; + const uint sh = ((bl.block.scales_h) >> (2 * ib32)) & 3; + const uint qshift = (idx & 16) >> 2; + const uint q = (bl.block.qs[16 * ib32 + (idx % 16)] >> qshift) & 0xF; + + float16_t ret = d * float16_t(int(sl | (sh << 4)) - 32) * float16_t(kvalues_iq4nl[q]); + return ret; +} +#endif + +#if defined(DATA_A_IQ4_NL) +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_NL { + block_iq4_nl block; +}; + +float16_t dequantFuncIQ4_NL(const in decodeBufIQ4_NL bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const float16_t d = bl.block.d; + const uint idx = coordInBlock[1]; + const uint iqs = idx & 0xF; + const uint shift = (idx & 0x10) >> 2; + uint32_t qs = bl.block.qs[iqs]; + qs >>= shift; + qs &= 0xF; + float16_t ret = float16_t(kvalues_iq4nl[qs]) * d; + return ret; +} +#endif + +#if defined(DATA_A_Q4_0) +#define dequantFuncA dequantFuncQ4_0 +#elif defined(DATA_A_Q4_1) +#define dequantFuncA dequantFuncQ4_1 +#elif defined(DATA_A_Q5_0) +#define dequantFuncA dequantFuncQ5_0 +#elif defined(DATA_A_Q5_1) +#define dequantFuncA dequantFuncQ5_1 +#elif defined(DATA_A_Q8_0) +#define dequantFuncA dequantFuncQ8_0 +#elif defined(DATA_A_Q2_K) +#define dequantFuncA dequantFuncQ2_K +#elif defined(DATA_A_Q3_K) +#define dequantFuncA dequantFuncQ3_K +#elif defined(DATA_A_Q4_K) +#define dequantFuncA dequantFuncQ4_K +#define fetch_scales fetch_scalesQ4_K +#define store_scales store_scalesQ4_K +#elif defined(DATA_A_Q5_K) +#define dequantFuncA dequantFuncQ5_K +#define fetch_scales fetch_scalesQ5_K +#define store_scales store_scalesQ4_K +#elif defined(DATA_A_Q6_K) +#define dequantFuncA dequantFuncQ6_K +#elif defined(DATA_A_IQ1_S) +#define dequantFuncA dequantFuncIQ1_S +#elif defined(DATA_A_IQ1_M) +#define dequantFuncA dequantFuncIQ1_M +#elif defined(DATA_A_IQ2_XXS) +#define dequantFuncA dequantFuncIQ2_XXS +#elif defined(DATA_A_IQ2_XS) +#define dequantFuncA dequantFuncIQ2_XS +#elif defined(DATA_A_IQ2_S) +#define dequantFuncA dequantFuncIQ2_S +#elif defined(DATA_A_IQ3_XXS) +#define dequantFuncA dequantFuncIQ3_XXS +#elif defined(DATA_A_IQ3_S) +#define dequantFuncA dequantFuncIQ3_S +#elif defined(DATA_A_IQ4_XS) +#define dequantFuncA dequantFuncIQ4_XS +#elif defined(DATA_A_IQ4_NL) +#define dequantFuncA dequantFuncIQ4_NL +#endif diff --git a/ggml/src/vulkan-shaders/dequant_iq1_m.comp b/ggml/src/vulkan-shaders/dequant_iq1_m.comp new file mode 100644 index 00000000..b604c188 --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq1_m.comp @@ -0,0 +1,42 @@ +#version 450 + +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq1_m data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 subblock (32 values with 2 scales) + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint ib32 = gl_LocalInvocationID.x % 8; + const uint ib64 = ib32 / 2; + const uint b_idx = 256 * ib + 32 * ib32; + + const uint16_t[4] scales = data_a[ib].scales; + const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12; + const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x); + + const uint sc = data_a[ib].scales[ib64]; + [[unroll]] for (int l = 0; l < 4; ++l) { + const uint ib16 = 2 * ib32 + l / 2; + const float dl = d * (2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1); + const uint qh = data_a[ib].qh[ib16] >> (4 * (l & 1)); + const uint qs = data_a[ib].qs[4 * ib32 + l]; + const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA; + const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]); + [[unroll]] for (int j = 0; j < 8; ++j) { + data_b[b_idx + 8 * l + j] = D_TYPE(dl * (bitfieldExtract(grid, 2*j, 2) + delta)); + } + } +} diff --git a/ggml/src/vulkan-shaders/dequant_iq1_s.comp b/ggml/src/vulkan-shaders/dequant_iq1_s.comp new file mode 100644 index 00000000..fd1e4e30 --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq1_s.comp @@ -0,0 +1,35 @@ +#version 450 + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq1_s data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 subblock (32 values with 2 scales) + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint ib32 = gl_LocalInvocationID.x % 8; + const uint b_idx = 256 * ib + 32 * ib32; + + uint qh = data_a[ib].qh[ib32]; + const float d = float(data_a[ib].d); + const float dl = d * float(2 * bitfieldExtract(qh, 12, 3) + 1); + const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; + [[unroll]] for (uint l = 0; l < 4; ++l) { + const uint qs = data_a[ib].qs[4 * ib32 + l]; + const uint hi = bitfieldExtract(qh, 3 * int(l), 3); + const int16_t grid = int16_t(iq1s_grid[qs | (hi << 8)]); + [[unroll]] for (int j = 0; j < 8; ++j) { + data_b[b_idx + 8 * l + j] = D_TYPE(dl * (bitfieldExtract(grid, 2*j, 2) + delta)); + } + } +} diff --git a/ggml/src/vulkan-shaders/dequant_iq2_s.comp b/ggml/src/vulkan-shaders/dequant_iq2_s.comp new file mode 100644 index 00000000..48f6b65b --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq2_s.comp @@ -0,0 +1,44 @@ +#version 450 + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq2_s data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 subblock (32 values with 2 scales) + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint ib32 = gl_LocalInvocationID.x % 8; + const uint b_idx = 256 * ib + 32 * ib32; + + const float d = float(data_a[ib].d); + const vec2 scale = vec2(data_a[ib].scales[ib32] & 0xf, data_a[ib].scales[ib32] >> 4); + const vec2 db = d * (0.5 + scale) * 0.25; + + uint qh = data_a[ib].qh[ib32]; + [[unroll]] for (uint l = 0; l < 4; ++l) { + uint qs = data_a[ib].qs[4 * ib32 + l]; + const uint8_t sign = data_a[ib].qs[QUANT_K / 8 + 4 * ib32 + l]; + qs |= (qh << (8 - 2 * l)) & 0x300; + const uvec2 grid = iq2s_grid[qs & 511]; + const u8vec4 grid0 = unpack8(grid.x); + const u8vec4 grid1 = unpack8(grid.y); + data_b[b_idx + 8 * l + 0] = D_TYPE(db[l/2] * grid0.x * ((sign & 1) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 1] = D_TYPE(db[l/2] * grid0.y * ((sign & 2) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 2] = D_TYPE(db[l/2] * grid0.z * ((sign & 4) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 3] = D_TYPE(db[l/2] * grid0.w * ((sign & 8) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 4] = D_TYPE(db[l/2] * grid1.x * ((sign & 16) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 5] = D_TYPE(db[l/2] * grid1.y * ((sign & 32) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 6] = D_TYPE(db[l/2] * grid1.z * ((sign & 64) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 7] = D_TYPE(db[l/2] * grid1.w * ((sign & 128) != 0 ? -1.0 : 1.0)); + } +} diff --git a/ggml/src/vulkan-shaders/dequant_iq2_xs.comp b/ggml/src/vulkan-shaders/dequant_iq2_xs.comp new file mode 100644 index 00000000..a08331c4 --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq2_xs.comp @@ -0,0 +1,43 @@ +#version 450 + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq2_xs data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 subblock (32 values with 2 scales) + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint ib32 = gl_LocalInvocationID.x % 8; + const uint b_idx = 256 * ib + 32 * ib32; + + const float d = float(data_a[ib].d); + const vec2 scale = vec2(data_a[ib].scales[ib32] & 0xf, data_a[ib].scales[ib32] >> 4); + const vec2 db = d * (0.5 + scale) * 0.25; + + [[unroll]] for (uint l = 0; l < 4; ++l) { + uint16_t qs = data_a[ib].qs[4 * ib32 + l]; + const uint sign7 = qs >> 9; + const uint sign8 = sign7 | (bitCount(sign7) << 7); // parity bit + const uvec2 grid = iq2xs_grid[qs & 511]; + const u8vec4 grid0 = unpack8(grid.x); + const u8vec4 grid1 = unpack8(grid.y); + data_b[b_idx + 8 * l + 0] = D_TYPE(db[l/2] * grid0.x * ((sign8 & 1) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 1] = D_TYPE(db[l/2] * grid0.y * ((sign8 & 2) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 2] = D_TYPE(db[l/2] * grid0.z * ((sign8 & 4) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 3] = D_TYPE(db[l/2] * grid0.w * ((sign8 & 8) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 4] = D_TYPE(db[l/2] * grid1.x * ((sign8 & 16) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 5] = D_TYPE(db[l/2] * grid1.y * ((sign8 & 32) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 6] = D_TYPE(db[l/2] * grid1.z * ((sign8 & 64) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 7] = D_TYPE(db[l/2] * grid1.w * ((sign8 & 128) != 0 ? -1.0 : 1.0)); + } +} diff --git a/ggml/src/vulkan-shaders/dequant_iq2_xxs.comp b/ggml/src/vulkan-shaders/dequant_iq2_xxs.comp new file mode 100644 index 00000000..e370690b --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq2_xxs.comp @@ -0,0 +1,48 @@ +#version 450 + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq2_xxs data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 scale block (32 values) + // Each block is described by 4 lattice indices, 4x7 sign bits and 4 scale bits + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint is = gl_LocalInvocationID.x % 8; + const uint b_idx = 256 * ib + 32 * is; + + const float d = float(data_a[ib].d); + uint signscale = pack32(u8vec4( + data_a[ib].qs[8*is + 4], + data_a[ib].qs[8*is + 5], + data_a[ib].qs[8*is + 6], + data_a[ib].qs[8*is + 7] + )); + const float db = d * (0.5 + (signscale >> 28)) * 0.25; + + [[unroll]] for (uint l = 0; l < 4; ++l) { + const uint sign7 = bitfieldExtract(signscale, 7 * int(l), 7); + const uint sign8 = sign7 | (bitCount(sign7) << 7); // parity bit + const uvec2 grid = iq2xxs_grid[data_a[ib].qs[8 * is + l]]; + const u8vec4 grid0 = unpack8(grid.x); + const u8vec4 grid1 = unpack8(grid.y); + data_b[b_idx + 8 * l + 0] = D_TYPE(db * grid0.x * ((sign8 & 1) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 1] = D_TYPE(db * grid0.y * ((sign8 & 2) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 2] = D_TYPE(db * grid0.z * ((sign8 & 4) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 3] = D_TYPE(db * grid0.w * ((sign8 & 8) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 4] = D_TYPE(db * grid1.x * ((sign8 & 16) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 5] = D_TYPE(db * grid1.y * ((sign8 & 32) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 6] = D_TYPE(db * grid1.z * ((sign8 & 64) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 7] = D_TYPE(db * grid1.w * ((sign8 & 128) != 0 ? -1.0 : 1.0)); + } +} diff --git a/ggml/src/vulkan-shaders/dequant_iq3_s.comp b/ggml/src/vulkan-shaders/dequant_iq3_s.comp new file mode 100644 index 00000000..c3f4bca5 --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq3_s.comp @@ -0,0 +1,39 @@ +#version 450 + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq3_s data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 scale nibble. + // Each block contains 4 scale bytes (8 scales) for 256 output values. + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint is = gl_LocalInvocationID.x % 8; + const uint b_idx = 256 * ib + 32 * is; + + const float d = float(data_a[ib].d); + const float db = d * (1 + 2 * ((data_a[ib].scales[is] >> (4 * (is % 2))) & 0xf)); + + // We must produce 32 values using 4 sign bytes, 1 qh byte, 8 qs bytes. + uint qh = data_a[ib].qh[is]; + [[unroll]] for (uint l = 0; l < 8; ++l) { + uint qs = data_a[ib].qs[8 * is + l]; + uint gidx = qs | ((qh << (8 - l)) & 256); + uint8_t signs = data_a[ib].signs[8 * is + l / 2] >> (4 * (l & 1)); + u8vec4 grid = unpack8(iq3s_grid[gidx]); + data_b[b_idx + 4 * l + 0] = D_TYPE(db * grid.x * ((signs & 1) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 4 * l + 1] = D_TYPE(db * grid.y * ((signs & 2) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 4 * l + 2] = D_TYPE(db * grid.z * ((signs & 4) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 4 * l + 3] = D_TYPE(db * grid.w * ((signs & 8) != 0 ? -1.0 : 1.0)); + } +} diff --git a/ggml/src/vulkan-shaders/dequant_iq3_xxs.comp b/ggml/src/vulkan-shaders/dequant_iq3_xxs.comp new file mode 100644 index 00000000..a92b8296 --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq3_xxs.comp @@ -0,0 +1,49 @@ +#version 450 + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq3_xxs data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 scale block (32 values) + // 8 threads handle 1 superblock + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint is = gl_LocalInvocationID.x % 8; + const uint b_idx = 256 * ib + 32 * is; + const uint s_idx = QUANT_K / 4 + 4 * is; + + const float d = float(data_a[ib].d); + uint signscale = pack32(u8vec4( + data_a[ib].qs[s_idx + 0], + data_a[ib].qs[s_idx + 1], + data_a[ib].qs[s_idx + 2], + data_a[ib].qs[s_idx + 3] + )); + const float db = d * (0.5 + (signscale >> 28)) * 0.5; + + [[unroll]] for (uint l = 0; l < 4; ++l) { + const uint sign7 = bitfieldExtract(signscale, 7 * int(l), 7); + // Restore parity bit. + const uint sign8 = sign7 | (bitCount(sign7) << 7); + const u8vec4 grid0 = unpack8(iq3xxs_grid[data_a[ib].qs[8 * is + 2 * l]]); + const u8vec4 grid1 = unpack8(iq3xxs_grid[data_a[ib].qs[8 * is + 2 * l + 1]]); + data_b[b_idx + 8 * l + 0] = D_TYPE(db * grid0.x * ((sign8 & 1) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 1] = D_TYPE(db * grid0.y * ((sign8 & 2) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 2] = D_TYPE(db * grid0.z * ((sign8 & 4) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 3] = D_TYPE(db * grid0.w * ((sign8 & 8) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 4] = D_TYPE(db * grid1.x * ((sign8 & 16) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 5] = D_TYPE(db * grid1.y * ((sign8 & 32) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 6] = D_TYPE(db * grid1.z * ((sign8 & 64) != 0 ? -1.0 : 1.0)); + data_b[b_idx + 8 * l + 7] = D_TYPE(db * grid1.w * ((sign8 & 128) != 0 ? -1.0 : 1.0)); + } +} diff --git a/ggml/src/vulkan-shaders/dequant_iq4_nl.comp b/ggml/src/vulkan-shaders/dequant_iq4_nl.comp index 34ef3da3..46d9ad15 100644 --- a/ggml/src/vulkan-shaders/dequant_iq4_nl.comp +++ b/ggml/src/vulkan-shaders/dequant_iq4_nl.comp @@ -10,6 +10,8 @@ layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; void main() { const uint i = gl_WorkGroupID.x * 4 + gl_LocalInvocationID.x / 64; + init_iq_shmem(gl_WorkGroupSize); + const uint tid = gl_LocalInvocationID.x % 64; const uint il = tid/32; const uint ir = tid%32; diff --git a/ggml/src/vulkan-shaders/dequant_iq4_xs.comp b/ggml/src/vulkan-shaders/dequant_iq4_xs.comp new file mode 100644 index 00000000..f930852a --- /dev/null +++ b/ggml/src/vulkan-shaders/dequant_iq4_xs.comp @@ -0,0 +1,34 @@ +#version 450 + +#include "dequant_head.comp" + +layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {block_iq4_xs data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; + +void main() { + // Each thread handles 1 subblock (1 scale and 32 quantized values) + const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8; + + init_iq_shmem(gl_WorkGroupSize); + + if (ib >= p.nel / 256) { + return; + } + + const uint ib32 = gl_LocalInvocationID.x % 8; + + const float d = float(data_a[ib].d); + // Scales are 6 bits + const uint scale = ((data_a[ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF) + | (((data_a[ib].scales_h >> (2 * ib32)) & 3) << 4); + const float dl = d * (int(scale) - 32); + + const uint b_idx = 256 * ib + 32 * ib32; + const uint q_idx = 16 * ib32; + [[unroll]] for (uint l = 0; l < 16; ++l) { + data_b[b_idx + l + 0] = D_TYPE(dl * kvalues_iq4nl[data_a[ib].qs[q_idx + l] & 0xF]); + data_b[b_idx + l + 16] = D_TYPE(dl * kvalues_iq4nl[data_a[ib].qs[q_idx + l] >> 4]); + } +} diff --git a/ggml/src/vulkan-shaders/dequant_q4_k.comp b/ggml/src/vulkan-shaders/dequant_q4_k.comp index 92acb754..987f113a 100644 --- a/ggml/src/vulkan-shaders/dequant_q4_k.comp +++ b/ggml/src/vulkan-shaders/dequant_q4_k.comp @@ -9,8 +9,8 @@ layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; void main() { [[unroll]] for (uint wgy = 0; wgy < 256; wgy++) { - const uint i = gl_WorkGroupID.x * 256 + wgy; - if (i >= p.M * p.K / QUANT_K) { + const uint ib = gl_WorkGroupID.x * 256 + wgy; + if (ib >= p.M * p.K / QUANT_K) { return; } @@ -20,37 +20,49 @@ void main() { const uint is = 2 * il; const uint n = 4; - const FLOAT_TYPE dall = FLOAT_TYPE(data_a[i].d.x); - const FLOAT_TYPE dmin = FLOAT_TYPE(data_a[i].d.y); + const FLOAT_TYPE dall = FLOAT_TYPE(data_a[ib].d.x); + const FLOAT_TYPE dmin = FLOAT_TYPE(data_a[ib].d.y); - const uint y_idx = i * QUANT_K + 64 * il + n * ir; + const uint y_idx = ib * QUANT_K + 64 * il + n * ir; const uint qs_idx = 32*il + n * ir; - uint8_t sc; - uint8_t m; - if (is < 4) { - sc = uint8_t(data_a[i].scales[is] & 63); - m = uint8_t(data_a[i].scales[is + 4] & 63); - } else { - sc = uint8_t((data_a[i].scales[is + 4] & 0xF) | ((data_a[i].scales[is - 4] >> 6) << 4)); - m = uint8_t((data_a[i].scales[is + 4] >> 4) | ((data_a[i].scales[is ] >> 6) << 4)); - } - const FLOAT_TYPE d1 = dall * sc; - const FLOAT_TYPE m1 = dmin * m; + uint scidx0 = (is < 4) ? is : (is + 4); + uint scidx1 = (is < 4) ? is : (is - 4); + uint scidxmask1 = (is < 4) ? 0x30 : 0xC0; + uint scidxshift1 = (is < 4) ? 0 : 2; + uint mbidx0 = is + 4; + uint mbidx1 = (is < 4) ? is + 4 : is; + uint mbidxmask0 = (is < 4) ? 0xF : 0xF0; + uint mbidxshift0 = (is < 4) ? 0 : 4; + uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0; + uint mbidxshift1 = (is < 4) ? 0 : 2; + + uint8_t sc = uint8_t((data_a[ib].scales[scidx0] & 0xF) | ((data_a[ib].scales[scidx1] & scidxmask1) >> scidxshift1)); + uint8_t mbyte = uint8_t((data_a[ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0 | ((data_a[ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1)); + + const FLOAT_TYPE d1 = dall * sc; + const FLOAT_TYPE m1 = dmin * mbyte; + + scidx0 = (is < 4) ? is + 1 : (is + 5); + scidx1 = (is < 4) ? is + 1 : (is - 3); + scidxmask1 = (is < 4) ? 0x30 : 0xC0; + scidxshift1 = (is < 4) ? 0 : 2; + mbidx0 = is + 5; + mbidx1 = (is < 4) ? is + 5 : is + 1; + mbidxmask0 = (is < 4) ? 0xF : 0xF0; + mbidxshift0 = (is < 4) ? 0 : 4; + mbidxmask1 = (is < 4) ? 0x30 : 0xC0; + mbidxshift1 = (is < 4) ? 0 : 2; + + sc = uint8_t((data_a[ib].scales[scidx0] & 0xF) | ((data_a[ib].scales[scidx1] & scidxmask1) >> scidxshift1)); + mbyte = uint8_t((data_a[ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0 | ((data_a[ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1)); - if (is < 4) { - sc = uint8_t(data_a[i].scales[is + 1] & 63); - m = uint8_t(data_a[i].scales[is + 5] & 63); - } else { - sc = uint8_t((data_a[i].scales[is + 5] & 0xF) | ((data_a[i].scales[is - 3] >> 6) << 4)); - m = uint8_t((data_a[i].scales[is + 5] >> 4) | ((data_a[i].scales[is + 1] >> 6) << 4)); - } const FLOAT_TYPE d2 = dall * sc; - const FLOAT_TYPE m2 = dmin * m; + const FLOAT_TYPE m2 = dmin * mbyte; [[unroll]] for (uint l = 0; l < n; ++l) { - data_b[y_idx + l ] = D_TYPE(d1 * FLOAT_TYPE(data_a[i].qs[qs_idx + l] & 0xF) - m1); - data_b[y_idx + l + 32] = D_TYPE(d2 * FLOAT_TYPE(data_a[i].qs[qs_idx + l] >> 4) - m2); + data_b[y_idx + l ] = D_TYPE(d1 * FLOAT_TYPE(data_a[ib].qs[qs_idx + l] & 0xF) - m1); + data_b[y_idx + l + 32] = D_TYPE(d2 * FLOAT_TYPE(data_a[ib].qs[qs_idx + l] >> 4) - m2); } } } diff --git a/ggml/src/vulkan-shaders/dequant_q5_k.comp b/ggml/src/vulkan-shaders/dequant_q5_k.comp index f314a76d..6db5403b 100644 --- a/ggml/src/vulkan-shaders/dequant_q5_k.comp +++ b/ggml/src/vulkan-shaders/dequant_q5_k.comp @@ -9,8 +9,8 @@ layout (binding = 1) writeonly buffer D {D_TYPE data_b[];}; void main() { [[unroll]] for (uint wgy = 0; wgy < 256; wgy++) { - const uint i = gl_WorkGroupID.x * 256 + wgy; - if (i >= p.M * p.K / QUANT_K) { + const uint ib = gl_WorkGroupID.x * 256 + wgy; + if (ib >= p.M * p.K / QUANT_K) { return; } @@ -19,40 +19,52 @@ void main() { const uint ir = tid % 16; const uint is = 2 * il; - const FLOAT_TYPE dall = FLOAT_TYPE(data_a[i].d.x); - const FLOAT_TYPE dmin = FLOAT_TYPE(data_a[i].d.y); + const FLOAT_TYPE dall = FLOAT_TYPE(data_a[ib].d.x); + const FLOAT_TYPE dmin = FLOAT_TYPE(data_a[ib].d.y); - const uint y_idx = i * QUANT_K + 64 * il + 2 * ir; + const uint y_idx = ib * QUANT_K + 64 * il + 2 * ir; const uint qs_idx = 32*il + 2 * ir; const uint qh_idx = 2 * ir; - uint8_t sc; - uint8_t m; - if (is < 4) { - sc = uint8_t(data_a[i].scales[is] & 63); - m = uint8_t(data_a[i].scales[is + 4] & 63); - } else { - sc = uint8_t((data_a[i].scales[is + 4] & 0xF) | ((data_a[i].scales[is - 4] >> 6) << 4)); - m = uint8_t((data_a[i].scales[is + 4] >> 4) | ((data_a[i].scales[is ] >> 6) << 4)); - } - const FLOAT_TYPE d1 = dall * sc; - const FLOAT_TYPE m1 = dmin * m; + uint scidx0 = (is < 4) ? is : (is + 4); + uint scidx1 = (is < 4) ? is : (is - 4); + uint scidxmask1 = (is < 4) ? 0x30 : 0xC0; + uint scidxshift1 = (is < 4) ? 0 : 2; + uint mbidx0 = is + 4; + uint mbidx1 = (is < 4) ? is + 4 : is; + uint mbidxmask0 = (is < 4) ? 0xF : 0xF0; + uint mbidxshift0 = (is < 4) ? 0 : 4; + uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0; + uint mbidxshift1 = (is < 4) ? 0 : 2; + + uint8_t sc = uint8_t((data_a[ib].scales[scidx0] & 0xF) | ((data_a[ib].scales[scidx1] & scidxmask1) >> scidxshift1)); + uint8_t mbyte = uint8_t((data_a[ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0 | ((data_a[ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1)); + + const FLOAT_TYPE d1 = dall * sc; + const FLOAT_TYPE m1 = dmin * mbyte; + + scidx0 = (is < 4) ? is + 1 : (is + 5); + scidx1 = (is < 4) ? is + 1 : (is - 3); + scidxmask1 = (is < 4) ? 0x30 : 0xC0; + scidxshift1 = (is < 4) ? 0 : 2; + mbidx0 = is + 5; + mbidx1 = (is < 4) ? is + 5 : is + 1; + mbidxmask0 = (is < 4) ? 0xF : 0xF0; + mbidxshift0 = (is < 4) ? 0 : 4; + mbidxmask1 = (is < 4) ? 0x30 : 0xC0; + mbidxshift1 = (is < 4) ? 0 : 2; + + sc = uint8_t((data_a[ib].scales[scidx0] & 0xF) | ((data_a[ib].scales[scidx1] & scidxmask1) >> scidxshift1)); + mbyte = uint8_t((data_a[ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0 | ((data_a[ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1)); - if (is < 4) { - sc = uint8_t(data_a[i].scales[is + 1] & 63); - m = uint8_t(data_a[i].scales[is + 5] & 63); - } else { - sc = uint8_t((data_a[i].scales[is + 5] & 0xF) | ((data_a[i].scales[is - 3] >> 6) << 4)); - m = uint8_t((data_a[i].scales[is + 5] >> 4) | ((data_a[i].scales[is + 1] >> 6) << 4)); - } const FLOAT_TYPE d2 = dall * sc; - const FLOAT_TYPE m2 = dmin * m; + const FLOAT_TYPE m2 = dmin * mbyte; const uint8_t hm1 = uint8_t(1 << (2 * il )); const uint8_t hm2 = uint8_t(1 << (2 * il + 1)); - data_b[y_idx ] = D_TYPE(d1 * FLOAT_TYPE((data_a[i].qs[qs_idx ] & 0xF) + (((data_a[i].qh[qh_idx ] & hm1) != 0) ? 16 : 0)) - m1); - data_b[y_idx + 1] = D_TYPE(d1 * FLOAT_TYPE((data_a[i].qs[qs_idx + 1] & 0xF) + (((data_a[i].qh[qh_idx + 1] & hm1) != 0) ? 16 : 0)) - m1); - data_b[y_idx + 32] = D_TYPE(d2 * FLOAT_TYPE((data_a[i].qs[qs_idx ] >> 4) + (((data_a[i].qh[qh_idx ] & hm2) != 0) ? 16 : 0)) - m2); - data_b[y_idx + 33] = D_TYPE(d2 * FLOAT_TYPE((data_a[i].qs[qs_idx + 1] >> 4) + (((data_a[i].qh[qh_idx + 1] & hm2) != 0) ? 16 : 0)) - m2); + data_b[y_idx ] = D_TYPE(d1 * FLOAT_TYPE((data_a[ib].qs[qs_idx ] & 0xF) + (((data_a[ib].qh[qh_idx ] & hm1) != 0) ? 16 : 0)) - m1); + data_b[y_idx + 1] = D_TYPE(d1 * FLOAT_TYPE((data_a[ib].qs[qs_idx + 1] & 0xF) + (((data_a[ib].qh[qh_idx + 1] & hm1) != 0) ? 16 : 0)) - m1); + data_b[y_idx + 32] = D_TYPE(d2 * FLOAT_TYPE((data_a[ib].qs[qs_idx ] >> 4) + (((data_a[ib].qh[qh_idx ] & hm2) != 0) ? 16 : 0)) - m2); + data_b[y_idx + 33] = D_TYPE(d2 * FLOAT_TYPE((data_a[ib].qs[qs_idx + 1] >> 4) + (((data_a[ib].qh[qh_idx + 1] & hm2) != 0) ? 16 : 0)) - m2); } } diff --git a/ggml/src/vulkan-shaders/diag_mask_inf.comp b/ggml/src/vulkan-shaders/diag_mask_inf.comp index 4e68742b..26d8bc22 100644 --- a/ggml/src/vulkan-shaders/diag_mask_inf.comp +++ b/ggml/src/vulkan-shaders/diag_mask_inf.comp @@ -12,7 +12,7 @@ layout (push_constant) uniform parameter #include "types.comp" -layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x = 1, local_size_y = 512, local_size_z = 1) in; layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; diff --git a/ggml/src/vulkan-shaders/div.comp b/ggml/src/vulkan-shaders/div.comp index 8cfce58b..9fb69c6c 100644 --- a/ggml/src/vulkan-shaders/div.comp +++ b/ggml/src/vulkan-shaders/div.comp @@ -3,12 +3,25 @@ #include "types.comp" #include "generic_binary_head.comp" +const uint num_threads = 256; + +layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in; + void main() { - const uint idx = get_idx(); + uint idx = get_idx(); - if (idx >= p.ne) { - return; + // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation + const uint num_iter = 2; + + [[unroll]] for (uint i = 0; i < num_iter; ++i) { + if (idx >= p.ne) { + continue; + } + uint i00, i01, i02, i03; + get_indices(idx, i00, i01, i02, i03); + + data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) / FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)])); + + idx += num_threads; } - - data_d[p.d_offset + dst_idx(idx)] = D_TYPE(FLOAT_TYPE(data_a[src0_idx(idx)]) / FLOAT_TYPE(data_b[src1_idx(idx)])); } diff --git a/ggml/src/vulkan-shaders/flash_attn.comp b/ggml/src/vulkan-shaders/flash_attn.comp new file mode 100644 index 00000000..ce230a8f --- /dev/null +++ b/ggml/src/vulkan-shaders/flash_attn.comp @@ -0,0 +1,337 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable +#extension GL_EXT_shader_16bit_storage : require + +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#extension GL_KHR_shader_subgroup_shuffle : enable + +#include "types.comp" +#include "flash_attn_base.comp" + +const uint32_t D_per_thread = D / D_split; + +const uint32_t cols_per_iter = WorkGroupSize / D_split; +const uint32_t cols_per_thread = Bc / cols_per_iter; + + +layout (binding = 0) readonly buffer Q {float data_q[];}; +layout (binding = 0) readonly buffer QV4 {vec4 data_qv4[];}; +layout (binding = 1) readonly buffer K {float16_t data_k[];}; +layout (binding = 1) readonly buffer KV4 {f16vec4 data_kv4[];}; +layout (binding = 2) readonly buffer V {float16_t data_v[];}; +layout (binding = 2) readonly buffer VV4 {f16vec4 data_vv4[];}; +layout (binding = 3) readonly buffer M {float16_t data_m[];}; + +// Store the output when doing grouped query attention. +// Rows index by Q's dimension 2, and the first N rows are valid. +D_TYPE perElemOpGqaStore(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t o_offset, const in uint32_t iq2, const in uint32_t N) +{ + uint32_t offset = (iq2 + r) * D + c; + data_o[o_offset + offset] = D_TYPE(elem); + return elem; +} + +shared FLOAT_TYPE tmpsh[WorkGroupSize]; +shared vec4 tmpshv4[WorkGroupSize]; + +shared float masksh[Bc][Br]; +shared vec4 Qf[Br][D / 4]; + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + + init_indices(); + + const uint32_t tid = gl_LocalInvocationIndex; + const uint32_t d_tid = gl_LocalInvocationIndex % D_split; + const uint32_t col_tid = gl_LocalInvocationIndex / D_split; + + uint32_t q_offset = (iq2*p.nb02+iq3*p.nb03) / 4; + + [[unroll]] for (uint32_t idx = 0; idx < Br * D / 4; idx += gl_WorkGroupSize.x) { + uint32_t d = (idx + tid) % (D / 4); + uint32_t r = (idx + tid) / (D / 4); + if (r < Br && d < D / 4 && + i * Br + r < N) { + Qf[r][d] = vec4(data_qv4[q_offset / 4 + (i * Br + r) * q_stride / 4 + d]) * p.scale; + } + } + barrier(); + + vec4 Of[Br][D_per_thread / 4]; + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Of[r][d] = vec4(0.0); + } + } + + float Lf[Br], Mf[Br]; + + // Use -FLT_MAX/2 rather than -inf to reduce the possibility of NaNs, e.g. when computing Mold-M. + const float NEG_FLT_MAX_OVER_2 = uintBitsToFloat(0xFEFFFFFF); + + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Lf[r] = 0; + Mf[r] = NEG_FLT_MAX_OVER_2; + } + + float slope[Br]; + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + slope[r] = 1.0; + } + + // ALiBi + if (p.max_bias > 0.0f) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + slope[r] = perElemOpComputeSlope(r, col_tid, ACC_TYPE(0), iq2); + } + } + +#if BLOCK_SIZE > 1 + uint32_t k_offset = (ik2*p.nb12 + ik3*p.nb13) / BLOCK_BYTE_SIZE; + uint32_t v_offset = (iv2*p.nb22 + iv3*p.nb23) / BLOCK_BYTE_SIZE; +#else + uint32_t k_offset = (ik2*p.nb12 + ik3*p.nb13) / 2; + uint32_t v_offset = (iv2*p.nb22 + iv3*p.nb23) / 2; +#endif + + [[dont_unroll]] + for (uint32_t j = start_j; j < end_j; ++j) { + + float Sf[Br][cols_per_thread]; + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + Sf[r][c] = 0.0; + } + } + + + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { +#if BLOCK_SIZE > 1 + uint coord = (j * Bc + c * cols_per_iter + col_tid) * k_stride * BLOCK_SIZE + 4 * (d * D_split + d_tid); + uint ib = coord / BLOCK_SIZE; + uint iqs = (coord % BLOCK_SIZE); + vec4 K_Tf = dequantize4(ib, iqs, k_offset, BINDING_IDX_K); +#else + vec4 K_Tf = vec4(data_kv4[k_offset / 4 + (j * Bc + c * cols_per_iter + col_tid) * k_stride / 4 + d * D_split + d_tid]); +#endif + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Sf[r][c] += dot(Qf[r][d * D_split + d_tid], K_Tf); + } + } + } + + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + // Compute sum across the D_split + [[unroll]] for (uint s = D_split / 2; s > 0; s >>= 1) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Sf[r][c] += subgroupShuffleXor(Sf[r][c], s); + } + } + } + + if (p.logit_softcap != 0.0f) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + Sf[r][c] = p.logit_softcap * tanh(Sf[r][c]); + } + } + } + + if (p.mask != 0) { + + [[unroll]] for (uint32_t idx = 0; idx < Bc * Br; idx += gl_WorkGroupSize.x) { + uint32_t c = (idx + tid) % Bc; + uint32_t r = (idx + tid) / Bc; + if (idx + tid < Bc * Br) { + masksh[c][r] = float(data_m[(i * Br + r) * m_stride + (j * Bc + c)]); + } + } + barrier(); + + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + float mvf = masksh[c * cols_per_iter + col_tid][r]; + + Sf[r][c] += slope[r]*mvf; + } + } + barrier(); + } + + float rowmaxf[Br], Pf[Br][cols_per_thread], rowsumf[Br], eMf[Br], Moldf[Br]; + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + rowmaxf[r] = Sf[r][0]; + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + rowmaxf[r] = max(rowmaxf[r], Sf[r][c]); + } + Moldf[r] = Mf[r]; + + // M = max(rowmax, Mold) + // P = e^(S - M) + // eM = e^(Mold - M) + Mf[r] = max(rowmaxf[r], Moldf[r]); + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + Pf[r][c] = exp(Sf[r][c] - Mf[r]); + } + eMf[r] = exp(Moldf[r] - Mf[r]); + + // Compute sum across row of P + rowsumf[r] = 0.0; + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + rowsumf[r] += Pf[r][c]; + } + + Lf[r] = eMf[r]*Lf[r] + rowsumf[r]; + } + + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Of[r][d] = eMf[r] * Of[r][d]; + } + } + + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { +#if BLOCK_SIZE > 1 + uint coord = (j * Bc + c * cols_per_iter + col_tid) * v_stride * BLOCK_SIZE + 4 * (d * D_split + d_tid); + uint ib = coord / BLOCK_SIZE; + uint iqs = (coord % BLOCK_SIZE); + vec4 Vf = dequantize4(ib, iqs, v_offset, BINDING_IDX_V); +#else + vec4 Vf = vec4(data_vv4[v_offset / 4 + (j * Bc + c * cols_per_iter + col_tid) * v_stride / 4 + d * D_split + d_tid]); +#endif + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Of[r][d] += Pf[r][c] * Vf; + } + } + } + + barrier(); + } + + // reduce across threads + + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + float rowmaxf, eMf; + + tmpsh[tid] = Mf[r]; + // Compute max across the row + barrier(); + [[unroll]] for (int s = int(gl_WorkGroupSize.x) / 2; s >= D_split; s >>= 1) { + if (tid < s) { + tmpsh[tid] = max(tmpsh[tid], tmpsh[tid + s]); + } + barrier(); + } + rowmaxf = tmpsh[d_tid]; + barrier(); + + float Moldf = Mf[r]; + + // M = max(rowmax, Mold) + // eM = e^(Mold - M) + Mf[r] = max(rowmaxf, Moldf); + eMf = exp(Moldf - Mf[r]); + + Lf[r] = eMf*Lf[r]; + + tmpsh[tid] = Lf[r]; + + // Compute sum across the row + barrier(); + [[unroll]] for (int s = int(gl_WorkGroupSize.x) / 2; s >= D_split; s >>= 1) { + if (tid < s) { + tmpsh[tid] = tmpsh[tid] + tmpsh[tid + s]; + } + barrier(); + } + Lf[r] = tmpsh[d_tid]; + barrier(); + + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + + Of[r][d] = eMf * Of[r][d]; + tmpshv4[tid] = Of[r][d]; + + barrier(); + [[unroll]] for (int s = int(gl_WorkGroupSize.x) / 2; s >= D_split; s >>= 1) { + if (tid < s) { + Of[r][d] += tmpshv4[tid + s]; + tmpshv4[tid] = Of[r][d]; + } + barrier(); + } + Of[r][d] = tmpshv4[d_tid]; + barrier(); + } + } + + + // If there is split_k, then the split_k resolve shader does the final + // division by L. Store the intermediate O value and per-row m and L values. + if (p.k_num > 1) { + uint32_t o_offset = D * p.ne1 * split_k_index; + + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + if (r < N) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { + perElemOpGqaStore(r, 4*(d * D_split + d_tid) + comp, Of[r][d][comp], o_offset, iq2, N); + } + } + } + } + + o_offset = D * p.ne1 * p.k_num + p.ne1 * split_k_index * 2; + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + if (r < N) { + perElemOpStoreCol0(r, 0u, ACC_TYPE(Lf[r]), o_offset, iq2, N); + perElemOpStoreCol0(r, 0u, ACC_TYPE(Mf[r]), o_offset + p.ne1, iq2, N); + } + } + + return; + } + + float Lfrcp[Br]; + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Lfrcp[r] = 1.0 / Lf[r]; + } + + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + Of[r][d] *= Lfrcp[r]; + } + } + + uint32_t o_offset = iq3*p.ne2*p.ne1; + + if (p.gqa_ratio > 1) { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + if (r < N) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { + perElemOpGqaStore(r, 4*(d * D_split + d_tid) + comp, Of[r][d][comp], o_offset, iq2, N); + } + } + } + } + } else { + [[unroll]] for (uint32_t r = 0; r < Br; ++r) { + if (i * Br + r < N) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { + data_o[o_offset + iq2 * D + (i * Br + r) * p.ne1 * D + 4*(d * D_split + d_tid) + comp] = D_TYPE(Of[r][d][comp]); + } + } + } + } + } +} diff --git a/ggml/src/vulkan-shaders/flash_attn_base.comp b/ggml/src/vulkan-shaders/flash_attn_base.comp new file mode 100644 index 00000000..61d90e2d --- /dev/null +++ b/ggml/src/vulkan-shaders/flash_attn_base.comp @@ -0,0 +1,162 @@ + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +layout (constant_id = 0) const uint32_t WorkGroupSize = 128; +layout (constant_id = 1) const uint32_t Br = 1; +layout (constant_id = 2) const uint32_t Bc = 32; +layout (constant_id = 3) const uint32_t D = 32; +layout (constant_id = 4) const uint32_t Clamp = 0; +layout (constant_id = 5) const uint32_t D_split = 16; + + +layout (push_constant) uniform parameter { + uint32_t N; + uint32_t KV; + + uint32_t ne1; + uint32_t ne2; + uint32_t ne3; + + uint32_t neq2; + uint32_t neq3; + uint32_t nek2; + uint32_t nek3; + uint32_t nev2; + uint32_t nev3; + uint32_t nem1; + + uint32_t nb01; + uint32_t nb02; + uint32_t nb03; + uint32_t nb11; + uint32_t nb12; + uint32_t nb13; + uint32_t nb21; + uint32_t nb22; + uint32_t nb23; + uint32_t nb31; + + float scale; + float max_bias; + float logit_softcap; + + uint32_t mask; + uint32_t n_head_log2; + float m0; + float m1; + + uint32_t gqa_ratio; + uint32_t split_kv; + uint32_t k_num; +} p; + +layout (binding = 4) writeonly buffer O {D_TYPE data_o[];}; + +#if defined(A_TYPE_PACKED16) +#define BINDING_IDX_K 0 +#define BINDING_IDX_V 1 +layout (binding = 1) readonly buffer KV_PACKED16 {A_TYPE_PACKED16 data_packed16[];} kv_packed[2]; +#endif + +#if defined(DATA_A_Q4_0) +#define BLOCK_BYTE_SIZE 18 + +vec4 dequantize4(uint ib, uint iqs, uint a_offset, uint binding_idx) { + uint vui_lo = uint(kv_packed[binding_idx].data_packed16[a_offset + ib].qs[(iqs & 0xF) / 2 + 0]); + uint vui_hi = uint(kv_packed[binding_idx].data_packed16[a_offset + ib].qs[(iqs & 0xF) / 2 + 1]); + uint shift = (iqs & 0x10) >> 2; + vui_lo >>= shift; + vui_hi >>= shift; + + return float(kv_packed[binding_idx].data_packed16[a_offset + ib].d) * (vec4(vui_lo & 0xF, (vui_lo >> 8) & 0xF, vui_hi & 0xF, (vui_hi >> 8) & 0xF) - 8.0f); +} +#endif + +#if defined(DATA_A_Q8_0) +#define BLOCK_BYTE_SIZE 34 +vec4 dequantize4(uint ib, uint iqs, uint a_offset, uint binding_idx) { + const i8vec2 v0 = unpack8(int32_t(kv_packed[binding_idx].data_packed16[a_offset + ib].qs[iqs / 2])).xy; // vec4 used due to #12147 + const i8vec2 v1 = unpack8(int32_t(kv_packed[binding_idx].data_packed16[a_offset + ib].qs[iqs / 2 + 1])).xy; + + return float(kv_packed[binding_idx].data_packed16[a_offset + ib].d) * vec4(v0.x, v0.y, v1.x, v1.y); +} +#endif + +#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b)) + + +// Store column zero. This is used to save per-row m and L values for split_k. +ACC_TYPE perElemOpStoreCol0(const in uint32_t r, const in uint32_t c, const in ACC_TYPE elem, const in uint32_t o_offset, const in uint32_t iq2, const in uint32_t N) +{ + if (r < N && c == 0) { + uint32_t offset = iq2 + r; + data_o[o_offset + offset] = D_TYPE(elem); + } + return elem; +} + +// Load the slope matrix, indexed by Q's dimension 2. +ACC_TYPE perElemOpComputeSlope(const in uint32_t r, const in uint32_t c, const in ACC_TYPE elem, const in uint32_t iq2) +{ + const uint32_t h = iq2 + (r % p.gqa_ratio); + + const ACC_TYPE base = ACC_TYPE(h < p.n_head_log2 ? p.m0 : p.m1); + const int exph = int(h < p.n_head_log2 ? h + 1 : 2*(h - p.n_head_log2) + 1); + + return ACC_TYPE(pow(base, ACC_TYPE(exph))); +} + +uint32_t i, N, KV, split_k_index, Tr, start_j, end_j, + iq2, iq3, rk2, rk3, rv2, rv3, ik2, ik3, iv2, iv3, + q_stride, k_stride, v_stride, m_stride; + +void init_indices() +{ + N = p.N; + KV = p.KV; + + i = gl_WorkGroupID.x; + split_k_index = 0; + + if (p.k_num > 1) { + i = 0; + split_k_index = gl_WorkGroupID.x; + } + + Tr = CEIL_DIV(N, Br); + + start_j = split_k_index * p.split_kv / Bc; + end_j = CEIL_DIV(min(KV, (split_k_index + 1) * p.split_kv), Bc); + + // When not using grouped query attention, all rows share the same iq2, equal to gl_WorkGroupID.y. + // When using grouped query attention, each workgroup does gqa_ratio consecutive values of iq2. + iq2 = gl_WorkGroupID.y * p.gqa_ratio; + iq3 = gl_WorkGroupID.z; + + // broadcast factors + rk2 = p.neq2/p.nek2; + rk3 = p.neq3/p.nek3; + + rv2 = p.neq2/p.nev2; + rv3 = p.neq3/p.nev3; + + // k indices + ik3 = iq3 / rk3; + ik2 = iq2 / rk2; + + // v indices + iv3 = iq3 / rv3; + iv2 = iq2 / rv2; + + // nb?1 are already divided by the type size and are in units of elements. + // When using grouped query attention, Q is indexed by iq2, so the stride + // should be nb02 (which is in bytes). + q_stride = p.gqa_ratio > 1 ? (p.nb02 / 4) : p.nb01; + k_stride = p.nb11; + v_stride = p.nb21; + // When using grouped query attention, all rows use the same mask (stride 0). + // "p.gqa_ratio >> 16" is just a roundabout way of writing zero + // that prevents the compiler from folding the "&" through the select + // and breaking the alignment detection. + m_stride = (p.gqa_ratio > 1) ? (p.gqa_ratio >> 16) : KV; +} diff --git a/ggml/src/vulkan-shaders/flash_attn_cm1.comp b/ggml/src/vulkan-shaders/flash_attn_cm1.comp new file mode 100644 index 00000000..da478be2 --- /dev/null +++ b/ggml/src/vulkan-shaders/flash_attn_cm1.comp @@ -0,0 +1,360 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable +#extension GL_EXT_shader_16bit_storage : require + +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#extension GL_KHR_shader_subgroup_basic : enable +#extension GL_KHR_memory_scope_semantics : enable +#extension GL_KHR_cooperative_matrix : enable + +#include "types.comp" +#include "flash_attn_base.comp" + +const uint32_t D_per_thread = D / D_split; +const uint32_t row_split = 4; +const uint32_t rows_per_thread = Br / row_split; +const uint32_t cols_per_iter = gl_WorkGroupSize.x / D_split / row_split; +const uint32_t cols_per_thread = Bc / cols_per_iter; + + +layout (binding = 0) readonly buffer Q {float data_q[];}; +layout (binding = 0) readonly buffer QV4 {vec4 data_qv4[];}; +layout (binding = 1) readonly buffer K {float16_t data_k[];}; +layout (binding = 1) readonly buffer KV4 {f16vec4 data_kv4[];}; +layout (binding = 2) readonly buffer V {float16_t data_v[];}; +layout (binding = 2) readonly buffer VV4 {f16vec4 data_vv4[];}; +layout (binding = 3) readonly buffer M {float16_t data_m[];}; + +// Store the output when doing grouped query attention. +// Rows index by Q's dimension 2, and the first N rows are valid. +D_TYPE perElemOpGqaStore(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t o_offset, const in uint32_t iq2, const in uint32_t N) +{ + uint32_t offset = (iq2 + r) * D + c; + data_o[o_offset + offset] = D_TYPE(elem); + return elem; +} + +// These need to be supported N,M values for a MatBc x MatBr x 16 coopmatmuladd +const uint32_t MatBr = 16; +const uint32_t MatBc = 16; + +shared FLOAT_TYPE tmpsh[gl_WorkGroupSize.x]; +shared ACC_TYPEV4 tmpshv4[gl_WorkGroupSize.x]; + +const uint32_t qstride = D / 4 + 2; // in units of f16vec4 +shared f16vec4 Qf[Br * qstride]; + +// Avoid padding for D==256 to make it fit in 48KB shmem. +const uint32_t sfshstride = (D <= 128) ? (Br + 8) : Br; +shared ACC_TYPE sfsh[Bc * sfshstride]; + +const uint32_t kshstride = D / 4 + 2; // in units of f16vec4 +shared f16vec4 ksh[Bc * kshstride]; + +shared float slope[Br]; + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + + init_indices(); + + const uint32_t tid = gl_LocalInvocationIndex; + + const uint32_t threads_per_rowgroup = gl_WorkGroupSize.x / row_split; + const uint32_t row_tid = gl_LocalInvocationIndex / threads_per_rowgroup; + const uint32_t d_tid = gl_LocalInvocationIndex % D_split; + const uint32_t col_tid = (gl_LocalInvocationIndex % threads_per_rowgroup) / D_split; + +#define tile_row(r) (row_tid * rows_per_thread + (r)) + + uint32_t q_offset = (iq2*p.nb02+iq3*p.nb03) / 4; + + [[unroll]] for (uint32_t idx = 0; idx < Br * D / 4; idx += gl_WorkGroupSize.x) { + uint32_t d = (idx + tid) % (D / 4); + uint32_t r = (idx + tid) / (D / 4); + if (r < Br && d < D / 4 && + i * Br + r < N) { + Qf[r * qstride + d] = f16vec4(data_qv4[q_offset / 4 + (i * Br + r) * q_stride / 4 + d] * p.scale); + } + } + barrier(); + + ACC_TYPEV4 Of[rows_per_thread][D_per_thread / 4]; + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Of[r][d] = ACC_TYPEV4(0.0); + } + } + + float Lf[rows_per_thread], Mf[rows_per_thread]; + + // Use -FLT_MAX/2 rather than -inf to reduce the possibility of NaNs, e.g. when computing Mold-M. + const float NEG_FLT_MAX_OVER_2 = uintBitsToFloat(0xFEFFFFFF); + + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Lf[r] = 0; + Mf[r] = NEG_FLT_MAX_OVER_2; + } + + // ALiBi + if (p.max_bias > 0.0f) { + if (tid < Br) { + uint r = tid; + slope[r] = perElemOpComputeSlope(r, col_tid, ACC_TYPE(0), iq2); + } + barrier(); + } else { + if (tid < Br) { + uint r = tid; + slope[r] = 1.0; + } + barrier(); + } + +#if BLOCK_SIZE > 1 + uint32_t k_offset = (ik2*p.nb12 + ik3*p.nb13) / BLOCK_BYTE_SIZE; + uint32_t v_offset = (iv2*p.nb22 + iv3*p.nb23) / BLOCK_BYTE_SIZE; +#else + uint32_t k_offset = (ik2*p.nb12 + ik3*p.nb13) / 2; + uint32_t v_offset = (iv2*p.nb22 + iv3*p.nb23) / 2; +#endif + + [[dont_unroll]] + for (uint32_t j = start_j; j < end_j; ++j) { + + [[unroll]] for (uint32_t idx = 0; idx < Bc * D / 4; idx += gl_WorkGroupSize.x) { + uint32_t d = (idx + tid) % (D / 4); + uint32_t c = (idx + tid) / (D / 4); + if (c < Bc && d < D / 4) { +#if BLOCK_SIZE > 1 + uint coord = (j * Bc + c) * k_stride * BLOCK_SIZE + 4 * d; + uint ib = coord / BLOCK_SIZE; + uint iqs = (coord % BLOCK_SIZE); + f16vec4 K_Tf = f16vec4(dequantize4(ib, iqs, k_offset, BINDING_IDX_K)); +#else + f16vec4 K_Tf = f16vec4(data_kv4[k_offset / 4 + (j * Bc + c) * k_stride / 4 + d]); +#endif + + ksh[c * kshstride + d] = K_Tf; + } + } + barrier(); + + // K * Q^T -> S^T: Bc x D * D x Br -> Bc x Br + // Bc split across workgroup (four subgroups), loop over D in chunks of 16: 16 x 16 * 16 x 16 -> 16 x 16 + // This is written transposed in order to allow for N being 8 if implementations need it + coopmat SfMat = coopmat(0); + coopmat KMat; + coopmat QMat; + + for (uint32_t d = 0; d < D / 16; ++d) { + coopMatLoad(QMat, Qf, d * 16 / 4, qstride, gl_CooperativeMatrixLayoutColumnMajor); + + uint coord = (gl_SubgroupID * MatBc) * kshstride + d * 16 / 4; + coopMatLoad(KMat, ksh, coord, kshstride, gl_CooperativeMatrixLayoutRowMajor); + + SfMat = coopMatMulAdd(KMat, QMat, SfMat); + } + + uint coord = gl_SubgroupID * MatBc * sfshstride; + coopMatStore(SfMat, sfsh, coord, sfshstride, gl_CooperativeMatrixLayoutRowMajor); + barrier(); + + if (p.logit_softcap != 0.0f) { + [[unroll]] for (uint32_t idx = 0; idx < Bc * Br; idx += gl_WorkGroupSize.x) { + uint32_t c = (idx + tid) / Br; + uint32_t r = (idx + tid) % Br; + if (idx + tid < Bc * Br || idx + gl_WorkGroupSize.x <= Bc * Br) { + sfsh[c * sfshstride + r] = ACC_TYPE(p.logit_softcap * tanh(sfsh[c * sfshstride + r])); + } + } + barrier(); + } + + if (p.mask != 0) { + [[unroll]] for (uint32_t idx = 0; idx < Bc * Br; idx += gl_WorkGroupSize.x) { + uint32_t c = (idx + tid) % Bc; + uint32_t r = (idx + tid) / Bc; + if (idx + tid < Bc * Br || idx + gl_WorkGroupSize.x <= Bc * Br) { + sfsh[c * sfshstride + r] += ACC_TYPE(slope[r] * float(data_m[(i * Br + r) * m_stride + (j * Bc + c)])); + } + } + barrier(); + } + + float eMf[rows_per_thread]; + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + float rowmaxf = sfsh[tile_row(r) + (0 * cols_per_iter + col_tid) * sfshstride]; + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + rowmaxf = max(rowmaxf, float(sfsh[tile_row(r) + (c * cols_per_iter + col_tid) * sfshstride])); + } + float Moldf = Mf[r]; + + // M = max(rowmax, Mold) + // P = e^(S - M) + // eM = e^(Mold - M) + Mf[r] = max(rowmaxf, Moldf); + eMf[r] = exp(Moldf - Mf[r]); + } + + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Of[r][d] = float16_t(eMf[r]) * Of[r][d]; + } + } + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Lf[r] = eMf[r]*Lf[r]; + } + + [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { + float Pf[rows_per_thread]; + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Pf[r] = exp(sfsh[tile_row(r) + (c * cols_per_iter + col_tid) * sfshstride] - Mf[r]); + Lf[r] += Pf[r]; + } + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { +#if BLOCK_SIZE > 1 + uint coord = (j * Bc + c * cols_per_iter + col_tid) * v_stride * BLOCK_SIZE + 4 * (d * D_split + d_tid); + uint ib = coord / BLOCK_SIZE; + uint iqs = (coord % BLOCK_SIZE); + vec4 Vf = dequantize4(ib, iqs, v_offset, BINDING_IDX_V); +#else + vec4 Vf = vec4(data_vv4[v_offset / 4 + (j * Bc + c * cols_per_iter + col_tid) * v_stride / 4 + d * D_split + d_tid]); +#endif + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Of[r][d] += float16_t(Pf[r]) * ACC_TYPEV4(Vf); + } + } + } + + barrier(); + } + + // reduce across threads + + float rowmaxf[rows_per_thread], eMf[rows_per_thread], Moldf[rows_per_thread]; + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + FLOAT_TYPE M = Mf[r]; + tmpsh[tid] = M; + // Compute max across the row + barrier(); + [[unroll]] for (int s = int(gl_WorkGroupSize.x / row_split) / 2; s >= D_split; s >>= 1) { + M = max(M, tmpsh[tid ^ s]); + barrier(); + tmpsh[tid] = M; + barrier(); + } + rowmaxf[r] = tmpsh[d_tid + row_tid * threads_per_rowgroup]; + barrier(); + } + + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Moldf[r] = Mf[r]; + + // M = max(rowmax, Mold) + // eM = e^(Mold - M) + Mf[r] = max(rowmaxf[r], Moldf[r]); + eMf[r] = exp(Moldf[r] - Mf[r]); + + Lf[r] = eMf[r]*Lf[r]; + } + + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + FLOAT_TYPE L = Lf[r]; + tmpsh[tid] = L; + // Compute sum across the row + barrier(); + [[unroll]] for (int s = int(gl_WorkGroupSize.x / row_split) / 2; s >= D_split; s >>= 1) { + L += tmpsh[tid ^ s]; + barrier(); + tmpsh[tid] = L; + barrier(); + } + Lf[r] = tmpsh[d_tid + row_tid * threads_per_rowgroup]; + barrier(); + } + + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + + Of[r][d] = float16_t(eMf[r]) * Of[r][d]; + tmpshv4[tid] = Of[r][d]; + + barrier(); + [[unroll]] for (int s = int(gl_WorkGroupSize.x / row_split) / 2; s >= D_split; s >>= 1) { + Of[r][d] += tmpshv4[tid ^ s]; + barrier(); + tmpshv4[tid] = Of[r][d]; + barrier(); + } + Of[r][d] = tmpshv4[d_tid + row_tid * threads_per_rowgroup]; + barrier(); + } + } + + // If there is split_k, then the split_k resolve shader does the final + // division by L. Store the intermediate O value and per-row m and L values. + if (p.k_num > 1) { + uint32_t o_offset = D * p.ne1 * split_k_index; + + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + if (tile_row(r) < N) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { + perElemOpGqaStore(tile_row(r), 4*(d * D_split + d_tid) + comp, float(Of[r][d][comp]), o_offset, iq2, N); + } + } + } + } + + o_offset = D * p.ne1 * p.k_num + p.ne1 * split_k_index * 2; + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + if (tile_row(r) < N) { + perElemOpStoreCol0(tile_row(r), 0u, ACC_TYPE(Lf[r]), o_offset, iq2, N); + perElemOpStoreCol0(tile_row(r), 0u, ACC_TYPE(Mf[r]), o_offset + p.ne1, iq2, N); + } + } + + return; + } + + float Lfrcp[rows_per_thread]; + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Lfrcp[r] = 1.0 / Lf[r]; + } + + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + Of[r][d] *= float16_t(Lfrcp[r]); + } + } + + uint32_t o_offset = iq3*p.ne2*p.ne1; + + if (p.gqa_ratio > 1) { + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + if (tile_row(r) < N) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { + perElemOpGqaStore(tile_row(r), 4*(d * D_split + d_tid) + comp, float(Of[r][d][comp]), o_offset, iq2, N); + } + } + } + } + } else { + [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { + if (i * Br + tile_row(r) < N) { + [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { + data_o[o_offset + iq2 * D + (i * Br + tile_row(r)) * p.ne1 * D + 4*(d * D_split + d_tid) + comp] = D_TYPE(Of[r][d][comp]); + } + } + } + } + } +} diff --git a/ggml/src/vulkan-shaders/flash_attn_cm2.comp b/ggml/src/vulkan-shaders/flash_attn_cm2.comp new file mode 100644 index 00000000..6acf67a0 --- /dev/null +++ b/ggml/src/vulkan-shaders/flash_attn_cm2.comp @@ -0,0 +1,267 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable +#extension GL_EXT_shader_16bit_storage : require + +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require + +#extension GL_KHR_memory_scope_semantics : enable +#extension GL_KHR_cooperative_matrix : enable +#extension GL_NV_cooperative_matrix2 : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_KHR_shader_subgroup_ballot : enable +#extension GL_KHR_shader_subgroup_vote : enable +#extension GL_EXT_null_initializer : enable + +#include "types.comp" +#include "dequant_funcs_cm2.comp" +#include "flash_attn_base.comp" + +layout (binding = 0) readonly buffer Q {uint8_t data_q[];}; +layout (binding = 1) readonly buffer K {uint8_t data_k[];}; +layout (binding = 2) readonly buffer V {uint8_t data_v[];}; +layout (binding = 3) readonly buffer M {uint8_t data_m[];}; + +ACC_TYPE maxReduce(const in ACC_TYPE x, const in ACC_TYPE y) { + return max(x, y); +} + +ACC_TYPE smearReduce(const in ACC_TYPE x, const in ACC_TYPE y) { + return x; +} + +// Replace matrix elements >= numRows or numCols with 'replace' +ACC_TYPE replacePadding(const in uint32_t row, const in uint32_t col, const in ACC_TYPE elem, const in ACC_TYPE replace, const in uint32_t numRows, const in uint32_t numCols) { + if (row >= numRows || col >= numCols) { + return replace; + } + return elem; +} + +ACC_TYPE Exp(const in uint32_t row, const in uint32_t col, const in ACC_TYPE elem) +{ + return exp(elem); +} + +ACC_TYPE Max(const in uint32_t row, const in uint32_t col, const in ACC_TYPE elem0, const in ACC_TYPE elem1) +{ + return max(elem0, elem1); +} + +#if defined(BLOCK_SIZE) +#define DECODEFUNC , DEQUANTFUNC +#else +#define DECODEFUNC +#endif + +// Store the output when doing grouped query attention. +// Rows index by Q's dimension 2, and the first N rows are valid. +D_TYPE perElemOpGqaStore(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t o_offset, const in uint32_t iq2, const in uint32_t N) +{ + if (r < N && c < D) { + uint32_t offset = (iq2 + r) * D + c; + data_o[o_offset + offset] = D_TYPE(elem); + } + return elem; +} + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + + init_indices(); + + tensorLayoutNV<2, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutQ = createTensorLayoutNV(2, gl_CooperativeMatrixClampModeConstantNV); + tensorLayoutNV<2, Clamp> tensorLayoutK = createTensorLayoutNV(2, Clamp); + tensorLayoutNV<2, Clamp> tensorLayoutV = createTensorLayoutNV(2, Clamp); + + tensorViewNV<2, false, 1, 0> tensorViewTranspose = createTensorViewNV(2, false, 1, 0); + +#if defined(BLOCK_SIZE) + tensorLayoutK = setTensorLayoutBlockSizeNV(tensorLayoutK, 1, BLOCK_SIZE); + tensorLayoutV = setTensorLayoutBlockSizeNV(tensorLayoutV, 1, BLOCK_SIZE); +#endif + + tensorLayoutQ = setTensorLayoutDimensionNV(tensorLayoutQ, N, D); + tensorLayoutK = setTensorLayoutDimensionNV(tensorLayoutK, KV, D); + tensorLayoutV = setTensorLayoutDimensionNV(tensorLayoutV, KV, D); + + // hint to the compiler that strides are aligned for the aligned variant of the shader + if (Clamp != gl_CooperativeMatrixClampModeConstantNV) + { + q_stride &= ~7; +#if !defined(BLOCK_SIZE) + k_stride &= ~7; + v_stride &= ~7; +#endif + m_stride &= ~7; + } + tensorLayoutQ = setTensorLayoutStrideNV(tensorLayoutQ, q_stride, 1); + tensorLayoutK = setTensorLayoutStrideNV(tensorLayoutK, k_stride, 1); + tensorLayoutV = setTensorLayoutStrideNV(tensorLayoutV, v_stride, 1); + + coopmat Q; + coopmat Qf16; + + uint32_t q_offset = iq2*p.nb02+iq3*p.nb03; + coopMatLoadTensorNV(Q, data_q, q_offset, sliceTensorLayoutNV(tensorLayoutQ, i * Br, Br, 0, D)); + + Qf16 = coopmat(Q); + Qf16 *= float16_t(p.scale); + + coopmat O = coopmat(0); + + coopmat L, M; + + // Use -FLT_MAX/2 rather than -inf to reduce the possibility of NaNs, e.g. when computing Mold-M. + const float NEG_FLT_MAX_OVER_2 = uintBitsToFloat(0xFEFFFFFF); + + L = coopmat(0); + M = coopmat(NEG_FLT_MAX_OVER_2); + + coopmat slopeMat = coopmat(1.0); + + // ALiBi + if (p.max_bias > 0.0f) { + coopMatPerElementNV(slopeMat, slopeMat, perElemOpComputeSlope, iq2); + } + + [[dont_unroll]] + for (uint32_t j = start_j; j < end_j; ++j) { + + coopmat S = coopmat(0); + + coopmat K_T; + + uint32_t k_offset = ik2*p.nb12 + ik3*p.nb13; + coopMatLoadTensorNV(K_T, data_k, k_offset, sliceTensorLayoutNV(tensorLayoutK, j * Bc, Bc, 0, D), tensorViewTranspose DECODEFUNC); + S = coopMatMulAdd(Qf16, K_T, S); + + if (p.logit_softcap != 0.0f) { + [[unroll]] + for (int k = 0; k < S.length(); ++k) { + S[k] = ACC_TYPE(p.logit_softcap)*tanh(S[k]); + } + } + + if (p.mask != 0) { + tensorLayoutNV<2, Clamp> tensorLayoutM = createTensorLayoutNV(2, Clamp); + tensorLayoutM = setTensorLayoutDimensionNV(tensorLayoutM, p.nem1, KV); + tensorLayoutM = setTensorLayoutStrideNV(tensorLayoutM, m_stride, 1); + + coopmat mv; + + coopMatLoadTensorNV(mv, data_m, 0, sliceTensorLayoutNV(tensorLayoutM, i * Br, Br, j * Bc, Bc)); + + S += slopeMat*coopmat(mv); + } + + // Clear padding elements to -inf, so they don't contribute to rowmax + if (Clamp != 0 && + ((j + 1) * Bc > KV || + (i + 1) * Br > N)) { + + uint R = ((i + 1) * Br > N) ? (N % Br) : Br; + uint C = ((j + 1) * Bc > KV) ? (KV % Bc) : Bc; + + coopMatPerElementNV(S, S, replacePadding, ACC_TYPE(NEG_FLT_MAX_OVER_2), R, C); + } + + coopmat rowmax, P, rowsum, eM; + + coopMatReduceNV(rowmax, S, gl_CooperativeMatrixReduceRowNV, maxReduce); + + coopmat Mold = M; + + // M = max(rowmax, Mold) + // P = e^(S - M) + // eM = e^(Mold - M) + coopMatPerElementNV(M, rowmax, Max, Mold); + coopMatPerElementNV(P, S - M, Exp); + coopMatPerElementNV(eM, Mold - M, Exp); + + // Clear padding elements to 0, so they don't contribute to rowsum + if (Clamp != 0 && + ((j + 1) * Bc > KV || + (i + 1) * Br > N)) { + + uint R = ((i + 1) * Br > N) ? (N % Br) : Br; + uint C = ((j + 1) * Bc > KV) ? (KV % Bc) : Bc; + + coopMatPerElementNV(P, P, replacePadding, ACC_TYPE(0.0), R, C); + } + + coopmat P_A = coopmat(P); + + // compute rowsum by multiplying by matrix of all ones. + coopmat One = coopmat(1.0); + + rowsum = coopmat(0.0); + rowsum = coopMatMulAdd(P_A, One, rowsum); + + coopmat V; + uint32_t v_offset = iv2*p.nb22 + iv3*p.nb23; + coopMatLoadTensorNV(V, data_v, v_offset, sliceTensorLayoutNV(tensorLayoutV, j * Bc, Bc, 0, D) DECODEFUNC); + + L = eM*L + rowsum; + + // This is the "diagonal" matrix in the paper, but since we do componentwise + // multiply rather than matrix multiply it has the diagonal element smeared + // across the row + coopmat eMdiag; + + // resize eM by using smear/reduce + coopMatReduceNV(eMdiag, eM, gl_CooperativeMatrixReduceRowNV, smearReduce); + + // multiply with fp16 accumulation, then add to O. + coopmat PV = coopmat(0); + PV = coopMatMulAdd(P_A, V, PV); + + O = eMdiag * O + coopmat(PV); + } + + // If there is split_k, then the split_k resolve shader does the final + // division by L. Store the intermediate O value and per-row m and L values. + if (p.k_num > 1) { + coopmat O_D = coopmat(O); + + uint32_t o_offset = D * p.ne1 * split_k_index; + coopMatPerElementNV(O_D, O_D, perElemOpGqaStore, o_offset, iq2, N); + + o_offset = D * p.ne1 * p.k_num + p.ne1 * split_k_index * 2; + coopMatPerElementNV(L, L, perElemOpStoreCol0, o_offset, iq2, N); + coopMatPerElementNV(M, M, perElemOpStoreCol0, o_offset + p.ne1, iq2, N); + return; + } + + coopmat Ldiag; + + // resize L by using smear/reduce + coopMatReduceNV(Ldiag, L, gl_CooperativeMatrixReduceRowNV, smearReduce); + + [[unroll]] + for (int k = 0; k < Ldiag.length(); ++k) { + Ldiag[k] = ACC_TYPE(1.0) / Ldiag[k]; + } + + O = Ldiag*O; + + uint32_t o_offset = iq3*p.ne2*p.ne1; + + coopmat O_D = coopmat(O); + if (p.gqa_ratio > 1) { + coopMatPerElementNV(O_D, O_D, perElemOpGqaStore, o_offset, iq2, N); + } else { + tensorLayoutNV<3, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutD = createTensorLayoutNV(3, gl_CooperativeMatrixClampModeConstantNV); + tensorLayoutD = setTensorLayoutDimensionNV(tensorLayoutD, p.ne2, p.ne1, D); + + // permute dimensions + tensorViewNV<3, false, 1, 0, 2> tensorViewPermute = createTensorViewNV(3, false, 1, 0, 2); + + coopMatStoreTensorNV(O_D, data_o, o_offset, sliceTensorLayoutNV(tensorLayoutD, i * Br, Br, iq2, N, 0, D), tensorViewPermute); + } +} diff --git a/ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp b/ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp new file mode 100644 index 00000000..a7e39568 --- /dev/null +++ b/ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp @@ -0,0 +1,59 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable + +#define BLOCK_SIZE 32 + +layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {float data_a[];}; +layout (binding = 1) writeonly buffer D {float data_d[];}; + +layout (push_constant) uniform parameter { + uint D; + uint N; + uint k_num; +} p; + +void main() { + // Each workgroup handles a row + const uint n = gl_WorkGroupID.x; + const uint tid = gl_LocalInvocationID.x; + + uint D = p.D; + uint N = p.N; + uint k_num = p.k_num; + + uint l_offset = D * N * k_num + n; + uint m_offset = D * N * k_num + N + n; + uint lm_stride = N * 2; + + // Compute the max m value for the row + float m_max = -1.0/0.0; + [[unroll]] for (uint k = 0; k < k_num; ++k) { + float m = data_a[m_offset + k * lm_stride]; + m_max = max(m_max, m); + } + + // Compute L based on m_max + float L = 0; + [[unroll]] for (uint k = 0; k < k_num; ++k) { + float l = data_a[l_offset + k * lm_stride]; + float m = data_a[m_offset + k * lm_stride]; + L += exp(m - m_max) * l; + } + + L = 1.0 / L; + + // Scale and sum the O contributions based on m_max and store the result to memory + for (uint d = tid; d < D; d += BLOCK_SIZE) { + float O = 0.0; + [[unroll]] for (uint k = 0; k < k_num; ++k) { + uint o_offset = D * N * k + D * n + d; + float m = data_a[m_offset + k * lm_stride]; + O += exp(m - m_max) * data_a[o_offset]; + } + O *= L; + data_d[D * n + d] = O; + } +} diff --git a/ggml/src/vulkan-shaders/generic_binary_head.comp b/ggml/src/vulkan-shaders/generic_binary_head.comp index b6beaff1..062e2a4c 100644 --- a/ggml/src/vulkan-shaders/generic_binary_head.comp +++ b/ggml/src/vulkan-shaders/generic_binary_head.comp @@ -1,4 +1,5 @@ #extension GL_EXT_shader_16bit_storage : require +#extension GL_EXT_control_flow_attributes : require layout (push_constant) uniform parameter { @@ -6,47 +7,58 @@ layout (push_constant) uniform parameter uint ne00; uint ne01; uint ne02; uint ne03; uint nb00; uint nb01; uint nb02; uint nb03; uint ne10; uint ne11; uint ne12; uint ne13; uint nb10; uint nb11; uint nb12; uint nb13; uint ne20; uint ne21; uint ne22; uint ne23; uint nb20; uint nb21; uint nb22; uint nb23; - uint d_offset; + uint misalign_offsets; float param1; float param2; int param3; } p; -layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; - layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; +// true if src0/src1 are the same shape and the indices can be reused without additional modulus +layout(constant_id = 0) const bool norepeat = false; + uint get_idx() { return gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; } -uint src0_idx(uint idx) { - const uint i03 = idx / (p.ne02*p.ne01*p.ne00); +uint get_aoffset() { return p.misalign_offsets >> 16; } +uint get_boffset() { return (p.misalign_offsets >> 8) & 0xFF; } +uint get_doffset() { return p.misalign_offsets & 0xFF; } + +// mod and div are expensive and coordinates/dimensions are often power of 2 or equal to 1 +uint fastmod(uint a, uint b) { + if ((b & (b-1)) == 0) { + return a & (b-1); + } + return a % b; +} + +uint fastdiv(uint a, uint b) { + return (a < b) ? 0 : (a / b); +} + +void get_indices(uint idx, out uint i00, out uint i01, out uint i02, out uint i03) { + i03 = fastdiv(idx, (p.ne02*p.ne01*p.ne00)); const uint i03_offset = i03 * p.ne02*p.ne01*p.ne00; - const uint i02 = (idx - i03_offset) / (p.ne01*p.ne00); + i02 = fastdiv((idx - i03_offset), (p.ne01*p.ne00)); const uint i02_offset = i02*p.ne01*p.ne00; - const uint i01 = (idx - i03_offset - i02_offset) / p.ne00; - const uint i00 = idx - i03_offset - i02_offset - i01*p.ne00; + i01 = (idx - i03_offset - i02_offset) / p.ne00; + i00 = idx - i03_offset - i02_offset - i01*p.ne00; +} + +uint src0_idx(uint i00, uint i01, uint i02, uint i03) { return i03*p.nb03 + i02*p.nb02 + i01*p.nb01 + i00*p.nb00; } -uint src1_idx(uint idx) { - const uint i03 = idx / (p.ne02*p.ne01*p.ne00); - const uint i03_offset = i03 * p.ne02*p.ne01*p.ne00; - const uint i02 = (idx - i03_offset) / (p.ne01*p.ne00); - const uint i02_offset = i02*p.ne01*p.ne00; - const uint i01 = (idx - i03_offset - i02_offset) / p.ne00; - const uint i00 = idx - i03_offset - i02_offset - i01*p.ne00; - - return (i03 % p.ne13)*p.nb13 + (i02 % p.ne12)*p.nb12 + (i01 % p.ne11)*p.nb11 + (i00 % p.ne10)*p.nb10; +uint src1_idx(uint i00, uint i01, uint i02, uint i03) { + if (norepeat) { + return i03*p.nb13 + i02*p.nb12 + i01*p.nb11 + i00*p.nb10; + } else { + return fastmod(i03, p.ne13)*p.nb13 + fastmod(i02, p.ne12)*p.nb12 + fastmod(i01, p.ne11)*p.nb11 + fastmod(i00, p.ne10)*p.nb10; + } } -uint dst_idx(uint idx) { - const uint i23 = idx / (p.ne22*p.ne21*p.ne20); - const uint i23_offset = i23 * p.ne22*p.ne21*p.ne20; - const uint i22 = (idx - i23_offset) / (p.ne21*p.ne20); - const uint i22_offset = i22*p.ne21*p.ne20; - const uint i21 = (idx - i23_offset - i22_offset) / p.ne20; - const uint i20 = idx - i23_offset - i22_offset - i21*p.ne20; - return i23*p.nb23 + i22*p.nb22 + i21*p.nb21 + i20*p.nb20; +uint dst_idx(uint i00, uint i01, uint i02, uint i03) { + return i03*p.nb23 + i02*p.nb22 + i01*p.nb21 + i00*p.nb20; } diff --git a/ggml/src/vulkan-shaders/generic_unary_head.comp b/ggml/src/vulkan-shaders/generic_unary_head.comp index eacdefc7..8dc9d360 100644 --- a/ggml/src/vulkan-shaders/generic_unary_head.comp +++ b/ggml/src/vulkan-shaders/generic_unary_head.comp @@ -1,15 +1,21 @@ #extension GL_EXT_shader_16bit_storage : require +#extension GL_EXT_control_flow_attributes : require layout (push_constant) uniform parameter { uint ne; uint ne00; uint ne01; uint ne02; uint ne03; uint nb00; uint nb01; uint nb02; uint nb03; uint ne10; uint ne11; uint ne12; uint ne13; uint nb10; uint nb11; uint nb12; uint nb13; - uint d_offset; + uint misalign_offsets; float param1; float param2; -} p; -layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + uint ne0_012mp; uint ne0_012L; + uint ne0_01mp; uint ne0_01L; + uint ne0_0mp; uint ne0_0L; + uint ne1_012mp; uint ne1_012L; + uint ne1_01mp; uint ne1_01L; + uint ne1_0mp; uint ne1_0L; +} p; layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; @@ -18,22 +24,53 @@ uint get_idx() { return gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; } +uint get_aoffset() { return p.misalign_offsets >> 16; } +uint get_doffset() { return p.misalign_offsets & 0xFFFF; } + +// see init_fastdiv_values in ggml-vulkan.cpp +uint fastdiv(uint n, uint mp, uint L) { + uint msbs, lsbs; + // msbs = mulhi(n, mp) + umulExtended(n, mp, msbs, lsbs); + return (msbs + n) >> L; +} + uint src0_idx(uint idx) { - const uint i03 = idx / (p.ne02*p.ne01*p.ne00); + const uint i03 = fastdiv(idx, p.ne0_012mp, p.ne0_012L); const uint i03_offset = i03 * p.ne02*p.ne01*p.ne00; - const uint i02 = (idx - i03_offset) / (p.ne01*p.ne00); + const uint i02 = fastdiv(idx - i03_offset, p.ne0_01mp, p.ne0_01L); const uint i02_offset = i02*p.ne01*p.ne00; - const uint i01 = (idx - i03_offset - i02_offset) / p.ne00; + const uint i01 = fastdiv(idx - i03_offset - i02_offset, p.ne0_0mp, p.ne0_0L); const uint i00 = idx - i03_offset - i02_offset - i01*p.ne00; return i03*p.nb03 + i02*p.nb02 + i01*p.nb01 + i00*p.nb00; } uint dst_idx(uint idx) { - const uint i13 = idx / (p.ne12*p.ne11*p.ne10); + const uint i13 = fastdiv(idx, p.ne1_012mp, p.ne1_012L); const uint i13_offset = i13 * p.ne12*p.ne11*p.ne10; - const uint i12 = (idx - i13_offset) / (p.ne11*p.ne10); + const uint i12 = fastdiv(idx - i13_offset, p.ne1_01mp, p.ne1_01L); const uint i12_offset = i12*p.ne11*p.ne10; - const uint i11 = (idx - i13_offset - i12_offset) / p.ne10; + const uint i11 = fastdiv(idx - i13_offset - i12_offset, p.ne1_0mp, p.ne1_0L); const uint i10 = idx - i13_offset - i12_offset - i11*p.ne10; return i13*p.nb13 + i12*p.nb12 + i11*p.nb11 + i10*p.nb10; } + +uint src0_idx_quant(uint idx, uint qk) { + const uint i03 = fastdiv(idx, p.ne0_012mp, p.ne0_012L); + const uint i03_offset = i03 * p.ne02*p.ne01*p.ne00; + const uint i02 = fastdiv(idx - i03_offset, p.ne0_01mp, p.ne0_01L); + const uint i02_offset = i02*p.ne01*p.ne00; + const uint i01 = fastdiv(idx - i03_offset - i02_offset, p.ne0_0mp, p.ne0_0L); + const uint i00 = idx - i03_offset - i02_offset - i01*p.ne00; + return i03*p.nb03 + i02*p.nb02 + i01*p.nb01 + (i00/qk)*p.nb00; +} + +uint dst_idx_quant(uint idx, uint qk) { + const uint i13 = fastdiv(idx, p.ne1_012mp, p.ne1_012L); + const uint i13_offset = i13 * p.ne12*p.ne11*p.ne10; + const uint i12 = fastdiv(idx - i13_offset, p.ne1_01mp, p.ne1_01L); + const uint i12_offset = i12*p.ne11*p.ne10; + const uint i11 = fastdiv(idx - i13_offset - i12_offset, p.ne1_0mp, p.ne1_0L); + const uint i10 = idx - i13_offset - i12_offset - i11*p.ne10; + return i13*p.nb13 + i12*p.nb12 + i11*p.nb11 + (i10/qk)*p.nb10; +} diff --git a/ggml/src/vulkan-shaders/get_rows.comp b/ggml/src/vulkan-shaders/get_rows.comp index e9ff22ef..ee6b86a1 100644 --- a/ggml/src/vulkan-shaders/get_rows.comp +++ b/ggml/src/vulkan-shaders/get_rows.comp @@ -3,6 +3,8 @@ #include "types.comp" #include "generic_binary_head.comp" +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + void main() { const uint i00 = gl_GlobalInvocationID.x; const uint i10 = gl_GlobalInvocationID.y; @@ -13,14 +15,19 @@ void main() { return; } - const uint i01 = data_b[i10*p.nb10 + i11*p.nb11 + i12*p.nb12]; + const uint i01 = data_b[get_boffset() + i10*p.nb10 + i11*p.nb11 + i12*p.nb12]; - const uint a_offset = i01*p.nb01 + i11*p.nb02 + i12*p.nb03; - const uint d_offset = i10*p.nb21 + i11*p.nb22 + i12*p.nb23; + const uint a_offset = get_aoffset() + i01*p.nb01 + i11*p.nb02 + i12*p.nb03; + const uint d_offset = get_doffset() + i10*p.nb21 + i11*p.nb22 + i12*p.nb23; -#ifndef OPTIMIZATION_ERROR_WORKAROUND - data_d[d_offset + i00] = D_TYPE(data_a[a_offset + i00]); +#if defined(DATA_A_BF16) + FLOAT_TYPE v = FLOAT_TYPE(bf16_to_fp32(data_a[a_offset + i00])); #else - data_d[d_offset + i00] = data_a[a_offset + i00]; + FLOAT_TYPE v = FLOAT_TYPE(data_a[a_offset + i00]); +#endif +#ifndef OPTIMIZATION_ERROR_WORKAROUND + data_d[d_offset + i00] = D_TYPE(v); +#else + data_d[d_offset + i00] = D_TYPE(v); #endif } diff --git a/ggml/src/vulkan-shaders/get_rows_quant.comp b/ggml/src/vulkan-shaders/get_rows_quant.comp index 53a9a96f..cfd645a3 100644 --- a/ggml/src/vulkan-shaders/get_rows_quant.comp +++ b/ggml/src/vulkan-shaders/get_rows_quant.comp @@ -1,15 +1,23 @@ #version 450 +#extension GL_EXT_control_flow_attributes : enable + #include "types.comp" #include "generic_binary_head.comp" #include "dequant_funcs.comp" +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + void main() { const uint i00 = (gl_GlobalInvocationID.x)*2; const uint i10 = gl_GlobalInvocationID.y; const uint i11 = (gl_GlobalInvocationID.z)/p.ne12; const uint i12 = (gl_GlobalInvocationID.z)%p.ne12; +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + if (i00 >= p.ne00) { return; } @@ -25,6 +33,8 @@ void main() { const uint y_offset = QUANT_R == 1 ? 1 : QUANT_K/2; vec2 v = dequantize(ib, iqs, 0); + const vec2 dm = get_dm(ib, 0); + v = v * dm.x + dm.y; data_d[d_offset + iybs + iqs ] = D_TYPE(v.x); data_d[d_offset + iybs + iqs + y_offset] = D_TYPE(v.y); diff --git a/ggml/src/vulkan-shaders/group_norm.comp b/ggml/src/vulkan-shaders/group_norm.comp index 5ad9b28d..b6a0d564 100644 --- a/ggml/src/vulkan-shaders/group_norm.comp +++ b/ggml/src/vulkan-shaders/group_norm.comp @@ -19,7 +19,7 @@ void main() { const uint tid = gl_LocalInvocationID.x; const uint start = gl_WorkGroupID.x * group_size + tid; - const uint end = start + group_size; + const uint end = (gl_WorkGroupID.x + 1) * group_size; tmp[tid] = 0.0f; diff --git a/ggml/src/vulkan-shaders/im2col.comp b/ggml/src/vulkan-shaders/im2col.comp index 4d48610a..09aa849e 100644 --- a/ggml/src/vulkan-shaders/im2col.comp +++ b/ggml/src/vulkan-shaders/im2col.comp @@ -1,6 +1,12 @@ #version 450 #extension GL_EXT_shader_16bit_storage : require +#extension GL_EXT_spirv_intrinsics: enable +#extension GL_EXT_control_flow_attributes : require + +#if RTE16 +spirv_execution_mode(capabilities = [4467], 4462, 16); // RoundingModeRTE, 16 bits +#endif layout (push_constant) uniform parameter { @@ -18,40 +24,77 @@ layout (push_constant) uniform parameter #include "types.comp" -#define BLOCK_SIZE 256 +layout(constant_id = 0) const uint BLOCK_SIZE = 32; -layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; +const uint NUM_ITER = 512 / BLOCK_SIZE; + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; void main() { - const uint i = gl_GlobalInvocationID.x; - if (i >= p.pelements) { - return; - } - - const uint ksize = p.OW * (p.KH > 1 ? p.KW : 1); - const uint kx = i / ksize; - const uint kd = kx * ksize; - const uint ky = (i - kd) / p.OW; - const uint ix = i % p.OW; + const uint gidx = gl_GlobalInvocationID.x; const uint oh = gl_GlobalInvocationID.y; const uint batch = gl_GlobalInvocationID.z / p.IC; const uint ic = gl_GlobalInvocationID.z % p.IC; - const uint iiw = ix * p.s0 + kx * p.d0 - p.p0; - const uint iih = oh * p.s1 + ky * p.d1 - p.p1; + const uint src_base = ic * p.offset_delta + batch * p.batch_offset; + const uint dst_base = ((batch * p.OH + oh) * p.OW) * p.CHW + ic * (p.KW * p.KH); + const int oh_s1 = int(oh) * p.s1; + const uint ksize = p.OW * (p.KH > 1 ? p.KW : 1); - const uint offset_dst = - ((batch * p.OH + oh) * p.OW + ix) * p.CHW + - (ic * (p.KW * p.KH) + ky * p.KW + kx); + const uint base_linear_idx = gidx * NUM_ITER; - if (iih < 0 || iih >= p.IH || iiw < 0 || iiw >= p.IW) { - data_d[offset_dst] = D_TYPE(0.0f); - } else { - const uint offset_src = ic * p.offset_delta + batch * p.batch_offset; - data_d[offset_dst] = D_TYPE(data_a[offset_src + iih * p.IW + iiw]); + const uint max_ky = ksize / p.OW; + + uint current_kx = base_linear_idx / ksize; + const uint rem = base_linear_idx - (current_kx * ksize); + uint current_ky = rem / p.OW; + uint current_ix = rem % p.OW; + + A_TYPE values[NUM_ITER]; + uint offset_dst[NUM_ITER]; + [[unroll]] for (uint idx = 0; idx < NUM_ITER; ++idx) { + values[idx] = A_TYPE(0); } + + [[unroll]] for (uint idx = 0; idx < NUM_ITER; ++idx) { + + const uint linear_idx = base_linear_idx + idx; + + if (linear_idx >= p.pelements) { + continue; + } + + const uint iiw = current_ix * p.s0 + current_kx * p.d0 - p.p0; + const uint iih = oh_s1 + current_ky * p.d1 - p.p1; + + offset_dst[idx] = dst_base + current_ix * p.CHW + current_ky * p.KW + current_kx; + + if ((iih < p.IH) && (iiw < p.IW)) { + values[idx] = data_a[src_base + iih * p.IW + iiw]; + } + + if (++current_ix == p.OW) { + current_ix = 0; + if (++current_ky == max_ky) { + current_ky = 0; + current_kx++; + } + } + } + + [[unroll]] for (uint idx = 0; idx < NUM_ITER; ++idx) { + + const uint linear_idx = base_linear_idx + idx; + + if (linear_idx >= p.pelements) { + continue; + } + + data_d[offset_dst[idx]] = D_TYPE(values[idx]); + } + } diff --git a/ggml/src/vulkan-shaders/mul.comp b/ggml/src/vulkan-shaders/mul.comp index bfb61c92..43de19df 100644 --- a/ggml/src/vulkan-shaders/mul.comp +++ b/ggml/src/vulkan-shaders/mul.comp @@ -3,12 +3,25 @@ #include "types.comp" #include "generic_binary_head.comp" +const uint num_threads = 256; + +layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in; + void main() { - const uint idx = get_idx(); + uint idx = get_idx(); - if (idx >= p.ne) { - return; + // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation + const uint num_iter = 2; + + [[unroll]] for (uint i = 0; i < num_iter; ++i) { + if (idx >= p.ne) { + continue; + } + uint i00, i01, i02, i03; + get_indices(idx, i00, i01, i02, i03); + + data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) * FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)])); + + idx += num_threads; } - - data_d[p.d_offset + dst_idx(idx)] = D_TYPE(FLOAT_TYPE(data_a[src0_idx(idx)]) * FLOAT_TYPE(data_b[src1_idx(idx)])); } diff --git a/ggml/src/vulkan-shaders/mul_mat_split_k_reduce.comp b/ggml/src/vulkan-shaders/mul_mat_split_k_reduce.comp index 825b9103..4c64fd47 100644 --- a/ggml/src/vulkan-shaders/mul_mat_split_k_reduce.comp +++ b/ggml/src/vulkan-shaders/mul_mat_split_k_reduce.comp @@ -5,7 +5,9 @@ layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; layout (binding = 0) readonly buffer A {float data_a[];}; +layout (binding = 0) readonly buffer A4 {vec4 data_a4[];}; layout (binding = 1) writeonly buffer D {float data_d[];}; +layout (binding = 1) writeonly buffer D4 {vec4 data_d4[];}; layout (push_constant) uniform parameter { uint ne; @@ -13,17 +15,34 @@ layout (push_constant) uniform parameter { } p; void main() { - const uint idx = gl_GlobalInvocationID.x; + // Each invocation handles four consecutive components + const uint idx = gl_GlobalInvocationID.x * 4; if (idx >= p.ne) { return; } - float result = 0.0f; + // Check if all four components are in bounds and aligned, + // then use vector loads + if (idx + 3 < p.ne && (p.ne % 4) == 0) { + vec4 result = vec4(0.0f); - [[unroll]] for (uint i = 0; i < p.k_num; i++) { - result += data_a[i * p.ne + idx]; + [[unroll]] for (uint i = 0; i < p.k_num; i++) { + result += data_a4[(i * p.ne + idx) / 4]; + } + + data_d4[idx / 4] = result; + } else { + [[unroll]] for (uint j = 0; j < 4; ++j) { + if (idx + j < p.ne) { + float result = 0.0f; + + [[unroll]] for (uint i = 0; i < p.k_num; i++) { + result += data_a[i * p.ne + idx + j]; + } + + data_d[idx + j] = result; + } + } } - - data_d[idx] = result; } diff --git a/ggml/src/vulkan-shaders/mul_mat_vec.comp b/ggml/src/vulkan-shaders/mul_mat_vec.comp index 46a6369b..bb429dd5 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec.comp @@ -1,57 +1,169 @@ #version 450 -#ifdef FLOAT16 -#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require -#endif +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require #include "mul_mat_vec_base.comp" layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -layout (constant_id = 0) const uint BLOCK_SIZE = 32; +#if !defined(DATA_A_F32) && !defined(DATA_A_F16) && !defined(DATA_A_BF16) +#define K_PER_ITER 8 +#else +#define K_PER_ITER 2 +#endif -shared FLOAT_TYPE tmp[BLOCK_SIZE]; -void main() { - const uint row = gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z; - const uint tid = gl_LocalInvocationID.x; +uint a_offset, b_offset, d_offset, y_offset; - // There are not enough cols to use all threads - if (tid >= p.ncols) { - return; - } - - const uint block_size = min(p.ncols, BLOCK_SIZE); - - uint a_offset, b_offset, d_offset; - get_offsets(a_offset, b_offset, d_offset); - - const uint y_offset = QUANT_R == 1 ? 1 : QUANT_K/2; - - tmp[tid] = FLOAT_TYPE(0.0f); - - [[unroll]] for (uint i = 0; i < p.ncols/block_size; i += 2) { - const uint col = i*block_size + 2*tid; - const uint ib = (row*p.ncols + col)/QUANT_K; // block index +void iter(inout FLOAT_TYPE temp[NUM_COLS][NUM_ROWS], const uint first_row, const uint num_rows, const uint tid, const uint i, bool lastiter) +{ + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + const uint col = i*BLOCK_SIZE + K_PER_ITER*tid; const uint iqs = (col%QUANT_K)/QUANT_R; // quant index const uint iybs = col - col%QUANT_K; // y block start index - vec2 v = dequantize(ib, iqs, a_offset / QUANT_K); +#if K_PER_ITER == 8 +#if QUANT_R == 2 + const vec4 bv02 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + iybs + iqs) / 4]); + const vec4 bv13 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + iybs + iqs + y_offset) / 4]); + const vec4 bv0 = vec4(bv02.x, bv13.x, bv02.y, bv13.y); + const vec4 bv1 = vec4(bv02.z, bv13.z, bv02.w, bv13.w); +#else + const vec4 bv0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + iybs + iqs) / 4]); + const vec4 bv1 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + iybs + iqs) / 4 + 1]); +#endif +#else + // Check if the second of the pair of elements is OOB, and don't fetch B or + // accumulate it. We still fetch a pair of elements for A, which is fine for + // quantized formats since they'll be within the same block. We should + // probably skip fetching the second element for F16/F32, but as of now we + // still do. + const bool OOB = lastiter && (iybs + iqs + y_offset >= p.ncols); - // matrix multiplication - tmp[tid] += FLOAT_TYPE(v.x) * FLOAT_TYPE(data_b[b_offset + iybs + iqs]) + - FLOAT_TYPE(v.y) * FLOAT_TYPE(data_b[b_offset + iybs + iqs + y_offset]); - } - - // sum up partial sums and write back result - barrier(); - [[unroll]] for (uint s = block_size/2; s > 0; s >>= 1) { - if (tid < s) { - tmp[tid] += tmp[tid + s]; + FLOAT_TYPE b0 = 0, b1 = 0; + b0 = FLOAT_TYPE(data_b[j*p.batch_stride_b + b_offset + iybs + iqs]); + if (!OOB) { + b1 = FLOAT_TYPE(data_b[j*p.batch_stride_b + b_offset + iybs + iqs + y_offset]); + } +#endif + uint ibi = first_row*p.ncols; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const uint ib = (ibi + col)/QUANT_K; // block index + ibi += p.ncols; + +#if K_PER_ITER == 8 + vec4 v = dequantize4(ib, iqs, a_offset); + vec4 v2 = dequantize4(ib, iqs+(4/QUANT_R), a_offset); + + const vec2 dm = get_dm(ib, a_offset); + if (dm.y != 0) { // quant has min component + v = v * dm.x + dm.y; + v2 = v2 * dm.x + dm.y; + } + + // matrix multiplication + FLOAT_TYPE rowtmp = dot(bv0, v); + rowtmp += dot(bv1, v2); + + if (dm.y == 0) + rowtmp *= dm.x; + + temp[j][n] += rowtmp; +#else + const vec2 v = dequantize(ib, iqs, a_offset); + + // matrix multiplication + temp[j][n] = fma(FLOAT_TYPE(v.x), b0, temp[j][n]); + if (!OOB) { + temp[j][n] = fma(FLOAT_TYPE(v.y), b1, temp[j][n]); + } +#endif } - barrier(); - } - if (tid == 0) { - data_d[d_offset + row] = D_TYPE(tmp[0]); + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + const uint tid = gl_LocalInvocationID.x; + + get_offsets(a_offset, b_offset, d_offset); + a_offset /= QUANT_K; + + y_offset = QUANT_R == 1 ? 1 : QUANT_K/2; + + FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + uint num_iters = p.ncols / (K_PER_ITER * BLOCK_SIZE); + if (num_iters * K_PER_ITER * BLOCK_SIZE + K_PER_ITER*tid < p.ncols) { + num_iters++; + } + int unroll_count = 4; + uint unrolled_iters = num_iters & ~(unroll_count - 1); + +#if K_PER_ITER == 2 + // If the K dimension is odd, we need lastiter==true on the last iteration + // so OOB is computed correctly. Skip some unrolling to make that happen. + if ((p.ncols & 1) != 0 && + unrolled_iters == num_iters && + unrolled_iters > 0) { + unrolled_iters -= unroll_count; + } +#endif + + uint i = 0; + while (i < unrolled_iters) { + // Manually partially unroll the loop + [[unroll]] for (uint k = 0; k < unroll_count; ++k) { + iter(temp, first_row, num_rows, tid, i*K_PER_ITER, false); + i++; + } + } + + unroll_count = 2; + unrolled_iters = num_iters & ~(unroll_count - 1); + +#if K_PER_ITER == 2 + if ((p.ncols & 1) != 0 && + unrolled_iters == num_iters && + unrolled_iters > 0) { + unrolled_iters -= unroll_count; + } +#endif + + while (i < unrolled_iters) { + // Manually partially unroll the loop + [[unroll]] for (uint k = 0; k < unroll_count; ++k) { + iter(temp, first_row, num_rows, tid, i*K_PER_ITER, false); + i++; + } + } + while (i < num_iters) { + iter(temp, first_row, num_rows, tid, i*K_PER_ITER, true); + i++; + } + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); } } diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_base.comp b/ggml/src/vulkan-shaders/mul_mat_vec_base.comp index 5920bc93..903753c7 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_base.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_base.comp @@ -2,8 +2,6 @@ #extension GL_EXT_shader_16bit_storage : require #extension GL_EXT_shader_8bit_storage : require -#define K_QUANTS_PER_ITERATION 2 - #ifdef MUL_MAT_ID #define EXPERT_COUNT 8 #endif @@ -12,6 +10,9 @@ layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; +layout (binding = 1) readonly buffer BV2 {B_TYPE_VEC2 data_b_v2[];}; +layout (binding = 1) readonly buffer BV4 {B_TYPE_VEC4 data_b_v4[];}; + layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; #ifdef MUL_MAT_ID layout (binding = 3) readonly buffer IDS {int data_ids[];}; @@ -49,13 +50,16 @@ void get_offsets(out uint a_offset, out uint b_offset, out uint d_offset) { #endif #ifndef MUL_MAT_ID - const uint i13 = batch_idx / p.ne12; - const uint i12 = batch_idx % p.ne12; + uint batch_idx_a = 0; + if (batch_idx != 0) { + const uint i13 = batch_idx / p.ne12; + const uint i12 = batch_idx % p.ne12; - const uint i03 = i13 / p.broadcast3; - const uint i02 = i12 / p.broadcast2; + const uint i03 = i13 / p.broadcast3; + const uint i02 = i12 / p.broadcast2; - const uint batch_idx_a = i03 * p.ne02 + i02; + batch_idx_a = i03 * p.ne02 + i02; + } #else const uint expert_id = data_ids[expert_idx]; #endif @@ -79,3 +83,36 @@ void get_offsets(out uint a_offset, out uint b_offset, out uint d_offset) { batch_idx * p.batch_stride_d; #endif } + +layout (constant_id = 0) const uint BLOCK_SIZE = 32; +layout (constant_id = 1) const uint NUM_ROWS = 1; +layout (constant_id = 2) const uint NUM_COLS = 1; + +shared FLOAT_TYPE tmpsh[NUM_COLS][NUM_ROWS][BLOCK_SIZE]; + +void reduce_result(const in FLOAT_TYPE temp[NUM_COLS][NUM_ROWS], const in uint32_t d_offset, const in uint32_t first_row, const in uint32_t num_rows, const in uint32_t tid) { + // sum up partial sums and write back result + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + tmpsh[j][n][tid] = temp[j][n]; + } + } + barrier(); + [[unroll]] for (uint s = BLOCK_SIZE/2; s > 0; s >>= 1) { + if (tid < s) { + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + tmpsh[j][n][tid] += tmpsh[j][n][tid + s]; + } + } + } + barrier(); + } + if (tid == 0) { + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + data_d[j*p.batch_stride_d + d_offset + first_row + n] = D_TYPE(tmpsh[j][n][0]); + } + } + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_iq1_m.comp b/ggml/src/vulkan-shaders/mul_mat_vec_iq1_m.comp new file mode 100644 index 00000000..e4acbd4f --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mat_vec_iq1_m.comp @@ -0,0 +1,82 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#include "mul_mat_vec_base.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + +void calc_superblock(const uint a_offset, const uint b_offset, const uint ib32, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows) { + const uint y_idx = i * QUANT_K + 32 * ib32; + + uint ibi = a_offset / QUANT_K + first_row * num_blocks_per_row + i; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const uint16_t[4] scales = data_a[ibi].scales; + const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12; + const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x); + + const uint sc = data_a[ibi].scales[ib32 / 2] >> (6 * (ib32 & 1)); + [[unroll]] for (uint l = 0; l < 4; ++l) { + const uint qh = data_a[ibi].qh[2 * ib32 + l / 2] >> (4 * (l&1)); + const uint qs = data_a[ibi].qs[4 * ib32 + l]; + const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA; + const float dl = d * (2 * bitfieldExtract(sc, 3 * int(l / 2), 3) + 1); + + const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec4 b0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 0]); + vec4 b4 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 1]); + + FLOAT_TYPE sum = FLOAT_TYPE(0.0); + [[unroll]] for (int k = 0; k < 4; ++k) { + sum = fma(FLOAT_TYPE(b0[k]), bitfieldExtract(grid, 2 * k, 2) + delta, + fma(FLOAT_TYPE(b4[k]), bitfieldExtract(grid, 8 + 2 * k, 2) + delta, sum)); + } + temp[j][n] = fma(dl, sum, temp[j][n]); + } + } + ibi += num_blocks_per_row; + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + uint a_offset, b_offset, d_offset; + get_offsets(a_offset, b_offset, d_offset); + + const uint num_blocks_per_row = p.ncols / QUANT_K; + + // 8 threads are used to process each block + const uint blocks_per_wg = gl_WorkGroupSize.x/8; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid % 8; // 0...7 + const uint ix = tid / 8; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += blocks_per_wg) + calc_superblock(a_offset, b_offset, itid, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + init_iq_shmem(gl_WorkGroupSize); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_iq1_s.comp b/ggml/src/vulkan-shaders/mul_mat_vec_iq1_s.comp new file mode 100644 index 00000000..309da099 --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mat_vec_iq1_s.comp @@ -0,0 +1,79 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#include "mul_mat_vec_base.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + +void calc_superblock(const uint a_offset, const uint b_offset, const uint ib32, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows) { + const uint y_idx = i * QUANT_K + 32 * ib32; + + uint ibi = a_offset / QUANT_K + first_row * num_blocks_per_row + i; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const float d = float(data_a[ibi].d); + const uint qh = data_a[ibi].qh[ib32]; + const float dl = d * float(2 * bitfieldExtract(qh, 12, 3) + 1); + const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; + + [[unroll]] for (uint l = 0; l < 4; ++l) { + const uint qs = data_a[ibi].qs[4 * ib32 + l]; + const uint idxhi = bitfieldExtract(qh, 3 * int(l), 3); + const int16_t grid = int16_t(iq1s_grid[qs | (idxhi << 8)]); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec4 b0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 0]); + vec4 b4 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 1]); + + FLOAT_TYPE sum = FLOAT_TYPE(0.0); + [[unroll]] for (int k = 0; k < 4; ++k) { + sum = fma(FLOAT_TYPE(b0[k]), bitfieldExtract(grid, 2 * k, 2) + delta, + fma(FLOAT_TYPE(b4[k]), bitfieldExtract(grid, 8 + 2 * k, 2) + delta, sum)); + } + temp[j][n] = fma(dl, sum, temp[j][n]); + } + } + ibi += num_blocks_per_row; + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + uint a_offset, b_offset, d_offset; + get_offsets(a_offset, b_offset, d_offset); + + const uint num_blocks_per_row = p.ncols / QUANT_K; + + // 8 threads are used to process each block + const uint blocks_per_wg = gl_WorkGroupSize.x/8; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid % 8; // 0...7 + const uint ix = tid / 8; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += blocks_per_wg) + calc_superblock(a_offset, b_offset, itid, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + init_iq_shmem(gl_WorkGroupSize); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_iq2_s.comp b/ggml/src/vulkan-shaders/mul_mat_vec_iq2_s.comp new file mode 100644 index 00000000..8d01536f --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mat_vec_iq2_s.comp @@ -0,0 +1,90 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#include "mul_mat_vec_base.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + +void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows) { + const uint y_idx = i * QUANT_K + 16 * itid; + const uint nibble_shift = 4 * (itid & 1); + const uint ib32 = itid / 2; // 0..7 + + uint ibi = a_offset / QUANT_K + first_row * num_blocks_per_row + i; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const float d = float(data_a[ibi].d); + const uint scale = (data_a[ibi].scales[ib32] >> nibble_shift) & 0xF; + const float db = d * (0.5 + scale) * 0.25; + + const uint qh = data_a[ibi].qh[ib32]; + const u8vec2 qs16 = unpack8(uint32_t(data_a_packed16[ibi].qs[itid])).xy; // vec4 used due to #12147 + const u8vec2 sign16 = unpack8(uint32_t(data_a_packed16[ibi].qs[QUANT_K / 16 + itid])).xy; + [[unroll]] for (uint l = 0; l < 2; ++l) { + const uint8_t sign = sign16[l]; + const uint qs = qs16[l] | ((qh << (8 - nibble_shift - 2 * l)) & 0x300); + const uvec2 grid = iq2s_grid[qs]; + const vec4 grid0 = vec4(unpack8(grid.x)); + const vec4 grid1 = vec4(unpack8(grid.y)); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec4 b0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 0]); + vec4 b4 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 1]); + + FLOAT_TYPE sum = + fma(FLOAT_TYPE(b0.x), FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x), + fma(FLOAT_TYPE(b0.y), FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y), + fma(FLOAT_TYPE(b0.z), FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z), + fma(FLOAT_TYPE(b0.w), FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w), + fma(FLOAT_TYPE(b4.x), FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x), + fma(FLOAT_TYPE(b4.y), FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y), + fma(FLOAT_TYPE(b4.z), FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z), + fma(FLOAT_TYPE(b4.w), FLOAT_TYPE((sign & 128) != 0 ? -grid1.w : grid1.w), + FLOAT_TYPE(0.0))))))))); + temp[j][n] = fma(db, sum, temp[j][n]); + } + } + ibi += num_blocks_per_row; + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + uint a_offset, b_offset, d_offset; + get_offsets(a_offset, b_offset, d_offset); + + const uint num_blocks_per_row = p.ncols / QUANT_K; + + // 16 threads are used to process each block + const uint blocks_per_wg = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid % 16; // 0...15 + const uint ix = tid / 16; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += blocks_per_wg) + calc_superblock(a_offset, b_offset, itid, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + init_iq_shmem(gl_WorkGroupSize); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_iq2_xs.comp b/ggml/src/vulkan-shaders/mul_mat_vec_iq2_xs.comp new file mode 100644 index 00000000..c4960432 --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mat_vec_iq2_xs.comp @@ -0,0 +1,87 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#include "mul_mat_vec_base.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + +void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows) { + const uint y_idx = i * QUANT_K + 16 * itid; + const uint nibble_shift = 4 * (itid & 1); + const uint ib32 = itid / 2; // 0..7 + + uint ibi = a_offset / QUANT_K + first_row * num_blocks_per_row + i; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const float d = float(data_a[ibi].d); + const uint scale = (data_a[ibi].scales[ib32] >> nibble_shift) & 0xF; + const float db = d * (0.5 + scale) * 0.25; + + [[unroll]] for (uint l = 0; l < 2; ++l) { + const uint qs = data_a[ibi].qs[2 * itid + l]; + const uint sign = qs >> 9; + const uint sign7 = bitCount(sign); + const vec4 grid0 = vec4(unpack8(iq2xs_grid[qs & 511].x)); + const vec4 grid1 = vec4(unpack8(iq2xs_grid[qs & 511].y)); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec4 b0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 0]); + vec4 b4 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 1]); + + FLOAT_TYPE sum = + fma(FLOAT_TYPE(b0.x), FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x), + fma(FLOAT_TYPE(b0.y), FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y), + fma(FLOAT_TYPE(b0.z), FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z), + fma(FLOAT_TYPE(b0.w), FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w), + fma(FLOAT_TYPE(b4.x), FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x), + fma(FLOAT_TYPE(b4.y), FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y), + fma(FLOAT_TYPE(b4.z), FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z), + fma(FLOAT_TYPE(b4.w), FLOAT_TYPE((sign7 & 1) != 0 ? -grid1.w : grid1.w), + FLOAT_TYPE(0.0))))))))); + temp[j][n] = fma(db, sum, temp[j][n]); + } + } + ibi += num_blocks_per_row; + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + uint a_offset, b_offset, d_offset; + get_offsets(a_offset, b_offset, d_offset); + + const uint num_blocks_per_row = p.ncols / QUANT_K; + + // 16 threads are used to process each block + const uint blocks_per_wg = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid % 16; // 0...15 + const uint ix = tid / 16; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += blocks_per_wg) + calc_superblock(a_offset, b_offset, itid, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + init_iq_shmem(gl_WorkGroupSize); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_iq2_xxs.comp b/ggml/src/vulkan-shaders/mul_mat_vec_iq2_xxs.comp new file mode 100644 index 00000000..94d4b92e --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mat_vec_iq2_xxs.comp @@ -0,0 +1,87 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#include "mul_mat_vec_base.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + +void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows) { + const uint y_idx = i * QUANT_K + 16 * itid; + const uint ib32 = itid / 2; // 0..7 + + uint ibi = a_offset / QUANT_K + first_row * num_blocks_per_row + i; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const float d = float(data_a[ibi].d); + const uint signscale = pack32(u16vec2( + data_a_packed16[ibi].qs[4 * ib32 + 2], + data_a_packed16[ibi].qs[4 * ib32 + 3])); + const float db = d * 0.25 * (0.5 + (signscale >> 28)); + [[unroll]] for (uint l = 0; l < 2; ++l) { + const uint qs = data_a[ibi].qs[8 * ib32 + 2 * (itid & 1) + l]; + const uint sign = bitfieldExtract(signscale, 7 * int(2 * (itid & 1) + l), 7); + const uint sign7 = bitCount(sign); + const vec4 grid0 = vec4(unpack8(iq2xxs_grid[qs].x)); + const vec4 grid1 = vec4(unpack8(iq2xxs_grid[qs].y)); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + const vec4 b0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 0]); + const vec4 b4 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 1]); + + FLOAT_TYPE sum = + fma(FLOAT_TYPE(b0.x), FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x), + fma(FLOAT_TYPE(b0.y), FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y), + fma(FLOAT_TYPE(b0.z), FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z), + fma(FLOAT_TYPE(b0.w), FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w), + fma(FLOAT_TYPE(b4.x), FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x), + fma(FLOAT_TYPE(b4.y), FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y), + fma(FLOAT_TYPE(b4.z), FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z), + fma(FLOAT_TYPE(b4.w), FLOAT_TYPE((sign7 & 1) != 0 ? -grid1.w : grid1.w), + FLOAT_TYPE(0.0))))))))); + temp[j][n] = fma(db, sum, temp[j][n]); + } + } + ibi += num_blocks_per_row; + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + uint a_offset, b_offset, d_offset; + get_offsets(a_offset, b_offset, d_offset); + + const uint num_blocks_per_row = p.ncols / QUANT_K; + + // 16 threads are used to process each block + const uint blocks_per_wg = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid % 16; // 0...15 + const uint ix = tid / 16; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += blocks_per_wg) + calc_superblock(a_offset, b_offset, itid, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + init_iq_shmem(gl_WorkGroupSize); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_iq3_s.comp b/ggml/src/vulkan-shaders/mul_mat_vec_iq3_s.comp new file mode 100644 index 00000000..f021e404 --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mat_vec_iq3_s.comp @@ -0,0 +1,90 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#include "mul_mat_vec_base.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + +void calc_superblock(const uint a_offset, const uint b_offset, const uint ib32, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows) { + const uint y_idx = i * QUANT_K + 32 * ib32; + + uint ibi = a_offset / QUANT_K + first_row * num_blocks_per_row + i; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const float d = float(data_a[ibi].d); + const uint scale = (data_a[ibi].scales[ib32/2] >> (4 * (ib32 & 1))) & 0xF; + const float dscale = d * (1 + 2 * scale); + const uint qh = data_a[ibi].qh[ib32]; + FLOAT_TYPE sum[NUM_COLS]; + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + sum[j] = 0.0; + } + [[unroll]] for (uint l = 0; l < 4; ++l) { + const u8vec2 qs = unpack8(uint32_t(data_a_packed16[ibi].qs[4 * ib32 + l])).xy; // vec4 used due to #12147 + const uint sign = data_a[ibi].signs[4 * ib32 + l]; + const vec4 grid0 = vec4(unpack8(iq3s_grid[qs.x | ((qh << (8 - 2*l)) & 0x100)])); + const vec4 grid1 = vec4(unpack8(iq3s_grid[qs.y | ((qh << (7 - 2*l)) & 0x100)])); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + const vec4 b0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 0]); + const vec4 b4 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 1]); + + sum[j] = + fma(FLOAT_TYPE(b0.x), FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x), + fma(FLOAT_TYPE(b0.y), FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y), + fma(FLOAT_TYPE(b0.z), FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z), + fma(FLOAT_TYPE(b0.w), FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w), + fma(FLOAT_TYPE(b4.x), FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x), + fma(FLOAT_TYPE(b4.y), FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y), + fma(FLOAT_TYPE(b4.z), FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z), + fma(FLOAT_TYPE(b4.w), FLOAT_TYPE((sign & 128) != 0 ? -grid1.w : grid1.w), + sum[j])))))))); + } + } + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + temp[j][n] = fma(dscale, sum[j], temp[j][n]); + } + ibi += num_blocks_per_row; + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + uint a_offset, b_offset, d_offset; + get_offsets(a_offset, b_offset, d_offset); + + const uint num_blocks_per_row = p.ncols / QUANT_K; + + // 8 threads are used to process each block + const uint blocks_per_wg = gl_WorkGroupSize.x/8; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid % 8; // 0...7 + const uint ix = tid / 8; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += blocks_per_wg) + calc_superblock(a_offset, b_offset, itid, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + init_iq_shmem(gl_WorkGroupSize); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_iq3_xxs.comp b/ggml/src/vulkan-shaders/mul_mat_vec_iq3_xxs.comp new file mode 100644 index 00000000..3fe9dc3a --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mat_vec_iq3_xxs.comp @@ -0,0 +1,88 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +#include "mul_mat_vec_base.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; + +void calc_superblock(const uint a_offset, const uint b_offset, const uint itid, const uint i, const uint num_blocks_per_row, const uint first_row, const uint num_rows) { + const uint y_idx = i * QUANT_K + 16 * itid; + const uint ib32 = itid / 2; // 0..7 + + uint ibi = a_offset / QUANT_K + first_row * num_blocks_per_row + i; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const float d = float(data_a[ibi].d); + const uint signscale = pack32(u16vec2( + data_a_packed16[ibi].qs[QUANT_K / 8 + 2 * ib32], + data_a_packed16[ibi].qs[QUANT_K / 8 + 2 * ib32 + 1])); + const float db = d * 0.5 * (0.5 + (signscale >> 28)); + [[unroll]] for (uint l = 0; l < 2; ++l) { + const uint qs0 = data_a[ibi].qs[8 * ib32 + 4 * (itid & 1) + 2 * l]; + const uint qs1 = data_a[ibi].qs[8 * ib32 + 4 * (itid & 1) + 2 * l + 1]; + const uint sign = bitfieldExtract(signscale, 7 * int(2 * (itid & 1) + l), 7); + const uint sign7 = bitCount(sign); + const vec4 grid0 = vec4(unpack8(iq3xxs_grid[qs0])); + const vec4 grid1 = vec4(unpack8(iq3xxs_grid[qs1])); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + const vec4 b0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 0]); + const vec4 b4 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 2*l + 1]); + + FLOAT_TYPE sum = + fma(FLOAT_TYPE(b0.x), FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x), + fma(FLOAT_TYPE(b0.y), FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y), + fma(FLOAT_TYPE(b0.z), FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z), + fma(FLOAT_TYPE(b0.w), FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w), + fma(FLOAT_TYPE(b4.x), FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x), + fma(FLOAT_TYPE(b4.y), FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y), + fma(FLOAT_TYPE(b4.z), FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z), + fma(FLOAT_TYPE(b4.w), FLOAT_TYPE((sign7 & 1) != 0 ? -grid1.w : grid1.w), + FLOAT_TYPE(0.0))))))))); + temp[j][n] = fma(db, sum, temp[j][n]); + } + } + ibi += num_blocks_per_row; + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { + uint a_offset, b_offset, d_offset; + get_offsets(a_offset, b_offset, d_offset); + + const uint num_blocks_per_row = p.ncols / QUANT_K; + + // 16 threads are used to process each block + const uint blocks_per_wg = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid % 16; // 0...15 + const uint ix = tid / 16; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); + } + } + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += blocks_per_wg) + calc_superblock(a_offset, b_offset, itid, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + init_iq_shmem(gl_WorkGroupSize); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_nc.comp b/ggml/src/vulkan-shaders/mul_mat_vec_nc.comp index cb3f3c0d..bc633369 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_nc.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_nc.comp @@ -12,13 +12,18 @@ layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; layout (binding = 2) writeonly buffer D {D_TYPE dst[];}; +layout (binding = 0) readonly buffer AV4 {A_TYPE_VEC4 data_a_v4[];}; +layout (binding = 1) readonly buffer BV4 {B_TYPE_VEC4 data_b_v4[];}; + layout (push_constant) uniform parameter { uint ncols_x; uint nrows_x; uint row_stride_x; uint channel_stride_x; + uint channel_stride_y; uint channel_x_divisor; + uint ne12; uint b_offset; uint d_offset; } p; @@ -30,6 +35,7 @@ void main() { const uint row_x = gl_GlobalInvocationID.y; const uint channel = gl_GlobalInvocationID.z; const uint channel_x = channel / p.channel_x_divisor; + const uint channel_y = channel % p.ne12; const uint nrows_y = p.ncols_x; const uint nrows_dst = p.nrows_x; @@ -37,25 +43,66 @@ void main() { const uint idst = channel*nrows_dst + row_dst; - tmp[tid] = 0.0f; + FLOAT_TYPE temp = 0.0f; - for (uint col_x0 = 0; col_x0 < p.ncols_x; col_x0 += BLOCK_SIZE) { - const uint col_x = col_x0 + tid; + // Detect alignment for vector loads + bool is_aligned = (p.ncols_x % 4) == 0 && (p.row_stride_x % 4) == 0 && (p.channel_stride_x % 4) == 0; - if (col_x >= p.ncols_x) { - break; + for (uint col_x0 = 0; col_x0 < p.ncols_x;) { + + // Unroll 2x and do vec4 loads if aligned + const uint unroll_count = 2; + if (col_x0 + unroll_count * 4 * BLOCK_SIZE <= p.ncols_x && is_aligned) { + [[unroll]] for (uint i = 0; i < unroll_count; ++i) { + const uint col_x = col_x0 + 4*tid; + + const uint row_y = col_x; + + const uint ix = channel_x*p.channel_stride_x + row_x*p.row_stride_x + col_x; + const uint iy = channel_y*p.channel_stride_y + row_y; + + const vec4 av4 = vec4(data_a_v4[ix / 4]); + const vec4 bv4 = vec4(data_b_v4[iy / 4]); + + temp += dot(av4, bv4); + + col_x0 += 4*BLOCK_SIZE; + } + // do vec4 loads if aligned + } else if (col_x0 + 4*BLOCK_SIZE <= p.ncols_x && is_aligned) { + const uint col_x = col_x0 + 4*tid; + + const uint row_y = col_x; + + const uint ix = channel_x*p.channel_stride_x + row_x*p.row_stride_x + col_x; + const uint iy = channel_y*p.channel_stride_y + row_y; + + const vec4 av4 = vec4(data_a_v4[ix / 4]); + const vec4 bv4 = vec4(data_b_v4[iy / 4]); + + temp += dot(av4, bv4); + + col_x0 += 4*BLOCK_SIZE; + } else { + const uint col_x = col_x0 + tid; + if (col_x >= p.ncols_x) { + break; + } + + const uint row_y = col_x; + + const uint ix = channel_x*p.channel_stride_x + row_x*p.row_stride_x + col_x; + const uint iy = channel_y*p.channel_stride_y + row_y; + + const FLOAT_TYPE xi = FLOAT_TYPE(data_a[ix]); + + temp = fma(xi, FLOAT_TYPE(data_b[iy]), temp); + col_x0 += BLOCK_SIZE; } - - const uint row_y = col_x; - - const uint ix = channel_x*p.channel_stride_x + row_x*p.row_stride_x + col_x; - const uint iy = channel*nrows_y + row_y; - - const FLOAT_TYPE xi = FLOAT_TYPE(data_a[ix]); - - tmp[tid] += xi * FLOAT_TYPE(data_b[iy]); } + tmp[tid] = temp; + // sum up partial sums and write back result barrier(); [[unroll]] for (int s = BLOCK_SIZE / 2; s > 0; s >>= 1) { diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_p021.comp b/ggml/src/vulkan-shaders/mul_mat_vec_p021.comp index 4b1871ca..7aa070ee 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_p021.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_p021.comp @@ -2,16 +2,25 @@ #extension GL_EXT_control_flow_attributes : enable #extension GL_EXT_shader_16bit_storage : require +#if USE_SUBGROUP_ADD +#extension GL_KHR_shader_subgroup_arithmetic : enable +#endif -#define BLOCK_SIZE 32 #define FLOAT_TYPE float -layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; layout (binding = 2) writeonly buffer D {D_TYPE dst[];}; +layout (binding = 0) readonly buffer AV4 {A_TYPE_VEC4 data_a_v4[];}; +layout (binding = 1) readonly buffer BV4 {B_TYPE_VEC4 data_b_v4[];}; + +layout(constant_id = 0) const int BLOCK_SIZE = 32; +// gqa_ratio is in the range [1,8] +layout(constant_id = 1) const uint gqa_ratio = 1; + layout (push_constant) uniform parameter { uint ncols_x; @@ -22,52 +31,124 @@ layout (push_constant) uniform parameter uint d_offset; } p; -shared FLOAT_TYPE tmp[BLOCK_SIZE]; +#if !USE_SUBGROUP_ADD +shared FLOAT_TYPE tmp[8][BLOCK_SIZE]; +#endif void main() { const uint tid = gl_LocalInvocationID.x; const uint row_x = gl_GlobalInvocationID.y; - const uint channel = gl_GlobalInvocationID.z; - const uint channel_x = channel / (p.nchannels_y / p.nchannels_x); + + uint channel, channel_x; + + // When gqa_ratio > 1, each invocation does multiple rows. + // The row in the A matrix is starting from channel / gqa_ratio and the + // rows in the B matrix are [channel, channel+gqa_ratio). + // When gpa_ratio is 1, each invocation does one row. + if (gqa_ratio > 1) { + channel_x = gl_GlobalInvocationID.z; + channel = channel_x * gqa_ratio; + } else { + channel = gl_GlobalInvocationID.z; + channel_x = channel / (p.nchannels_y / p.nchannels_x);; + } const uint nrows_y = p.ncols_x; const uint nrows_dst = p.nrows_x; const uint row_dst = row_x; - tmp[tid] = FLOAT_TYPE(0.0f); - - for (uint col_x0 = 0; col_x0 < p.ncols_x; col_x0 += BLOCK_SIZE) { - const uint col_x = col_x0 + tid; - - if (col_x >= p.ncols_x) { - break; - } - - // x is transposed and permuted - const uint ix = row_x*p.nchannels_x*p.ncols_x + channel_x*p.ncols_x + col_x; - const FLOAT_TYPE xi = FLOAT_TYPE(data_a[ix]); - - const uint row_y = col_x; - - // y is not transposed but permuted - const uint iy = channel*nrows_y + row_y; - - tmp[tid] += xi * FLOAT_TYPE(data_b[iy]); + FLOAT_TYPE temp[8]; + [[unroll]] for (uint i = 0; i < 8; ++i) { + temp[i] = FLOAT_TYPE(0.0f); } - // dst is not transposed and not permuted - const uint idst = channel*nrows_dst + row_dst; + // Detect alignment for vector loads + bool is_aligned = (p.ncols_x % 4) == 0 && (p.nchannels_x % 4) == 0 && (nrows_y % 4) == 0; + for (uint col_x0 = 0; col_x0 < p.ncols_x; col_x0 += BLOCK_SIZE) { + + // Use vec4 loads if aligned + if (col_x0 + 4*BLOCK_SIZE <= p.ncols_x && is_aligned) { + + uint col_x = col_x0 + 4*tid; + const uint row_y = col_x; + + // x is transposed and permuted + const uint ix = row_x*p.nchannels_x*p.ncols_x + channel_x*p.ncols_x + col_x; + const vec4 av4 = vec4(data_a_v4[ix / 4]); + + [[unroll]] for (uint c = 0; c < gqa_ratio; ++c) { + // y is not transposed but permuted + const uint iy = (channel + c)*nrows_y + row_y; + + vec4 bv4 = data_b_v4[iy / 4]; + temp[c] += dot(av4, bv4); + } + + col_x0 += 3*BLOCK_SIZE; + } else { + const uint col_x = col_x0 + tid; + + if (col_x >= p.ncols_x) { + break; + } + + // x is transposed and permuted + const uint ix = row_x*p.nchannels_x*p.ncols_x + channel_x*p.ncols_x + col_x; + const FLOAT_TYPE xi = FLOAT_TYPE(data_a[ix]); + + const uint row_y = col_x; + + [[unroll]] for (uint c = 0; c < gqa_ratio; ++c) { + // y is not transposed but permuted + const uint iy = (channel + c)*nrows_y + row_y; + + temp[c] = fma(xi, FLOAT_TYPE(data_b[iy]), temp[c]); + } + } + } + +#if USE_SUBGROUP_ADD + // reduce vec4 at a time + vec4 t = vec4(temp[0], temp[1], temp[2], temp[3]); + t = subgroupAdd(t); + temp[0] = t[0]; + temp[1] = t[1]; + temp[2] = t[2]; + temp[3] = t[3]; + if (gqa_ratio > 4) { + t = vec4(temp[4], temp[5], temp[6], temp[7]); + t = subgroupAdd(t); + temp[4] = t[0]; + temp[5] = t[1]; + temp[6] = t[2]; + temp[7] = t[3]; + } +#else + [[unroll]] for (uint c = 0; c < gqa_ratio; ++c) { + tmp[c][tid] = temp[c]; + } // sum up partial sums and write back result barrier(); [[unroll]] for (int s = BLOCK_SIZE / 2; s > 0; s >>= 1) { if (tid < s) { - tmp[tid] += tmp[tid + s]; + [[unroll]] for (uint c = 0; c < gqa_ratio; ++c) { + temp[c] += tmp[c][tid + s]; + tmp[c][tid] = temp[c]; + } } barrier(); } + [[unroll]] for (uint c = 0; c < gqa_ratio; ++c) { + temp[c] = tmp[c][tid]; + } +#endif if (tid == 0) { - dst[idst] = tmp[0]; + [[unroll]] for (uint c = 0; c < gqa_ratio; ++c) { + // dst is not transposed and not permuted + const uint idst = (channel + c)*nrows_dst + row_dst; + dst[idst] = temp[c]; + } } } diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_q2_k.comp b/ggml/src/vulkan-shaders/mul_mat_vec_q2_k.comp index 4cd97799..423ceb8a 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_q2_k.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_q2_k.comp @@ -1,73 +1,130 @@ #version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require #include "mul_mat_vec_base.comp" -layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE tmp[32]; +shared FLOAT_TYPE sccache1[2][BLOCK_SIZE/16][16]; +shared FLOAT_TYPE sccache2[2][BLOCK_SIZE/16][16]; -void main() { - const uint row = gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z; +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; + + 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[csel][ix][itid] = FLOAT_TYPE(scale & 0xF); + sccache2[csel][ix][itid] = FLOAT_TYPE((scale >> 4) & 0xF); + } + barrier(); + + if (i >= num_blocks_per_row) + continue; + } else { + const uint32_t scale = uint32_t(data_a[ib0 + i].scales[itid]); + sccache1[csel][ix][itid] = FLOAT_TYPE(scale & 0xF); + sccache2[csel][ix][itid] = FLOAT_TYPE((scale >> 4) & 0xF); + barrier(); + } + + const uint32_t qs_u32 = uint32_t(data_a_packed16[ib0 + i].qs[q_offset / 2]) | (uint32_t(data_a_packed16[ib0 + i].qs[q_offset / 2 + 8]) << 16); + const vec4 qs_u32_0 = vec4(unpack8(qs_u32 & 0x03030303)); + const vec4 qs_u32_2 = vec4(unpack8((qs_u32 >> 2) & 0x03030303)); + const vec4 qs_u32_4 = vec4(unpack8((qs_u32 >> 4) & 0x03030303)); + const vec4 qs_u32_6 = vec4(unpack8((qs_u32 >> 6) & 0x03030303)); + + vec2 d = vec2(data_a[ib0 + i].d); + const FLOAT_TYPE dall = FLOAT_TYPE(d.x); + const FLOAT_TYPE dmin = FLOAT_TYPE(d.y); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec2 b0 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 0]); + vec2 b16 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 8]); + vec2 b32 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 16]); + vec2 b48 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 24]); + vec2 b64 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 32]); + vec2 b80 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 40]); + vec2 b96 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 48]); + vec2 b112 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 56]); + + 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[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])); + } + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { uint a_offset, b_offset, d_offset; get_offsets(a_offset, b_offset, d_offset); const uint num_blocks_per_row = p.ncols / QUANT_K; - const uint ib0 = a_offset / QUANT_K + row*num_blocks_per_row; - const uint tid = gl_LocalInvocationID.x/K_QUANTS_PER_ITERATION; // 0...31 or 0...16 - const uint ix = gl_LocalInvocationID.x%K_QUANTS_PER_ITERATION; // 0 or 0, 1 + // 16 threads are used to process each block + const uint it_size = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid%16; // 0...15 + const uint ix = tid/16; - const uint step = 16/K_QUANTS_PER_ITERATION; // 16 or 8 + const uint v_im = itid/8; // 0 or 1. 0 computes 0..., 1 computes 128... + const uint v_in = itid - 8*v_im; // 0...7 - const uint v_im = tid/step; // 0 or 1. 0 computes 0..., 1 computes 128... - const uint v_in = tid - step*v_im; // 0...15 or 0...7 - - const uint l0 = K_QUANTS_PER_ITERATION*v_in; // 0...15 + const uint l0 = 2*v_in; // 0...15 const uint q_offset = 32*v_im + l0; - const uint s_offset = 8*v_im; const uint y_offset = 128*v_im + l0; - tmp[16 * ix + tid] = FLOAT_TYPE(0.0); // partial sum for thread in warp - - [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += K_QUANTS_PER_ITERATION) { - const uint y_idx = i * QUANT_K + y_offset; - - const FLOAT_TYPE dall = FLOAT_TYPE(data_a[ib0 + i].d.x); - const FLOAT_TYPE dmin = FLOAT_TYPE(data_a[ib0 + i].d.y); - - FLOAT_TYPE sum1 = FLOAT_TYPE(0.0); - FLOAT_TYPE sum2 = FLOAT_TYPE(0.0); - for (int l = 0; l < K_QUANTS_PER_ITERATION; ++l) { - sum1 += FLOAT_TYPE(data_b[b_offset + y_idx + l + 0]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 0] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l + 0] >> 0) & 3) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 16]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 1] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l +16] >> 0) & 3) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 32]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 2] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l + 0] >> 2) & 3) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 48]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 3] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l +16] >> 2) & 3) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 64]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 4] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l + 0] >> 4) & 3) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 80]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 5] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l +16] >> 4) & 3) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 96]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 6] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l + 0] >> 6) & 3) - + FLOAT_TYPE(data_b[b_offset + y_idx + l +112]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 7] & 0xF) * FLOAT_TYPE((data_a[ib0 + i].qs[q_offset + l +16] >> 6) & 3); - sum2 += FLOAT_TYPE(data_b[b_offset + y_idx + l + 0]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 0] >> 4) & 0xF) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 16]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 1] >> 4) & 0xF) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 32]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 2] >> 4) & 0xF) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 48]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 3] >> 4) & 0xF) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 64]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 4] >> 4) & 0xF) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 80]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 5] >> 4) & 0xF) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 96]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 6] >> 4) & 0xF) - + FLOAT_TYPE(data_b[b_offset + y_idx + l +112]) * FLOAT_TYPE((data_a[ib0 + i].scales[s_offset + 7] >> 4) & 0xF); + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); } - tmp[16 * ix + tid] += dall * sum1 - dmin * sum2; } - // sum up partial sums and write back result - barrier(); - [[unroll]] for (uint s = 16; s > 0; s >>= 1) { - if (tid < s) { - tmp[tid] += tmp[tid + s]; + const uint nbr_par_th = num_blocks_per_row%it_size; + const uint nbr_all_th = num_blocks_per_row - nbr_par_th; + uint i0 = 0; + [[unroll]] for (; i0 < nbr_all_th; i0 += it_size) + calc_superblock(a_offset, b_offset, itid, v_im, ix, q_offset, y_offset, i0 + ix, num_blocks_per_row, first_row, num_rows, true); + calc_superblock(a_offset, b_offset, itid, v_im, ix, q_offset, y_offset, i0 + ix, num_blocks_per_row, first_row, num_rows, false); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; } - barrier(); - } - if (tid == 0) { - data_d[d_offset + row] = D_TYPE(tmp[0]); + compute_outputs(first_row, p.stride_d - first_row); } } diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_q3_k.comp b/ggml/src/vulkan-shaders/mul_mat_vec_q3_k.comp index a6e430ea..e91724a2 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_q3_k.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_q3_k.comp @@ -1,66 +1,132 @@ #version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require #include "mul_mat_vec_base.comp" -layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE tmp[32]; +shared FLOAT_TYPE sccache[2][BLOCK_SIZE/16][2][8]; -void main() { - const uint row = gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z; +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 + if (i < num_blocks_per_row) + 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) + continue; + } + + const uint32_t hmk = ~(uint32_t(data_a_packed16[ib0 + i].hmask[v_in]) | (uint32_t(data_a_packed16[ib0 + i].hmask[v_in + 8]) << 16)); + const vec4 hmk_0 = vec4(unpack8(((hmk & hm_m[0]) >> ( v_im4)) << 2)); + const vec4 hmk_1 = vec4(unpack8(((hmk & hm_m[1]) >> (1 + v_im4)) << 2)); + const vec4 hmk_2 = vec4(unpack8(((hmk & hm_m[2]) >> (2 + v_im4)) << 2)); + const vec4 hmk_3 = vec4(unpack8(((hmk & hm_m[3]) >> (3 + v_im4)) << 2)); + + // 0, 1, 16, 17 + uint32_t qs_u32 = uint32_t(data_a[ib0 + i].qs[q_offset]) | (uint32_t(data_a[ib0 + i].qs[q_offset + 1]) << 8); + qs_u32 |= (uint32_t(data_a[ib0 + i].qs[q_offset + 16]) | (uint32_t(data_a[ib0 + i].qs[q_offset + 17]) << 8)) << 16; + const vec4 qs_u32_0 = vec4(unpack8(qs_u32 & 0x03030303)); + const vec4 qs_u32_2 = vec4(unpack8((qs_u32 >> 2) & 0x03030303)); + const vec4 qs_u32_4 = vec4(unpack8((qs_u32 >> 4) & 0x03030303)); + const vec4 qs_u32_6 = vec4(unpack8((qs_u32 >> 6) & 0x03030303)); + + if (all_threads) { + 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(); + } + + const FLOAT_TYPE d = FLOAT_TYPE(data_a[ib0 + i].d); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec2 b0 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 0]); + vec2 b16 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 8]); + vec2 b32 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 16]); + vec2 b48 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 24]); + vec2 b64 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 32]); + vec2 b80 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 40]); + vec2 b96 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 48]); + vec2 b112 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y_idx) / 2 + 56]); + + FLOAT_TYPE sum = FLOAT_TYPE(0.0); + [[unroll]] for (int l = 0; l < 2; ++l) { + 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]); + } + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { uint a_offset, b_offset, d_offset; get_offsets(a_offset, b_offset, d_offset); const uint num_blocks_per_row = p.ncols / QUANT_K; - const uint ib0 = a_offset / QUANT_K + row*num_blocks_per_row; - const uint tid = gl_LocalInvocationID.x/K_QUANTS_PER_ITERATION; // 0...31 or 0...16 - const uint ix = gl_LocalInvocationID.x%K_QUANTS_PER_ITERATION; // 0 or 0, 1 + // 16 threads are used to process each block + const uint it_size = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid%16; // 0...15 + const uint ix = tid/16; + const uint itid8 = itid%8; - const uint step = 16/K_QUANTS_PER_ITERATION; // 16 or 8 + const uint v_im = itid/8; // 0 or 1. 0 computes 0..., 1 computes 128... + const uint v_im4 = v_im*4; + const uint v_in = itid - 8*v_im; // 0...7 - const uint v_im = tid/step; // 0 or 1. 0 computes 0..., 1 computes 128... - const uint v_in = tid - step*v_im; // 0...15 or 0...7 + const uint32_t m = 0x01010101 << (4 * v_im); + uint32_t hm_m[4]; + [[unroll]] for (uint j = 0; j < 4; ++j) + hm_m[j] = m << j; - const uint8_t m = uint8_t(1 << (4 * v_im)); - - const uint l0 = K_QUANTS_PER_ITERATION*v_in; // 0...15 + const uint l0 = 2*v_in; // 0...15 const uint q_offset = 32*v_im + l0; const uint y_offset = 128*v_im + l0; - tmp[16 * ix + tid] = FLOAT_TYPE(0.0); // partial sum for thread in warp - - const uint s_shift = 4 * v_im; - - [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += K_QUANTS_PER_ITERATION) { - const uint y_idx = i * QUANT_K + y_offset; - - const FLOAT_TYPE d = FLOAT_TYPE(data_a[ib0 + i].d); - - FLOAT_TYPE sum = FLOAT_TYPE(0.0); - for (int l = 0; l < K_QUANTS_PER_ITERATION; ++l) { - sum += FLOAT_TYPE(data_b[b_offset + y_idx + l + 0]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[0] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[ 8] >> (s_shift + 0) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l ] ) & 3) - (((data_a[ib0 + i].hmask[l0 + l ] & (m << 0)) != 0) ? 0 : 4)) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 32]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[2] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[10] >> (s_shift + 0) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l ] >> 2) & 3) - (((data_a[ib0 + i].hmask[l0 + l ] & (m << 1)) != 0) ? 0 : 4)) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 64]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[4] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[ 8] >> (s_shift + 2) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l ] >> 4) & 3) - (((data_a[ib0 + i].hmask[l0 + l ] & (m << 2)) != 0) ? 0 : 4)) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 96]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[6] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[10] >> (s_shift + 2) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l ] >> 6) & 3) - (((data_a[ib0 + i].hmask[l0 + l ] & (m << 3)) != 0) ? 0 : 4)) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 16]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[1] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[ 9] >> (s_shift + 0) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l+16] ) & 3) - (((data_a[ib0 + i].hmask[l0 + l+16] & (m << 0)) != 0) ? 0 : 4)) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 48]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[3] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[11] >> (s_shift + 0) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l+16] >> 2) & 3) - (((data_a[ib0 + i].hmask[l0 + l+16] & (m << 1)) != 0) ? 0 : 4)) - + FLOAT_TYPE(data_b[b_offset + y_idx + l + 80]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[5] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[ 9] >> (s_shift + 2) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l+16] >> 4) & 3) - (((data_a[ib0 + i].hmask[l0 + l+16] & (m << 2)) != 0) ? 0 : 4)) - + FLOAT_TYPE(data_b[b_offset + y_idx + l +112]) * FLOAT_TYPE(int8_t(((data_a[ib0 + i].scales[7] >> s_shift) & 0xF) | ((data_a[ib0 + i].scales[11] >> (s_shift + 2) & 0x3) << 4)) - 32) * FLOAT_TYPE(((data_a[ib0 + i].qs[q_offset + l+16] >> 6) & 3) - (((data_a[ib0 + i].hmask[l0 + l+16] & (m << 3)) != 0) ? 0 : 4)); + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); } - tmp[16 * ix + tid] += d * sum; } - // sum up partial sums and write back result - barrier(); - [[unroll]] for (uint s = 16; s > 0; s >>= 1) { - if (tid < s) { - tmp[tid] += tmp[tid + s]; + const uint s_shift = v_im4 + 2*(itid8/4); + + const uint nbr_par_th = num_blocks_per_row%it_size; + const uint nbr_all_th = num_blocks_per_row - nbr_par_th; + uint i0 = 0; + [[unroll]] for (; i0 < nbr_all_th; i0 += it_size) + calc_superblock(a_offset, b_offset, ix, itid8, v_im, v_im4, v_in, hm_m, q_offset, y_offset, s_shift, i0 + ix, num_blocks_per_row, first_row, num_rows, true); + calc_superblock(a_offset, b_offset, ix, itid8, v_im, v_im4, v_in, hm_m, q_offset, y_offset, s_shift, i0 + ix, num_blocks_per_row, first_row, num_rows, false); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; } - barrier(); - } - if (tid == 0) { - data_d[d_offset + row] = D_TYPE(tmp[0]); + compute_outputs(first_row, p.stride_d - first_row); } } diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_q4_k.comp b/ggml/src/vulkan-shaders/mul_mat_vec_q4_k.comp index 75569363..f9cde064 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_q4_k.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_q4_k.comp @@ -1,28 +1,106 @@ #version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + #include "mul_mat_vec_base.comp" -layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE tmp[32]; +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; -void main() { - const uint row = gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z; +void calc_superblock(const uint a_offset, const uint b_offset, const uint v_im, 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 uint y1_idx = i * QUANT_K + y_offset; + const uint y2_idx = y1_idx + 128; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const uint ib0 = a_offset / QUANT_K + (first_row+n)*num_blocks_per_row; + vec2 d = vec2(data_a[ib0 + i].d); + const FLOAT_TYPE dall = FLOAT_TYPE(d.x); + const FLOAT_TYPE dmin = FLOAT_TYPE(d.y); + + const uint32_t scale0_u32 = data_a_packed16[ib0 + i].scales[v_im ]; + const uint32_t scale4_u32 = data_a_packed16[ib0 + i].scales[v_im + 2]; + const uint32_t scale8_u32 = data_a_packed16[ib0 + i].scales[v_im + 4]; + + const uint32_t scale_0_4_l = (scale4_u32 << 16) | scale0_u32; + const uint32_t scale_0_4_h = (scale_0_4_l & 0xC0C0C0C0) >> 2; + const vec4 scale_0_4_l_f = vec4(unpack8(scale_0_4_l & 0x3F3F3F3F)); + const vec4 scale8_f = vec4(unpack8((((scale8_u32 << 12) | scale8_u32) & 0x0F0F0F0F) | scale_0_4_h)); + + const FLOAT_TYPE sc0 = scale_0_4_l_f.x; + const FLOAT_TYPE sc1 = scale_0_4_l_f.y; + const FLOAT_TYPE sc2 = scale_0_4_l_f.z; + const FLOAT_TYPE sc3 = scale_0_4_l_f.w; + const FLOAT_TYPE sc4 = scale8_f.x; + const FLOAT_TYPE sc5 = scale8_f.y; + const FLOAT_TYPE sc6 = scale8_f.z; + const FLOAT_TYPE sc7 = scale8_f.w; + + const uint32_t qs0_u32 = data_a_packed32[ib0 + i].qs[q_offset / 4]; + const uint32_t qs64_u32 = data_a_packed32[ib0 + i].qs[q_offset / 4 + 16]; + + const uint32_t qs0_u32_lo4 = qs0_u32 & 0x0F0F0F0F; + const uint32_t qs0_u32_hi4 = (qs0_u32 >> 4) & 0x0F0F0F0F; + const uint32_t qs64_u32_lo4 = qs64_u32 & 0x0F0F0F0F; + const uint32_t qs64_u32_hi4 = (qs64_u32 >> 4) & 0x0F0F0F0F; + + const vec4 qs0_lo4 = vec4(unpack8(qs0_u32_lo4)); + const vec4 qs64_lo4 = vec4(unpack8(qs64_u32_lo4)); + const vec4 qs0_hi4 = vec4(unpack8(qs0_u32_hi4)); + const vec4 qs64_hi4 = vec4(unpack8(qs64_u32_hi4)); + + const FLOAT_TYPE q4_0 = qs0_lo4.x; + const FLOAT_TYPE q4_1 = qs0_lo4.y; + const FLOAT_TYPE q4_2 = qs0_lo4.z; + const FLOAT_TYPE q4_3 = qs0_lo4.w; + const FLOAT_TYPE q4_4 = qs0_hi4.x; + const FLOAT_TYPE q4_5 = qs0_hi4.y; + const FLOAT_TYPE q4_6 = qs0_hi4.z; + const FLOAT_TYPE q4_7 = qs0_hi4.w; + const FLOAT_TYPE q4_8 = qs64_lo4.x; + const FLOAT_TYPE q4_9 = qs64_lo4.y; + const FLOAT_TYPE q4_10 = qs64_lo4.z; + const FLOAT_TYPE q4_11 = qs64_lo4.w; + const FLOAT_TYPE q4_12 = qs64_hi4.x; + const FLOAT_TYPE q4_13 = qs64_hi4.y; + const FLOAT_TYPE q4_14 = qs64_hi4.z; + const FLOAT_TYPE q4_15 = qs64_hi4.w; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec4 by10 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y1_idx) / 4 ]); + vec4 by132 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y1_idx) / 4 + 8]); + vec4 by20 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y2_idx) / 4 ]); + vec4 by232 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y2_idx) / 4 + 8]); + + const FLOAT_TYPE sx = fma(FLOAT_TYPE(by10.x), q4_0, fma(FLOAT_TYPE(by10.y), q4_1, fma(FLOAT_TYPE(by10.z), q4_2, FLOAT_TYPE(by10.w) * q4_3))); + const FLOAT_TYPE sy = fma(FLOAT_TYPE(by132.x), q4_4, fma(FLOAT_TYPE(by132.y), q4_5, fma(FLOAT_TYPE(by132.z), q4_6, FLOAT_TYPE(by132.w) * q4_7))); + const FLOAT_TYPE sz = fma(FLOAT_TYPE(by20.x), q4_8, fma(FLOAT_TYPE(by20.y), q4_9, fma(FLOAT_TYPE(by20.z), q4_10, FLOAT_TYPE(by20.w) * q4_11))); + const FLOAT_TYPE sw = fma(FLOAT_TYPE(by232.x), q4_12, fma(FLOAT_TYPE(by232.y), q4_13, fma(FLOAT_TYPE(by232.z), q4_14, FLOAT_TYPE(by232.w) * q4_15))); + const FLOAT_TYPE smin = + fma(FLOAT_TYPE(by10.x), sc2, fma(FLOAT_TYPE(by132.x), sc3, fma(FLOAT_TYPE(by20.x), sc6, fma(FLOAT_TYPE(by232.x), sc7, + fma(FLOAT_TYPE(by10.y), sc2, fma(FLOAT_TYPE(by132.y), sc3, fma(FLOAT_TYPE(by20.y), sc6, fma(FLOAT_TYPE(by232.y), sc7, + fma(FLOAT_TYPE(by10.z), sc2, fma(FLOAT_TYPE(by132.z), sc3, fma(FLOAT_TYPE(by20.z), sc6, fma(FLOAT_TYPE(by232.z), sc7, + fma(FLOAT_TYPE(by10.w), sc2, fma(FLOAT_TYPE(by132.w), sc3, fma(FLOAT_TYPE(by20.w), sc6, FLOAT_TYPE(by232.w) * sc7))))))))))))))); + temp[j][n] = fma(dall, fma(sx, sc0, fma(sy, sc1, fma(sz, sc4, sw * sc5))), fma(-dmin, smin, temp[j][n])); + } + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { uint a_offset, b_offset, d_offset; get_offsets(a_offset, b_offset, d_offset); const uint num_blocks_per_row = p.ncols / QUANT_K; - const uint ib0 = a_offset / QUANT_K + row*num_blocks_per_row; - const uint tid = gl_LocalInvocationID.x/K_QUANTS_PER_ITERATION; // 0...31 or 0...16 - const uint ix = gl_LocalInvocationID.x%K_QUANTS_PER_ITERATION; // 0 or 0, 1 + // 16 threads are used to process each block + const uint it_size = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid%16; // 0...15 + const uint ix = tid/16; - const uint step = 8/K_QUANTS_PER_ITERATION; // 8 or 4 - - const uint il = tid/step; // 0...3 - const uint ir = tid - step*il; // 0...7 or 0...3 - const uint n = 2 * K_QUANTS_PER_ITERATION; // 2 or 4 + const uint il = itid/4; // 0...3 + const uint ir = itid - 4*il; // 0...3 + const uint n = 4; const uint v_im = il / 2; // 0 or 1. 0 computes 0,32 + 128,160, 1 computes 64,96 + 192,224 const uint v_in = il % 2; @@ -31,85 +109,28 @@ void main() { const uint q_offset = 32*v_im + l0; const uint y_offset = 64*v_im + l0; - tmp[16 * ix + tid] = FLOAT_TYPE(0.0); // partial sum for thread in warp - - [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += K_QUANTS_PER_ITERATION) { - const uint y1_idx = i * QUANT_K + y_offset; - const uint y2_idx = y1_idx + 128; - - const FLOAT_TYPE dall = FLOAT_TYPE(data_a[ib0 + i].d.x); - const FLOAT_TYPE dmin = FLOAT_TYPE(data_a[ib0 + i].d.y); - - const uint8_t sc0 = uint8_t( data_a[ib0 + i].scales[v_im * 2 ] & 0x3f); - const uint8_t sc1 = uint8_t( data_a[ib0 + i].scales[v_im * 2 + 1] & 0x3f); - const uint8_t sc2 = uint8_t( data_a[ib0 + i].scales[v_im * 2 + 4] & 0x3f); - const uint8_t sc3 = uint8_t( data_a[ib0 + i].scales[v_im * 2 + 5] & 0x3f); - const uint8_t sc4 = uint8_t(( data_a[ib0 + i].scales[v_im * 2 + 8] & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 ] & 0xc0) >> 2)); - const uint8_t sc5 = uint8_t(( data_a[ib0 + i].scales[v_im * 2 + 9] & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 + 1] & 0xc0) >> 2)); - const uint8_t sc6 = uint8_t(((data_a[ib0 + i].scales[v_im * 2 + 8] >> 4) & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 + 4] & 0xc0) >> 2)); - const uint8_t sc7 = uint8_t(((data_a[ib0 + i].scales[v_im * 2 + 9] >> 4) & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 + 5] & 0xc0) >> 2)); - -#if K_QUANTS_PER_ITERATION == 2 - const uint8_t q4_0 = uint8_t(data_a[ib0 + i].qs[q_offset ] & 0xf); - const uint8_t q4_1 = uint8_t(data_a[ib0 + i].qs[q_offset + 1] & 0xf); - const uint8_t q4_2 = uint8_t(data_a[ib0 + i].qs[q_offset + 2] & 0xf); - const uint8_t q4_3 = uint8_t(data_a[ib0 + i].qs[q_offset + 3] & 0xf); - const uint8_t q4_4 = uint8_t(data_a[ib0 + i].qs[q_offset ] >> 4); - const uint8_t q4_5 = uint8_t(data_a[ib0 + i].qs[q_offset + 1] >> 4); - const uint8_t q4_6 = uint8_t(data_a[ib0 + i].qs[q_offset + 2] >> 4); - const uint8_t q4_7 = uint8_t(data_a[ib0 + i].qs[q_offset + 3] >> 4); - const uint8_t q4_8 = uint8_t(data_a[ib0 + i].qs[q_offset + 64] & 0xf); - const uint8_t q4_9 = uint8_t(data_a[ib0 + i].qs[q_offset + 65] & 0xf); - const uint8_t q4_10 = uint8_t(data_a[ib0 + i].qs[q_offset + 66] & 0xf); - const uint8_t q4_11 = uint8_t(data_a[ib0 + i].qs[q_offset + 67] & 0xf); - const uint8_t q4_12 = uint8_t(data_a[ib0 + i].qs[q_offset + 64] >> 4); - const uint8_t q4_13 = uint8_t(data_a[ib0 + i].qs[q_offset + 65] >> 4); - const uint8_t q4_14 = uint8_t(data_a[ib0 + i].qs[q_offset + 66] >> 4); - const uint8_t q4_15 = uint8_t(data_a[ib0 + i].qs[q_offset + 67] >> 4); - - const FLOAT_TYPE sx = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y1_idx]) * q4_0 + FLOAT_TYPE(data_b[b_offset + y1_idx + 1]) * q4_1 + FLOAT_TYPE(data_b[b_offset + y1_idx + 2]) * q4_2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 3]) * q4_3); - const FLOAT_TYPE sy = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y1_idx + 32]) * q4_4 + FLOAT_TYPE(data_b[b_offset + y1_idx + 33]) * q4_5 + FLOAT_TYPE(data_b[b_offset + y1_idx + 34]) * q4_6 + FLOAT_TYPE(data_b[b_offset + y1_idx + 35]) * q4_7); - const FLOAT_TYPE sz = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y2_idx]) * q4_8 + FLOAT_TYPE(data_b[b_offset + y2_idx + 1]) * q4_9 + FLOAT_TYPE(data_b[b_offset + y2_idx + 2]) * q4_10 + FLOAT_TYPE(data_b[b_offset + y2_idx + 3]) * q4_11); - const FLOAT_TYPE sw = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y2_idx + 32]) * q4_12 + FLOAT_TYPE(data_b[b_offset + y2_idx + 33]) * q4_13 + FLOAT_TYPE(data_b[b_offset + y2_idx + 34]) * q4_14 + FLOAT_TYPE(data_b[b_offset + y2_idx + 35]) * q4_15); - const FLOAT_TYPE smin = FLOAT_TYPE( - FLOAT_TYPE(data_b[b_offset + y1_idx ]) * sc2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 32]) * sc3 + FLOAT_TYPE(data_b[b_offset + y2_idx ]) * sc6 + FLOAT_TYPE(data_b[b_offset + y2_idx + 32]) * sc7 - + FLOAT_TYPE(data_b[b_offset + y1_idx + 1]) * sc2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 33]) * sc3 + FLOAT_TYPE(data_b[b_offset + y2_idx + 1]) * sc6 + FLOAT_TYPE(data_b[b_offset + y2_idx + 33]) * sc7 - + FLOAT_TYPE(data_b[b_offset + y1_idx + 2]) * sc2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 34]) * sc3 + FLOAT_TYPE(data_b[b_offset + y2_idx + 2]) * sc6 + FLOAT_TYPE(data_b[b_offset + y2_idx + 34]) * sc7 - + FLOAT_TYPE(data_b[b_offset + y1_idx + 3]) * sc2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 35]) * sc3 + FLOAT_TYPE(data_b[b_offset + y2_idx + 3]) * sc6 + FLOAT_TYPE(data_b[b_offset + y2_idx + 35]) * sc7 - ); - tmp[16 * ix + tid] += FLOAT_TYPE(dall * (sx * sc0 + sy * sc1 + sz * sc4 + sw * sc5) - dmin * smin); -#else - const uint8_t q4_0 = uint8_t(data_a[ib0 + i].qs[q_offset ] & 0xf); - const uint8_t q4_1 = uint8_t(data_a[ib0 + i].qs[q_offset + 1] & 0xf); - const uint8_t q4_2 = uint8_t(data_a[ib0 + i].qs[q_offset ] >> 4); - const uint8_t q4_3 = uint8_t(data_a[ib0 + i].qs[q_offset + 1] >> 4); - const uint8_t q4_4 = uint8_t(data_a[ib0 + i].qs[q_offset + 64] & 0xf); - const uint8_t q4_5 = uint8_t(data_a[ib0 + i].qs[q_offset + 65] & 0xf); - const uint8_t q4_6 = uint8_t(data_a[ib0 + i].qs[q_offset + 64] >> 4); - const uint8_t q4_7 = uint8_t(data_a[ib0 + i].qs[q_offset + 65] >> 4); - - const FLOAT_TYPE sx = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y1_idx ]) * q4_0 + FLOAT_TYPE(data_b[b_offset + y1_idx + 1]) * q4_1); - const FLOAT_TYPE sy = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y1_idx + 32]) * q4_2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 33]) * q4_3); - const FLOAT_TYPE sz = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y2_idx ]) * q4_4 + FLOAT_TYPE(data_b[b_offset + y2_idx + 1]) * q4_5); - const FLOAT_TYPE sw = FLOAT_TYPE(FLOAT_TYPE(data_b[b_offset + y2_idx + 32]) * q4_6 + FLOAT_TYPE(data_b[b_offset + y2_idx + 33]) * q4_7); - const FLOAT_TYPE smin = FLOAT_TYPE( - FLOAT_TYPE(data_b[b_offset + y1_idx]) * sc2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 32]) * sc3 + FLOAT_TYPE(data_b[b_offset + y2_idx]) * sc6 + FLOAT_TYPE(data_b[b_offset + y2_idx + 32]) * sc7 - + FLOAT_TYPE(data_b[b_offset + y1_idx + 1]) * sc2 + FLOAT_TYPE(data_b[b_offset + y1_idx + 33]) * sc3 + FLOAT_TYPE(data_b[b_offset + y2_idx + 1]) * sc6 + FLOAT_TYPE(data_b[b_offset + y2_idx + 33]) * sc7 - ); - - tmp[16 * ix + tid] += FLOAT_TYPE(dall * (sx * FLOAT_TYPE(data_a[ib0 + i].scales[v_im] & 0x3f) + sy * FLOAT_TYPE(data_a[ib0 + i].scales[v_im + 1] & 0x3f) + sz * FLOAT_TYPE((data_a[ib0 + i].scales[v_im + 4] & 0x0f) | ((data_a[ib0 + i].scales[v_im] & 0xc0) >> 2)) + sw * FLOAT_TYPE((data_a[ib0 + i].scales[v_im + 5] & 0x0f) | ((data_a[ib0 + i].scales[v_im + 1] & 0xc0) >> 2))) - dmin * smin); -#endif - } - - // sum up partial sums and write back result - barrier(); - [[unroll]] for (uint s = 16; s > 0; s >>= 1) { - if (tid < s) { - tmp[tid] += tmp[tid + s]; + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); } - barrier(); } - if (tid == 0) { - data_d[d_offset + row] = D_TYPE(tmp[0]); + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += it_size) + calc_superblock(a_offset, b_offset, v_im, q_offset, y_offset, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); } } diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_q5_k.comp b/ggml/src/vulkan-shaders/mul_mat_vec_q5_k.comp index 9be3645b..6c84ef3c 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_q5_k.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_q5_k.comp @@ -1,25 +1,137 @@ #version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + #include "mul_mat_vec_base.comp" -layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE tmp[32]; +FLOAT_TYPE temp[NUM_COLS][NUM_ROWS]; -void main() { - const uint row = gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z; +void calc_superblock(const uint a_offset, const uint b_offset, const uint v_im, const uint l0, 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 uint y1_idx = i * QUANT_K + y_offset; + const uint y2_idx = y1_idx + 128; + [[unroll]] for (uint n = 0; n < num_rows; ++n) { + const uint ib0 = a_offset / QUANT_K + (first_row+n)*num_blocks_per_row; + vec2 d = vec2(data_a[ib0 + i].d); + const FLOAT_TYPE dall = FLOAT_TYPE(d.x); + const FLOAT_TYPE dmin = FLOAT_TYPE(d.y); + + const uint32_t scale0_u32 = data_a_packed16[ib0 + i].scales[v_im ]; + const uint32_t scale4_u32 = data_a_packed16[ib0 + i].scales[v_im + 2]; + const uint32_t scale8_u32 = data_a_packed16[ib0 + i].scales[v_im + 4]; + + const uint32_t scale_0_4_l = (scale4_u32 << 16) | scale0_u32; + const uint32_t scale_0_4_h = (scale_0_4_l & 0xC0C0C0C0) >> 2; + const vec4 scale_0_4_l_f = vec4(unpack8(scale_0_4_l & 0x3F3F3F3F)); + const vec4 scale8_f = vec4(unpack8((((scale8_u32 << 12) | scale8_u32) & 0x0F0F0F0F) | scale_0_4_h)); + + const FLOAT_TYPE sc0 = scale_0_4_l_f.x; + const FLOAT_TYPE sc1 = scale_0_4_l_f.y; + const FLOAT_TYPE sc2 = scale_0_4_l_f.z; + const FLOAT_TYPE sc3 = scale_0_4_l_f.w; + const FLOAT_TYPE sc4 = scale8_f.x; + const FLOAT_TYPE sc5 = scale8_f.y; + const FLOAT_TYPE sc6 = scale8_f.z; + const FLOAT_TYPE sc7 = scale8_f.w; + + const uint32_t qs0_16_u32 = uint32_t(data_a_packed16[ib0 + i].qs[q_offset / 2]) | (uint32_t(data_a_packed16[ib0 + i].qs[q_offset / 2 + 8]) << 16); + const uint32_t qs64_80_u32 = uint32_t(data_a_packed16[ib0 + i].qs[q_offset / 2 + 32]) | (uint32_t(data_a_packed16[ib0 + i].qs[q_offset / 2 + 40]) << 16); + + uint32_t qs0_16_u32_lo4 = qs0_16_u32 & 0x0F0F0F0F; + uint32_t qs0_16_u32_hi4 = (qs0_16_u32 >> 4) & 0x0F0F0F0F; + uint32_t qs64_80_u32_lo4 = qs64_80_u32 & 0x0F0F0F0F; + uint32_t qs64_80_u32_hi4 = (qs64_80_u32 >> 4) & 0x0F0F0F0F; + + const uint32_t qh = pack32(u16vec2(data_a_packed16[ib0 + i].qh[l0 / 2], data_a_packed16[ib0 + i].qh[l0 / 2 + 8])); + + const uint32_t qs0_16_lo4_offset16 = ((qh >> (2*v_im)) & 0x01010101) << 4; + const uint32_t qs0_16_hi4_offset16 = ((qh >> (2*v_im)) & 0x02020202) << 3; + const uint32_t qs64_80_lo4_offset16 = ((qh >> (2*v_im)) & 0x10101010); + const uint32_t qs64_80_hi4_offset16 = ((qh >> (2*v_im)) & 0x20202020) >> 1; + + qs0_16_u32_lo4 += qs0_16_lo4_offset16; + qs0_16_u32_hi4 += qs0_16_hi4_offset16; + qs64_80_u32_lo4 += qs64_80_lo4_offset16; + qs64_80_u32_hi4 += qs64_80_hi4_offset16; + + const vec4 qs0_16_lo4 = vec4(unpack8(qs0_16_u32_lo4)); + const vec4 qs64_80_lo4 = vec4(unpack8(qs64_80_u32_lo4)); + const vec4 qs0_16_hi4 = vec4(unpack8(qs0_16_u32_hi4)); + const vec4 qs64_80_hi4 = vec4(unpack8(qs64_80_u32_hi4)); + + const FLOAT_TYPE q4_0 = qs0_16_lo4.x; + const FLOAT_TYPE q4_1 = qs0_16_lo4.y; + const FLOAT_TYPE q4_2 = qs0_16_lo4.z; + const FLOAT_TYPE q4_3 = qs0_16_lo4.w; + const FLOAT_TYPE q4_4 = qs0_16_hi4.x; + const FLOAT_TYPE q4_5 = qs0_16_hi4.y; + const FLOAT_TYPE q4_6 = qs0_16_hi4.z; + const FLOAT_TYPE q4_7 = qs0_16_hi4.w; + const FLOAT_TYPE q4_8 = qs64_80_lo4.x; + const FLOAT_TYPE q4_9 = qs64_80_lo4.y; + const FLOAT_TYPE q4_10 = qs64_80_lo4.z; + const FLOAT_TYPE q4_11 = qs64_80_lo4.w; + const FLOAT_TYPE q4_12 = qs64_80_hi4.x; + const FLOAT_TYPE q4_13 = qs64_80_hi4.y; + const FLOAT_TYPE q4_14 = qs64_80_hi4.z; + const FLOAT_TYPE q4_15 = qs64_80_hi4.w; + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec2 by10 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y1_idx) / 2 ]); + vec2 by116 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y1_idx) / 2 + 8]); + vec2 by132 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y1_idx) / 2 + 16]); + vec2 by148 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y1_idx) / 2 + 24]); + vec2 by20 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y2_idx) / 2 ]); + vec2 by216 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y2_idx) / 2 + 8]); + vec2 by232 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y2_idx) / 2 + 16]); + vec2 by248 = vec2(data_b_v2[(j*p.batch_stride_b + b_offset + y2_idx) / 2 + 24]); + + const FLOAT_TYPE sx = + fma(FLOAT_TYPE(by10.x), q4_0, + fma(FLOAT_TYPE(by10.y), q4_1, + fma(FLOAT_TYPE(by116.x), q4_2, + FLOAT_TYPE(by116.y) * q4_3))); + const FLOAT_TYPE sy = + fma(FLOAT_TYPE(by132.x), q4_4, + fma(FLOAT_TYPE(by132.y), q4_5, + fma(FLOAT_TYPE(by148.x), q4_6, + FLOAT_TYPE(by148.y) * q4_7))); + const FLOAT_TYPE sz = + fma(FLOAT_TYPE(by20.x), q4_8, + fma(FLOAT_TYPE(by20.y), q4_9, + fma(FLOAT_TYPE(by216.x), q4_10, + FLOAT_TYPE(by216.y) * q4_11))); + const FLOAT_TYPE sw = + fma(FLOAT_TYPE(by232.x), q4_12, + fma(FLOAT_TYPE(by232.y), q4_13, + fma(FLOAT_TYPE(by248.x), q4_14, + FLOAT_TYPE(by248.y) * q4_15))); + const FLOAT_TYPE smin = + fma(FLOAT_TYPE(by10.x) + FLOAT_TYPE(by10.y) + FLOAT_TYPE(by116.x) + FLOAT_TYPE(by116.y), sc2, + fma(FLOAT_TYPE(by132.x) + FLOAT_TYPE(by132.y) + FLOAT_TYPE(by148.x) + FLOAT_TYPE(by148.y), sc3, + fma(FLOAT_TYPE(by20.x) + FLOAT_TYPE(by20.y) + FLOAT_TYPE(by216.x) + FLOAT_TYPE(by216.y), sc6, + (FLOAT_TYPE(by232.x) + FLOAT_TYPE(by232.y) + FLOAT_TYPE(by248.x) + FLOAT_TYPE(by248.y)) * sc7))); + temp[j][n] = fma(dall, fma(sx, sc0, fma(sy, sc1, fma(sz, sc4, sw * sc5))), fma(-dmin, smin, temp[j][n])); + } + } +} + +void compute_outputs(const uint32_t first_row, const uint32_t num_rows) { uint a_offset, b_offset, d_offset; get_offsets(a_offset, b_offset, d_offset); const uint num_blocks_per_row = p.ncols / QUANT_K; - const uint ib0 = a_offset / QUANT_K + row*num_blocks_per_row; - const uint tid = gl_LocalInvocationID.x/2; // 0...31 or 0...16 - const uint ix = gl_LocalInvocationID.x%2; // 0 or 0, 1 + // 16 threads are used to process each block + const uint it_size = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid%16; // 0...15 + const uint ix = tid/16; - const uint il = tid/4; // 0...3 - const uint ir = tid - 4*il; // 0...7 or 0...3 + const uint il = itid/4; // 0...3 + const uint ir = itid - 4*il; // 0...3 const uint v_im = il / 2; // 0 or 1. 0 computes 0,32 + 128,160, 1 computes 64,96 + 192,224 const uint v_in = il % 2; @@ -28,84 +140,28 @@ void main() { const uint q_offset = 32*v_im + l0; const uint y_offset = 64*v_im + l0; - const uint8_t hm1 = uint8_t(1 << (2*v_im)); - const uint8_t hm2 = uint8_t(hm1 << 4); - - tmp[16 * ix + tid] = FLOAT_TYPE(0.0); // partial sum for thread in warp - - [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += 2) { - const uint y1_idx = i * QUANT_K + y_offset; - const uint y2_idx = y1_idx + 128; - - const FLOAT_TYPE dall = FLOAT_TYPE(data_a[ib0 + i].d.x); - const FLOAT_TYPE dmin = FLOAT_TYPE(data_a[ib0 + i].d.y); - - const uint8_t sc0 = uint8_t( data_a[ib0 + i].scales[v_im * 2 ] & 0x3f); - const uint8_t sc1 = uint8_t( data_a[ib0 + i].scales[v_im * 2 + 1] & 0x3f); - const uint8_t sc2 = uint8_t( data_a[ib0 + i].scales[v_im * 2 + 4] & 0x3f); - const uint8_t sc3 = uint8_t( data_a[ib0 + i].scales[v_im * 2 + 5] & 0x3f); - const uint8_t sc4 = uint8_t(( data_a[ib0 + i].scales[v_im * 2 + 8] & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 ] & 0xc0) >> 2)); - const uint8_t sc5 = uint8_t(( data_a[ib0 + i].scales[v_im * 2 + 9] & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 + 1] & 0xc0) >> 2)); - const uint8_t sc6 = uint8_t(((data_a[ib0 + i].scales[v_im * 2 + 8] >> 4) & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 + 4] & 0xc0) >> 2)); - const uint8_t sc7 = uint8_t(((data_a[ib0 + i].scales[v_im * 2 + 9] >> 4) & 0x0f) | ((data_a[ib0 + i].scales[v_im * 2 + 5] & 0xc0) >> 2)); - - const uint8_t q4_0 = uint8_t(data_a[ib0 + i].qs[q_offset ] & 0xf); - const uint8_t q4_1 = uint8_t(data_a[ib0 + i].qs[q_offset + 1] & 0xf); - const uint8_t q4_2 = uint8_t(data_a[ib0 + i].qs[q_offset + 16] & 0xf); - const uint8_t q4_3 = uint8_t(data_a[ib0 + i].qs[q_offset + 17] & 0xf); - const uint8_t q4_4 = uint8_t(data_a[ib0 + i].qs[q_offset ] >> 4); - const uint8_t q4_5 = uint8_t(data_a[ib0 + i].qs[q_offset + 1] >> 4); - const uint8_t q4_6 = uint8_t(data_a[ib0 + i].qs[q_offset + 16] >> 4); - const uint8_t q4_7 = uint8_t(data_a[ib0 + i].qs[q_offset + 17] >> 4); - const uint8_t q4_8 = uint8_t(data_a[ib0 + i].qs[q_offset + 64] & 0xf); - const uint8_t q4_9 = uint8_t(data_a[ib0 + i].qs[q_offset + 65] & 0xf); - const uint8_t q4_10 = uint8_t(data_a[ib0 + i].qs[q_offset + 80] & 0xf); - const uint8_t q4_11 = uint8_t(data_a[ib0 + i].qs[q_offset + 81] & 0xf); - const uint8_t q4_12 = uint8_t(data_a[ib0 + i].qs[q_offset + 64] >> 4); - const uint8_t q4_13 = uint8_t(data_a[ib0 + i].qs[q_offset + 65] >> 4); - const uint8_t q4_14 = uint8_t(data_a[ib0 + i].qs[q_offset + 80] >> 4); - const uint8_t q4_15 = uint8_t(data_a[ib0 + i].qs[q_offset + 81] >> 4); - - const FLOAT_TYPE sx = FLOAT_TYPE( - FLOAT_TYPE(data_b[b_offset + y1_idx ]) * (q4_0 + (((data_a[ib0 + i].qh[l0 ] & hm1) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y1_idx + 1]) * (q4_1 + (((data_a[ib0 + i].qh[l0 + 1] & hm1) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y1_idx + 16]) * (q4_2 + (((data_a[ib0 + i].qh[l0 + 16] & hm1) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y1_idx + 17]) * (q4_3 + (((data_a[ib0 + i].qh[l0 + 17] & hm1) != 0) ? 16 : 0)) - ); - const FLOAT_TYPE sy = FLOAT_TYPE( - FLOAT_TYPE(data_b[b_offset + y1_idx + 32]) * (q4_4 + (((data_a[ib0 + i].qh[l0 ] & (hm1 << 1)) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y1_idx + 33]) * (q4_5 + (((data_a[ib0 + i].qh[l0 + 1] & (hm1 << 1)) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y1_idx + 48]) * (q4_6 + (((data_a[ib0 + i].qh[l0 + 16] & (hm1 << 1)) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y1_idx + 49]) * (q4_7 + (((data_a[ib0 + i].qh[l0 + 17] & (hm1 << 1)) != 0) ? 16 : 0)) - ); - const FLOAT_TYPE sz = FLOAT_TYPE( - FLOAT_TYPE(data_b[b_offset + y2_idx ]) * (q4_8 + (((data_a[ib0 + i].qh[l0 ] & hm2) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y2_idx + 1]) * (q4_9 + (((data_a[ib0 + i].qh[l0 + 1] & hm2) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y2_idx + 16]) * (q4_10 + (((data_a[ib0 + i].qh[l0 + 16] & hm2) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y2_idx + 17]) * (q4_11 + (((data_a[ib0 + i].qh[l0 + 17] & hm2) != 0) ? 16 : 0)) - ); - const FLOAT_TYPE sw = FLOAT_TYPE( - FLOAT_TYPE(data_b[b_offset + y2_idx + 32]) * (q4_12 + (((data_a[ib0 + i].qh[l0 ] & (hm2 << 1)) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y2_idx + 33]) * (q4_13 + (((data_a[ib0 + i].qh[l0 + 1] & (hm2 << 1)) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y2_idx + 48]) * (q4_14 + (((data_a[ib0 + i].qh[l0 + 16] & (hm2 << 1)) != 0) ? 16 : 0)) - + FLOAT_TYPE(data_b[b_offset + y2_idx + 49]) * (q4_15 + (((data_a[ib0 + i].qh[l0 + 17] & (hm2 << 1)) != 0) ? 16 : 0)) - ); - const FLOAT_TYPE smin = FLOAT_TYPE( - (FLOAT_TYPE(data_b[b_offset + y1_idx]) + FLOAT_TYPE(data_b[b_offset + y1_idx + 1]) + FLOAT_TYPE(data_b[b_offset + y1_idx + 16]) + FLOAT_TYPE(data_b[b_offset + y1_idx + 17])) * sc2 + (FLOAT_TYPE(data_b[b_offset + y1_idx + 32]) + FLOAT_TYPE(data_b[b_offset + y1_idx + 33]) + FLOAT_TYPE(data_b[b_offset + y1_idx + 48]) + FLOAT_TYPE(data_b[b_offset + y1_idx + 49])) * sc3 - + (FLOAT_TYPE(data_b[b_offset + y2_idx]) + FLOAT_TYPE(data_b[b_offset + y2_idx + 1]) + FLOAT_TYPE(data_b[b_offset + y2_idx + 16]) + FLOAT_TYPE(data_b[b_offset + y2_idx + 17])) * sc6 + (FLOAT_TYPE(data_b[b_offset + y2_idx + 32]) + FLOAT_TYPE(data_b[b_offset + y2_idx + 33]) + FLOAT_TYPE(data_b[b_offset + y2_idx + 48]) + FLOAT_TYPE(data_b[b_offset + y2_idx + 49])) * sc7 - ); - tmp[16 * ix + tid] += FLOAT_TYPE(dall * (sx * sc0 + sy * sc1 + sz * sc4 + sw * sc5) - dmin * smin); - } - - // sum up partial sums and write back result - barrier(); - [[unroll]] for (uint s = 16; s > 0; s >>= 1) { - if (tid < s) { - tmp[tid] += tmp[tid + s]; + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); } - barrier(); } - if (tid == 0) { - data_d[d_offset + row] = D_TYPE(tmp[0]); + + [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += it_size) + calc_superblock(a_offset, b_offset, v_im, l0, q_offset, y_offset, i, num_blocks_per_row, first_row, num_rows); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); } } diff --git a/ggml/src/vulkan-shaders/mul_mat_vec_q6_k.comp b/ggml/src/vulkan-shaders/mul_mat_vec_q6_k.comp index d610cf03..d53d9ee0 100644 --- a/ggml/src/vulkan-shaders/mul_mat_vec_q6_k.comp +++ b/ggml/src/vulkan-shaders/mul_mat_vec_q6_k.comp @@ -1,79 +1,130 @@ #version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + #include "mul_mat_vec_base.comp" -layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; -shared FLOAT_TYPE tmp[32]; +shared FLOAT_TYPE sccache[2][BLOCK_SIZE/16][16]; -void main() { - const uint row = gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z; +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 + if (i < num_blocks_per_row) + sccache[csel][ix][itid] = FLOAT_TYPE(data_a[ib0 + i].scales[itid]); + barrier(); + + if (i >= num_blocks_per_row) + continue; + } + + const uint32_t ql0_u32 = uint32_t(data_a_packed16[ib0 + i].ql[ql_offset / 2]) | (uint32_t(data_a_packed16[ib0 + i].ql[ql_offset / 2 + 1]) << 16); + const uint32_t ql32_u32 = uint32_t(data_a_packed16[ib0 + i].ql[ql_offset / 2 + 16]) | (uint32_t(data_a_packed16[ib0 + i].ql[ql_offset / 2 + 17]) << 16); + + const uint32_t ql0_u32_lo4 = ql0_u32 & 0x0F0F0F0F; + const uint32_t ql0_u32_hi4 = (ql0_u32 >> 4) & 0x0F0F0F0F; + const uint32_t ql32_u32_lo4 = ql32_u32 & 0x0F0F0F0F; + const uint32_t ql32_u32_hi4 = (ql32_u32 >> 4) & 0x0F0F0F0F; + + const uint32_t qh_u32 = uint32_t(data_a_packed16[ib0 + i].qh[qh_offset / 2]) | (uint32_t(data_a_packed16[ib0 + i].qh[qh_offset / 2 + 1]) << 16); + const uint32_t qh0_u32 = (qh_u32 & 0x03030303) << 4; + const uint32_t qh2_u32 = (qh_u32 & 0x0C0C0C0C) << 2; + const uint32_t qh4_u32 = (qh_u32 & 0x30303030); + const uint32_t qh6_u32 = (qh_u32 & 0xC0C0C0C0) >> 2; + + const uint32_t q0_u32 = ql0_u32_lo4 | qh0_u32; + const uint32_t q1_u32 = ql32_u32_lo4 | qh2_u32; + const uint32_t q2_u32 = ql0_u32_hi4 | qh4_u32; + const uint32_t q3_u32 = ql32_u32_hi4 | qh6_u32; + + const vec4 q0 = vec4(unpack8(q0_u32)) - 32; + const vec4 q1 = vec4(unpack8(q1_u32)) - 32; + const vec4 q2 = vec4(unpack8(q2_u32)) - 32; + const vec4 q3 = vec4(unpack8(q3_u32)) - 32; + + if (all_threads) { + sccache[csel][ix][itid] = FLOAT_TYPE(data_a[ib0 + i].scales[itid]); + barrier(); + } + + const FLOAT_TYPE d = FLOAT_TYPE(data_a[ib0 + i].d); + + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + vec4 by0 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 ]); + vec4 by32 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 8]); + vec4 by64 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 16]); + vec4 by96 = vec4(data_b_v4[(j*p.batch_stride_b + b_offset + y_idx) / 4 + 24]); + + FLOAT_TYPE sum[4] = {0, 0, 0, 0}; + [[unroll]] for (uint l = 0; l < 4; ++l) { + sum[0] = fma(FLOAT_TYPE(by0[l]), q0[l], sum[0]); + sum[1] = fma(FLOAT_TYPE(by32[l]), q1[l], sum[1]); + 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[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]); + } + } +} + +void compute_outputs(const uint first_row, const uint num_rows) { uint a_offset, b_offset, d_offset; get_offsets(a_offset, b_offset, d_offset); const uint num_blocks_per_row = p.ncols / QUANT_K; - const uint ib0 = a_offset / QUANT_K + row*num_blocks_per_row; - const uint tid = gl_LocalInvocationID.x/K_QUANTS_PER_ITERATION; // 0...31 or 0...16 - const uint ix = gl_LocalInvocationID.x%K_QUANTS_PER_ITERATION; // 0 or 0, 1 + // 16 threads are used to process each block + const uint it_size = gl_WorkGroupSize.x/16; + const uint tid = gl_LocalInvocationID.x; + const uint itid = tid%16; // 0...15 + const uint ix = tid/16; - const uint step = 16/K_QUANTS_PER_ITERATION; // 16 or 8 + const uint v_im = itid/8; // 0 or 1. 0 computes 0..., 1 computes 128... + const uint v_in = itid - 8*v_im; // 0...7 - const uint v_im = tid/step; // 0 or 1. 0 computes 0..., 1 computes 128... - const uint v_in = tid - step*v_im; // 0...15 or 0...7 - -#if K_QUANTS_PER_ITERATION == 1 - const uint l0 = v_in; // 0...15 - const uint is = 0; -#else const uint l0 = 4 * v_in; // 0, 4, 8, ..., 28 const uint is = v_in / 4; -#endif const uint ql_offset = 64*v_im + l0; const uint qh_offset = 32*v_im + l0; const uint s_offset = 8*v_im + is; const uint y_offset = 128*v_im + l0; - tmp[16 * ix + tid] = FLOAT_TYPE(0.0); // partial sum for thread in warp - - [[unroll]] for (uint i = ix; i < num_blocks_per_row; i += K_QUANTS_PER_ITERATION) { - const uint y_idx = i * QUANT_K + y_offset; - - const FLOAT_TYPE d = FLOAT_TYPE(data_a[ib0 + i].d); - -#if K_QUANTS_PER_ITERATION == 1 - FLOAT_TYPE sum = FLOAT_TYPE(data_b[b_offset + y_idx + 0]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 0]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 0] & 0xF) | ((data_a[ib0 + i].qh[qh_offset + 0] & 0x03) << 4)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + 16]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 1]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 16] & 0xF) | ((data_a[ib0 + i].qh[qh_offset + 16] & 0x03) << 4)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + 32]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 2]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 32] & 0xF) | ((data_a[ib0 + i].qh[qh_offset + 0] & 0x0c) << 2)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + 48]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 3]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 48] & 0xF) | ((data_a[ib0 + i].qh[qh_offset + 16] & 0x0c) << 2)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + 64]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 4]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 0] >> 4) | ((data_a[ib0 + i].qh[qh_offset + 0] & 0x30) >> 0)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + 80]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 5]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 16] >> 4) | ((data_a[ib0 + i].qh[qh_offset + 16] & 0x30) >> 0)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + 96]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 6]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 32] >> 4) | ((data_a[ib0 + i].qh[qh_offset + 0] & 0xc0) >> 2)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx +112]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 7]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + 48] >> 4) | ((data_a[ib0 + i].qh[qh_offset + 16] & 0xc0) >> 2)) - 32); - tmp[16 * ix + tid] += sum; -#else - FLOAT_TYPE sum = FLOAT_TYPE(0.0); - [[unroll]] for (int l = 0; l < 4; ++l) { - sum += FLOAT_TYPE(data_b[b_offset + y_idx + l+ 0]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 0]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + l+ 0] & 0xF) | (((data_a[ib0 + i].qh[qh_offset + l] >> 0) & 3) << 4)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + l+32]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 2]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + l+32] & 0xF) | (((data_a[ib0 + i].qh[qh_offset + l] >> 2) & 3) << 4)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + l+64]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 4]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + l+ 0] >> 4) | (((data_a[ib0 + i].qh[qh_offset + l] >> 4) & 3) << 4)) - 32) - + FLOAT_TYPE(data_b[b_offset + y_idx + l+96]) * FLOAT_TYPE(data_a[ib0 + i].scales[s_offset + 6]) * d * FLOAT_TYPE(int8_t((data_a[ib0 + i].ql[ql_offset + l+32] >> 4) | (((data_a[ib0 + i].qh[qh_offset + l] >> 6) & 3) << 4)) - 32); + [[unroll]] for (uint j = 0; j < NUM_COLS; ++j) { + [[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) { + temp[j][i] = FLOAT_TYPE(0); } - tmp[16 * ix + tid] += sum; -#endif } - // sum up partial sums and write back result - barrier(); - [[unroll]] for (uint s = 16; s > 0; s >>= 1) { - if (tid < s) { - tmp[tid] += tmp[tid + s]; - } - barrier(); - } - if (tid == 0) { - data_d[d_offset + row] = D_TYPE(tmp[0]); + const uint nbr_par_th = num_blocks_per_row%it_size; + const uint nbr_all_th = num_blocks_per_row - nbr_par_th; + uint i0 = 0; + [[unroll]] for (; i0 < nbr_all_th; i0 += it_size) + calc_superblock(a_offset, b_offset, itid, ix, ql_offset, qh_offset, s_offset, y_offset, i0 + ix, num_blocks_per_row, first_row, num_rows, true); + calc_superblock(a_offset, b_offset, itid, ix, ql_offset, qh_offset, s_offset, y_offset, i0 + ix, num_blocks_per_row, first_row, num_rows, false); + + reduce_result(temp, d_offset, first_row, num_rows, tid); +} + +void main() { + const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z); + + // do NUM_ROWS at a time, unless there aren't enough remaining rows + if (first_row + NUM_ROWS <= p.stride_d) { + compute_outputs(first_row, NUM_ROWS); + } else { + if (first_row >= p.stride_d) { + return; + } + compute_outputs(first_row, p.stride_d - first_row); } } diff --git a/ggml/src/vulkan-shaders/mul_mm.comp b/ggml/src/vulkan-shaders/mul_mm.comp index 5fe9d524..26163b16 100644 --- a/ggml/src/vulkan-shaders/mul_mm.comp +++ b/ggml/src/vulkan-shaders/mul_mm.comp @@ -6,6 +6,19 @@ #ifdef FLOAT16 #extension GL_EXT_shader_explicit_arithmetic_types_float16 : require #endif +#if defined(DATA_A_IQ1_M) +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require +#endif + +#if defined(DATA_A_BF16) && defined(COOPMAT) +#extension GL_EXT_bfloat16 : enable +#endif + +#ifdef COOPMAT +#extension GL_KHR_cooperative_matrix : enable +#extension GL_KHR_memory_scope_semantics : enable +#extension GL_KHR_shader_subgroup_basic : enable +#endif #ifdef MUL_MAT_ID #extension GL_EXT_shader_explicit_arithmetic_types_int16 : require @@ -20,9 +33,20 @@ #define LOAD_VEC_B 1 #endif +#if !defined(TO_FLOAT_TYPE) +#define TO_FLOAT_TYPE FLOAT_TYPE +#endif + layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; +#if defined(A_TYPE_PACKED16) +layout (binding = 0) readonly buffer A_PACKED16 {A_TYPE_PACKED16 data_a_packed16[];}; +#endif +#if defined(A_TYPE_PACKED32) +layout (binding = 0) readonly buffer A_PACKED32 {A_TYPE_PACKED32 data_a_packed32[];}; +#endif + layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; @@ -57,6 +81,7 @@ layout (push_constant) uniform parameter #endif } p; +layout (constant_id = 0) const uint BLOCK_SIZE = 64; layout (constant_id = 1) const uint BM = 64; layout (constant_id = 2) const uint BN = 64; layout (constant_id = 3) const uint BK = 16; // Assumed to be 32 if working with a quant @@ -65,16 +90,33 @@ layout (constant_id = 5) const uint WN = 32; layout (constant_id = 6) const uint WMITER = 2; layout (constant_id = 7) const uint TM = 4; layout (constant_id = 8) const uint TN = 2; -layout (constant_id = 9) const uint WARP = 32; +layout (constant_id = 9) const uint TK = 1; // Only needed for coopmat +layout (constant_id = 10) const uint WARP = 32; -shared FLOAT_TYPE buf_a[BM * (BK+1)]; -shared FLOAT_TYPE buf_b[BN * (BK+1)]; +#ifdef COOPMAT +#define SHMEM_STRIDE (BK + 8) +#else +#define SHMEM_STRIDE (BK + 1) +#endif + +shared FLOAT_TYPE buf_a[BM * SHMEM_STRIDE]; +shared FLOAT_TYPE buf_b[BN * SHMEM_STRIDE]; #ifdef MUL_MAT_ID -shared u16vec2 row_ids[3072]; +shared u16vec2 row_ids[4096]; +#endif // MUL_MAT_ID + +#define NUM_WARPS (BLOCK_SIZE / WARP) + +#ifdef COOPMAT +shared ACC_TYPE coopmat_stage[TM * TN * NUM_WARPS]; #endif void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + #ifdef MUL_MAT_ID const uint expert_idx = gl_GlobalInvocationID.z; #else @@ -94,17 +136,32 @@ void main() { const uint ik = gl_WorkGroupID.x / blocks_m; const uint ic = gl_WorkGroupID.y; - const uint warp_i = gl_LocalInvocationID.x / WARP; - const uint warp_r = warp_i % (BM / WM); - const uint warp_c = warp_i / (BM / WM); - const uint WNITER = (WM * WN) / (WARP * TM * TN * WMITER); const uint WSUBM = WM / WMITER; const uint WSUBN = WN / WNITER; +#ifdef COOPMAT + const uint warp_i = gl_SubgroupID; + + const uint tiw = gl_SubgroupInvocationID; + + const uint cms_per_row = WM / TM; + const uint cms_per_col = WN / TN; + + const uint storestride = WARP / TM; + const uint store_r = tiw % TM; + const uint store_c = tiw / TM; +#else + const uint warp_i = gl_LocalInvocationID.x / WARP; + const uint tiw = gl_LocalInvocationID.x % WARP; + const uint tiwr = tiw % (WSUBM / TM); const uint tiwc = tiw / (WSUBM / TM); +#endif + + const uint warp_r = warp_i % (BM / WM); + const uint warp_c = warp_i / (BM / WM); const uint loadr_a = gl_LocalInvocationID.x % (BK / LOAD_VEC_A); const uint loadc_a = gl_LocalInvocationID.x / (BK / LOAD_VEC_A); @@ -152,21 +209,31 @@ void main() { uint pos_b = (batch_idx * p.batch_stride_b + ic * BN * p.stride_b + start_k) / LOAD_VEC_B; #endif - float sums[WMITER * TM * WNITER * TN]; +#ifdef COOPMAT + coopmat cache_a; + coopmat cache_b; + coopmat sums[cms_per_row * cms_per_col]; + + [[unroll]] for (uint i = 0; i < cms_per_row * cms_per_col; i++) { + sums[i] = coopmat(0.0f); + } +#else + ACC_TYPE sums[WMITER * TM * WNITER * TN]; FLOAT_TYPE cache_a[WMITER * TM]; - FLOAT_TYPE cache_b[WNITER * TN]; + FLOAT_TYPE cache_b[TN]; [[unroll]] for (uint i = 0; i < WMITER*TM*WNITER*TN; i++) { - sums[i] = 0.0f; + sums[i] = ACC_TYPE(0.0f); } +#endif - [[unroll]] for (uint block = start_k; block < end_k; block += BK) { + for (uint block = start_k; block < end_k; block += BK) { [[unroll]] for (uint l = 0; l < BM; l += loadstride_a) { #if defined(DATA_A_F32) || defined(DATA_A_F16) #if LOAD_VEC_A == 8 const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; buf_a[buf_idx ] = FLOAT_TYPE(data_a[idx][0].x); buf_a[buf_idx + 1] = FLOAT_TYPE(data_a[idx][0].y); buf_a[buf_idx + 2] = FLOAT_TYPE(data_a[idx][0].z); @@ -177,91 +244,132 @@ void main() { buf_a[buf_idx + 7] = FLOAT_TYPE(data_a[idx][1].w); #elif LOAD_VEC_A == 4 const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; buf_a[buf_idx ] = FLOAT_TYPE(data_a[idx].x); buf_a[buf_idx + 1] = FLOAT_TYPE(data_a[idx].y); buf_a[buf_idx + 2] = FLOAT_TYPE(data_a[idx].z); buf_a[buf_idx + 3] = FLOAT_TYPE(data_a[idx].w); #else if (ir * BM + loadc_a + l < p.M && block + loadr_a < end_k) { - buf_a[(loadc_a + l) * (BK+1) + loadr_a] = FLOAT_TYPE(data_a[pos_a + (loadc_a + l) * p.stride_a + loadr_a]); + buf_a[(loadc_a + l) * SHMEM_STRIDE + loadr_a] = FLOAT_TYPE(data_a[pos_a + (loadc_a + l) * p.stride_a + loadr_a]); } else { - buf_a[(loadc_a + l) * (BK+1) + loadr_a] = FLOAT_TYPE(0.0f); + buf_a[(loadc_a + l) * SHMEM_STRIDE + loadr_a] = FLOAT_TYPE(0.0f); + } +#endif +#elif defined(DATA_A_BF16) +#if LOAD_VEC_A == 4 + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + buf_a[buf_idx ] = TO_FLOAT_TYPE(data_a[idx].x); + buf_a[buf_idx + 1] = TO_FLOAT_TYPE(data_a[idx].y); + buf_a[buf_idx + 2] = TO_FLOAT_TYPE(data_a[idx].z); + buf_a[buf_idx + 3] = TO_FLOAT_TYPE(data_a[idx].w); +#else + if (ir * BM + loadc_a + l < p.M && block + loadr_a < end_k) { + buf_a[(loadc_a + l) * SHMEM_STRIDE + loadr_a] = TO_FLOAT_TYPE(data_a[pos_a + (loadc_a + l) * p.stride_a + loadr_a]); + } else { + buf_a[(loadc_a + l) * SHMEM_STRIDE + loadr_a] = TO_FLOAT_TYPE(uint16_t(0)); } #endif #elif defined(DATA_A_Q4_0) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + 4 * loadr_a; - const uint ib = idx / 16; - const uint iqs = idx & 0xF; + const uint ib = idx / 4; + const uint iqs = idx & 0x03; - const float d = float(data_a[ib].d); - const uint vui = uint(data_a[ib].qs[iqs]); - const vec2 v = (vec2(vui & 0xF, vui >> 4) - 8.0f) * d; + const float d = float(data_a_packed16[ib].d); + const uint vui = uint(data_a_packed16[ib].qs[2*iqs]) | (uint(data_a_packed16[ib].qs[2*iqs + 1]) << 16); + const vec4 v0 = (vec4(unpack8(vui & 0x0F0F0F0F)) - 8.0f) * d; + const vec4 v1 = (vec4(unpack8((vui >> 4) & 0x0F0F0F0F)) - 8.0f) * d; - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 16] = FLOAT_TYPE(v.y); + buf_a[buf_idx ] = FLOAT_TYPE(v0.x); + buf_a[buf_idx + 1 ] = FLOAT_TYPE(v0.y); + buf_a[buf_idx + 2 ] = FLOAT_TYPE(v0.z); + buf_a[buf_idx + 3 ] = FLOAT_TYPE(v0.w); + buf_a[buf_idx + 16] = FLOAT_TYPE(v1.x); + buf_a[buf_idx + 17] = FLOAT_TYPE(v1.y); + buf_a[buf_idx + 18] = FLOAT_TYPE(v1.z); + buf_a[buf_idx + 19] = FLOAT_TYPE(v1.w); #elif defined(DATA_A_Q4_1) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + 4 * loadr_a; - const uint ib = idx / 16; - const uint iqs = idx & 0xF; + const uint ib = idx / 4; + const uint iqs = idx & 0x03; - const float d = float(data_a[ib].d); - const float m = float(data_a[ib].m); - const uint vui = uint(data_a[ib].qs[iqs]); - const vec2 v = vec2(vui & 0xF, vui >> 4) * d + m; + const float d = float(data_a_packed16[ib].d); + const float m = float(data_a_packed16[ib].m); + const uint vui = uint(data_a_packed16[ib].qs[2*iqs]) | (uint(data_a_packed16[ib].qs[2*iqs + 1]) << 16); + const vec4 v0 = vec4(unpack8(vui & 0x0F0F0F0F)) * d + m; + const vec4 v1 = vec4(unpack8((vui >> 4) & 0x0F0F0F0F)) * d + m; - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 16] = FLOAT_TYPE(v.y); + buf_a[buf_idx ] = FLOAT_TYPE(v0.x); + buf_a[buf_idx + 1 ] = FLOAT_TYPE(v0.y); + buf_a[buf_idx + 2 ] = FLOAT_TYPE(v0.z); + buf_a[buf_idx + 3 ] = FLOAT_TYPE(v0.w); + buf_a[buf_idx + 16] = FLOAT_TYPE(v1.x); + buf_a[buf_idx + 17] = FLOAT_TYPE(v1.y); + buf_a[buf_idx + 18] = FLOAT_TYPE(v1.z); + buf_a[buf_idx + 19] = FLOAT_TYPE(v1.w); #elif defined(DATA_A_Q5_0) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + 2 * loadr_a; - const uint ib = idx / 16; - const uint iqs = idx & 0xF; + const uint ib = idx / 8; + const uint iqs = idx & 0x07; - const float d = float(data_a[ib].d); - const uint uint_qh = uint(data_a[ib].qh[1]) << 16 | data_a[ib].qh[0]; - const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10); - const uint vui = uint(data_a[ib].qs[iqs]); - const vec2 v = (vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y) - 16.0f) * d; + const float d = float(data_a_packed16[ib].d); + const uint uint_qh = uint(data_a_packed16[ib].qh[1]) << 16 | uint(data_a_packed16[ib].qh[0]); + const ivec2 qh0 = ivec2(((uint_qh >> 2*iqs) << 4) & 0x10, (uint_qh >> (2*iqs + 12)) & 0x10); + const ivec2 qh1 = ivec2(((uint_qh >> (2*iqs + 1)) << 4) & 0x10, (uint_qh >> (2*iqs + 13)) & 0x10); + + const uint vui = uint(data_a_packed16[ib].qs[iqs]); + const vec4 v = (vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y) - 16.0f) * d; buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1 ] = FLOAT_TYPE(v.z); buf_a[buf_idx + 16] = FLOAT_TYPE(v.y); + buf_a[buf_idx + 17] = FLOAT_TYPE(v.w); #elif defined(DATA_A_Q5_1) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + 2 * loadr_a; - const uint ib = idx / 16; - const uint iqs = idx & 0xF; + const uint ib = idx / 8; + const uint iqs = idx & 0x07; - const float d = float(data_a[ib].d); - const float m = float(data_a[ib].m); - const uint uint_qh = data_a[ib].qh; - const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10); - const uint vui = uint(data_a[ib].qs[iqs]); - const vec2 v = vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y) * d + m; + const float d = float(data_a_packed16[ib].d); + const float m = float(data_a_packed16[ib].m); + const uint uint_qh = data_a_packed16[ib].qh; + const ivec2 qh0 = ivec2(((uint_qh >> 2*iqs) << 4) & 0x10, (uint_qh >> (2*iqs + 12)) & 0x10); + const ivec2 qh1 = ivec2(((uint_qh >> (2*iqs + 1)) << 4) & 0x10, (uint_qh >> (2*iqs + 13)) & 0x10); + + const uint vui = uint(data_a_packed16[ib].qs[iqs]); + const vec4 v = vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y) * d + m; buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1 ] = FLOAT_TYPE(v.z); buf_a[buf_idx + 16] = FLOAT_TYPE(v.y); + buf_a[buf_idx + 17] = FLOAT_TYPE(v.w); #elif defined(DATA_A_Q8_0) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 16; - const uint iqs = (idx & 0xF) * 2; + const uint ib = idx / 8; + const uint iqs = idx & 0x07; - const float d = float(data_a[ib].d); - const vec2 v = vec2(int(data_a[ib].qs[iqs]), int(data_a[ib].qs[iqs + 1])) * d; + const float d = float(data_a_packed16[ib].d); + const i8vec2 v0 = unpack8(int32_t(data_a_packed16[ib].qs[2*iqs])).xy; // vec4 used due to #12147 + const i8vec2 v1 = unpack8(int32_t(data_a_packed16[ib].qs[2*iqs + 1])).xy; + const vec4 v = vec4(v0.x, v0.y, v1.x, v1.y) * d; buf_a[buf_idx ] = FLOAT_TYPE(v.x); buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + buf_a[buf_idx + 2] = FLOAT_TYPE(v.z); + buf_a[buf_idx + 3] = FLOAT_TYPE(v.w); #elif defined(DATA_A_Q2_K) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; const uint ib = idx / 128; // 2 values per idx const uint iqs = idx % 128; // 0..127 @@ -280,7 +388,7 @@ void main() { buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); #elif defined(DATA_A_Q3_K) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; const uint ib = idx / 128; // 2 values per idx const uint iqs = idx % 128; // 0..127 @@ -294,17 +402,15 @@ void main() { const uint qsshift = halfsplit * 2; // 0,2,4,6 const uint m = 1 << (4 * n + halfsplit); // 1,2,4,8,16,32,64,128 - const int8_t us = int8_t(is < 4 ? (data_a[ib].scales[is-0] & 0xF) | (((data_a[ib].scales[is+8] >> 0) & 3) << 4) : - is < 8 ? (data_a[ib].scales[is-0] & 0xF) | (((data_a[ib].scales[is+4] >> 2) & 3) << 4) : - is < 12 ? (data_a[ib].scales[is-8] >> 4) | (((data_a[ib].scales[is+0] >> 4) & 3) << 4) : - (data_a[ib].scales[is-8] >> 4) | (((data_a[ib].scales[is-4] >> 6) & 3) << 4)); + const int8_t us = int8_t(((data_a[ib].scales[is % 8] >> (4 * int(is / 8))) & 0xF) + | (((data_a[ib].scales[8 + (is % 4)] >> (2 * int(is / 4))) & 3) << 4)); const float dl = float(data_a[ib].d) * float(us - 32); buf_a[buf_idx ] = FLOAT_TYPE(dl * float(int8_t((data_a[ib].qs[qsi ] >> qsshift) & 3) - (((data_a[ib].hmask[hmi ] & m) != 0) ? 0 : 4))); buf_a[buf_idx + 1] = FLOAT_TYPE(dl * float(int8_t((data_a[ib].qs[qsi + 1] >> qsshift) & 3) - (((data_a[ib].hmask[hmi + 1] & m) != 0) ? 0 : 4))); #elif defined(DATA_A_Q4_K) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; const uint ib = idx / 128; // 2 values per idx const uint iqs = idx % 128; // 0..127 @@ -316,23 +422,28 @@ void main() { const vec2 loadd = vec2(data_a[ib].d); - uint8_t sc; - uint8_t mbyte; - if (is < 4) { - sc = uint8_t(data_a[ib].scales[is ] & 63); - mbyte = uint8_t(data_a[ib].scales[is + 4] & 63); - } else { - sc = uint8_t((data_a[ib].scales[is + 4] & 0xF) | ((data_a[ib].scales[is - 4] >> 6) << 4)); - mbyte = uint8_t((data_a[ib].scales[is + 4] >> 4) | ((data_a[ib].scales[is ] >> 6) << 4)); - } - const float d = loadd.x * sc; - const float m = loadd.y * mbyte; + const uint scidx0 = (is < 4) ? is : (is + 4); + const uint scidx1 = (is < 4) ? is : (is - 4); + const uint scidxmask1 = (is < 4) ? 0x30 : 0xC0; + const uint scidxshift1 = (is < 4) ? 0 : 2; + const uint mbidx0 = is + 4; + const uint mbidx1 = (is < 4) ? is + 4 : is; + const uint mbidxmask0 = (is < 4) ? 0xF : 0xF0; + const uint mbidxshift0 = (is < 4) ? 0 : 4; + const uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0; + const uint mbidxshift1 = (is < 4) ? 0 : 2; - buf_a[buf_idx ] = FLOAT_TYPE(d * float((data_a[ib].qs[qsi ] >> (b * 4)) & 0xF) - m); - buf_a[buf_idx + 1] = FLOAT_TYPE(d * float((data_a[ib].qs[qsi + 1] >> (b * 4)) & 0xF) - m); + const uint8_t sc = uint8_t((data_a[ib].scales[scidx0] & 0xF) | ((data_a[ib].scales[scidx1] & scidxmask1) >> scidxshift1)); + const uint8_t mbyte = uint8_t((data_a[ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0 | ((data_a[ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1)); + + const float d = loadd.x * sc; + const float m = -loadd.y * mbyte; + + buf_a[buf_idx ] = FLOAT_TYPE(fma(d, float((data_a[ib].qs[qsi ] >> (b * 4)) & 0xF), m)); + buf_a[buf_idx + 1] = FLOAT_TYPE(fma(d, float((data_a[ib].qs[qsi + 1] >> (b * 4)) & 0xF), m)); #elif defined(DATA_A_Q5_K) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; const uint ib = idx / 128; // 2 values per idx const uint iqs = idx % 128; // 0..127 @@ -347,23 +458,28 @@ void main() { const vec2 loadd = vec2(data_a[ib].d); - uint8_t sc; - uint8_t mbyte; - if (is < 4) { - sc = uint8_t(data_a[ib].scales[is ] & 63); - mbyte = uint8_t(data_a[ib].scales[is + 4] & 63); - } else { - sc = uint8_t((data_a[ib].scales[is + 4] & 0xF) | ((data_a[ib].scales[is - 4] >> 6) << 4)); - mbyte = uint8_t((data_a[ib].scales[is + 4] >> 4) | ((data_a[ib].scales[is ] >> 6) << 4)); - } - const float d = loadd.x * sc; - const float m = loadd.y * mbyte; + const uint scidx0 = (is < 4) ? is : (is + 4); + const uint scidx1 = (is < 4) ? is : (is - 4); + const uint scidxmask1 = (is < 4) ? 0x30 : 0xC0; + const uint scidxshift1 = (is < 4) ? 0 : 2; + const uint mbidx0 = is + 4; + const uint mbidx1 = (is < 4) ? is + 4 : is; + const uint mbidxmask0 = (is < 4) ? 0xF : 0xF0; + const uint mbidxshift0 = (is < 4) ? 0 : 4; + const uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0; + const uint mbidxshift1 = (is < 4) ? 0 : 2; - buf_a[buf_idx ] = FLOAT_TYPE(d * (float((data_a[ib].qs[qsi ] >> (b * 4)) & 0xF) + float((data_a[ib].qh[qhi ] & hm) != 0 ? 16 : 0)) - m); - buf_a[buf_idx + 1] = FLOAT_TYPE(d * (float((data_a[ib].qs[qsi + 1] >> (b * 4)) & 0xF) + float((data_a[ib].qh[qhi + 1] & hm) != 0 ? 16 : 0)) - m); + const uint8_t sc = uint8_t((data_a[ib].scales[scidx0] & 0xF) | ((data_a[ib].scales[scidx1] & scidxmask1) >> scidxshift1)); + const uint8_t mbyte = uint8_t(((data_a[ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0) | ((data_a[ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1)); + + const float d = loadd.x * sc; + const float m = -loadd.y * mbyte; + + buf_a[buf_idx ] = FLOAT_TYPE(fma(d, float((data_a[ib].qs[qsi ] >> (b * 4)) & 0xF) + float((data_a[ib].qh[qhi ] & hm) != 0 ? 16 : 0), m)); + buf_a[buf_idx + 1] = FLOAT_TYPE(fma(d, float((data_a[ib].qs[qsi + 1] >> (b * 4)) & 0xF) + float((data_a[ib].qh[qhi + 1] & hm) != 0 ? 16 : 0), m)); #elif defined(DATA_A_Q6_K) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a * LOAD_VEC_A; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; const uint ib = idx / 128; // 2 values per idx const uint iqs = idx % 128; // 0..127 @@ -380,19 +496,201 @@ void main() { buf_a[buf_idx ] = FLOAT_TYPE(dscale * float(int8_t(((data_a[ib].ql[qsi ] >> (b * 4)) & 0xF) | (((data_a[ib].qh[qhi ] >> qhshift) & 3) << 4)) - 32)); buf_a[buf_idx + 1] = FLOAT_TYPE(dscale * float(int8_t(((data_a[ib].ql[qsi + 1] >> (b * 4)) & 0xF) | (((data_a[ib].qh[qhi + 1] >> qhshift) & 3) << 4)) - 32)); -#elif defined(DATA_A_IQ4_NL) +#elif defined(DATA_A_IQ1_S) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; - const uint buf_idx = (loadc_a + l) * (BK+1) + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 16; - const uint iqs = idx & 0xF; + const uint ib = idx / 128; // 2 values per idx + const uint ib32 = (idx % 128) / 16; // 0..7 + const uint ib8 = (idx % 128) / 4; + const int i8 = 2 * int(idx % 4); const float d = float(data_a[ib].d); - const uint vui = uint(data_a[ib].qs[iqs]); - const vec2 v = vec2(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[vui >> 4]) * d; + const uint qh = data_a[ib].qh[ib32]; + const uint qs = data_a[ib].qs[ib8]; + const float dl = d * (2 * bitfieldExtract(qh, 12, 3) + 1); + const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; + const int16_t grid = int16_t(iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)]); - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 16] = FLOAT_TYPE(v.y); + const ivec2 gvec = ivec2( + bitfieldExtract(grid, 2 * (i8), 2), + bitfieldExtract(grid, 2 * (i8 + 1), 2) + ); + const vec2 v = dl * (vec2(gvec) + delta); + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ1_M) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + + const uint ib = idx / 128; // 2 values per idx + const uint ib8 = (idx % 128) / 4; + const uint ib16 = ib8 / 2; + const int i8 = 2 * int(idx % 4); + + const uint16_t[4] scales = data_a[ib].scales; + const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12; + const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x); + const uint sc = scales[ib8 / 8]; + const uint qs = data_a[ib].qs[ib8]; + const uint qh = data_a[ib].qh[ib16] >> (4 * (ib8 & 1)); + const float dl = d * (2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1); + const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA; + const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]); + const ivec2 gvec = ivec2( + bitfieldExtract(grid, 2 * (i8), 2), + bitfieldExtract(grid, 2 * (i8 + 1), 2) + ); + const vec2 v = dl * (vec2(gvec) + delta); + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ2_XXS) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + + const uint ib = idx / 128; // 2 values per idx + const uint ib32 = (idx % 128) / 16; // 0..7 + const uint ib8 = (idx / 4) % 4; + + const float d = float(data_a[ib].d); + const uint qs = data_a[ib].qs[8 * ib32 + ib8]; + const uint signs = pack32(u8vec4( + data_a[ib].qs[8*ib32 + 4], + data_a[ib].qs[8*ib32 + 5], + data_a[ib].qs[8*ib32 + 6], + data_a[ib].qs[8*ib32 + 7] + )); + const float db = d * 0.25 * (0.5 + (signs >> 28)); + const uint32_t sign7 = bitfieldExtract(signs, 7 * int(ib8), 7); + const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (2 * (idx % 4)); + const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); + const uint grid = iq2xxs_grid[qs][(idx % 4) / 2] >> (16 * (idx & 1)); + const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ2_XS) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + + const uint ib = idx / 128; // 2 values per idx + const uint ib32 = (idx % 128) / 16; // 0..7 + const uint ib8 = (idx / 4) % 4; // 0..3 + + const float d = float(data_a[ib].d); + const uint scale = (data_a[ib].scales[ib32] >> (2 * (ib8 & 2))) & 0xf; + const float db = d * 0.25 * (0.5 + scale); + const uint qs = data_a[ib].qs[4 * ib32 + ib8]; + const uint sign7 = qs >> 9; + const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (2 * (idx % 4)); + const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); + const uint grid = iq2xs_grid[qs & 511][(idx % 4) / 2] >> (16 * (idx & 1)); + const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ2_S) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + + const uint ib = idx / 128; // 2 values per idx + const uint ib8 = (idx % 128) / 4; // 0..31 + const uint ib32 = ib8 / 4; // 0..7 + + const uint scale = (data_a[ib].scales[ib32] >> (2 * (ib8 & 2))) & 0xf; + const uint qs = data_a[ib].qs[ib8]; + const uint qh = data_a[ib].qh[ib32]; + const uint qhshift = 2 * (ib8 % 4); + const uint sign = data_a[ib].qs[QUANT_K / 8 + ib8] >> (2 * (idx % 4)); + + const float d = float(data_a[ib].d); + const float db = d * 0.25 * (0.5 + scale); + const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); + const uint16_t grid = unpack16(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(idx & 2) >> 1])[idx & 1]; + const vec2 v = db * vec2(sign01) * vec2(unpack8(uint32_t(grid)).xy); // vec4 used due to #12147 + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ3_XXS) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + + const uint ib = idx / 128; // 2 values per idx + const uint iqs = (idx % 128) / 2; // 0..63 + const uint is = QUANT_K / 4 + 4 * (iqs / 8); // 8 values + + const float d = float(data_a[ib].d); + const uint qs = data_a[ib].qs[iqs]; + const uint signs = pack32(u8vec4( + data_a[ib].qs[is+0], + data_a[ib].qs[is+1], + data_a[ib].qs[is+2], + data_a[ib].qs[is+3] + )); + const float db = d * 0.5 * (0.5 + (signs >> 28)); + const uint32_t sign7 = bitfieldExtract(signs, 7 * (int(iqs / 2) % 4), 7); + const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (2 * (idx % 4)); + const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); + const uint grid = iq3xxs_grid[qs] >> (16 * (idx & 1)); + const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ3_S) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + + const uint ib = idx / 128; // 2 values per idx + const uint iqs = (idx % 128) / 2; // 0..63 + const uint iqh = iqs / 8; + + const float d = float(data_a[ib].d); + const uint qs = data_a[ib].qs[iqs]; + const uint qh = data_a[ib].qh[iqh]; + const int8_t sign = int8_t(data_a[ib].signs[iqs / 2] >> (2 * (idx % 4))); + const uint scale = data_a[ib].scales[iqs / 16]; + const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(sign << 1, sign))); + const float db = d * (1 + 2 * ((scale >> (4 * (iqh & 1))) & 0xf)); + const uint32_t grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)] >> (16 * (idx % 2)); + const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ4_XS) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; + + const uint ib = idx / 128; // 2 values per idx + const uint ib32 = (idx % 128) / 16; // 0..7 + const uint iq = 16 * ib32 + 2 * (idx % 8); + + const uint sl = (data_a[ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF; + const uint sh = ((data_a[ib].scales_h) >> (2 * ib32)) & 3; + const uint qshift = (idx & 8) >> 1; + u8vec2 qs = u8vec2(data_a[ib].qs[iq], data_a[ib].qs[iq + 1]); + qs = (qs >> qshift) & uint8_t(0xF); + + const float d = float(data_a[ib].d); + const vec2 v = d * float(int(sl | (sh << 4)) - 32) * vec2(kvalues_iq4nl[qs.x], kvalues_iq4nl[qs.y]); + + buf_a[buf_idx ] = FLOAT_TYPE(v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); +#elif defined(DATA_A_IQ4_NL) + const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; + const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + 2 * loadr_a; + + const uint ib = idx / 8; + const uint iqs = idx & 0x07; + + const FLOAT_TYPE d = FLOAT_TYPE(data_a_packed16[ib].d); + const uint vui = uint(data_a_packed16[ib].qs[iqs]); + + buf_a[buf_idx ] = FLOAT_TYPE(kvalues_iq4nl[vui & 0xF]) * d; + buf_a[buf_idx + 1 ] = FLOAT_TYPE(kvalues_iq4nl[bitfieldExtract(vui, 8, 4)]) * d; + buf_a[buf_idx + 16] = FLOAT_TYPE(kvalues_iq4nl[bitfieldExtract(vui, 4, 4)]) * d; + buf_a[buf_idx + 17] = FLOAT_TYPE(kvalues_iq4nl[vui >> 12]) * d; #endif } [[unroll]] for (uint l = 0; l < BN; l += loadstride_b) { @@ -403,7 +701,7 @@ void main() { #else const uint idx = pos_b + (loadc_b + l) * p.stride_b / LOAD_VEC_B + loadr_b; #endif - const uint buf_idx = (loadc_b + l) * (BK+1) + loadr_b * LOAD_VEC_B; + const uint buf_idx = (loadc_b + l) * SHMEM_STRIDE + loadr_b * LOAD_VEC_B; buf_b[buf_idx + 0] = FLOAT_TYPE(data_b[idx][0].x); buf_b[buf_idx + 1] = FLOAT_TYPE(data_b[idx][0].y); buf_b[buf_idx + 2] = FLOAT_TYPE(data_b[idx][0].z); @@ -419,24 +717,24 @@ void main() { #else const uint idx = pos_b + (loadc_b + l) * p.stride_b / LOAD_VEC_B + loadr_b; #endif - const uint buf_idx = (loadc_b + l) * (BK+1) + loadr_b * LOAD_VEC_B; - buf_b[buf_idx + 0] = FLOAT_TYPE(data_b[idx].x); - buf_b[buf_idx + 1] = FLOAT_TYPE(data_b[idx].y); - buf_b[buf_idx + 2] = FLOAT_TYPE(data_b[idx].z); - buf_b[buf_idx + 3] = FLOAT_TYPE(data_b[idx].w); + const uint buf_idx = (loadc_b + l) * SHMEM_STRIDE + loadr_b * LOAD_VEC_B; + buf_b[buf_idx + 0] = TO_FLOAT_TYPE(data_b[idx].x); + buf_b[buf_idx + 1] = TO_FLOAT_TYPE(data_b[idx].y); + buf_b[buf_idx + 2] = TO_FLOAT_TYPE(data_b[idx].z); + buf_b[buf_idx + 3] = TO_FLOAT_TYPE(data_b[idx].w); #elif !MUL_MAT_ID if (ic * BN + loadc_b + l < p.N && block + loadr_b < end_k) { - buf_b[(loadc_b + l) * (BK+1) + loadr_b] = FLOAT_TYPE(data_b[pos_b + (loadc_b + l) * p.stride_b + loadr_b]); + buf_b[(loadc_b + l) * SHMEM_STRIDE + loadr_b] = TO_FLOAT_TYPE(data_b[pos_b + (loadc_b + l) * p.stride_b + loadr_b]); } else { - buf_b[(loadc_b + l) * (BK+1) + loadr_b] = FLOAT_TYPE(0.0f); + buf_b[(loadc_b + l) * SHMEM_STRIDE + loadr_b] = FLOAT_TYPE(0.0f); } #else const uint row_i = ic * BN + loadc_b + l; if (row_i < _ne1) { const u16vec2 row_idx = row_ids[row_i]; - buf_b[(loadc_b + l) * (BK+1) + loadr_b] = FLOAT_TYPE(data_b[pos_b + row_idx.y * p.batch_stride_b + (row_idx.x % p.ne11) * p.stride_b + loadr_b]); + buf_b[(loadc_b + l) * SHMEM_STRIDE + loadr_b] = TO_FLOAT_TYPE(data_b[pos_b + row_idx.y * p.batch_stride_b + (row_idx.x % p.ne11) * p.stride_b + loadr_b]); } else { - buf_b[(loadc_b + l) * (BK+1) + loadr_b] = FLOAT_TYPE(0.0f); + buf_b[(loadc_b + l) * SHMEM_STRIDE + loadr_b] = FLOAT_TYPE(0.0f); } #endif } @@ -446,29 +744,43 @@ void main() { pos_a += BK / LOAD_VEC_A; pos_b += BK / LOAD_VEC_B; - for (uint i = 0; i < BK; i++) { +#ifdef COOPMAT + [[unroll]] for (uint i = 0; i < BK; i += TK) { + [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) { + // Load from shared into cache + coopMatLoad(cache_a, buf_a, (warp_r * WM + cm_row * TM) * SHMEM_STRIDE + i, SHMEM_STRIDE, gl_CooperativeMatrixLayoutRowMajor); + + [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) { + coopMatLoad(cache_b, buf_b, (warp_c * WN + cm_col * TN) * SHMEM_STRIDE + i, SHMEM_STRIDE, gl_CooperativeMatrixLayoutColumnMajor); + + sums[cm_col * cms_per_row + cm_row] = coopMatMulAdd(cache_a, cache_b, sums[cm_col * cms_per_row + cm_row]); + } + } + } +#else + [[unroll]] for (uint i = 0; i < BK; i++) { // Load from shared into cache [[unroll]] for (uint wsir = 0; wsir < WMITER; wsir++) { [[unroll]] for (uint j = 0; j < TM; j++) { - cache_a[wsir * TM + j] = buf_a[(warp_r * WM + wsir * WSUBM + tiwr * TM + j) * (BK+1) + i]; + cache_a[wsir * TM + j] = buf_a[(warp_r * WM + wsir * WSUBM + tiwr * TM + j) * SHMEM_STRIDE + i]; } } [[unroll]] for (uint wsic = 0; wsic < WNITER; wsic++) { [[unroll]] for (uint j = 0; j < TN; j++) { - cache_b[wsic * TN + j] = buf_b[(warp_c * WN + wsic * WSUBN + tiwc * TN + j) * (BK+1) + i]; + cache_b[j] = buf_b[(warp_c * WN + wsic * WSUBN + tiwc * TN + j) * SHMEM_STRIDE + i]; } - } - [[unroll]] for (uint wsic = 0; wsic < WNITER; wsic++) { [[unroll]] for (uint wsir = 0; wsir < WMITER; wsir++) { [[unroll]] for (uint cc = 0; cc < TN; cc++) { [[unroll]] for (uint cr = 0; cr < TM; cr++) { - sums[(wsic * TN + cc) * (WMITER * TM) + wsir * TM + cr] += float(cache_a[wsir * TM + cr]) * float(cache_b[wsic * TN + cc]); + const uint sums_idx = (wsic * TN + cc) * (WMITER * TM) + wsir * TM + cr; + sums[sums_idx] = fma(ACC_TYPE(cache_a[wsir * TM + cr]), ACC_TYPE(cache_b[cc]), sums[sums_idx]); } } } } } +#endif barrier(); } @@ -480,6 +792,54 @@ void main() { const uint offsets = batch_idx * p.batch_stride_d + ik * p.batch_stride_d * gl_NumWorkGroups.z; #endif +#ifdef COOPMAT +#ifdef MUL_MAT_ID + [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) { + [[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 < TN; col += storestride) { + const uint row_i = dc + cm_col * TN + col + store_c; + if (row_i >= _ne1) break; + + const u16vec2 row_idx = row_ids[row_i]; + + data_d[row_idx.y * p.batch_stride_d + row_idx.x * p.stride_d + dr + cm_row * TM + store_r] = D_TYPE(coopmat_stage[warp_i * TM * TN + (col + store_c) * TM + store_r]); + } + } + } +#else + const bool is_aligned = p.stride_d % 4 == 0; // Assumption: D_TYPE == float + + [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) { + [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) { + const bool is_in_bounds = dr + (cm_row + 1) * TM <= p.M && dc + (cm_col + 1) * TN <= p.N; + + if (is_aligned && is_in_bounds) { + // Full coopMat is within bounds and stride_d is aligned with 16B + coopmat cm_dtype = coopmat(sums[cm_col * cms_per_row + cm_row]); + coopMatStore(cm_dtype, data_d, offsets + (dc + cm_col * TN) * p.stride_d + dr + cm_row * TM, p.stride_d, gl_CooperativeMatrixLayoutColumnMajor); + } else if (is_in_bounds) { + // Full coopMat is within bounds, but stride_d is not aligned + coopMatStore(sums[cm_col * cms_per_row + cm_row], coopmat_stage, warp_i * TM * TN, TM, gl_CooperativeMatrixLayoutColumnMajor); + + [[unroll]] for (uint col = 0; col < TN; col += storestride) { + data_d[offsets + (dc + cm_col * TN + col + store_c) * p.stride_d + dr + cm_row * TM + store_r] = D_TYPE(coopmat_stage[warp_i * TM * TN + (col + store_c) * TM + store_r]); + } + } else if (dr + cm_row * TM < p.M && dc + cm_col * TN < p.N) { + // Partial coopMat is within bounds + coopMatStore(sums[cm_col * cms_per_row + cm_row], coopmat_stage, warp_i * TM * TN, TM, gl_CooperativeMatrixLayoutColumnMajor); + + [[unroll]] for (uint col = 0; col < TN; col += storestride) { + if (dr + cm_row * TM + store_r < p.M && dc + cm_col * TN + col + store_c < p.N) { + data_d[offsets + (dc + cm_col * TN + col + store_c) * p.stride_d + dr + cm_row * TM + store_r] = D_TYPE(coopmat_stage[warp_i * TM * TN + (col + store_c) * TM + store_r]); + } + } + } + } + } +#endif // MUL_MAT_ID +#else [[unroll]] for (uint wsic = 0; wsic < WNITER; wsic++) { [[unroll]] for (uint wsir = 0; wsir < WMITER; wsir++) { @@ -491,7 +851,7 @@ void main() { if (row_i >= _ne1) break; const u16vec2 row_idx = row_ids[row_i]; -#endif +#endif // MUL_MAT_ID [[unroll]] for (uint cr = 0; cr < TM; cr++) { #ifdef MUL_MAT_ID data_d[row_idx.y * p.batch_stride_d + row_idx.x * p.stride_d + dr_warp + cr] = D_TYPE(sums[(wsic * TN + cc) * (WMITER * TM) + wsir * TM + cr]); @@ -499,9 +859,10 @@ void main() { if (dr_warp + cr < p.M && dc_warp + cc < p.N) { data_d[offsets + (dc_warp + cc) * p.stride_d + dr_warp + cr] = D_TYPE(sums[(wsic * TN + cc) * (WMITER * TM) + wsir * TM + cr]); } -#endif +#endif // MUL_MAT_ID } } } } +#endif // COOPMAT } diff --git a/ggml/src/vulkan-shaders/mul_mm_cm2.comp b/ggml/src/vulkan-shaders/mul_mm_cm2.comp new file mode 100644 index 00000000..91846575 --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mm_cm2.comp @@ -0,0 +1,441 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable +#extension GL_EXT_shader_16bit_storage : require + +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require + +#extension GL_KHR_memory_scope_semantics : enable +#extension GL_KHR_cooperative_matrix : enable +#extension GL_NV_cooperative_matrix2 : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_KHR_shader_subgroup_ballot : enable +#extension GL_KHR_shader_subgroup_vote : enable +#ifdef DATA_A_BF16 +#extension GL_EXT_bfloat16 : enable +#endif + +#include "types.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +#define IS_MUL_MM2 1 + +layout (constant_id = 0) const uint BLOCK_SIZE = 256; +layout (constant_id = 1) const uint BM = 64; +layout (constant_id = 2) const uint BN = 64; +layout (constant_id = 3) const uint BK = 16; // Assumed to be 32 if working with a quant + +layout (constant_id = 4) const bool enable_smaller_matrices = false; +const uint BNover2 = enable_smaller_matrices ? (BN / 2) : BN; +const uint BNover4 = enable_smaller_matrices ? (BN / 4) : BN; + +layout (push_constant) uniform parameter +{ + uint M; + uint N; + uint K; + uint stride_a; + uint stride_b; + uint stride_d; + + uint batch_stride_a; + uint batch_stride_b; + uint batch_stride_d; + +#ifdef MUL_MAT_ID + uint nei0; + uint nei1; + uint nbi1; + uint ne11; +#else + uint k_split; + uint ne02; + uint ne12; + uint broadcast2; + uint broadcast3; +#endif + // N dimension for the B matrix can be >= p.N + uint padded_N; +} p; + + +layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; +layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +#if QUANT_K > 1 +#define DECODEFUNCA , dequantFuncA + +#include "dequant_funcs_cm2.comp" + +#else +#define DECODEFUNCA +#endif + +#if !defined(fetch_scales) +#define fetch_scales(a, b, c, d, e, f) +#endif +#if !defined(store_scales) +#define store_scales(a) +#endif + +#if defined(DATA_A_BF16) +#define MAT_TYPE bfloat16_t +#else +#define MAT_TYPE FLOAT_TYPE +#endif + +#ifdef MUL_MAT_ID +layout (binding = 3) readonly buffer IDS {int data_ids[];}; + +shared u16vec4 row_ids[4096]; + +layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufB { + B_TYPE b[]; +}; + +uint _ne1; +shared uint _ne1_sh; + +B_TYPE decodeFuncB(const in decodeBufB bl, const in uint blockCoords[2], const in uint coordInBlock[2]) +{ + const uint row_i = blockCoords[0]; + + if (row_i >= _ne1) { + return B_TYPE(0.0); + } + + const u16vec4 row_idx = row_ids[row_i]; + B_TYPE ret = data_b[row_idx.y * p.batch_stride_b + row_idx.x * p.stride_b + blockCoords[1]]; + + return ret; +} + +D_TYPE perElemOpD(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t ir, const in uint32_t ic) +{ + uint dr = ir * BM + r; + uint dc = ic * BN + c; + + if (dr < p.M && dc < _ne1) { + uint row_i = dc; + const u16vec4 row_idx = row_ids[row_i]; + data_d[row_idx.y * p.batch_stride_d + row_idx.z * p.stride_d + dr] = elem; + } + return elem; +} + +#endif + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + + const uint tid = gl_LocalInvocationIndex; + +#ifdef MUL_MAT_ID + const uint expert_idx = gl_GlobalInvocationID.z; +#else + const uint batch_idx = gl_GlobalInvocationID.z; + + const uint i13 = batch_idx / p.ne12; + const uint i12 = batch_idx % p.ne12; + + const uint i03 = i13 / p.broadcast3; + const uint i02 = i12 / p.broadcast2; + + const uint batch_idx_a = i03 * p.ne02 + i02; +#endif + + const uint blocks_m = (p.M + BM - 1) / BM; + const uint ir = gl_WorkGroupID.x % blocks_m; + const uint ik = gl_WorkGroupID.x / blocks_m; + const uint ic = gl_WorkGroupID.y; + +#ifdef MUL_MAT_ID + // Spread the search across all elements in the first subgroup + if (gl_SubgroupID == 0) { + _ne1 = 0; + uint num_elements = p.nei1 * p.nei0; + + for (uint i = gl_SubgroupInvocationID; subgroupAny(i < num_elements); i += gl_SubgroupSize) { + bool in_range = i < num_elements; + uint ii0 = i % p.nei0; + uint ii1 = i / p.nei0; + uint id = in_range ? data_ids[ii1*p.nbi1 + ii0] : 0; + uvec4 ballot = subgroupBallot(in_range && id == expert_idx); + uint idx = subgroupBallotExclusiveBitCount(ballot); + if (in_range && id == expert_idx) { + row_ids[_ne1 + idx] = u16vec4(ii0 % p.ne11, ii1, ii0, 0); + } + _ne1 += subgroupBallotBitCount(ballot); + } + _ne1_sh = _ne1; + } + + barrier(); + + _ne1 = _ne1_sh; + + // Workgroup has no work + if (ic * BN >= _ne1) return; +#endif + +#ifdef MUL_MAT_ID + uint start_k = 0; + const uint end_k = p.K; +#else + uint start_k = ik * p.k_split; + const uint end_k = min(p.K, (ik + 1) * p.k_split); +#endif + +#ifdef MUL_MAT_ID + uint pos_a = (expert_idx * p.batch_stride_a) / QUANT_K; + uint pos_b = 0; +#else + uint pos_a = (batch_idx_a * p.batch_stride_a) / QUANT_K; + uint pos_b = batch_idx * p.batch_stride_b; + uint pos_d = batch_idx * p.batch_stride_d + ik * p.batch_stride_d * gl_NumWorkGroups.z; +#endif + + uint stride_a = p.stride_a / QUANT_K; + uint stride_b = p.stride_b; + + // Hint to the compiler that values are aligned (want 16B alignment). + // Quants are always block-aligned, no alignment needed. +#if ALIGNED +#if QUANT_K == 1 + stride_a &= ~7; +#endif + stride_b &= ~7; +#endif + + // Create layouts for both clamped and unclamped accesses + tensorLayoutNV<2> tensorLayoutA = createTensorLayoutNV(2); + tensorLayoutNV<2, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutAClamp = createTensorLayoutNV(2, gl_CooperativeMatrixClampModeConstantNV); + tensorLayoutNV<2> tensorLayoutB = createTensorLayoutNV(2); + tensorLayoutNV<2, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutBClamp = createTensorLayoutNV(2, gl_CooperativeMatrixClampModeConstantNV); + tensorLayoutNV<2, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutD = createTensorLayoutNV(2, gl_CooperativeMatrixClampModeConstantNV); + tensorLayoutD = setTensorLayoutStrideNV(tensorLayoutD, p.stride_d, 1); + +#if QUANT_K > 1 + tensorLayoutA = setTensorLayoutBlockSizeNV(tensorLayoutA, 1, QUANT_K); + tensorLayoutAClamp = setTensorLayoutBlockSizeNV(tensorLayoutAClamp, 1, QUANT_K); +#endif + + // Use end_k rather than p.K as the dimension because that's what + // we need to bound check against when using split_k. + // Bounds check B against padded_N, but bounds check D against N. + tensorLayoutA = setTensorLayoutDimensionNV(tensorLayoutA, p.M, end_k); + tensorLayoutB = setTensorLayoutDimensionNV(tensorLayoutB, p.padded_N, end_k); + tensorLayoutD = setTensorLayoutDimensionNV(tensorLayoutD, p.N, p.M); + tensorLayoutAClamp = setTensorLayoutDimensionNV(tensorLayoutAClamp, p.M, end_k); + tensorLayoutBClamp = setTensorLayoutDimensionNV(tensorLayoutBClamp, p.padded_N, end_k); + + tensorViewNV<2, false, 1, 0> tensorViewTranspose = createTensorViewNV(2, false, 1, 0); + +#if !defined(MUL_MAT_ID) + + const uint START_ALIGN_K = 256; + // For Qi_K (block size 256), unroll whole 256 element tiles. + // For legacy quants (block size 32), unroll 8x. + const uint UNROLL_K = (QUANT_K == 256) ? 256 : (BK * 8); + const uint unroll_count = UNROLL_K / BK; + + // Detect a fast path where all loads are entirely in bounds and no clamping is required + if ((ir + 1) * BM <= p.M && (ic + 1) * BN <= p.padded_N && (start_k % START_ALIGN_K) == 0 && (end_k % BK) == 0 && +#if QUANT_K == 1 + (stride_a % 8) == 0 && +#endif + (stride_b % 8) == 0) { + // Hint to the compiler that values are aligned (want 16B alignment) + start_k &= ~(START_ALIGN_K-1); + stride_b &= ~7; +#if QUANT_K == 1 + stride_a &= ~7; +#endif + + tensorLayoutA = setTensorLayoutStrideNV(tensorLayoutA, stride_a, 1); + tensorLayoutB = setTensorLayoutStrideNV(tensorLayoutB, stride_b, 1); + + uint k_iters = (end_k - start_k) / UNROLL_K; + uint block_k = start_k; + + // fetch scale values for a tile of quants. These will be copied into shared memory. + // The fetches and stores are pipelined to hide the latency. + fetch_scales(ir * BM, pos_a, stride_a, start_k, tid, true); + + if (enable_smaller_matrices && ic * BN + BNover4 >= p.N) { + coopmat sum = coopmat(0.0); + for (uint i = 0; i < k_iters; ++i) { + + store_scales(tid); + if (block_k + UNROLL_K < end_k) { + fetch_scales(ir * BM, pos_a, stride_a, block_k + UNROLL_K, tid, true); + } + + // Manually partial unroll + [[unroll]] for (uint j = 0; j < unroll_count; ++j) { + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover4, block_k, BK), tensorViewTranspose); + + sum = coopMatMulAdd(mat_a, mat_b, sum); + block_k += BK; + } + } + // Do any remaining iterations that were not unrolled + if (block_k < end_k) { + store_scales(tid); + } + while (block_k < end_k) { + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover4, block_k, BK), tensorViewTranspose); + + sum = coopMatMulAdd(mat_a, mat_b, sum); + block_k += BK; + } + coopmat mat_d = coopmat(sum); + + coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BNover4, ir * BM, BM), tensorViewTranspose); + return; + } else if (enable_smaller_matrices && ic * BN + BNover2 >= p.N) { + coopmat sum = coopmat(0.0); + for (uint i = 0; i < k_iters; ++i) { + + store_scales(tid); + if (block_k + UNROLL_K < end_k) { + fetch_scales(ir * BM, pos_a, stride_a, block_k + UNROLL_K, tid, true); + } + + // Manually partial unroll + [[unroll]] for (uint j = 0; j < unroll_count; ++j) { + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover2, block_k, BK), tensorViewTranspose); + + sum = coopMatMulAdd(mat_a, mat_b, sum); + block_k += BK; + } + } + // Do any remaining iterations that were not unrolled + if (block_k < end_k) { + store_scales(tid); + } + while (block_k < end_k) { + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover2, block_k, BK), tensorViewTranspose); + + sum = coopMatMulAdd(mat_a, mat_b, sum); + block_k += BK; + } + coopmat mat_d = coopmat(sum); + + coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BNover2, ir * BM, BM), tensorViewTranspose); + return; + } else { + coopmat sum = coopmat(0.0); + + for (uint i = 0; i < k_iters; ++i) { + + store_scales(tid); + if (block_k + UNROLL_K < end_k) { + fetch_scales(ir * BM, pos_a, stride_a, block_k + UNROLL_K, tid, true); + } + + // Manually partial unroll + [[unroll]] for (uint j = 0; j < unroll_count; ++j) { + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose); + + sum = coopMatMulAdd(mat_a, mat_b, sum); + block_k += BK; + } + } + // Do any remaining iterations that were not unrolled + if (block_k < end_k) { + store_scales(tid); + } + while (block_k < end_k) { + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose); + + sum = coopMatMulAdd(mat_a, mat_b, sum); + block_k += BK; + } + coopmat mat_d = coopmat(sum); + + coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BN, ir * BM, BM), tensorViewTranspose); + return; + } + } else +#endif // !defined(MUL_MAT_ID) + { + tensorLayoutA = setTensorLayoutStrideNV(tensorLayoutA, stride_a, 1); + + tensorLayoutAClamp = setTensorLayoutStrideNV(tensorLayoutAClamp, stride_a, 1); + + tensorLayoutB = setTensorLayoutStrideNV(tensorLayoutB, stride_b, 1); + + tensorLayoutBClamp = setTensorLayoutStrideNV(tensorLayoutBClamp, stride_b, 1); + + coopmat sum; + sum = coopmat(0.0); + + uint k_iters = (end_k - start_k + BK - 1) / BK; + + fetch_scales(ir * BM, pos_a, stride_a, start_k, tid, false); + + [[dont_unroll]] + for (uint block_k = start_k, i = 0; i < k_iters; block_k += BK, ++i) { + + store_scales(tid); + if (block_k + BK < end_k) { + fetch_scales(ir * BM, pos_a, stride_a, block_k + BK, tid, false); + } + + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutAClamp, ir * BM, BM, block_k, BK) DECODEFUNCA); +#ifdef MUL_MAT_ID + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose, decodeFuncB); +#else + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutBClamp, ic * BN, BN, block_k, BK), tensorViewTranspose); +#endif + + sum = coopMatMulAdd(mat_a, mat_b, sum); + } + + // Convert from ACC_TYPE to D_TYPE + coopmat mat_d; + mat_d = coopmat(sum); + +#ifdef MUL_MAT_ID + // Call callback to store each element, remapping row through shared memory + coopMatPerElementNV(mat_d, mat_d, perElemOpD, ir, ic); +#else + coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BN, ir * BM, BM), tensorViewTranspose); +#endif + } +} diff --git a/ggml/src/vulkan-shaders/mul_mmq.comp b/ggml/src/vulkan-shaders/mul_mmq.comp new file mode 100644 index 00000000..83de90eb --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mmq.comp @@ -0,0 +1,442 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable +#extension GL_EXT_shader_16bit_storage : require +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require + +#extension GL_EXT_integer_dot_product : require + +#ifdef FLOAT16 +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#endif + +#ifdef COOPMAT +#extension GL_KHR_cooperative_matrix : enable +#extension GL_KHR_memory_scope_semantics : enable +#extension GL_KHR_shader_subgroup_basic : enable +#endif + +#ifdef MUL_MAT_ID +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require +#endif + +#include "types.comp" + +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {A_TYPE_PACKED16 data_a[];}; +#if defined(A_TYPE_PACKED32) +layout (binding = 0) readonly buffer A_PACKED32 {A_TYPE_PACKED32 data_a_packed32[];}; +#endif +layout (binding = 1) readonly buffer B {block_q8_1_packed32 data_b[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +#ifdef MUL_MAT_ID +layout (binding = 3) readonly buffer IDS {int data_ids[];}; +#endif + +layout (push_constant) uniform parameter +{ + uint M; + uint N; + uint K; + uint stride_a; + uint stride_b; + uint stride_d; + + uint batch_stride_a; + uint batch_stride_b; + uint batch_stride_d; + +#ifdef MUL_MAT_ID + uint nei0; + uint nei1; + uint nbi1; + uint ne11; +#else + uint k_split; + uint ne02; + uint ne12; + uint broadcast2; + uint broadcast3; +#endif +} p; + +layout (constant_id = 0) const uint BLOCK_SIZE = 64; +layout (constant_id = 1) const uint BM = 64; +layout (constant_id = 2) const uint BN = 64; +// layout (constant_id = 3) const uint BK = 32; +layout (constant_id = 4) const uint WM = 32; +layout (constant_id = 5) const uint WN = 32; +layout (constant_id = 6) const uint WMITER = 2; +layout (constant_id = 7) const uint TM = 4; +layout (constant_id = 8) const uint TN = 2; +layout (constant_id = 9) const uint TK = 1; // Only needed for coopmat +layout (constant_id = 10) const uint WARP = 32; + +#define BK 32 + +#ifdef COOPMAT +#define SHMEM_STRIDE (BK / 4 + 4) +#else +#define SHMEM_STRIDE (BK / 4 + 1) +#endif + +shared int32_t buf_a_qs[BM * SHMEM_STRIDE]; + +#ifndef COOPMAT +#if QUANT_AUXF == 1 +shared FLOAT_TYPE buf_a_dm[BM]; +#else +shared FLOAT_TYPE_VEC2 buf_a_dm[BM]; +#endif +#endif + +shared int32_t buf_b_qs[BN * SHMEM_STRIDE]; +#ifndef COOPMAT +shared FLOAT_TYPE_VEC2 buf_b_ds[BN]; +#endif + +#define LOAD_VEC_A (4 * QUANT_R) +#define LOAD_VEC_B 4 + +#ifdef MUL_MAT_ID +shared u16vec2 row_ids[4096]; +#endif // MUL_MAT_ID + +#define NUM_WARPS (BLOCK_SIZE / WARP) + +#ifdef COOPMAT +shared ACC_TYPE coopmat_stage[TM * TN * NUM_WARPS]; +#endif + +#include "mul_mmq_funcs.comp" + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + +#ifdef MUL_MAT_ID + const uint expert_idx = gl_GlobalInvocationID.z; +#else + const uint batch_idx = gl_GlobalInvocationID.z; + + const uint i13 = batch_idx / p.ne12; + const uint i12 = batch_idx % p.ne12; + + const uint i03 = i13 / p.broadcast3; + const uint i02 = i12 / p.broadcast2; + + const uint batch_idx_a = i03 * p.ne02 + i02; +#endif + + const uint blocks_m = (p.M + BM - 1) / BM; + const uint ir = gl_WorkGroupID.x % blocks_m; + const uint ik = gl_WorkGroupID.x / blocks_m; + const uint ic = gl_WorkGroupID.y; + + const uint WNITER = (WM * WN) / (WARP * TM * TN * WMITER); + const uint WSUBM = WM / WMITER; + const uint WSUBN = WN / WNITER; + +#ifdef COOPMAT + const uint warp_i = gl_SubgroupID; + + const uint tiw = gl_SubgroupInvocationID; + + const uint cms_per_row = WM / TM; + const uint cms_per_col = WN / TN; + + const uint storestride = WARP / TM; + const uint store_r = tiw % TM; + const uint store_c = tiw / TM; +#else + const uint warp_i = gl_LocalInvocationID.x / WARP; + + const uint tiw = gl_LocalInvocationID.x % WARP; + + const uint tiwr = tiw % (WSUBM / TM); + const uint tiwc = tiw / (WSUBM / TM); +#endif + + const uint warp_r = warp_i % (BM / WM); + const uint warp_c = warp_i / (BM / WM); + + const uint loadr_a = gl_LocalInvocationID.x % (BK / LOAD_VEC_A); + const uint loadc_a = gl_LocalInvocationID.x / (BK / LOAD_VEC_A); + const uint loadr_b = gl_LocalInvocationID.x % (BK / LOAD_VEC_B); + const uint loadc_b = gl_LocalInvocationID.x / (BK / LOAD_VEC_B); + + const uint loadstride_a = BLOCK_SIZE * LOAD_VEC_A / BK; + const uint loadstride_b = BLOCK_SIZE * LOAD_VEC_B / BK; + +#ifdef MUL_MAT_ID + uint _ne1 = 0; + for (uint ii1 = 0; ii1 < p.nei1; ii1++) { + for (uint ii0 = 0; ii0 < p.nei0; ii0++) { + if (data_ids[ii1*p.nbi1 + ii0] == expert_idx) { + row_ids[_ne1] = u16vec2(ii0, ii1); + _ne1++; + } + } + } + + barrier(); + + // Workgroup has no work + if (ic * BN >= _ne1) return; +#endif + +#ifdef MUL_MAT_ID + const uint start_k = 0; + const uint end_k = p.K; +#else + const uint start_k = ik * p.k_split; + const uint end_k = min(p.K, (ik + 1) * p.k_split); +#endif + + uint pos_a_ib = ( +#ifdef MUL_MAT_ID + expert_idx * p.batch_stride_a + +#else + batch_idx_a * p.batch_stride_a + +#endif + ir * BM * p.stride_a + start_k) / BK; +#ifdef MUL_MAT_ID + uint pos_b_ib = 0; +#else + uint pos_b_ib = (batch_idx * p.batch_stride_b + ic * BN * p.stride_b + start_k) / BK; +#endif + +#ifdef COOPMAT + coopmat cache_a; + coopmat cache_b; + coopmat cm_result; + + coopmat factors[cms_per_row * cms_per_col]; + + coopmat sums[cms_per_row * cms_per_col]; + + [[unroll]] for (uint i = 0; i < cms_per_row * cms_per_col; i++) { + sums[i] = coopmat(0.0f); + } +#else + int32_t cache_a_qs[WMITER * TM * BK / 4]; + + int32_t cache_b_qs[TN * BK / 4]; + + ACC_TYPE sums[WMITER * TM * WNITER * TN]; + + [[unroll]] for (uint i = 0; i < WMITER*TM*WNITER*TN; i++) { + sums[i] = ACC_TYPE(0.0f); + } +#endif + +#if QUANT_AUXF == 1 + FLOAT_TYPE cache_a_dm[WMITER * TM]; +#else + FLOAT_TYPE_VEC2 cache_a_dm[WMITER * TM]; +#endif + + FLOAT_TYPE_VEC2 cache_b_ds[TN]; + + for (uint block = start_k; block < end_k; block += BK) { + [[unroll]] for (uint l = 0; loadc_a + l < BM; l += loadstride_a) { + const uint ib = pos_a_ib + (loadc_a + l) * p.stride_a / BK; + const uint iqs = loadr_a; + const uint buf_ib = loadc_a + l; + + if (iqs == 0) { +#if QUANT_AUXF == 1 + buf_a_dm[buf_ib] = get_d(ib); +#else + buf_a_dm[buf_ib] = get_dm(ib); +#endif + } +#if QUANT_R == 1 + buf_a_qs[buf_ib * SHMEM_STRIDE + iqs] = repack(ib, iqs); +#else + const i32vec2 vals = repack(ib, iqs); + buf_a_qs[buf_ib * SHMEM_STRIDE + iqs ] = vals.x; + buf_a_qs[buf_ib * SHMEM_STRIDE + iqs + 4] = vals.y; +#endif + } + [[unroll]] for (uint l = 0; loadc_b + l < BN; l += loadstride_b) { +#ifdef MUL_MAT_ID + const u16vec2 row_idx = row_ids[ic * BN + loadc_b + l]; + const uint idx = pos_b_ib + row_idx.y * p.batch_stride_b / LOAD_VEC_B + (row_idx.x % p.ne11) * p.stride_b / LOAD_VEC_B + loadr_b; + const uint ib = idx / 8; + const uint iqs = idx & 0x7; +#else + const uint ib = pos_b_ib + (loadc_b + l) * p.stride_b / BK; + const uint iqs = loadr_b; +#endif + + const uint buf_ib = loadc_b + l; + + if (iqs == 0) { + buf_b_ds[buf_ib] = FLOAT_TYPE_VEC2(data_b[ib].ds); + } + buf_b_qs[buf_ib * SHMEM_STRIDE + iqs] = data_b[ib].qs[iqs]; + } + + barrier(); + + pos_a_ib += 1; + pos_b_ib += 1; + +#ifdef COOPMAT + [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) { + const uint ib_a = warp_r * WM + cm_row * TM; + // Load from shared into cache + coopMatLoad(cache_a, buf_a_qs, ib_a * SHMEM_STRIDE, SHMEM_STRIDE, gl_CooperativeMatrixLayoutRowMajor); + + // TODO: only cache values that are actually needed + [[unroll]] for (uint t_idx = 0; t_idx < TM; t_idx++) { + cache_a_dm[t_idx] = buf_a_dm[ib_a + t_idx]; + } + + [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) { + const uint ib_b = warp_c * WN + cm_col * TN; + coopMatLoad(cache_b, buf_b_qs, ib_b * SHMEM_STRIDE, SHMEM_STRIDE, gl_CooperativeMatrixLayoutColumnMajor); + + // TODO: only cache values that are actually needed + [[unroll]] for (uint t_idx = 0; t_idx < TN; t_idx++) { + cache_b_dm[t_idx] = buf_b_d[ib_b + t_idx]; + } + + cm_result = coopmat(0); + cm_result = coopMatMulAdd(cache_a, cache_b, cm_result); + + [[unroll]] for (uint col = 0; col < TN; col += storestride) { + coopmat_stage[warp_i * TM * TN + (store_c + col) * TM + store_r] = ACC_TYPE(float(cache_a_d[store_r]) * float(cache_b_d[store_c + col])); + } + + coopMatLoad(factors, coopmat_stage, warp_i * TM * TN, TM, gl_CooperativeMatrixLayoutColumnMajor); + sums[cm_col * cms_per_row + cm_row] += factors * coopmat(cm_result); + } + } +#else + // Load from shared into cache + [[unroll]] for (uint wsir = 0; wsir < WMITER; wsir++) { + [[unroll]] for (uint cr = 0; cr < TM; cr++) { + const uint ib = warp_r * WM + wsir * WSUBM + tiwr * TM + cr; + cache_a_dm[wsir * TM + cr] = buf_a_dm[ib]; + [[unroll]] for (uint idx_k = 0; idx_k < BK / 4; idx_k++) { + cache_a_qs[(wsir * TM + cr) * (BK / 4) + idx_k] = buf_a_qs[ib * SHMEM_STRIDE + idx_k]; + } + } + } + + [[unroll]] for (uint wsic = 0; wsic < WNITER; wsic++) { + [[unroll]] for (uint cc = 0; cc < TN; cc++) { + const uint ib = warp_c * WN + wsic * WSUBN + tiwc * TN + cc; + cache_b_ds[cc] = buf_b_ds[ib]; + [[unroll]] for (uint idx_k = 0; idx_k < BK / 4; idx_k++) { + cache_b_qs[cc * (BK / 4) + idx_k] = buf_b_qs[ib * SHMEM_STRIDE + idx_k]; + } + } + + [[unroll]] for (uint wsir = 0; wsir < WMITER; wsir++) { + [[unroll]] for (uint cc = 0; cc < TN; cc++) { + [[unroll]] for (uint cr = 0; cr < TM; cr++) { + const uint cache_a_idx = wsir * TM + cr; + const uint sums_idx = (wsic * TN + cc) * (WMITER * TM) + wsir * TM + cr; + int32_t q_sum = 0; + [[unroll]] for (uint idx_k = 0; idx_k < BK / 4; idx_k++) { + q_sum += dotPacked4x8EXT(cache_a_qs[cache_a_idx * (BK / 4) + idx_k], + cache_b_qs[cc * (BK / 4) + idx_k]); + } + + sums[sums_idx] += mul_q8_1(q_sum, cache_a_dm[cache_a_idx], cache_b_ds[cc]); + } + } + } + } +#endif + + barrier(); + } + + const uint dr = ir * BM + warp_r * WM; + const uint dc = ic * BN + warp_c * WN; + +#ifndef MUL_MAT_ID + const uint offsets = batch_idx * p.batch_stride_d + ik * p.batch_stride_d * gl_NumWorkGroups.z; +#endif + +#ifdef COOPMAT +#ifdef MUL_MAT_ID + [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) { + [[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) { + const uint row_i = dc + cm_col * TN + col + store_c; + if (row_i >= _ne1) break; + + const u16vec2 row_idx = row_ids[row_i]; + + data_d[row_idx.y * p.batch_stride_d + row_idx.x * p.stride_d + dr + cm_row * TM + store_r] = D_TYPE(coopmat_stage[warp_i * TM * TN + (col + store_c) * TM + store_r]); + } + } + } +#else + const bool is_aligned = p.stride_d % 4 == 0; // Assumption: D_TYPE == float + + [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) { + [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) { + const bool is_in_bounds = dr + (cm_row + 1) * TM <= p.M && dc + (cm_col + 1) * TN <= p.N; + + if (is_aligned && is_in_bounds) { + // Full coopMat is within bounds and stride_d is aligned with 16B + coopmat cm_dtype = coopmat(sums[cm_col * cms_per_row + cm_row]); + coopMatStore(cm_dtype, data_d, offsets + (dc + cm_col * TN) * p.stride_d + dr + cm_row * TM, p.stride_d, gl_CooperativeMatrixLayoutColumnMajor); + } else if (is_in_bounds) { + // Full coopMat is within bounds, but stride_d is not aligned + coopMatStore(sums[cm_col * cms_per_row + cm_row], coopmat_stage, warp_i * TM * TN, TM, gl_CooperativeMatrixLayoutColumnMajor); + + [[unroll]] for (uint col = 0; col < TN; col += storestride) { + data_d[offsets + (dc + cm_col * TN + col + store_c) * p.stride_d + dr + cm_row * TM + store_r] = D_TYPE(coopmat_stage[warp_i * TM * TN + (col + store_c) * TM + store_r]); + } + } else if (dr + cm_row * TM < p.M && dc + cm_col * TN < p.N) { + // Partial coopMat is within bounds + coopMatStore(sums[cm_col * cms_per_row + cm_row], coopmat_stage, warp_i * TM * TN, TM, gl_CooperativeMatrixLayoutColumnMajor); + + [[unroll]] for (uint col = 0; col < TN; col += storestride) { + if (dr + cm_row * TM + store_r < p.M && dc + cm_col * TN + col + store_c < p.N) { + data_d[offsets + (dc + cm_col * TN + col + store_c) * p.stride_d + dr + cm_row * TM + store_r] = D_TYPE(coopmat_stage[warp_i * TM * TN + (col + store_c) * TM + store_r]); + } + } + } + } + } +#endif // MUL_MAT_ID +#else + [[unroll]] for (uint wsic = 0; wsic < WNITER; wsic++) { + [[unroll]] for (uint wsir = 0; wsir < WMITER; wsir++) { + + const uint dr_warp = dr + wsir * WSUBM + tiwr * TM; + const uint dc_warp = dc + wsic * WSUBN + tiwc * TN; + [[unroll]] for (uint cc = 0; cc < TN; cc++) { +#ifdef MUL_MAT_ID + const uint row_i = dc_warp + cc; + if (row_i >= _ne1) break; + + const u16vec2 row_idx = row_ids[row_i]; +#endif // MUL_MAT_ID + [[unroll]] for (uint cr = 0; cr < TM; cr++) { +#ifdef MUL_MAT_ID + data_d[row_idx.y * p.batch_stride_d + row_idx.x * p.stride_d + dr_warp + cr] = D_TYPE(sums[(wsic * TN + cc) * (WMITER * TM) + wsir * TM + cr]); +#else + if (dr_warp + cr < p.M && dc_warp + cc < p.N) { + data_d[offsets + (dc_warp + cc) * p.stride_d + dr_warp + cr] = D_TYPE(sums[(wsic * TN + cc) * (WMITER * TM) + wsir * TM + cr]); + } +#endif // MUL_MAT_ID + } + } + } + } +#endif // COOPMAT +} diff --git a/ggml/src/vulkan-shaders/mul_mmq_funcs.comp b/ggml/src/vulkan-shaders/mul_mmq_funcs.comp new file mode 100644 index 00000000..63b15471 --- /dev/null +++ b/ggml/src/vulkan-shaders/mul_mmq_funcs.comp @@ -0,0 +1,99 @@ +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require + +#include "types.comp" + +// Each iqs value maps to a 32-bit integer + +#if defined(DATA_A_Q4_0) +i32vec2 repack(uint ib, uint iqs) { + // Use 2-byte loads since a q4_0 block (18 bytes) is not divisible by 4 + const u16vec2 quants = u16vec2(data_a[ib].qs[iqs * 2 ], + data_a[ib].qs[iqs * 2 + 1]); + const uint32_t vui = pack32(quants); + return i32vec2( vui & 0x0F0F0F0F, + (vui >> 4) & 0x0F0F0F0F); +} + +ACC_TYPE mul_q8_1(int32_t q_sum, float da, vec2 dsb) { + return ACC_TYPE(da * (float(q_sum) * dsb.x - 8.0f * dsb.y)); +} +#endif + +#if defined(DATA_A_Q4_1) +i32vec2 repack(uint ib, uint iqs) { + // Use 4-byte loads since a q4_1 block (20 bytes) is divisible by 4 + const uint32_t vui = data_a_packed32[ib].qs[iqs]; + return i32vec2( vui & 0x0F0F0F0F, + (vui >> 4) & 0x0F0F0F0F); +} + +ACC_TYPE mul_q8_1(int32_t q_sum, vec2 dma, vec2 dsb) { + return ACC_TYPE(float(q_sum) * dma.x * dsb.x + dma.y * dsb.y); +} +#endif + +#if defined(DATA_A_Q5_0) +i32vec2 repack(uint ib, uint iqs) { + // Use 2-byte loads since a q5_0 block (22 bytes) is not divisible by 4 + const u16vec2 quants = u16vec2(data_a[ib].qs[iqs * 2 ], + data_a[ib].qs[iqs * 2 + 1]); + const uint32_t vui = pack32(quants); + const int32_t qh = int32_t((uint32_t(data_a[ib].qh[1]) << 16 | data_a[ib].qh[0]) >> (4 * iqs)); + const int32_t v0 = int32_t(vui & 0x0F0F0F0F) + | ((qh & 0xF) * 0x02040810) & 0x10101010; // (0,1,2,3) -> (4,12,20,28) + + const int32_t v1 = int32_t((vui >> 4) & 0x0F0F0F0F) + | (((qh >> 16) & 0xF) * 0x02040810) & 0x10101010; // (16,17,18,19) -> (4,12,20,28) + + return i32vec2(v0, v1); +} + +ACC_TYPE mul_q8_1(int32_t q_sum, float da, vec2 dsb) { + return ACC_TYPE(da * (float(q_sum) * dsb.x - 16.0f * dsb.y)); +} +#endif + +#if defined(DATA_A_Q5_1) +i32vec2 repack(uint ib, uint iqs) { + // Use 4-byte loads since a q5_1 block (24 bytes) is divisible by 4 + const uint32_t vui = data_a_packed32[ib].qs[iqs]; + const int32_t qh = int32_t(data_a_packed32[ib].qh >> (4 * iqs)); + const int32_t v0 = int32_t(vui & 0x0F0F0F0F) + | ((qh & 0xF) * 0x02040810) & 0x10101010; // (0,1,2,3) -> (4,12,20,28) + + const int32_t v1 = int32_t((vui >> 4) & 0x0F0F0F0F) + | (((qh >> 16) & 0xF) * 0x02040810) & 0x10101010; // (16,17,18,19) -> (4,12,20,28) + + return i32vec2(v0, v1); +} + +ACC_TYPE mul_q8_1(int32_t q_sum, vec2 dma, vec2 dsb) { + return ACC_TYPE(float(q_sum) * dma.x * dsb.x + dma.y * dsb.y); +} +#endif + +#if defined(DATA_A_Q8_0) +int32_t repack(uint ib, uint iqs) { + // Use 2-byte loads since a q8_0 block (34 bytes) is not divisible by 4 + return pack32(i16vec2(data_a[ib].qs[iqs * 2 ], + data_a[ib].qs[iqs * 2 + 1])); +} + +ACC_TYPE mul_q8_1(int32_t q_sum, float da, vec2 dsb) { + return ACC_TYPE(float(q_sum) * da * dsb.x); +} +#endif + +#if defined(DATA_A_Q4_0) || defined(DATA_A_Q5_0) || defined(DATA_A_Q8_0) || defined(DATA_A_IQ1_S) || defined(DATA_A_IQ2_XXS) || defined(DATA_A_IQ2_XS) || defined(DATA_A_IQ2_S) || defined(DATA_A_IQ3_XXS) || defined(DATA_A_IQ3_S) || defined(DATA_A_IQ4_XS) || defined(DATA_A_IQ4_NL) +FLOAT_TYPE get_d(uint ib) { + return FLOAT_TYPE(data_a[ib].d); +} +#endif + +#if defined(DATA_A_Q4_1) || defined(DATA_A_Q5_1) +FLOAT_TYPE_VEC2 get_dm(uint ib) { + return FLOAT_TYPE_VEC2(data_a_packed32[ib].dm); +} +#endif diff --git a/ggml/src/vulkan-shaders/opt_step_adamw.comp b/ggml/src/vulkan-shaders/opt_step_adamw.comp new file mode 100644 index 00000000..e0214fe7 --- /dev/null +++ b/ggml/src/vulkan-shaders/opt_step_adamw.comp @@ -0,0 +1,42 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) buffer X {A_TYPE x[];}; +layout (binding = 1) readonly buffer G {A_TYPE grad[];}; +layout (binding = 2) buffer GM {A_TYPE gradm[];}; +layout (binding = 3) buffer GV {A_TYPE gradv[];}; +layout (binding = 4) readonly buffer P {float params[7];}; + +void main() { + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.KX) { + return; + } + + const float alpha = params[0]; + const float beta1 = params[1]; + const float beta2 = params[2]; + const float eps = params[3]; + const float wd = params[4]; + const float beta1h = params[5]; + const float beta2h = params[6]; + + const float gi = grad[i]; + const float gmi = gradm[i]*beta1 + gi*(1.0f - beta1); + const float gvi = gradv[i]*beta2 + gi*gi*(1.0f - beta2); + + gradm[i] = gmi; + gradv[i] = gvi; + + const float mh = gmi*beta1h; + const float vh = sqrt(gvi*beta2h) + eps; + + x[i] = x[i]*(1.0f - alpha*wd) - alpha*mh/vh; +} diff --git a/ggml/src/vulkan-shaders/pad.comp b/ggml/src/vulkan-shaders/pad.comp index a465cd52..450b67fc 100644 --- a/ggml/src/vulkan-shaders/pad.comp +++ b/ggml/src/vulkan-shaders/pad.comp @@ -3,6 +3,8 @@ #include "types.comp" #include "generic_unary_head.comp" +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + void main() { const uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; @@ -22,5 +24,5 @@ void main() { const bool is_src0 = i0 < p.ne00 && i1 < p.ne01 && i2 < p.ne02 && i3 < p.ne03; - data_d[p.d_offset + dst_idx] = D_TYPE(is_src0 ? data_a[src0_idx] : 0.0f); + data_d[get_doffset() + dst_idx] = D_TYPE(is_src0 ? data_a[get_aoffset() + src0_idx] : 0.0f); } diff --git a/ggml/src/vulkan-shaders/pool2d.comp b/ggml/src/vulkan-shaders/pool2d.comp new file mode 100644 index 00000000..b6124411 --- /dev/null +++ b/ggml/src/vulkan-shaders/pool2d.comp @@ -0,0 +1,74 @@ +#version 450 + +#include "types.comp" + +#extension GL_EXT_shader_16bit_storage : require + +layout(push_constant) uniform parameter { + uint IW; uint IH; + uint OW; uint OH; + uint OC; + uint pelements; + uint op; + int k0; int k1; + int s0; int s1; + int p0; int p1; +} p; + +#define BLOCK_SIZE 512 +#define FLT_MAX 3.402823466e+38F +#define OP_POOL_MAX 0u +#define OP_POOL_AVG 1u + +layout (local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout(binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout(binding = 1) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + const uint idx = gl_GlobalInvocationID.x; + if (idx >= p.pelements) { + return; + } + + const uint O_HW = p.OW * p.OH; + + const uint nc = idx / O_HW; + const uint cur_oh = (idx % O_HW) / p.OW; + const uint cur_ow = (idx % O_HW) % p.OW; + + const int start_h = int(cur_oh) * p.s0 - p.p0; + const uint bh = max(start_h, 0); + const uint eh = min(start_h + p.k0, p.IH); + + const int start_w = int(cur_ow) * p.s1 - p.p1; + const uint bw = max(start_w, 0); + const uint ew = min(start_w + p.k1, p.IW); + + const float scale = 1.0 / float(p.k0 * p.k1); + float res; + + if (p.op == OP_POOL_AVG) { + res = 0.0; + } else if (p.op == OP_POOL_MAX) { + res = -FLT_MAX; + } else { + return; + } + + #pragma unroll + for (uint i = bh; i < eh; i++) { + #pragma unroll + for (uint j = bw; j < ew; j++) { + const float cur = D_TYPE(data_a[nc * p.IH * p.IW + i * p.IW + j]); + + if (p.op == OP_POOL_AVG) { + res += cur * scale; + } else if (p.op == OP_POOL_MAX) { + res = max(res, cur); + } + } + } + + data_d[nc * O_HW + cur_oh * p.OW + cur_ow] = res; +} diff --git a/ggml/src/vulkan-shaders/quantize_q8_1.comp b/ggml/src/vulkan-shaders/quantize_q8_1.comp new file mode 100644 index 00000000..e2e020fe --- /dev/null +++ b/ggml/src/vulkan-shaders/quantize_q8_1.comp @@ -0,0 +1,77 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : require +#extension GL_EXT_shader_16bit_storage : require + +layout (push_constant) uniform parameter +{ + uint ne; +} p; + +#include "types.comp" + +layout(constant_id = 0) const uint GROUP_SIZE = 32; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {vec4 data_a[];}; +layout (binding = 1) writeonly buffer D {block_q8_1_packed32 data_b[];}; + +shared float shmem[GROUP_SIZE]; + +void quantize() { + const uint wgid = gl_WorkGroupID.x; + const uint tid = gl_LocalInvocationID.x; + + // Each thread handles a vec4, so 8 threads handle a block + const uint blocks_per_group = GROUP_SIZE / 8; + + const uint block_in_wg = tid / 8; + + const uint ib = wgid * blocks_per_group + block_in_wg; + const uint iqs = tid % 8; + + if (ib >= gl_NumWorkGroups.x * blocks_per_group) { + return; + } + + const uint a_idx = ib * 8 + iqs; + + vec4 vals = a_idx < p.ne ? data_a[a_idx] : vec4(0.0f); + const vec4 abs_vals = abs(vals); + + // Find absolute max for each block + shmem[tid] = max(max(abs_vals.x, abs_vals.y), max(abs_vals.z, abs_vals.w)); + barrier(); + [[unroll]] for (uint s = 4; s > 0; s >>= 1) { + if (iqs < s) { + shmem[tid] = max(shmem[tid], shmem[tid + s]); + } + barrier(); + } + + const float amax = shmem[block_in_wg * 8]; + const float d = amax / 127.0; + const float d_inv = d != 0.0 ? 1.0 / d : 0.0; + vals = round(vals * d_inv); + data_b[ib].qs[iqs] = pack32(i8vec4(round(vals))); + barrier(); + + // Calculate the sum for each block + shmem[tid] = vals.x + vals.y + vals.z + vals.w; + barrier(); + [[unroll]] for (uint s = 4; s > 0; s >>= 1) { + if (iqs < s) { + shmem[tid] += shmem[tid + s]; + } + barrier(); + } + if (iqs == 0) { + const float sum = shmem[tid]; + + data_b[ib].ds = f16vec2(vec2(d, sum * d)); + } +} + +void main() { + quantize(); +} diff --git a/ggml/src/vulkan-shaders/relu.comp b/ggml/src/vulkan-shaders/relu.comp index 52a19b62..4f806270 100644 --- a/ggml/src/vulkan-shaders/relu.comp +++ b/ggml/src/vulkan-shaders/relu.comp @@ -17,5 +17,5 @@ void main() { return; } - data_d[i] = max(float(data_a[i]), 0); + data_d[i] = D_TYPE(max(float(data_a[i]), 0)); } diff --git a/ggml/src/vulkan-shaders/repeat.comp b/ggml/src/vulkan-shaders/repeat.comp new file mode 100644 index 00000000..1568b141 --- /dev/null +++ b/ggml/src/vulkan-shaders/repeat.comp @@ -0,0 +1,26 @@ +#version 450 + +#include "types.comp" +#include "generic_unary_head.comp" + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +uint src0_idx_mod(uint idx) { + const uint i13 = idx / (p.ne12*p.ne11*p.ne10); + const uint i13_offset = i13 * p.ne12*p.ne11*p.ne10; + const uint i12 = (idx - i13_offset) / (p.ne11*p.ne10); + const uint i12_offset = i12*p.ne11*p.ne10; + const uint i11 = (idx - i13_offset - i12_offset) / p.ne10; + const uint i10 = idx - i13_offset - i12_offset - i11*p.ne10; + return (i13 % p.ne03)*p.nb03 + (i12 % p.ne02)*p.nb02 + (i11 % p.ne01)*p.nb01 + (i10 % p.ne00)*p.nb00; +} + +void main() { + const uint idx = get_idx(); + + if (idx >= p.ne) { + return; + } + + data_d[get_doffset() + dst_idx(idx)] = D_TYPE(data_a[get_aoffset() + src0_idx_mod(idx)]); +} diff --git a/ggml/src/vulkan-shaders/repeat_back.comp b/ggml/src/vulkan-shaders/repeat_back.comp new file mode 100644 index 00000000..d8627993 --- /dev/null +++ b/ggml/src/vulkan-shaders/repeat_back.comp @@ -0,0 +1,37 @@ +#version 450 + +#include "types.comp" +#include "generic_unary_head.comp" + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +void main() { + const uint idx = get_idx(); + + if (idx >= p.ne) { + return; + } + + // Destination multi-index (inlined dst_idx) + const uint i13 = fastdiv(idx, p.ne1_012mp, p.ne1_012L); + const uint i13_offset = i13 * p.ne12*p.ne11*p.ne10; + const uint i12 = fastdiv(idx - i13_offset, p.ne1_01mp, p.ne1_01L); + const uint i12_offset = i12*p.ne11*p.ne10; + const uint i11 = fastdiv(idx - i13_offset - i12_offset, p.ne1_0mp, p.ne1_0L); + const uint i10 = idx - i13_offset - i12_offset - i11*p.ne10; + const uint d_idx = i13*p.nb13 + i12*p.nb12 + i11*p.nb11 + i10*p.nb10; + + // Accumulate from sources + A_TYPE acc = A_TYPE(0); + for (uint i3 = i13; i3 < p.ne03; i3 += p.ne13) { + for (uint i2 = i12; i2 < p.ne02; i2 += p.ne12) { + for (uint i1 = i11; i1 < p.ne01; i1 += p.ne11) { + for (uint i0 = i10; i0 < p.ne00; i0 += p.ne10) { + acc += data_a[i3*p.nb03 + i2*p.nb02 + i1*p.nb01 + i0*p.nb00]; + } + } + } + } + + data_d[get_doffset() + d_idx] = D_TYPE(acc); +} diff --git a/ggml/src/vulkan-shaders/rms_norm.comp b/ggml/src/vulkan-shaders/rms_norm.comp index b554400b..deb8ee99 100644 --- a/ggml/src/vulkan-shaders/rms_norm.comp +++ b/ggml/src/vulkan-shaders/rms_norm.comp @@ -1,6 +1,6 @@ #version 450 -#include "generic_head.comp" +#include "generic_unary_head.comp" #include "types.comp" #extension GL_EXT_control_flow_attributes : enable @@ -8,19 +8,29 @@ layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; -layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; -layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; - shared FLOAT_TYPE sum[BLOCK_SIZE]; void main() { - const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x; - const uint tid = gl_LocalInvocationID.x; + const uint ncols = p.ne00; + const uint nrows = gl_NumWorkGroups.x; + const uint nchannels = gl_NumWorkGroups.y; + + const uint row = gl_WorkGroupID.x; + const uint channel = gl_WorkGroupID.y; + const uint samp = gl_WorkGroupID.z; + const uint tid = gl_LocalInvocationID.x; + + const uint stride_row = p.nb01; + const uint stride_channel = p.nb02; + const uint stride_sample = p.nb03; + + uint32_t a_offset = samp*stride_sample + channel*stride_channel + row*stride_row + get_aoffset(); + uint32_t d_offset = ((samp*nchannels + channel)*nrows + row)*ncols + get_doffset(); sum[tid] = FLOAT_TYPE(0.0f); // partial sum for thread in warp - [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { - const FLOAT_TYPE xi = FLOAT_TYPE(data_a[row*p.KX + col]); + [[unroll]] for (uint col = tid; col < ncols; col += BLOCK_SIZE) { + const FLOAT_TYPE xi = FLOAT_TYPE(data_a[a_offset + col]); sum[tid] += xi * xi; } @@ -33,10 +43,10 @@ void main() { barrier(); } - const FLOAT_TYPE mean = sum[0] / FLOAT_TYPE(p.KX); + const FLOAT_TYPE mean = sum[0] / FLOAT_TYPE(ncols); const FLOAT_TYPE scale = inversesqrt(mean + FLOAT_TYPE(p.param1)); - [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { - data_d[row*p.KX + col] = D_TYPE(scale * FLOAT_TYPE(data_a[row*p.KX + col])); + [[unroll]] for (uint col = tid; col < ncols; col += BLOCK_SIZE) { + data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col])); } } diff --git a/ggml/src/vulkan-shaders/rms_norm_back.comp b/ggml/src/vulkan-shaders/rms_norm_back.comp new file mode 100644 index 00000000..76009f3d --- /dev/null +++ b/ggml/src/vulkan-shaders/rms_norm_back.comp @@ -0,0 +1,55 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable +#define BLOCK_SIZE 512 + +layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer G {A_TYPE data_a[];}; +layout (binding = 1) readonly buffer X {B_TYPE data_b[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +shared FLOAT_TYPE sum_xx[BLOCK_SIZE]; +shared FLOAT_TYPE sum_xg[BLOCK_SIZE]; + +void main() { + const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x; + const uint tid = gl_LocalInvocationID.x; + + // Compute derivative of x[i]/norm(x) = g[i]/norm(x) - x[i] dot(x,g)/KX / norm(x)^1.5 + + // partial sums for thread in warp + sum_xx[tid] = FLOAT_TYPE(0.0f); + sum_xg[tid] = FLOAT_TYPE(0.0f); + + [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { + const FLOAT_TYPE gi = FLOAT_TYPE(data_a[row*p.KX + col]); + const FLOAT_TYPE xi = FLOAT_TYPE(data_b[row*p.KX + col]); + sum_xx[tid] += xi * xi; + sum_xg[tid] += xi * gi; + } + + // sum up partial sums and write back result + barrier(); + [[unroll]] for (int s = BLOCK_SIZE / 2; s > 0; s >>= 1) { + if (tid < s) { + sum_xx[tid] += sum_xx[tid + s]; + sum_xg[tid] += sum_xg[tid + s]; + } + barrier(); + } + + const FLOAT_TYPE eps = FLOAT_TYPE(p.param1); + const FLOAT_TYPE mean = sum_xx[0] / FLOAT_TYPE(p.KX); + const FLOAT_TYPE scale_g = inversesqrt(mean + eps); + const FLOAT_TYPE scale_x = -scale_g * sum_xg[0] / (sum_xx[0] + FLOAT_TYPE(p.KX) * eps); + + [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { + data_d[row*p.KX + col] = D_TYPE( + scale_g * FLOAT_TYPE(data_a[row*p.KX + col]) + + scale_x * FLOAT_TYPE(data_b[row*p.KX + col])); + } +} diff --git a/ggml/src/vulkan-shaders/rope_head.comp b/ggml/src/vulkan-shaders/rope_head.comp index ea895422..96c9c4cb 100644 --- a/ggml/src/vulkan-shaders/rope_head.comp +++ b/ggml/src/vulkan-shaders/rope_head.comp @@ -1,6 +1,11 @@ #include "types.comp" #extension GL_EXT_shader_16bit_storage : require +#extension GL_EXT_spirv_intrinsics: enable + +#if RTE16 +spirv_execution_mode(capabilities = [4467], 4462, 16); // RoundingModeRTE, 16 bits +#endif layout(local_size_x = 1, local_size_y = 256, local_size_z = 1) in; @@ -20,6 +25,11 @@ layout (push_constant) uniform parameter { float corr_dims[2]; float theta_scale; uint has_ff; + uint ne02; + uint s1; + uint s2; + int sections[4]; + uint is_back; } p; float rope_yarn_ramp(const float low, const float high, const uint i0) { @@ -39,6 +49,10 @@ void rope_yarn(const float theta_extrap, const uint i0, out float cos_theta, out // Get n-d magnitude scaling corrected for interpolation mscale *= 1.0f + 0.1f * log(1.0f / p.freq_scale); } + // Backprogagation uses inverted rotation + if (p.is_back != 0) { + theta = -theta; + } cos_theta = cos(theta) * mscale; sin_theta = sin(theta) * mscale; } diff --git a/ggml/src/vulkan-shaders/rope_multi.comp b/ggml/src/vulkan-shaders/rope_multi.comp new file mode 100644 index 00000000..4f5b1a0e --- /dev/null +++ b/ggml/src/vulkan-shaders/rope_multi.comp @@ -0,0 +1,60 @@ +#version 450 + +#include "rope_head.comp" + +void main() { + const uint i0 = 2*gl_GlobalInvocationID.y; + uint ne0 = p.ncols; + uint ne1 = p.p_delta_rows; + uint ne2 = p.ne02; + + if (i0 >= ne0) { + return; + } + + const uint row_dst = gl_GlobalInvocationID.x; + + if (i0 >= p.n_dims) { + const uint i = row_dst*ne0 + i0; + + data_d[i + 0] = data_a[i + 0]; + data_d[i + 1] = data_a[i + 1]; + + return; + } + + const uint row_x = row_dst % ne1; + const uint channel_x = row_dst / ne1; + + const uint idst = row_dst*ne0 + i0/2; + const uint ix = channel_x*p.s2 + row_x*p.s1 + i0/2; + + const int sect_dims = p.sections[0] + p.sections[1] + p.sections[2] + p.sections[3]; + const int sec_w = p.sections[1] + p.sections[0]; + const uint sector = (i0 / 2) % sect_dims; + + float theta_base = 0.0; + if (sector < p.sections[0]) { + theta_base = data_pos[channel_x]*pow(p.theta_scale, i0/2.0f); + } + else if (sector >= p.sections[0] && sector < sec_w) { + theta_base = data_pos[channel_x + ne2 * 1]*pow(p.theta_scale, i0/2.0f); + } + else if (sector >= sec_w && sector < sec_w + p.sections[2]) { + theta_base = data_pos[channel_x + ne2 * 2]*pow(p.theta_scale, i0/2.0f); + } + else if (sector >= sec_w + p.sections[2]) { + theta_base = data_pos[channel_x + ne2 * 3]*pow(p.theta_scale, i0/2.0f); + } + + const float freq_factor = p.has_ff != 0 ? data_ff[i0/2] : 1.0f; + + float cos_theta, sin_theta; + rope_yarn(theta_base / freq_factor, i0, cos_theta, sin_theta); + + const float x0 = float(data_a[ix + 0]); + const float x1 = float(data_a[ix + p.n_dims/2]); + + data_d[idst + 0] = D_TYPE(x0*cos_theta - x1*sin_theta); + data_d[idst + p.n_dims/2] = D_TYPE(x0*sin_theta + x1*cos_theta); +} diff --git a/ggml/src/vulkan-shaders/rope_neox.comp b/ggml/src/vulkan-shaders/rope_neox.comp index 83b46b69..db775c45 100644 --- a/ggml/src/vulkan-shaders/rope_neox.comp +++ b/ggml/src/vulkan-shaders/rope_neox.comp @@ -3,15 +3,18 @@ #include "rope_head.comp" void main() { - const uint col = gl_GlobalInvocationID.y * 2; - const uint row = gl_GlobalInvocationID.x; + const uint i0 = 2*gl_GlobalInvocationID.y; + uint ne0 = p.ncols; + uint ne1 = p.p_delta_rows; - if (col >= p.ncols) { + if (i0 >= ne0) { return; } - if (col >= p.n_dims) { - const uint i = row*p.ncols + col; + const uint row_dst = gl_GlobalInvocationID.x; + + if (i0 >= p.n_dims) { + const uint i = row_dst*ne0 + i0; data_d[i + 0] = data_a[i + 0]; data_d[i + 1] = data_a[i + 1]; @@ -19,19 +22,22 @@ void main() { return; } - const uint i = row*p.ncols + col/2; - const uint i2 = row/p.p_delta_rows; + const uint row_x = row_dst % ne1; + const uint channel_x = row_dst / ne1; - const float theta_base = data_pos[i2] * pow(p.theta_scale, col/2.0f); + const uint idst = row_dst*ne0 + i0/2; + const uint ix = channel_x*p.s2 + row_x*p.s1 + i0/2; - const float freq_factor = p.has_ff != 0 ? data_ff[col/2] : 1.0f; + const float theta_base = data_pos[channel_x] * pow(p.theta_scale, i0/2.0f); + + const float freq_factor = p.has_ff != 0 ? data_ff[i0/2] : 1.0f; float cos_theta, sin_theta; - rope_yarn(theta_base / freq_factor, col, cos_theta, sin_theta); + rope_yarn(theta_base / freq_factor, i0, cos_theta, sin_theta); - const float x0 = float(data_a[i + 0]); - const float x1 = float(data_a[i + p.n_dims/2]); + const float x0 = float(data_a[ix + 0]); + const float x1 = float(data_a[ix + p.n_dims/2]); - data_d[i + 0] = D_TYPE(x0*cos_theta - x1*sin_theta); - data_d[i + p.n_dims/2] = D_TYPE(x0*sin_theta + x1*cos_theta); + data_d[idst + 0] = D_TYPE(x0*cos_theta - x1*sin_theta); + data_d[idst + p.n_dims/2] = D_TYPE(x0*sin_theta + x1*cos_theta); } diff --git a/ggml/src/vulkan-shaders/rope_norm.comp b/ggml/src/vulkan-shaders/rope_norm.comp index e416ad93..4ad35e54 100644 --- a/ggml/src/vulkan-shaders/rope_norm.comp +++ b/ggml/src/vulkan-shaders/rope_norm.comp @@ -3,15 +3,18 @@ #include "rope_head.comp" void main() { - const uint col = gl_GlobalInvocationID.y * 2; - const uint row = gl_GlobalInvocationID.x; + const uint i0 = 2*gl_GlobalInvocationID.y; + uint ne0 = p.ncols; + uint ne1 = p.p_delta_rows; - if (col >= p.ncols) { + if (i0 >= ne0) { return; } - if (col >= p.n_dims) { - const uint i = row*p.ncols + col; + const uint row_dst = gl_GlobalInvocationID.x; + + if (i0 >= p.n_dims) { + const uint i = row_dst*ne0 + i0; data_d[i + 0] = data_a[i + 0]; data_d[i + 1] = data_a[i + 1]; @@ -19,19 +22,22 @@ void main() { return; } - const uint i = row*p.ncols + col; - const uint i2 = row/p.p_delta_rows; + const uint row_x = row_dst % ne1; + const uint channel_x = row_dst / ne1; - const float theta_base = data_pos[i2] * pow(p.theta_scale, col/2.0f); + const uint idst = row_dst*ne0 + i0; + const uint ix = channel_x*p.s2 + row_x*p.s1 + i0; - const float freq_factor = p.has_ff != 0 ? data_ff[col/2] : 1.0f; + const float theta_base = data_pos[channel_x] * pow(p.theta_scale, i0/2.0f); + + const float freq_factor = p.has_ff != 0 ? data_ff[i0/2] : 1.0f; float cos_theta, sin_theta; - rope_yarn(theta_base / freq_factor, col, cos_theta, sin_theta); + rope_yarn(theta_base / freq_factor, i0, cos_theta, sin_theta); - const float x0 = float(data_a[i + 0]); - const float x1 = float(data_a[i + 1]); + const float x0 = float(data_a[ix + 0]); + const float x1 = float(data_a[ix + 1]); - data_d[i + 0] = D_TYPE(x0*cos_theta - x1*sin_theta); - data_d[i + 1] = D_TYPE(x0*sin_theta + x1*cos_theta); + data_d[idst + 0] = D_TYPE(x0*cos_theta - x1*sin_theta); + data_d[idst + 1] = D_TYPE(x0*sin_theta + x1*cos_theta); } diff --git a/ggml/src/vulkan-shaders/rope_vision.comp b/ggml/src/vulkan-shaders/rope_vision.comp new file mode 100644 index 00000000..cedacc4d --- /dev/null +++ b/ggml/src/vulkan-shaders/rope_vision.comp @@ -0,0 +1,47 @@ +#version 450 + +#include "rope_head.comp" + +void main() { + const uint i0 = 2*gl_GlobalInvocationID.y; + uint ne0 = p.ncols; + uint ne1 = p.p_delta_rows; + uint ne2 = p.ne02; + + if (i0 >= ne0) { + return; + } + + const uint row_dst = gl_GlobalInvocationID.x; + + const uint row_x = row_dst % ne1; + const uint channel_x = row_dst / ne1; + + const uint idst = row_dst*ne0 + i0/2; + const uint ix = channel_x*p.s2 + row_x*p.s1 + i0/2; + + const int sect_dims = p.sections[0] + p.sections[1]; + const int sec_w = p.sections[1] + p.sections[0]; + const uint sector = (i0 / 2) % sect_dims; + + float theta_base = 0.0; + if (sector < p.sections[0]) { + const uint p0 = sector; + theta_base = data_pos[channel_x]*pow(p.theta_scale, p0); + } + else if (sector >= p.sections[0] && sector < sec_w) { + const uint p0 = sector - p.sections[0]; + theta_base = data_pos[channel_x + ne2]*pow(p.theta_scale, p0); + } + + const float freq_factor = p.has_ff != 0 ? data_ff[i0/2] : 1.0f; + + float cos_theta, sin_theta; + rope_yarn(theta_base / freq_factor, i0, cos_theta, sin_theta); + + const float x0 = float(data_a[ix + 0]); + const float x1 = float(data_a[ix + p.n_dims]); + + data_d[idst + 0] = D_TYPE(x0*cos_theta - x1*sin_theta); + data_d[idst + p.n_dims] = D_TYPE(x0*sin_theta + x1*cos_theta); +} diff --git a/ggml/src/vulkan-shaders/scale.comp b/ggml/src/vulkan-shaders/scale.comp index 5cd2f668..4663428d 100644 --- a/ggml/src/vulkan-shaders/scale.comp +++ b/ggml/src/vulkan-shaders/scale.comp @@ -3,12 +3,22 @@ #include "types.comp" #include "generic_unary_head.comp" +const uint num_threads = 128; + +layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in; + void main() { - const uint idx = get_idx(); + uint idx = get_idx(); - if (idx >= p.ne) { - return; + // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation + const uint num_iter = 4; + + [[unroll]] for (uint i = 0; i < num_iter; ++i) { + if (idx >= p.ne) { + continue; + } + + data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + idx]) * FLOAT_TYPE(p.param1)); + idx += num_threads; } - - data_d[p.d_offset + dst_idx(idx)] = D_TYPE(FLOAT_TYPE(data_a[src0_idx(idx)]) * FLOAT_TYPE(p.param1)); } diff --git a/ggml/src/vulkan-shaders/sigmoid.comp b/ggml/src/vulkan-shaders/sigmoid.comp new file mode 100644 index 00000000..5c9e5c35 --- /dev/null +++ b/ggml/src/vulkan-shaders/sigmoid.comp @@ -0,0 +1,20 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.KX) { + return; + } + data_d[i] = D_TYPE(1. / (1 + exp(-1. * float(data_a[i])))); +} diff --git a/ggml/src/vulkan-shaders/silu_back.comp b/ggml/src/vulkan-shaders/silu_back.comp new file mode 100644 index 00000000..f9afa9b1 --- /dev/null +++ b/ggml/src/vulkan-shaders/silu_back.comp @@ -0,0 +1,26 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer G {A_TYPE data_g[];}; +layout (binding = 1) readonly buffer X {B_TYPE data_x[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.KX) { + return; + } + + // Compute derivative of SiLU(x): 1/(1+exp(-x)) - x*exp(-x)/(1+exp(-x))^2 + + const float xi = float(data_x[i]); + const float s = 1.0f / (1.0f + exp(-xi)); + data_d[i] = D_TYPE(data_g[i] * (s + xi * s * (1 - s))); +} diff --git a/ggml/src/vulkan-shaders/sin.comp b/ggml/src/vulkan-shaders/sin.comp new file mode 100644 index 00000000..d7c15a16 --- /dev/null +++ b/ggml/src/vulkan-shaders/sin.comp @@ -0,0 +1,17 @@ +#version 450 + +#include "types.comp" +#include "generic_unary_head.comp" + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +void main() { + const uint idx = get_idx(); + + if (idx >= p.ne) { + return; + } + + const FLOAT_TYPE val = FLOAT_TYPE(data_a[get_aoffset() + src0_idx(idx)]); + data_d[get_doffset() + dst_idx(idx)] = D_TYPE(sin(val)); +} diff --git a/ggml/src/vulkan-shaders/soft_max.comp b/ggml/src/vulkan-shaders/soft_max.comp index 0bd51eca..51fc2dc7 100644 --- a/ggml/src/vulkan-shaders/soft_max.comp +++ b/ggml/src/vulkan-shaders/soft_max.comp @@ -1,6 +1,6 @@ #version 450 -#extension GL_EXT_shader_16bit_storage : require +#extension GL_EXT_control_flow_attributes : enable layout (push_constant) uniform parameter { @@ -11,14 +11,13 @@ layout (push_constant) uniform parameter float m0; float m1; uint n_head_log2; + uint nrows_x; } p; #include "types.comp" -#extension GL_EXT_control_flow_attributes : enable -#define BLOCK_SIZE 512 - -layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; +layout(constant_id = 0) const uint BLOCK_SIZE = 32; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; layout (binding = 1) readonly buffer Y {B_TYPE data_b[];}; @@ -26,10 +25,17 @@ layout (binding = 2) buffer D {D_TYPE data_d[];}; shared FLOAT_TYPE vals[BLOCK_SIZE]; -void main() { +// num_iters is the number of BLOCK_SIZE loop iterations we need to iterate +// over all the columns. The main function tries to pass a constant here, +// as if it were a template function, to allow unrolling. +void soft_max(uint num_iters) { const uint tid = gl_LocalInvocationID.x; const uint rowx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x; - const uint rowy = rowx % p.KY; + const uint rowy = (p.KY > 0) ? (rowx % p.KY) : 0; + + if (rowx >= p.nrows_x) { + return; + } float slope = 1.0f; @@ -46,19 +52,39 @@ void main() { // Find max FLOAT_TYPE max_val = uintBitsToFloat(0xFF800000); - [[unroll]] for (uint col0 = 0; col0 < p.KX; col0 += BLOCK_SIZE) { + // Cache values while we compute the max, so we don't need to read them + // again when we're ready to compute exp(x-max). + const uint DATA_CACHE_SIZE = 16; + FLOAT_TYPE data_cache[DATA_CACHE_SIZE]; + + [[unroll]] for (uint col0 = 0, idx = 0; idx < num_iters; col0 += BLOCK_SIZE, ++idx) { const uint col = col0 + tid; - if (col >= p.KX) { - break; + FLOAT_TYPE a = FLOAT_TYPE(0); + if (col < p.KX) { + a = data_a[rowx * p.KX + col]; } - max_val = max(max_val, FLOAT_TYPE(data_a[rowx * p.KX + col]) * p.scale + (p.KY > 0 ? slope * FLOAT_TYPE(data_b[rowy * p.KX + col]) : FLOAT_TYPE(0.0f))); - } - vals[tid] = max_val; + FLOAT_TYPE b = FLOAT_TYPE(0); + if (p.KY > 0 && col < p.KX) { + b = data_b[rowy * p.KX + col]; + } + FLOAT_TYPE v = a * p.scale + slope * b; + + if (col < p.KX) { + max_val = max(max_val, v); + } + + if (idx < DATA_CACHE_SIZE) { + data_cache[idx] = v; + } + } + + // reduce across the workgroup + vals[tid] = max_val; barrier(); - [[unroll]] for (int s = BLOCK_SIZE / 2; s > 0; s >>= 1) { + [[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) { if (tid < s) { vals[tid] = max(vals[tid], vals[tid + s]); } @@ -68,39 +94,80 @@ void main() { max_val = vals[0]; barrier(); - // Sum up values - vals[tid] = FLOAT_TYPE(0.0f); + FLOAT_TYPE sum = FLOAT_TYPE(0.0f); - [[unroll]] for (uint col0 = 0; col0 < p.KX; col0 += BLOCK_SIZE) { + // Compute sum{exp(x - max)} + [[unroll]] for (uint col0 = 0, idx = 0; idx < num_iters; col0 += BLOCK_SIZE, ++idx) { const uint col = col0 + tid; if (col >= p.KX) { break; } + // compute exp(a*scale+b*slope), add it to sum, and cache the new value + // in data_cache if possible. const uint i = rowx * p.KX + col; - const FLOAT_TYPE val = exp(FLOAT_TYPE(data_a[i]) * p.scale + (p.KY > 0 ? slope * FLOAT_TYPE(data_b[rowy * p.KX + col]) : FLOAT_TYPE(0.0f)) - max_val); - vals[tid] += val; - data_d[i] = D_TYPE(val); + FLOAT_TYPE val; + if (idx < DATA_CACHE_SIZE) { + val = exp(data_cache[idx] - max_val); + } else { + val = exp(FLOAT_TYPE(data_a[i]) * p.scale + (p.KY > 0 ? slope * FLOAT_TYPE(data_b[rowy * p.KX + col]) : FLOAT_TYPE(0.0f)) - max_val); + } + sum += val; + if (idx < DATA_CACHE_SIZE) { + data_cache[idx] = val; + } else { + data_d[i] = D_TYPE(val); + } } + // reduce across the workgroup + vals[tid] = sum; barrier(); - [[unroll]] for (int s = BLOCK_SIZE / 2; s > 0; s >>= 1) { + [[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) { if (tid < s) { vals[tid] += vals[tid + s]; } barrier(); } + sum = vals[0]; - const D_TYPE divisor = D_TYPE(vals[0]); + FLOAT_TYPE rcpdivisor = 1.0/sum; - [[unroll]] for (uint col0 = 0; col0 < p.KX; col0 += BLOCK_SIZE) { + [[unroll]] for (uint col0 = 0, idx = 0; idx < num_iters; col0 += BLOCK_SIZE, ++idx) { const uint col = col0 + tid; if (col >= p.KX) { - break; + continue; } - data_d[rowx*p.KX + col] /= divisor; + if (idx < DATA_CACHE_SIZE) { + data_d[rowx*p.KX + col] = D_TYPE(data_cache[idx] * rcpdivisor); + } else { + data_d[rowx*p.KX + col] *= D_TYPE(rcpdivisor); + } + } +} + +void main() { + // instantiate the soft_max function for several different + // dimensions, to allow loop unrolling + uint num_blocks = (p.KX + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (num_blocks > 32) { + soft_max(num_blocks); + } else if (num_blocks > 16) { + soft_max(32); + } else if (num_blocks > 8) { + soft_max(16); + } else if (num_blocks > 4) { + soft_max(8); + } else if (num_blocks == 4) { + soft_max(4); + } else if (num_blocks == 3) { + soft_max(3); + } else if (num_blocks == 2) { + soft_max(2); + } else if (num_blocks == 1) { + soft_max(1); } } diff --git a/ggml/src/vulkan-shaders/soft_max_back.comp b/ggml/src/vulkan-shaders/soft_max_back.comp new file mode 100644 index 00000000..29bd77d7 --- /dev/null +++ b/ggml/src/vulkan-shaders/soft_max_back.comp @@ -0,0 +1,50 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : enable + +#include "generic_head.comp" +#include "types.comp" + +layout(constant_id = 0) const uint BLOCK_SIZE = 32; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; + +// In this shader Y = softmax(X) and X is not provided as input. + +layout (binding = 0) readonly buffer G {A_TYPE data_g[];}; +layout (binding = 1) readonly buffer Y {B_TYPE data_y[];}; +layout (binding = 2) buffer D {D_TYPE data_d[];}; + +shared FLOAT_TYPE sum_yg[BLOCK_SIZE]; + +void main() { + const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x; + const uint tid = gl_LocalInvocationID.x; + + FLOAT_TYPE scale = p.param1; + + // partial sums for thread in warp + sum_yg[tid] = FLOAT_TYPE(0.0f); + + [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { + const FLOAT_TYPE gi = FLOAT_TYPE(data_g[row*p.KX + col]); + const FLOAT_TYPE yi = FLOAT_TYPE(data_y[row*p.KX + col]); + sum_yg[tid] += yi * gi; + } + + // sum up partial sums and write back result + barrier(); + [[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) { + if (tid < s) { + sum_yg[tid] += sum_yg[tid + s]; + } + barrier(); + } + + const FLOAT_TYPE dot_yg = sum_yg[0]; + + [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { + data_d[row*p.KX + col] = D_TYPE(scale + * (FLOAT_TYPE(data_g[row*p.KX + col]) - dot_yg) + * FLOAT_TYPE(data_y[row*p.KX + col])); + } +} diff --git a/ggml/src/vulkan-shaders/square.comp b/ggml/src/vulkan-shaders/square.comp index 1fa118c9..ef43598b 100644 --- a/ggml/src/vulkan-shaders/square.comp +++ b/ggml/src/vulkan-shaders/square.comp @@ -3,6 +3,8 @@ #include "types.comp" #include "generic_unary_head.comp" +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + void main() { const uint idx = get_idx(); @@ -10,6 +12,6 @@ void main() { return; } - const FLOAT_TYPE val = FLOAT_TYPE(data_a[src0_idx(idx)]); - data_d[p.d_offset + dst_idx(idx)] = D_TYPE(val * val); + const FLOAT_TYPE val = FLOAT_TYPE(data_a[get_aoffset() + src0_idx(idx)]); + data_d[get_doffset() + dst_idx(idx)] = D_TYPE(val * val); } diff --git a/ggml/src/vulkan-shaders/sub.comp b/ggml/src/vulkan-shaders/sub.comp new file mode 100644 index 00000000..72353cc3 --- /dev/null +++ b/ggml/src/vulkan-shaders/sub.comp @@ -0,0 +1,29 @@ +#version 450 + +#extension GL_EXT_shader_16bit_storage : require + +#include "types.comp" +#include "generic_binary_head.comp" + +const uint num_threads = 256; + +layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in; + +void main() { + uint idx = get_idx(); + + // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation + const uint num_iter = 2; + + [[unroll]] for (uint i = 0; i < num_iter; ++i) { + if (idx >= p.ne) { + continue; + } + uint i00, i01, i02, i03; + get_indices(idx, i00, i01, i02, i03); + + data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) - FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)])); + + idx += num_threads; + } +} diff --git a/ggml/src/vulkan-shaders/tanh.comp b/ggml/src/vulkan-shaders/tanh.comp index 74630dc7..8a6f868f 100644 --- a/ggml/src/vulkan-shaders/tanh.comp +++ b/ggml/src/vulkan-shaders/tanh.comp @@ -16,6 +16,5 @@ void main() { if (i >= p.KX) { return; } - - data_d[i] = D_TYPE(tanh(data_a[i])); + data_d[i] = D_TYPE(1. - 2. / (exp(2.*float(data_a[i])) + 1.)); } diff --git a/ggml/src/vulkan-shaders/test_bfloat16_support.comp b/ggml/src/vulkan-shaders/test_bfloat16_support.comp new file mode 100644 index 00000000..fd0ba401 --- /dev/null +++ b/ggml/src/vulkan-shaders/test_bfloat16_support.comp @@ -0,0 +1,7 @@ +#version 460 + +#extension GL_EXT_bfloat16 : require + +void main() +{ +} diff --git a/ggml/src/vulkan-shaders/test_coopmat2_support.comp b/ggml/src/vulkan-shaders/test_coopmat2_support.comp new file mode 100644 index 00000000..28eb24e1 --- /dev/null +++ b/ggml/src/vulkan-shaders/test_coopmat2_support.comp @@ -0,0 +1,7 @@ +#version 460 + +#extension GL_NV_cooperative_matrix2 : require + +void main() +{ +} diff --git a/ggml/src/vulkan-shaders/test_coopmat_support.comp b/ggml/src/vulkan-shaders/test_coopmat_support.comp new file mode 100644 index 00000000..8c5dd1bd --- /dev/null +++ b/ggml/src/vulkan-shaders/test_coopmat_support.comp @@ -0,0 +1,7 @@ +#version 460 + +#extension GL_KHR_cooperative_matrix : require + +void main() +{ +} diff --git a/ggml/src/vulkan-shaders/test_integer_dot_support.comp b/ggml/src/vulkan-shaders/test_integer_dot_support.comp new file mode 100644 index 00000000..470e3074 --- /dev/null +++ b/ggml/src/vulkan-shaders/test_integer_dot_support.comp @@ -0,0 +1,7 @@ +#version 460 + +#extension GL_EXT_integer_dot_product : require + +void main() +{ +} diff --git a/ggml/src/vulkan-shaders/types.comp b/ggml/src/vulkan-shaders/types.comp index 21dce72f..3bde7178 100644 --- a/ggml/src/vulkan-shaders/types.comp +++ b/ggml/src/vulkan-shaders/types.comp @@ -1,6 +1,11 @@ -#if !defined(DATA_A_F32) && !defined(DATA_A_F16) +#if !defined(GGML_TYPES_COMP) +#define GGML_TYPES_COMP + +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require #extension GL_EXT_shader_explicit_arithmetic_types_int8 : require -#endif +#extension GL_EXT_shader_16bit_storage : require #if defined(DATA_A_F32) #define QUANT_K 1 @@ -28,24 +33,43 @@ #endif #endif -#if defined(DATA_A_Q4_0) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 32 -#define QUANT_R 2 +#if defined(DATA_A_BF16) +#define QUANT_K 1 +#define QUANT_R 1 + +#if !defined(LOAD_VEC_A) || LOAD_VEC_A == 1 +#define A_TYPE uint16_t +#elif LOAD_VEC_A == 4 +#define A_TYPE u16vec4 +#elif LOAD_VEC_A == 8 +#error unsupported +#endif +#endif + +#define QUANT_K_Q4_0 32 +#define QUANT_R_Q4_0 2 struct block_q4_0 { float16_t d; uint8_t qs[16]; }; +struct block_q4_0_packed16 +{ + float16_t d; + uint16_t qs[16/2]; +}; +#if defined(DATA_A_Q4_0) +#define QUANT_K QUANT_K_Q4_0 +#define QUANT_R QUANT_R_Q4_0 +#define QUANT_AUXF 1 #define A_TYPE block_q4_0 +#define A_TYPE_PACKED16 block_q4_0_packed16 #endif -#if defined(DATA_A_Q4_1) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 32 -#define QUANT_R 2 +#define QUANT_K_Q4_1 32 +#define QUANT_R_Q4_1 2 struct block_q4_1 { @@ -54,14 +78,30 @@ struct block_q4_1 uint8_t qs[16]; }; +struct block_q4_1_packed16 +{ + float16_t d; + float16_t m; + uint16_t qs[16/2]; +}; + +struct block_q4_1_packed32 +{ + f16vec2 dm; + uint32_t qs[16/4]; +}; + +#if defined(DATA_A_Q4_1) +#define QUANT_K QUANT_K_Q4_1 +#define QUANT_R QUANT_R_Q4_1 +#define QUANT_AUXF 2 #define A_TYPE block_q4_1 +#define A_TYPE_PACKED16 block_q4_1_packed16 +#define A_TYPE_PACKED32 block_q4_1_packed32 #endif -#if defined(DATA_A_Q5_0) -#extension GL_EXT_shader_16bit_storage : require -#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require -#define QUANT_K 32 -#define QUANT_R 2 +#define QUANT_K_Q5_0 32 +#define QUANT_R_Q5_0 2 struct block_q5_0 { @@ -70,14 +110,23 @@ struct block_q5_0 uint8_t qs[16]; }; +struct block_q5_0_packed16 +{ + float16_t d; + uint16_t qh[2]; + uint16_t qs[16/2]; +}; + +#if defined(DATA_A_Q5_0) +#define QUANT_K QUANT_K_Q5_0 +#define QUANT_R QUANT_R_Q5_0 +#define QUANT_AUXF 1 #define A_TYPE block_q5_0 +#define A_TYPE_PACKED16 block_q5_0_packed16 #endif -#if defined(DATA_A_Q5_1) -#extension GL_EXT_shader_16bit_storage : require -#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require -#define QUANT_K 32 -#define QUANT_R 2 +#define QUANT_K_Q5_1 32 +#define QUANT_R_Q5_1 2 struct block_q5_1 { @@ -87,114 +136,1238 @@ struct block_q5_1 uint8_t qs[16]; }; +struct block_q5_1_packed16 +{ + float16_t d; + float16_t m; + uint qh; + uint16_t qs[16/2]; +}; + +struct block_q5_1_packed32 +{ + f16vec2 dm; + uint qh; + uint32_t qs[16/4]; +}; + +#if defined(DATA_A_Q5_1) +#define QUANT_K QUANT_K_Q5_1 +#define QUANT_R QUANT_R_Q5_1 +#define QUANT_AUXF 2 #define A_TYPE block_q5_1 +#define A_TYPE_PACKED16 block_q5_1_packed16 +#define A_TYPE_PACKED32 block_q5_1_packed32 #endif -#if defined(DATA_A_Q8_0) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 32 -#define QUANT_R 1 +#define QUANT_K_Q8_0 32 +#define QUANT_R_Q8_0 1 struct block_q8_0 { float16_t d; int8_t qs[32]; }; +struct block_q8_0_packed16 +{ + float16_t d; + int16_t qs[32/2]; +}; +struct block_q8_0_packed32 +{ + float16_t d; + int32_t qs[32/4]; +}; +#if defined(DATA_A_Q8_0) +#define QUANT_K QUANT_K_Q8_0 +#define QUANT_R QUANT_R_Q8_0 +#define QUANT_AUXF 1 #define A_TYPE block_q8_0 +#define A_TYPE_PACKED16 block_q8_0_packed16 +#define A_TYPE_PACKED32 block_q8_0_packed32 #endif +#define QUANT_K_Q8_1 32 +#define QUANT_R_Q8_1 1 + +struct block_q8_1 +{ + f16vec2 ds; + int8_t qs[32]; +}; +struct block_q8_1_packed16 +{ + f16vec2 ds; + int16_t qs[16]; +}; +struct block_q8_1_packed32 +{ + f16vec2 ds; + int32_t qs[8]; +}; + // K-quants -#if defined(DATA_A_Q2_K) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 256 +#define QUANT_K_Q2_K 256 struct block_q2_K { - uint8_t scales[QUANT_K/16]; - uint8_t qs[QUANT_K/4]; + uint8_t scales[QUANT_K_Q2_K/16]; + uint8_t qs[QUANT_K_Q2_K/4]; f16vec2 d; }; +struct block_q2_K_packed16 +{ + uint16_t scales[QUANT_K_Q2_K/16/2]; + uint16_t qs[QUANT_K_Q2_K/4/2]; + f16vec2 d; +}; + +struct block_q2_K_packed32 +{ + uint32_t scales[QUANT_K_Q2_K/16/4]; + uint32_t qs[QUANT_K_Q2_K/4/4]; + f16vec2 d; +}; + +#if defined(DATA_A_Q2_K) +#define QUANT_K QUANT_K_Q2_K #define A_TYPE block_q2_K +#define A_TYPE_PACKED16 block_q2_K_packed16 +#define A_TYPE_PACKED32 block_q2_K_packed32 #endif -#if defined(DATA_A_Q3_K) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 256 +#define QUANT_K_Q3_K 256 struct block_q3_K { - uint8_t hmask[QUANT_K/8]; - uint8_t qs[QUANT_K/4]; + uint8_t hmask[QUANT_K_Q3_K/8]; + uint8_t qs[QUANT_K_Q3_K/4]; uint8_t scales[12]; float16_t d; }; +struct block_q3_K_packed16 +{ + uint16_t hmask[QUANT_K_Q3_K/8/2]; + uint16_t qs[QUANT_K_Q3_K/4/2]; + uint16_t scales[12/2]; + float16_t d; +}; + +#if defined(DATA_A_Q3_K) +#define QUANT_K QUANT_K_Q3_K #define A_TYPE block_q3_K +#define A_TYPE_PACKED16 block_q3_K_packed16 #endif -#if defined(DATA_A_Q4_K) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 256 +#define QUANT_K_Q4_K 256 struct block_q4_K { f16vec2 d; - uint8_t scales[3*QUANT_K/64]; - uint8_t qs[QUANT_K/2]; + uint8_t scales[3*QUANT_K_Q4_K/64]; + uint8_t qs[QUANT_K_Q4_K/2]; }; +struct block_q4_K_packed16 +{ + f16vec2 d; + uint16_t scales[3*QUANT_K_Q4_K/64/2]; + uint16_t qs[QUANT_K_Q4_K/2/2]; +}; + +struct block_q4_K_packed32 +{ + f16vec2 d; + uint32_t scales[3*QUANT_K_Q4_K/64/4]; + uint32_t qs[QUANT_K_Q4_K/2/4]; +}; + +struct block_q4_K_packed128 +{ + uvec4 q4k[9]; +}; + +#if defined(DATA_A_Q4_K) +#define QUANT_K QUANT_K_Q4_K #define A_TYPE block_q4_K +#define A_TYPE_PACKED16 block_q4_K_packed16 +#define A_TYPE_PACKED32 block_q4_K_packed32 #endif -#if defined(DATA_A_Q5_K) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 256 +#define QUANT_K_Q5_K 256 struct block_q5_K { f16vec2 d; uint8_t scales[12]; - uint8_t qh[QUANT_K/8]; - uint8_t qs[QUANT_K/2]; + uint8_t qh[QUANT_K_Q5_K/8]; + uint8_t qs[QUANT_K_Q5_K/2]; }; +struct block_q5_K_packed16 +{ + f16vec2 d; + uint16_t scales[12/2]; + uint16_t qh[QUANT_K_Q5_K/8/2]; + uint16_t qs[QUANT_K_Q5_K/2/2]; +}; + +struct block_q5_K_packed128 +{ + uvec4 q5k[11]; +}; + +#if defined(DATA_A_Q5_K) +#define QUANT_K QUANT_K_Q5_K #define A_TYPE block_q5_K +#define A_TYPE_PACKED16 block_q5_K_packed16 #endif -#if defined(DATA_A_Q6_K) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 256 +#define QUANT_K_Q6_K 256 struct block_q6_K { - uint8_t ql[QUANT_K/2]; - uint8_t qh[QUANT_K/4]; - int8_t scales[QUANT_K/16]; + uint8_t ql[QUANT_K_Q6_K/2]; + uint8_t qh[QUANT_K_Q6_K/4]; + int8_t scales[QUANT_K_Q6_K/16]; float16_t d; }; +struct block_q6_K_packed16 +{ + uint16_t ql[QUANT_K_Q6_K/2/2]; + uint16_t qh[QUANT_K_Q6_K/4/2]; + int8_t scales[QUANT_K_Q6_K/16]; + float16_t d; +}; + +#if defined(DATA_A_Q6_K) +#define QUANT_K QUANT_K_Q6_K #define A_TYPE block_q6_K +#define A_TYPE_PACKED16 block_q6_K_packed16 #endif // IQuants -#if defined(DATA_A_IQ4_NL) -#extension GL_EXT_shader_16bit_storage : require -#define QUANT_K 32 -#define QUANT_R 2 +#define QUANT_K_IQ1_S 256 +#define QUANT_R_IQ1_S 1 + +struct block_iq1_s { + float16_t d; + uint8_t qs[QUANT_K_IQ1_S/8]; + uint16_t qh[QUANT_K_IQ1_S/32]; +}; + +#define QUANT_K_IQ1_M 256 +#define QUANT_R_IQ1_M 1 + +struct block_iq1_m { + uint8_t qs[QUANT_K_IQ1_M/8]; + uint8_t qh[QUANT_K_IQ1_M/16]; + uint16_t scales[QUANT_K_IQ1_M/64]; +}; + +struct block_iq1_m_packed64 { + uint64_t qs[QUANT_K_IQ1_M/8/8]; + uint64_t qh[QUANT_K_IQ1_M/16/8]; + uint64_t scales; +}; + +#if defined(DATA_A_IQ1_S) +#define QUANT_K QUANT_K_IQ1_S +#define QUANT_R QUANT_R_IQ1_S +#define A_TYPE block_iq1_s +#endif + +#if defined(DATA_A_IQ1_M) +#define QUANT_K QUANT_K_IQ1_M +#define QUANT_R QUANT_R_IQ1_M +#define A_TYPE block_iq1_m +#endif + +#if defined(DATA_A_IQ1_S) || defined(DATA_A_IQ1_M) +#define IQ1S_DELTA 0.125f +#define IQ1M_DELTA 0.125f + +// Packed IQ1S grid where every 2 vec8 are encoded on 32 bits (2 bits per coordinate). +const uint[1024] iq1s_grid_const = { + 0xfffdffff, 0xfff7fff0, 0xffccfff5, 0xffdfffc0, 0xffd7ffdd, 0xff30ffd5, 0xff03ff0c, 0xff10ff01, + 0xff7dff7f, 0xff75ff77, 0xff5fff40, 0xff57ff5d, 0xfcf3ff55, 0xfcccfcf0, 0xfcc1fcc3, 0xfcc5fcc4, + 0xfc3cfcd0, 0xfc34fc31, 0xfc00fc0d, 0xfc1cfc05, 0xfc11fc13, 0xfc70fc17, 0xfc43fc4c, 0xfc50fc41, + 0xfdfdfdff, 0xfdf5fdf7, 0xfddffdc0, 0xfdd7fddd, 0xfd30fdd5, 0xfd04fd0c, 0xfd14fd13, 0xfd7dfd7f, + 0xfd75fd77, 0xfd40fd4c, 0xfd5ffd44, 0xfd57fd5d, 0xf3ccfd55, 0xf3c1f3c3, 0xf33cf3d0, 0xf300f334, + 0xf313f305, 0xf34cf310, 0xf350f344, 0xf0f3f0fc, 0xf0f1f0f0, 0xf0c7f0c0, 0xf0d4f0c5, 0xf030f03f, + 0xf00ff035, 0xf003f00c, 0xf001f000, 0xf01ff004, 0xf010f01d, 0xf015f017, 0xf04cf07c, 0xf047f040, + 0xf05cf045, 0xf050f053, 0xf054f051, 0xf1c4f1c3, 0xf133f13c, 0xf10df10f, 0xf107f100, 0xf11cf11f, + 0xf114f111, 0xf14cf170, 0xf144f143, 0xf7fdf7ff, 0xf7f5f7f7, 0xf7dff7c0, 0xf7d7f7dd, 0xf730f7d5, + 0xf701f70c, 0xf77ff710, 0xf777f77d, 0xf740f775, 0xf75df75f, 0xf755f757, 0xf4ccf4f0, 0xf4c4f4c3, + 0xf4d0f4d3, 0xf40ff43c, 0xf400f40c, 0xf413f41c, 0xf44cf414, 0xf441f443, 0xf450f444, 0xf5fdf5ff, + 0xf5f5f5f7, 0xf5dff5c0, 0xf5d7f5dd, 0xf530f5d5, 0xf504f50c, 0xf510f51c, 0xf57df57f, 0xf577f570, + 0xf540f575, 0xf55df55f, 0xf555f557, 0xcfcccfcf, 0xcfc4cfc3, 0xcfd0cfd3, 0xcf33cf3c, 0xcf00cf0f, + 0xcf1ccf07, 0xcf10cf13, 0xcf4ccf14, 0xcf41cf43, 0xcf50cf5c, 0xccf3ccfc, 0xccf4ccf1, 0xcccdcccf, + 0xccc7ccc0, 0xccd3ccdc, 0xcc30ccd4, 0xcc0fcc35, 0xcc0dcc0c, 0xcc00cc03, 0xcc04cc01, 0xcc10cc1f, + 0xcc4dcc73, 0xcc5ccc40, 0xcdcccc53, 0xcdc1cdc3, 0xcd3fcdd0, 0xcd34cd31, 0xcd00cd0d, 0xcd05cd07, + 0xcd11cd13, 0xcd4ccd70, 0xcd41cd43, 0xc3fccd50, 0xc3f4c3f1, 0xc3c0c3c3, 0xc3c4c3c7, 0xc3d1c3dc, + 0xc330c33c, 0xc337c331, 0xc30cc335, 0xc300c303, 0xc304c301, 0xc310c31d, 0xc373c317, 0xc34fc374, + 0xc340c343, 0xc344c347, 0xc35cc345, 0xc350c353, 0xc0fdc354, 0xc0f5c0f0, 0xc0c3c0cc, 0xc0c1c0c0, + 0xc0dfc0c4, 0xc0d0c0dd, 0xc0d5c0d7, 0xc033c03c, 0xc031c030, 0xc00dc00c, 0xc000c003, 0xc004c001, + 0xc01cc005, 0xc010c013, 0xc014c011, 0xc07dc07f, 0xc070c073, 0xc075c077, 0xc04cc04f, 0xc040c043, + 0xc044c041, 0xc05fc045, 0xc050c05d, 0xc1f3c1fc, 0xc1f1c1f0, 0xc1c1c1c0, 0xc1c5c1c7, 0xc1d1c1dc, + 0xc13dc13f, 0xc130c133, 0xc135c137, 0xc100c10c, 0xc107c101, 0xc11cc104, 0xc110c113, 0xc114c117, + 0xc171c115, 0xc14dc175, 0xc153c140, 0xc7ccc154, 0xc7d0c7c1, 0xc733c73c, 0xc734c731, 0xc700c70f, + 0xc705c707, 0xc71cc71f, 0xc711c713, 0xc770c714, 0xc743c74c, 0xc4cfc750, 0xc4c0c4cd, 0xc4dcc4c5, + 0xc43dc4d0, 0xc430c433, 0xc40cc437, 0xc400c403, 0xc404c401, 0xc41fc405, 0xc415c410, 0xc44cc474, + 0xc440c44d, 0xc45cc447, 0xc454c451, 0xc5c1c5f4, 0xc5d1c5d3, 0xc531c533, 0xc50fc534, 0xc500c50d, + 0xc51cc507, 0xc514c511, 0xc54cc570, 0xc545c541, 0xdffddfff, 0xdff5dff7, 0xdfdfdfc0, 0xdfd0dfdd, + 0xdfd5dfd7, 0xdf0cdf30, 0xdf1cdf04, 0xdf7fdf10, 0xdf77df7d, 0xdf40df75, 0xdf5ddf5f, 0xdf57df50, + 0xdcf0df55, 0xdcc3dccc, 0xdcd0dcc4, 0xdc33dc3d, 0xdc00dc34, 0xdc05dc07, 0xdc13dc1c, 0xdc11dc10, + 0xdc4fdc70, 0xdc44dc41, 0xddfcdc50, 0xddf5ddf7, 0xddc0ddcc, 0xdddddddf, 0xddd5ddd7, 0xdd0cdd30, + 0xdd04dd01, 0xdd7cdd10, 0xdd75dd77, 0xdd40dd4c, 0xdd5ddd5f, 0xdd55dd57, 0xd3c3d3f0, 0xd3c4d3c1, + 0xd333d3d0, 0xd331d330, 0xd30dd334, 0xd307d300, 0xd311d305, 0xd34cd370, 0xd344d343, 0xd350d35c, + 0xd0c0d0f4, 0xd0d4d0dc, 0xd030d03f, 0xd00cd037, 0xd000d003, 0xd01dd004, 0xd017d010, 0xd04fd074, + 0xd040d043, 0xd045d047, 0xd053d05c, 0xd054d051, 0xd1cfd1f0, 0xd1c4d1cd, 0xd13cd1d0, 0xd100d134, + 0xd11cd11f, 0xd173d114, 0xd14fd171, 0xd7ffd145, 0xd7f7d7fd, 0xd7c0d7f5, 0xd7ddd7df, 0xd7d5d7d7, + 0xd70cd730, 0xd710d703, 0xd77dd77f, 0xd775d777, 0xd75dd75f, 0xd755d757, 0xd4ccd4f4, 0xd4c4d4c3, + 0xd431d4d0, 0xd40dd434, 0xd41cd400, 0xd411d413, 0xd470d414, 0xd441d44f, 0xd453d444, 0xd5ffd450, + 0xd5f7d5fd, 0xd5dfd5f5, 0xd5d7d5dd, 0xd530d5d5, 0xd501d50c, 0xd510d504, 0xd57dd57f, 0xd575d577, + 0xd55fd540, 0xd557d55d, 0x3ff0d555, 0x3fc13fcc, 0x3f343fd0, 0x3f003f0d, 0x3f053f07, 0x3f133f1c, + 0x3f433f11, 0x3f5c3f44, 0x3cff3f51, 0x3cf33cfc, 0x3cf43cf1, 0x3cc03ccd, 0x3cc73cc1, 0x3cdc3cc5, + 0x3cd43cd1, 0x3c373c30, 0x3c0c3c35, 0x3c003c03, 0x3c043c01, 0x3c103c05, 0x3c153c17, 0x3c733c7c, + 0x3c4f3c71, 0x3c403c4d, 0x3c5c3c5f, 0x3df03c5d, 0x3dc33dcc, 0x3dd03dc1, 0x3d0d3d3c, 0x3d053d00, + 0x3d143d13, 0x3d433d74, 0x33fc3d50, 0x33c433c0, 0x333033d4, 0x33353337, 0x3303330c, 0x33013300, + 0x331d331c, 0x33173310, 0x337c3315, 0x33743371, 0x334d334f, 0x335f3340, 0x3354335c, 0x30fd30fc, + 0x30f530f0, 0x30c330cc, 0x30c130c0, 0x30df30c4, 0x30d530d0, 0x3033303c, 0x30313030, 0x300f3034, + 0x3003300c, 0x30013000, 0x30043007, 0x3013301c, 0x30113010, 0x307d3014, 0x30703073, 0x304c3077, + 0x30403043, 0x30443041, 0x30503045, 0x30553057, 0x31f031fc, 0x31c331f4, 0x31c731c0, 0x31dc31c5, + 0x31d431d3, 0x313d313f, 0x31373130, 0x310c310f, 0x3100310d, 0x31043101, 0x3110311d, 0x317c3117, + 0x31753170, 0x31403143, 0x3153315c, 0x37f03151, 0x37c037cc, 0x37d037c5, 0x3734373d, 0x3700370f, + 0x371c3707, 0x37113713, 0x37703714, 0x3743374c, 0x37443741, 0x34fc3750, 0x34f134f0, 0x34cf34f5, + 0x34c034c3, 0x34dc34c7, 0x34d134d3, 0x3430343f, 0x340c3435, 0x3403340d, 0x34013400, 0x341f3404, + 0x3410341d, 0x34153411, 0x34743471, 0x3440344d, 0x34473441, 0x3453345c, 0x34543451, 0x353335c1, + 0x35343531, 0x35073500, 0x35133505, 0x35433514, 0x0ffc3550, 0x0ff00ff3, 0x0ff40ff1, 0x0fc00fcd, + 0x0fdc0fc5, 0x0fd40fd3, 0x0f300f3f, 0x0f0c0f37, 0x0f000f03, 0x0f040f01, 0x0f170f10, 0x0f740f71, + 0x0f470f40, 0x0f5c0f5f, 0x0f540f51, 0x0cf70cf0, 0x0cf50cf4, 0x0cc30ccc, 0x0cc10cc0, 0x0cc40cc7, + 0x0cd00cdf, 0x0cd70cd1, 0x0c3c0cd5, 0x0c300c33, 0x0c340c31, 0x0c0c0c0f, 0x0c030c0d, 0x0c010c00, + 0x0c040c07, 0x0c1c0c05, 0x0c100c13, 0x0c140c11, 0x0c700c7d, 0x0c430c4c, 0x0c410c40, 0x0c5f0c44, + 0x0c550c50, 0x0df10dfc, 0x0dc00dcd, 0x0ddc0dc5, 0x0d3d0dd3, 0x0d350d30, 0x0d030d0c, 0x0d010d00, + 0x0d1d0d04, 0x0d700d10, 0x0d4d0d4f, 0x0d440d40, 0x0d530d45, 0x03f003f3, 0x03c303cc, 0x03c103c0, + 0x03c403c7, 0x03d003dc, 0x03d503d7, 0x0333033c, 0x03310330, 0x03350334, 0x030c030f, 0x03000303, + 0x03070301, 0x03050304, 0x031d031c, 0x03100313, 0x03140311, 0x0377037f, 0x034c0375, 0x03400343, + 0x03440341, 0x0353035c, 0x03550350, 0x00fd00fc, 0x00f000f3, 0x00f400f1, 0x00cc00cf, 0x00c300cd, + 0x00c100c0, 0x00c500c4, 0x00d300dc, 0x00d100d0, 0x003f00d4, 0x003d003c, 0x00300033, 0x00370031, + 0x000f0034, 0x000d000c, 0x00000003, 0x00070001, 0x00050004, 0x001c001f, 0x00100013, 0x00170011, + 0x00150014, 0x0073007c, 0x00740070, 0x004f0075, 0x0043004c, 0x00410040, 0x00440047, 0x0053005c, + 0x00510050, 0x01ff0054, 0x01fd01fc, 0x01f101f3, 0x01f401f7, 0x01c301cc, 0x01c701c0, 0x01df01c4, + 0x01dd01dc, 0x01d001d3, 0x01d701d1, 0x013c01d4, 0x01310130, 0x01340137, 0x010f0135, 0x010d010c, + 0x01000103, 0x01070101, 0x01050104, 0x0113011c, 0x01140110, 0x0170017d, 0x01770171, 0x01750174, + 0x0140014c, 0x015d0145, 0x01510150, 0x01540157, 0x07f007f3, 0x07f407f1, 0x07c007cf, 0x07dc07c7, + 0x073007d5, 0x07350737, 0x0703070c, 0x07010700, 0x07040707, 0x071d071f, 0x07100713, 0x0774077d, + 0x074d074f, 0x07470740, 0x0754075c, 0x04fd04fc, 0x04f504f0, 0x04c304cc, 0x04c104c0, 0x04d004c4, + 0x0433043c, 0x04310430, 0x040f0434, 0x040d040c, 0x04000403, 0x04070401, 0x04050404, 0x0413041c, + 0x04110410, 0x047c0414, 0x04740470, 0x0443044c, 0x04410440, 0x04440447, 0x05f30450, 0x05c005f7, + 0x05df05c5, 0x05d105d0, 0x053005d4, 0x05340537, 0x0500050c, 0x05070501, 0x051d0504, 0x05170510, + 0x057c0515, 0x054d0575, 0x05410540, 0x05450547, 0x1ff0055c, 0x1fc11fc3, 0x1fd01fc4, 0x1f0f1f33, + 0x1f011f00, 0x1f051f07, 0x1f131f1c, 0x1f141f11, 0x1f411f7c, 0x1cfc1f50, 0x1cf11cf3, 0x1ccd1cf4, + 0x1cdc1cc0, 0x1cd11cdd, 0x1c301cd4, 0x1c0c1c34, 0x1c011c00, 0x1c101c04, 0x1c151c11, 0x1c751c73, + 0x1c401c4d, 0x1c511c5c, 0x1dcc1c54, 0x1dc41dc1, 0x1d3c1d3f, 0x1d001d31, 0x1d071d01, 0x1d701d1f, + 0x1d411d4c, 0x13cc1d50, 0x13c013cd, 0x13c513c1, 0x13d113dc, 0x133f13d4, 0x1330133d, 0x13351337, + 0x1303130c, 0x13011300, 0x13051304, 0x131d131f, 0x13731310, 0x13741370, 0x134d134f, 0x13401343, + 0x13471341, 0x135c1345, 0x13541353, 0x10f710f0, 0x10cc10f5, 0x10c110c0, 0x103310c4, 0x10311030, + 0x100f1034, 0x1003100c, 0x10011000, 0x101c1004, 0x10101013, 0x10141011, 0x10741071, 0x104c1075, + 0x10411040, 0x10451044, 0x1050105d, 0x10571051, 0x11f411fd, 0x11df11c0, 0x11d711d1, 0x113f11d4, + 0x11371130, 0x110c1135, 0x11001103, 0x11071101, 0x111f1105, 0x11171110, 0x117d117f, 0x11751170, + 0x11411143, 0x11441147, 0x1153115f, 0x11551151, 0x17c417c1, 0x173c17d0, 0x1700170d, 0x171c1705, + 0x17701714, 0x1747174c, 0x14fc1751, 0x14cf14f3, 0x14dc14c0, 0x14d114d3, 0x143f14d4, 0x1430143c, + 0x14371431, 0x1403140c, 0x14011400, 0x141f1404, 0x14151410, 0x1473147d, 0x14401475, 0x1453145c, + 0x14541450, 0x15c115cc, 0x153c15c7, 0x15341533, 0x1500150f, 0x15051507, 0x15101513, 0x15711514, + 0x15471543, 0x15511545, 0x7ffd7fff, 0x7ff57ff7, 0x7fdd7fdf, 0x7fd57fd7, 0x7f0f7f30, 0x7f037f0c, + 0x7f047f01, 0x7f7f7f10, 0x7f777f7d, 0x7f407f75, 0x7f5d7f5f, 0x7f557f57, 0x7ccc7cf0, 0x7cc17cc3, + 0x7cd07cc4, 0x7c337c3c, 0x7c0f7c34, 0x7c007c0d, 0x7c077c01, 0x7c137c04, 0x7c147c11, 0x7c747c70, + 0x7c417c43, 0x7c507c44, 0x7dfd7dff, 0x7df57df7, 0x7ddf7dc0, 0x7dd77ddd, 0x7d0c7dd5, 0x7d047d03, + 0x7d7f7d10, 0x7d777d7d, 0x7d407d75, 0x7d5d7d5f, 0x7d557d57, 0x73c473c3, 0x7333733c, 0x7300730c, + 0x731c7305, 0x73147313, 0x73447343, 0x70f470fc, 0x70c070cd, 0x70d170c5, 0x703f70d4, 0x7030703c, + 0x700c7037, 0x70007003, 0x70047001, 0x70107005, 0x70177011, 0x707c7015, 0x70717073, 0x704f7074, + 0x7040704d, 0x70517047, 0x71c171cc, 0x71d071c4, 0x7133713c, 0x71357134, 0x7100710f, 0x71057104, + 0x7111711c, 0x71707115, 0x7145714c, 0x77ff7153, 0x77f777fd, 0x77c077f5, 0x77dd77df, 0x77d577d7, + 0x7730773c, 0x7703770c, 0x77107704, 0x777f7714, 0x7777777d, 0x77407775, 0x775d775f, 0x77557757, + 0x74f174f0, 0x74c374cc, 0x74d074c1, 0x7433743c, 0x74347431, 0x740d740f, 0x74057400, 0x7413741c, + 0x74417470, 0x74507444, 0x75fd75ff, 0x75f575f7, 0x75df75c0, 0x75d775dd, 0x753075d5, 0x7503750c, + 0x757f7501, 0x7577757d, 0x75407575, 0x755d755f, 0x75557557, 0x4fcc4ff0, 0x4fc74fc1, 0x4fd04fc4, + 0x4f314f3c, 0x4f004f34, 0x4f054f07, 0x4f154f14, 0x4f4c4f70, 0x4f414f43, 0x4f504f44, 0x4cf34cfc, + 0x4cf44cf1, 0x4cc04ccf, 0x4cc54cc7, 0x4cd34cdc, 0x4cd44cd1, 0x4c304c3f, 0x4c0c4c0f, 0x4c004c03, + 0x4c044c01, 0x4c104c1d, 0x4c714c73, 0x4c404c4d, 0x4c5c4c47, 0x4c514c53, 0x4df04c54, 0x4dc34dcc, + 0x4dd04dc4, 0x4d314d33, 0x4d0f4d34, 0x4d004d0d, 0x4d114d07, 0x4d704d14, 0x4d414d43, 0x43fc4d54, + 0x43f143f3, 0x43c043cf, 0x43d143c7, 0x4335433f, 0x4303430c, 0x43014300, 0x43044307, 0x431c431f, + 0x4310431d, 0x43714373, 0x4343434d, 0x43474340, 0x4354435c, 0x40f040ff, 0x40f540f7, 0x40cc40cf, + 0x40c040c3, 0x40c440c1, 0x40d040dc, 0x40d540d4, 0x4033403c, 0x40314030, 0x400f4034, 0x400d400c, + 0x40004003, 0x40074001, 0x40054004, 0x4013401c, 0x40114010, 0x407c4014, 0x40774070, 0x404d404c, + 0x40404043, 0x40444041, 0x405f4045, 0x4050405d, 0x40554057, 0x41f341fc, 0x41c041cf, 0x41df41c4, + 0x41d441d1, 0x41374130, 0x410c4134, 0x4100410d, 0x41044101, 0x41174110, 0x4173417d, 0x41754174, + 0x4143414d, 0x41534140, 0x41544151, 0x47c147f0, 0x47d047c4, 0x4731473c, 0x470d470f, 0x47014700, + 0x47134705, 0x47704710, 0x4741474c, 0x47504744, 0x44f144f3, 0x44cf44f4, 0x44c044cd, 0x44c544c7, + 0x44dc44df, 0x44d144d3, 0x443d443f, 0x44374430, 0x440c4435, 0x44004403, 0x44044401, 0x4410441d, + 0x44154411, 0x4473447c, 0x444d444f, 0x44454440, 0x4451445c, 0x45c045f0, 0x453345d0, 0x45344531, + 0x4500450f, 0x451c4507, 0x454c4570, 0x45404543, 0x5fff4541, 0x5ff75ffd, 0x5fc05ff5, 0x5fdd5fdf, + 0x5fd55fd7, 0x5f0c5f30, 0x5f015f03, 0x5f7f5f04, 0x5f775f7d, 0x5f405f75, 0x5f5d5f5f, 0x5f555f57, + 0x5cf45cf0, 0x5cc35ccc, 0x5cc45cc1, 0x5c315cc5, 0x5c0c5c34, 0x5c075c00, 0x5c1c5c05, 0x5c705c13, + 0x5c4d5c4f, 0x5c445c41, 0x5df75dfd, 0x5dcf5df5, 0x5ddd5dc4, 0x5dd55dd7, 0x5d0c5d30, 0x5d045d01, + 0x5d7f5d10, 0x5d775d7d, 0x5d405d75, 0x5d5d5d5f, 0x5d555d57, 0x53d053c4, 0x5333533c, 0x5303530f, + 0x53075300, 0x531c5305, 0x53115310, 0x53145317, 0x50f15370, 0x50cf50f4, 0x50c050cd, 0x50d150c7, + 0x503d50d4, 0x500c5030, 0x50005003, 0x50045001, 0x50155010, 0x5073507c, 0x50715070, 0x504d5074, + 0x50475040, 0x51cc51f0, 0x51c551c1, 0x51d051dc, 0x51315133, 0x510d5135, 0x51015100, 0x511f5107, + 0x5171511d, 0x5140514f, 0x51445141, 0x5153515c, 0x57ff5151, 0x57f757fd, 0x57df57f5, 0x57d757dd, + 0x570c57d5, 0x57015703, 0x577f5704, 0x5777577d, 0x57405775, 0x575d575f, 0x57555757, 0x54c354f0, + 0x54dc54c4, 0x543c54d0, 0x5400540f, 0x541c5405, 0x54145411, 0x5441544f, 0x55fd55ff, 0x55f555f7, + 0x55dd55df, 0x55d555d7, 0x5503550c, 0x557f5501, 0x5577557d, 0x55405575, 0x555d555f, 0x55555557 +}; + +shared uint16_t iq1s_grid[2048]; + +#define NEEDS_INIT_IQ_SHMEM +void init_iq_shmem(uvec3 wgsize) +{ + // copy the table into shared memory and sync + [[unroll]] for (uint i = 0; i < iq1s_grid_const.length(); i += wgsize.x) { + uint idx = i + gl_LocalInvocationIndex.x; + if (iq1s_grid_const.length() % wgsize.x == 0 || idx < iq1s_grid_const.length()) { + u16vec2 g = unpack16(iq1s_grid_const[idx]); + iq1s_grid[2*idx+0] = g.x; + iq1s_grid[2*idx+1] = g.y; + } + } + barrier(); +} +#endif + +#define QUANT_K_IQ2_XXS 256 +#define QUANT_R_IQ2_XXS 1 + +struct block_iq2_xxs +{ + float16_t d; + uint8_t qs[QUANT_K_IQ2_XXS/4]; +}; + +struct block_iq2_xxs_packed16 +{ + float16_t d; + uint16_t qs[QUANT_K_IQ2_XXS/8]; +}; + +#if defined(DATA_A_IQ2_XXS) + +const uvec2[256] iq2xxs_grid_const = { + uvec2(0x08080808, 0x08080808), uvec2(0x0808082b, 0x08080808), uvec2(0x08081919, 0x08080808), uvec2(0x08082b08, 0x08080808), + uvec2(0x08082b2b, 0x08080808), uvec2(0x08190819, 0x08080808), uvec2(0x08191908, 0x08080808), uvec2(0x082b0808, 0x08080808), + uvec2(0x082b082b, 0x08080808), uvec2(0x082b2b08, 0x08080808), uvec2(0x082b2b2b, 0x08080808), uvec2(0x19080819, 0x08080808), + uvec2(0x19081908, 0x08080808), uvec2(0x19190808, 0x08080808), uvec2(0x19192b08, 0x08080808), uvec2(0x192b0819, 0x08080808), + uvec2(0x192b1908, 0x08080808), uvec2(0x2b080808, 0x08080808), uvec2(0x2b08082b, 0x08080808), uvec2(0x2b082b2b, 0x08080808), + uvec2(0x2b2b082b, 0x08080808), uvec2(0x08080819, 0x08080819), uvec2(0x08081908, 0x08080819), uvec2(0x08190808, 0x08080819), + uvec2(0x08191919, 0x08080819), uvec2(0x19080808, 0x08080819), uvec2(0x2b081908, 0x08080819), uvec2(0x2b192b08, 0x08080819), + uvec2(0x08080808, 0x0808082b), uvec2(0x0808082b, 0x0808082b), uvec2(0x082b082b, 0x0808082b), uvec2(0x2b08082b, 0x0808082b), + uvec2(0x08080819, 0x08081908), uvec2(0x08081908, 0x08081908), uvec2(0x08190808, 0x08081908), uvec2(0x082b0819, 0x08081908), + uvec2(0x082b1908, 0x08081908), uvec2(0x19080808, 0x08081908), uvec2(0x1908082b, 0x08081908), uvec2(0x19082b08, 0x08081908), + uvec2(0x192b0808, 0x08081908), uvec2(0x2b080819, 0x08081908), uvec2(0x2b081908, 0x08081908), uvec2(0x2b190808, 0x08081908), + uvec2(0x2b2b1908, 0x08081908), uvec2(0x08080808, 0x08081919), uvec2(0x0808082b, 0x08081919), uvec2(0x08082b08, 0x08081919), + uvec2(0x082b0808, 0x08081919), uvec2(0x1908192b, 0x08081919), uvec2(0x192b2b19, 0x08081919), uvec2(0x2b080808, 0x08081919), + uvec2(0x2b190819, 0x08081919), uvec2(0x08082b19, 0x0808192b), uvec2(0x08190808, 0x0808192b), uvec2(0x19080808, 0x0808192b), + uvec2(0x2b081908, 0x0808192b), uvec2(0x2b2b1908, 0x0808192b), uvec2(0x08080808, 0x08082b08), uvec2(0x08081919, 0x08082b08), + uvec2(0x08082b08, 0x08082b08), uvec2(0x08191908, 0x08082b08), uvec2(0x082b2b08, 0x08082b08), uvec2(0x19080819, 0x08082b08), + uvec2(0x19081908, 0x08082b08), uvec2(0x19190808, 0x08082b08), uvec2(0x1919082b, 0x08082b08), uvec2(0x2b082b08, 0x08082b08), + uvec2(0x08081908, 0x08082b19), uvec2(0x19080808, 0x08082b19), uvec2(0x0808082b, 0x08082b2b), uvec2(0x08191908, 0x08082b2b), + uvec2(0x08080819, 0x08190808), uvec2(0x08081908, 0x08190808), uvec2(0x08190808, 0x08190808), uvec2(0x082b0819, 0x08190808), + uvec2(0x19080808, 0x08190808), uvec2(0x192b0808, 0x08190808), uvec2(0x2b081908, 0x08190808), uvec2(0x2b190808, 0x08190808), + uvec2(0x2b191919, 0x08190808), uvec2(0x08080808, 0x08190819), uvec2(0x08082b08, 0x08190819), uvec2(0x082b0808, 0x08190819), + uvec2(0x19190808, 0x08190819), uvec2(0x19192b2b, 0x08190819), uvec2(0x2b080808, 0x08190819), uvec2(0x082b1908, 0x0819082b), + uvec2(0x19081919, 0x0819082b), uvec2(0x08080808, 0x08191908), uvec2(0x08082b08, 0x08191908), uvec2(0x082b0808, 0x08191908), + uvec2(0x082b1919, 0x08191908), uvec2(0x19082b19, 0x08191908), uvec2(0x2b080808, 0x08191908), uvec2(0x08192b08, 0x08191919), + uvec2(0x192b082b, 0x08191919), uvec2(0x08080808, 0x0819192b), uvec2(0x0819192b, 0x0819192b), uvec2(0x08080819, 0x08192b08), + uvec2(0x08081908, 0x08192b08), uvec2(0x08190808, 0x08192b08), uvec2(0x19080808, 0x08192b08), uvec2(0x2b080819, 0x08192b08), + uvec2(0x08080808, 0x08192b19), uvec2(0x08081919, 0x08192b19), uvec2(0x2b2b0808, 0x08192b19), uvec2(0x19190819, 0x08192b2b), + uvec2(0x08080808, 0x082b0808), uvec2(0x0808082b, 0x082b0808), uvec2(0x08082b2b, 0x082b0808), uvec2(0x19081908, 0x082b0808), + uvec2(0x192b0819, 0x082b0808), uvec2(0x2b080808, 0x082b0808), uvec2(0x2b08082b, 0x082b0808), uvec2(0x082b2b19, 0x082b0819), + uvec2(0x19082b08, 0x082b0819), uvec2(0x08080808, 0x082b082b), uvec2(0x0808082b, 0x082b082b), uvec2(0x08080819, 0x082b1908), + uvec2(0x08081908, 0x082b1908), uvec2(0x08190808, 0x082b1908), uvec2(0x19080808, 0x082b1908), uvec2(0x1919192b, 0x082b1908), + uvec2(0x08080808, 0x082b1919), uvec2(0x19080819, 0x082b1919), uvec2(0x192b1908, 0x082b1919), uvec2(0x2b190808, 0x082b192b), + uvec2(0x08082b08, 0x082b2b08), uvec2(0x082b0808, 0x082b2b08), uvec2(0x2b191908, 0x082b2b08), uvec2(0x19081908, 0x082b2b2b), + uvec2(0x08080819, 0x19080808), uvec2(0x08081908, 0x19080808), uvec2(0x08190808, 0x19080808), uvec2(0x08192b08, 0x19080808), + uvec2(0x082b0819, 0x19080808), uvec2(0x082b1908, 0x19080808), uvec2(0x19080808, 0x19080808), uvec2(0x19082b08, 0x19080808), + uvec2(0x1919192b, 0x19080808), uvec2(0x192b0808, 0x19080808), uvec2(0x2b080819, 0x19080808), uvec2(0x2b081908, 0x19080808), + uvec2(0x2b190808, 0x19080808), uvec2(0x08080808, 0x19080819), uvec2(0x082b0808, 0x19080819), uvec2(0x192b0819, 0x19080819), + uvec2(0x2b080808, 0x19080819), uvec2(0x2b081919, 0x19080819), uvec2(0x08080819, 0x1908082b), uvec2(0x08190808, 0x1908082b), + uvec2(0x19082b08, 0x1908082b), uvec2(0x1919192b, 0x1908082b), uvec2(0x192b2b08, 0x1908082b), uvec2(0x08080808, 0x19081908), + uvec2(0x08082b08, 0x19081908), uvec2(0x082b0808, 0x19081908), uvec2(0x2b080808, 0x19081908), uvec2(0x2b192b19, 0x19081908), + uvec2(0x0819082b, 0x19081919), uvec2(0x082b1908, 0x19081919), uvec2(0x08080808, 0x1908192b), uvec2(0x08080819, 0x19082b08), + uvec2(0x08081908, 0x19082b08), uvec2(0x08190808, 0x19082b08), uvec2(0x19080808, 0x19082b08), uvec2(0x19081919, 0x19082b08), + uvec2(0x08080808, 0x19082b19), uvec2(0x19192b08, 0x19082b19), uvec2(0x192b0819, 0x19082b19), uvec2(0x2b08082b, 0x19082b19), + uvec2(0x19081919, 0x19082b2b), uvec2(0x2b190808, 0x19082b2b), uvec2(0x08080808, 0x19190808), uvec2(0x08082b08, 0x19190808), + uvec2(0x08190819, 0x19190808), uvec2(0x08192b19, 0x19190808), uvec2(0x082b0808, 0x19190808), uvec2(0x2b080808, 0x19190808), + uvec2(0x2b082b08, 0x19190808), uvec2(0x08081908, 0x19190819), uvec2(0x1908082b, 0x19190819), uvec2(0x2b2b1908, 0x19190819), + uvec2(0x2b190819, 0x1919082b), uvec2(0x2b190808, 0x19191908), uvec2(0x2b19082b, 0x19191908), uvec2(0x08082b2b, 0x19191919), + uvec2(0x08080819, 0x1919192b), uvec2(0x19191908, 0x1919192b), uvec2(0x08080808, 0x19192b08), uvec2(0x08190819, 0x19192b08), + uvec2(0x08192b19, 0x19192b08), uvec2(0x192b1908, 0x19192b08), uvec2(0x19080808, 0x19192b19), uvec2(0x08082b08, 0x19192b2b), + uvec2(0x08081908, 0x192b0808), uvec2(0x08190808, 0x192b0808), uvec2(0x19080808, 0x192b0808), uvec2(0x192b2b08, 0x192b0808), + uvec2(0x08080808, 0x192b0819), uvec2(0x19191919, 0x192b0819), uvec2(0x08192b08, 0x192b082b), uvec2(0x192b0808, 0x192b082b), + uvec2(0x08080808, 0x192b1908), uvec2(0x08081919, 0x192b1908), uvec2(0x08190808, 0x192b1919), uvec2(0x0819082b, 0x192b1919), + uvec2(0x2b081908, 0x192b1919), uvec2(0x1908082b, 0x192b2b08), uvec2(0x08080808, 0x2b080808), uvec2(0x0808082b, 0x2b080808), + uvec2(0x08082b2b, 0x2b080808), uvec2(0x19080819, 0x2b080808), uvec2(0x2b08082b, 0x2b080808), uvec2(0x08081908, 0x2b080819), + uvec2(0x08192b08, 0x2b080819), uvec2(0x19080808, 0x2b080819), uvec2(0x08190819, 0x2b08082b), uvec2(0x08080819, 0x2b081908), + uvec2(0x08081908, 0x2b081908), uvec2(0x08190808, 0x2b081908), uvec2(0x08191919, 0x2b081908), uvec2(0x19080808, 0x2b081908), + uvec2(0x192b0808, 0x2b081908), uvec2(0x08080808, 0x2b081919), uvec2(0x1908192b, 0x2b081919), uvec2(0x2b191908, 0x2b081919), + uvec2(0x08082b19, 0x2b08192b), uvec2(0x19080808, 0x2b08192b), uvec2(0x192b0808, 0x2b08192b), uvec2(0x0808082b, 0x2b082b08), + uvec2(0x08081908, 0x2b082b19), uvec2(0x08190819, 0x2b082b2b), uvec2(0x08081908, 0x2b190808), uvec2(0x08190808, 0x2b190808), + uvec2(0x082b1908, 0x2b190808), uvec2(0x19080808, 0x2b190808), uvec2(0x2b2b0819, 0x2b190808), uvec2(0x0819192b, 0x2b190819), + uvec2(0x2b080808, 0x2b190819), uvec2(0x19081919, 0x2b19082b), uvec2(0x08080808, 0x2b191908), uvec2(0x082b082b, 0x2b191908), + uvec2(0x19081908, 0x2b191908), uvec2(0x19190819, 0x2b191919), uvec2(0x2b080819, 0x2b192b08), uvec2(0x082b0808, 0x2b192b19), + uvec2(0x0808082b, 0x2b2b0808), uvec2(0x19190808, 0x2b2b0808), uvec2(0x2b081919, 0x2b2b0808), uvec2(0x08082b19, 0x2b2b0819), + uvec2(0x08080808, 0x2b2b082b), uvec2(0x08192b08, 0x2b2b1908), uvec2(0x19190808, 0x2b2b2b08), uvec2(0x08081908, 0x2b2b2b19) +}; + +shared uvec2 iq2xxs_grid[256]; + +#define NEEDS_INIT_IQ_SHMEM +void init_iq_shmem(uvec3 wgsize) +{ + // copy the table into shared memory and sync + [[unroll]] for (uint i = 0; i < iq2xxs_grid.length(); i += wgsize.x) { + if (iq2xxs_grid_const.length() % wgsize.x == 0 || i + gl_LocalInvocationIndex.x < iq2xxs_grid_const.length()) { + iq2xxs_grid[i + gl_LocalInvocationIndex.x] = iq2xxs_grid_const[i + gl_LocalInvocationIndex.x]; + } + } + barrier(); +} + +#define QUANT_K QUANT_K_IQ2_XXS +#define QUANT_R QUANT_R_IQ2_XXS +#define A_TYPE block_iq2_xxs +#define A_TYPE_PACKED16 block_iq2_xxs_packed16 +#endif + +#define QUANT_K_IQ2_XS 256 +#define QUANT_R_IQ2_XS 1 + +struct block_iq2_xs +{ + float16_t d; + uint16_t qs[QUANT_K_IQ2_XS/8]; + uint8_t scales[QUANT_K_IQ2_XS/32]; +}; + +struct block_iq2_xs_packed16 +{ + float16_t d; + uint16_t qs[QUANT_K_IQ2_XS/8]; + uint16_t scales[QUANT_K_IQ2_XS/64]; +}; + +#if defined(DATA_A_IQ2_XS) + +const uvec2 iq2xs_grid_const[512] = { + uvec2(0x08080808, 0x08080808), uvec2(0x0808082b, 0x08080808), uvec2(0x08081919, 0x08080808), uvec2(0x08082b08, 0x08080808), + uvec2(0x08082b2b, 0x08080808), uvec2(0x08190819, 0x08080808), uvec2(0x08191908, 0x08080808), uvec2(0x0819192b, 0x08080808), + uvec2(0x08192b19, 0x08080808), uvec2(0x082b0808, 0x08080808), uvec2(0x082b082b, 0x08080808), uvec2(0x082b1919, 0x08080808), + uvec2(0x082b2b08, 0x08080808), uvec2(0x19080819, 0x08080808), uvec2(0x19081908, 0x08080808), uvec2(0x1908192b, 0x08080808), + uvec2(0x19082b19, 0x08080808), uvec2(0x19190808, 0x08080808), uvec2(0x1919082b, 0x08080808), uvec2(0x19191919, 0x08080808), + uvec2(0x19192b08, 0x08080808), uvec2(0x192b0819, 0x08080808), uvec2(0x192b1908, 0x08080808), uvec2(0x2b080808, 0x08080808), + uvec2(0x2b08082b, 0x08080808), uvec2(0x2b081919, 0x08080808), uvec2(0x2b082b08, 0x08080808), uvec2(0x2b190819, 0x08080808), + uvec2(0x2b191908, 0x08080808), uvec2(0x2b192b19, 0x08080808), uvec2(0x2b2b0808, 0x08080808), uvec2(0x08080819, 0x08080819), + uvec2(0x08081908, 0x08080819), uvec2(0x0808192b, 0x08080819), uvec2(0x08082b19, 0x08080819), uvec2(0x08190808, 0x08080819), + uvec2(0x0819082b, 0x08080819), uvec2(0x08191919, 0x08080819), uvec2(0x08192b08, 0x08080819), uvec2(0x08192b2b, 0x08080819), + uvec2(0x082b0819, 0x08080819), uvec2(0x082b1908, 0x08080819), uvec2(0x19080808, 0x08080819), uvec2(0x1908082b, 0x08080819), + uvec2(0x19081919, 0x08080819), uvec2(0x19082b08, 0x08080819), uvec2(0x19190819, 0x08080819), uvec2(0x19191908, 0x08080819), + uvec2(0x192b0808, 0x08080819), uvec2(0x192b2b08, 0x08080819), uvec2(0x2b080819, 0x08080819), uvec2(0x2b081908, 0x08080819), + uvec2(0x2b190808, 0x08080819), uvec2(0x08080808, 0x0808082b), uvec2(0x0808082b, 0x0808082b), uvec2(0x08081919, 0x0808082b), + uvec2(0x08082b08, 0x0808082b), uvec2(0x08190819, 0x0808082b), uvec2(0x08191908, 0x0808082b), uvec2(0x082b0808, 0x0808082b), + uvec2(0x19080819, 0x0808082b), uvec2(0x19081908, 0x0808082b), uvec2(0x19190808, 0x0808082b), uvec2(0x19191919, 0x0808082b), + uvec2(0x2b080808, 0x0808082b), uvec2(0x2b082b2b, 0x0808082b), uvec2(0x08080819, 0x08081908), uvec2(0x08081908, 0x08081908), + uvec2(0x0808192b, 0x08081908), uvec2(0x08082b19, 0x08081908), uvec2(0x08190808, 0x08081908), uvec2(0x0819082b, 0x08081908), + uvec2(0x08191919, 0x08081908), uvec2(0x08192b08, 0x08081908), uvec2(0x082b0819, 0x08081908), uvec2(0x082b1908, 0x08081908), + uvec2(0x19080808, 0x08081908), uvec2(0x1908082b, 0x08081908), uvec2(0x19081919, 0x08081908), uvec2(0x19082b08, 0x08081908), + uvec2(0x19190819, 0x08081908), uvec2(0x19191908, 0x08081908), uvec2(0x1919192b, 0x08081908), uvec2(0x192b0808, 0x08081908), + uvec2(0x2b080819, 0x08081908), uvec2(0x2b081908, 0x08081908), uvec2(0x2b190808, 0x08081908), uvec2(0x08080808, 0x08081919), + uvec2(0x0808082b, 0x08081919), uvec2(0x08081919, 0x08081919), uvec2(0x08082b08, 0x08081919), uvec2(0x08190819, 0x08081919), + uvec2(0x08191908, 0x08081919), uvec2(0x082b0808, 0x08081919), uvec2(0x19080819, 0x08081919), uvec2(0x19081908, 0x08081919), + uvec2(0x19190808, 0x08081919), uvec2(0x192b0819, 0x08081919), uvec2(0x2b080808, 0x08081919), uvec2(0x08080819, 0x0808192b), + uvec2(0x08081908, 0x0808192b), uvec2(0x08190808, 0x0808192b), uvec2(0x082b192b, 0x0808192b), uvec2(0x19080808, 0x0808192b), + uvec2(0x1908082b, 0x0808192b), uvec2(0x2b081908, 0x0808192b), uvec2(0x08080808, 0x08082b08), uvec2(0x0808082b, 0x08082b08), + uvec2(0x08081919, 0x08082b08), uvec2(0x08082b08, 0x08082b08), uvec2(0x08082b2b, 0x08082b08), uvec2(0x08190819, 0x08082b08), + uvec2(0x08191908, 0x08082b08), uvec2(0x082b0808, 0x08082b08), uvec2(0x082b1919, 0x08082b08), uvec2(0x19080819, 0x08082b08), + uvec2(0x19081908, 0x08082b08), uvec2(0x19190808, 0x08082b08), uvec2(0x19192b08, 0x08082b08), uvec2(0x2b080808, 0x08082b08), + uvec2(0x2b2b0808, 0x08082b08), uvec2(0x2b2b2b2b, 0x08082b08), uvec2(0x08080819, 0x08082b19), uvec2(0x08081908, 0x08082b19), + uvec2(0x08190808, 0x08082b19), uvec2(0x19080808, 0x08082b19), uvec2(0x2b080819, 0x08082b19), uvec2(0x2b082b19, 0x08082b19), + uvec2(0x08080808, 0x08082b2b), uvec2(0x082b0808, 0x08082b2b), uvec2(0x082b2b08, 0x08082b2b), uvec2(0x2b19192b, 0x08082b2b), + uvec2(0x2b2b0808, 0x08082b2b), uvec2(0x08080819, 0x08190808), uvec2(0x08081908, 0x08190808), uvec2(0x0808192b, 0x08190808), + uvec2(0x08082b19, 0x08190808), uvec2(0x08190808, 0x08190808), uvec2(0x0819082b, 0x08190808), uvec2(0x08191919, 0x08190808), + uvec2(0x08192b08, 0x08190808), uvec2(0x082b0819, 0x08190808), uvec2(0x082b1908, 0x08190808), uvec2(0x19080808, 0x08190808), + uvec2(0x1908082b, 0x08190808), uvec2(0x19081919, 0x08190808), uvec2(0x19082b08, 0x08190808), uvec2(0x19190819, 0x08190808), + uvec2(0x19191908, 0x08190808), uvec2(0x192b0808, 0x08190808), uvec2(0x192b2b2b, 0x08190808), uvec2(0x2b080819, 0x08190808), + uvec2(0x2b081908, 0x08190808), uvec2(0x2b190808, 0x08190808), uvec2(0x08080808, 0x08190819), uvec2(0x0808082b, 0x08190819), + uvec2(0x08081919, 0x08190819), uvec2(0x08082b08, 0x08190819), uvec2(0x08190819, 0x08190819), uvec2(0x08191908, 0x08190819), + uvec2(0x082b0808, 0x08190819), uvec2(0x19080819, 0x08190819), uvec2(0x19081908, 0x08190819), uvec2(0x19190808, 0x08190819), + uvec2(0x2b080808, 0x08190819), uvec2(0x2b191908, 0x08190819), uvec2(0x2b19192b, 0x08190819), uvec2(0x08080819, 0x0819082b), + uvec2(0x08081908, 0x0819082b), uvec2(0x0808192b, 0x0819082b), uvec2(0x08190808, 0x0819082b), uvec2(0x19080808, 0x0819082b), + uvec2(0x192b0808, 0x0819082b), uvec2(0x08080808, 0x08191908), uvec2(0x0808082b, 0x08191908), uvec2(0x08081919, 0x08191908), + uvec2(0x08082b08, 0x08191908), uvec2(0x08190819, 0x08191908), uvec2(0x08191908, 0x08191908), uvec2(0x082b0808, 0x08191908), + uvec2(0x19080819, 0x08191908), uvec2(0x19081908, 0x08191908), uvec2(0x19082b19, 0x08191908), uvec2(0x19190808, 0x08191908), + uvec2(0x192b1908, 0x08191908), uvec2(0x2b080808, 0x08191908), uvec2(0x08080819, 0x08191919), uvec2(0x08081908, 0x08191919), + uvec2(0x08190808, 0x08191919), uvec2(0x19080808, 0x08191919), uvec2(0x08080808, 0x0819192b), uvec2(0x08191908, 0x0819192b), + uvec2(0x19082b19, 0x0819192b), uvec2(0x08080819, 0x08192b08), uvec2(0x08081908, 0x08192b08), uvec2(0x08190808, 0x08192b08), + uvec2(0x0819082b, 0x08192b08), uvec2(0x19080808, 0x08192b08), uvec2(0x19191908, 0x08192b08), uvec2(0x2b08192b, 0x08192b08), + uvec2(0x08080808, 0x08192b19), uvec2(0x08081919, 0x08192b19), uvec2(0x192b192b, 0x08192b19), uvec2(0x19190819, 0x08192b2b), + uvec2(0x2b2b2b19, 0x08192b2b), uvec2(0x08080808, 0x082b0808), uvec2(0x0808082b, 0x082b0808), uvec2(0x08081919, 0x082b0808), + uvec2(0x08082b08, 0x082b0808), uvec2(0x08082b2b, 0x082b0808), uvec2(0x08190819, 0x082b0808), uvec2(0x08191908, 0x082b0808), + uvec2(0x082b0808, 0x082b0808), uvec2(0x19080819, 0x082b0808), uvec2(0x19081908, 0x082b0808), uvec2(0x19190808, 0x082b0808), + uvec2(0x2b080808, 0x082b0808), uvec2(0x2b2b0808, 0x082b0808), uvec2(0x08080819, 0x082b0819), uvec2(0x08081908, 0x082b0819), + uvec2(0x08190808, 0x082b0819), uvec2(0x19080808, 0x082b0819), uvec2(0x19082b08, 0x082b0819), uvec2(0x192b1919, 0x082b0819), + uvec2(0x08080808, 0x082b082b), uvec2(0x082b082b, 0x082b082b), uvec2(0x2b080808, 0x082b082b), uvec2(0x2b2b2b08, 0x082b082b), + uvec2(0x08080819, 0x082b1908), uvec2(0x08081908, 0x082b1908), uvec2(0x08190808, 0x082b1908), uvec2(0x082b2b19, 0x082b1908), + uvec2(0x19080808, 0x082b1908), uvec2(0x08080808, 0x082b1919), uvec2(0x19080819, 0x082b1919), uvec2(0x1919082b, 0x082b1919), + uvec2(0x2b192b19, 0x082b1919), uvec2(0x08080819, 0x082b192b), uvec2(0x08192b2b, 0x082b192b), uvec2(0x2b2b192b, 0x082b192b), + uvec2(0x08080808, 0x082b2b08), uvec2(0x08082b08, 0x082b2b08), uvec2(0x08082b2b, 0x082b2b08), uvec2(0x082b0808, 0x082b2b08), + uvec2(0x19191919, 0x082b2b08), uvec2(0x2b082b08, 0x082b2b08), uvec2(0x2b2b082b, 0x082b2b08), uvec2(0x192b2b08, 0x082b2b19), + uvec2(0x2b190808, 0x082b2b19), uvec2(0x08082b08, 0x082b2b2b), uvec2(0x082b0808, 0x082b2b2b), uvec2(0x2b08082b, 0x082b2b2b), + uvec2(0x2b082b08, 0x082b2b2b), uvec2(0x2b082b2b, 0x082b2b2b), uvec2(0x08080819, 0x19080808), uvec2(0x08081908, 0x19080808), + uvec2(0x0808192b, 0x19080808), uvec2(0x08082b19, 0x19080808), uvec2(0x08190808, 0x19080808), uvec2(0x0819082b, 0x19080808), + uvec2(0x08191919, 0x19080808), uvec2(0x08192b08, 0x19080808), uvec2(0x082b0819, 0x19080808), uvec2(0x082b1908, 0x19080808), + uvec2(0x19080808, 0x19080808), uvec2(0x1908082b, 0x19080808), uvec2(0x19081919, 0x19080808), uvec2(0x19082b08, 0x19080808), + uvec2(0x19082b2b, 0x19080808), uvec2(0x19190819, 0x19080808), uvec2(0x19191908, 0x19080808), uvec2(0x192b0808, 0x19080808), + uvec2(0x192b1919, 0x19080808), uvec2(0x2b080819, 0x19080808), uvec2(0x2b081908, 0x19080808), uvec2(0x2b190808, 0x19080808), + uvec2(0x08080808, 0x19080819), uvec2(0x0808082b, 0x19080819), uvec2(0x08081919, 0x19080819), uvec2(0x08082b08, 0x19080819), + uvec2(0x08190819, 0x19080819), uvec2(0x08191908, 0x19080819), uvec2(0x082b0808, 0x19080819), uvec2(0x19080819, 0x19080819), + uvec2(0x19081908, 0x19080819), uvec2(0x19190808, 0x19080819), uvec2(0x2b080808, 0x19080819), uvec2(0x2b081919, 0x19080819), + uvec2(0x2b2b082b, 0x19080819), uvec2(0x08080819, 0x1908082b), uvec2(0x08081908, 0x1908082b), uvec2(0x08190808, 0x1908082b), + uvec2(0x0819082b, 0x1908082b), uvec2(0x082b2b19, 0x1908082b), uvec2(0x19080808, 0x1908082b), uvec2(0x08080808, 0x19081908), + uvec2(0x0808082b, 0x19081908), uvec2(0x08081919, 0x19081908), uvec2(0x08082b08, 0x19081908), uvec2(0x08190819, 0x19081908), + uvec2(0x08191908, 0x19081908), uvec2(0x08192b19, 0x19081908), uvec2(0x082b0808, 0x19081908), uvec2(0x19080819, 0x19081908), + uvec2(0x19081908, 0x19081908), uvec2(0x19190808, 0x19081908), uvec2(0x2b080808, 0x19081908), uvec2(0x2b191908, 0x19081908), + uvec2(0x08080819, 0x19081919), uvec2(0x08081908, 0x19081919), uvec2(0x08190808, 0x19081919), uvec2(0x082b1908, 0x19081919), + uvec2(0x19080808, 0x19081919), uvec2(0x2b192b2b, 0x19081919), uvec2(0x08080808, 0x1908192b), uvec2(0x08082b2b, 0x1908192b), + uvec2(0x19081908, 0x1908192b), uvec2(0x19190808, 0x1908192b), uvec2(0x08080819, 0x19082b08), uvec2(0x08081908, 0x19082b08), + uvec2(0x08190808, 0x19082b08), uvec2(0x19080808, 0x19082b08), uvec2(0x19081919, 0x19082b08), uvec2(0x19191908, 0x19082b08), + uvec2(0x192b082b, 0x19082b08), uvec2(0x08080808, 0x19082b19), uvec2(0x08190819, 0x19082b19), uvec2(0x19081908, 0x19082b19), + uvec2(0x19190808, 0x19082b19), uvec2(0x192b2b19, 0x19082b19), uvec2(0x08081908, 0x19082b2b), uvec2(0x08080808, 0x19190808), + uvec2(0x0808082b, 0x19190808), uvec2(0x08081919, 0x19190808), uvec2(0x08082b08, 0x19190808), uvec2(0x08190819, 0x19190808), + uvec2(0x08191908, 0x19190808), uvec2(0x082b0808, 0x19190808), uvec2(0x082b2b08, 0x19190808), uvec2(0x19080819, 0x19190808), + uvec2(0x19081908, 0x19190808), uvec2(0x19190808, 0x19190808), uvec2(0x2b080808, 0x19190808), uvec2(0x08080819, 0x19190819), + uvec2(0x08081908, 0x19190819), uvec2(0x08190808, 0x19190819), uvec2(0x08191919, 0x19190819), uvec2(0x19080808, 0x19190819), + uvec2(0x1908082b, 0x19190819), uvec2(0x08080808, 0x1919082b), uvec2(0x19081908, 0x1919082b), uvec2(0x2b2b2b2b, 0x1919082b), + uvec2(0x08080819, 0x19191908), uvec2(0x08081908, 0x19191908), uvec2(0x08190808, 0x19191908), uvec2(0x082b0819, 0x19191908), + uvec2(0x19080808, 0x19191908), uvec2(0x192b0808, 0x19191908), uvec2(0x2b080819, 0x19191908), uvec2(0x2b2b0819, 0x19191908), + uvec2(0x08080808, 0x19191919), uvec2(0x08082b08, 0x19191919), uvec2(0x2b080808, 0x19191919), uvec2(0x2b082b08, 0x19191919), + uvec2(0x082b0819, 0x1919192b), uvec2(0x192b2b08, 0x1919192b), uvec2(0x2b2b0819, 0x1919192b), uvec2(0x08080808, 0x19192b08), + uvec2(0x08191908, 0x19192b08), uvec2(0x19080819, 0x19192b08), uvec2(0x19190808, 0x19192b08), uvec2(0x2b192b19, 0x19192b08), + uvec2(0x08192b2b, 0x19192b19), uvec2(0x19080808, 0x19192b19), uvec2(0x1908082b, 0x19192b19), uvec2(0x2b081919, 0x19192b2b), + uvec2(0x08080819, 0x192b0808), uvec2(0x08081908, 0x192b0808), uvec2(0x08190808, 0x192b0808), uvec2(0x19080808, 0x192b0808), + uvec2(0x19191908, 0x192b0808), uvec2(0x192b082b, 0x192b0808), uvec2(0x2b08192b, 0x192b0808), uvec2(0x2b2b2b19, 0x192b0808), + uvec2(0x08080808, 0x192b0819), uvec2(0x082b1908, 0x192b082b), uvec2(0x19082b2b, 0x192b082b), uvec2(0x2b19082b, 0x192b082b), + uvec2(0x08080808, 0x192b1908), uvec2(0x0819192b, 0x192b1908), uvec2(0x08190808, 0x192b1919), uvec2(0x19080808, 0x192b1919), + uvec2(0x19081919, 0x192b1919), uvec2(0x2b2b1908, 0x192b1919), uvec2(0x08080819, 0x192b2b08), uvec2(0x192b2b2b, 0x192b2b08), + uvec2(0x082b1919, 0x192b2b19), uvec2(0x0808192b, 0x192b2b2b), uvec2(0x19191908, 0x192b2b2b), uvec2(0x192b082b, 0x192b2b2b), + uvec2(0x08080808, 0x2b080808), uvec2(0x0808082b, 0x2b080808), uvec2(0x08081919, 0x2b080808), uvec2(0x08082b08, 0x2b080808), + uvec2(0x08190819, 0x2b080808), uvec2(0x08191908, 0x2b080808), uvec2(0x082b0808, 0x2b080808), uvec2(0x082b2b2b, 0x2b080808), + uvec2(0x19080819, 0x2b080808), uvec2(0x19081908, 0x2b080808), uvec2(0x19190808, 0x2b080808), uvec2(0x2b080808, 0x2b080808), + uvec2(0x2b08082b, 0x2b080808), uvec2(0x2b2b2b08, 0x2b080808), uvec2(0x2b2b2b2b, 0x2b080808), uvec2(0x08080819, 0x2b080819), + uvec2(0x08081908, 0x2b080819), uvec2(0x0808192b, 0x2b080819), uvec2(0x08190808, 0x2b080819), uvec2(0x19080808, 0x2b080819), + uvec2(0x19190819, 0x2b080819), uvec2(0x19192b19, 0x2b080819), uvec2(0x08080808, 0x2b08082b), uvec2(0x082b0808, 0x2b08082b), + uvec2(0x2b080808, 0x2b08082b), uvec2(0x2b08082b, 0x2b08082b), uvec2(0x2b2b0808, 0x2b08082b), uvec2(0x2b2b2b08, 0x2b08082b), + uvec2(0x08080819, 0x2b081908), uvec2(0x08081908, 0x2b081908), uvec2(0x08190808, 0x2b081908), uvec2(0x0819082b, 0x2b081908), + uvec2(0x08191919, 0x2b081908), uvec2(0x19080808, 0x2b081908), uvec2(0x192b0808, 0x2b081908), uvec2(0x2b082b19, 0x2b081908), + uvec2(0x08080808, 0x2b081919), uvec2(0x19081908, 0x2b081919), uvec2(0x2b2b1919, 0x2b081919), uvec2(0x08192b08, 0x2b08192b), + uvec2(0x192b2b2b, 0x2b08192b), uvec2(0x08080808, 0x2b082b08), uvec2(0x08082b08, 0x2b082b08), uvec2(0x082b1919, 0x2b082b08), + uvec2(0x19192b2b, 0x2b082b08), uvec2(0x2b080808, 0x2b082b08), uvec2(0x2b08082b, 0x2b082b08), uvec2(0x2b2b2b08, 0x2b082b08), + uvec2(0x0808192b, 0x2b082b19), uvec2(0x082b082b, 0x2b082b2b), uvec2(0x2b080808, 0x2b082b2b), uvec2(0x2b082b08, 0x2b082b2b), + uvec2(0x2b19192b, 0x2b082b2b), uvec2(0x2b2b2b08, 0x2b082b2b), uvec2(0x08080819, 0x2b190808), uvec2(0x08081908, 0x2b190808), + uvec2(0x08190808, 0x2b190808), uvec2(0x19080808, 0x2b190808), uvec2(0x1919192b, 0x2b190808), uvec2(0x2b081908, 0x2b190808), + uvec2(0x08080808, 0x2b190819), uvec2(0x082b082b, 0x2b190819), uvec2(0x192b1908, 0x2b190819), uvec2(0x1919192b, 0x2b19082b), + uvec2(0x2b082b19, 0x2b19082b), uvec2(0x08080808, 0x2b191908), uvec2(0x08081919, 0x2b191908), uvec2(0x19081908, 0x2b191908), + uvec2(0x19190808, 0x2b191908), uvec2(0x19192b08, 0x2b191908), uvec2(0x082b2b19, 0x2b191919), uvec2(0x2b190808, 0x2b191919), + uvec2(0x2b19082b, 0x2b191919), uvec2(0x19080819, 0x2b19192b), uvec2(0x19190819, 0x2b192b08), uvec2(0x2b2b192b, 0x2b192b08), + uvec2(0x19082b19, 0x2b192b19), uvec2(0x08191919, 0x2b192b2b), uvec2(0x192b0808, 0x2b192b2b), uvec2(0x08080808, 0x2b2b0808), + uvec2(0x0808082b, 0x2b2b0808), uvec2(0x08082b08, 0x2b2b0808), uvec2(0x08082b2b, 0x2b2b0808), uvec2(0x082b0808, 0x2b2b0808), + uvec2(0x082b2b2b, 0x2b2b0808), uvec2(0x2b2b0808, 0x2b2b0808), uvec2(0x19190819, 0x2b2b0819), uvec2(0x19192b19, 0x2b2b0819), + uvec2(0x2b2b192b, 0x2b2b0819), uvec2(0x08080808, 0x2b2b082b), uvec2(0x0808082b, 0x2b2b082b), uvec2(0x08082b08, 0x2b2b082b), + uvec2(0x082b2b2b, 0x2b2b082b), uvec2(0x2b080808, 0x2b2b082b), uvec2(0x2b2b0808, 0x2b2b082b), uvec2(0x19080808, 0x2b2b1908), + uvec2(0x2b191919, 0x2b2b1908), uvec2(0x192b1919, 0x2b2b192b), uvec2(0x2b192b08, 0x2b2b192b), uvec2(0x08082b2b, 0x2b2b2b08), + uvec2(0x082b0808, 0x2b2b2b08), uvec2(0x082b082b, 0x2b2b2b08), uvec2(0x082b2b08, 0x2b2b2b08), uvec2(0x2b2b0808, 0x2b2b2b08), + uvec2(0x2b2b2b08, 0x2b2b2b08), uvec2(0x08081908, 0x2b2b2b19), uvec2(0x2b081908, 0x2b2b2b19), uvec2(0x2b08192b, 0x2b2b2b19), + uvec2(0x082b2b08, 0x2b2b2b2b), uvec2(0x082b2b2b, 0x2b2b2b2b), uvec2(0x2b190819, 0x2b2b2b2b), uvec2(0x2b2b2b2b, 0x2b2b2b2b), +}; + +shared uvec2 iq2xs_grid[512]; + +#define NEEDS_INIT_IQ_SHMEM +void init_iq_shmem(uvec3 wgsize) +{ + // copy the table into shared memory and sync + [[unroll]] for (uint i = 0; i < iq2xs_grid.length(); i += wgsize.x) { + if (iq2xs_grid.length() % wgsize.x == 0 || i + gl_LocalInvocationIndex.x < iq2xs_grid_const.length()) { + iq2xs_grid[i + gl_LocalInvocationIndex.x] = iq2xs_grid_const[i + gl_LocalInvocationIndex.x]; + } + } + barrier(); +} + +#define QUANT_K QUANT_K_IQ2_XS +#define QUANT_R QUANT_R_IQ2_XS +#define A_TYPE block_iq2_xs +#define A_TYPE_PACKED16 block_iq2_xs_packed16 +#endif + +#define QUANT_K_IQ2_S 256 +#define QUANT_R_IQ2_S 1 + +struct block_iq2_s +{ + float16_t d; + uint8_t qs[QUANT_K_IQ2_S/4]; + uint8_t qh[QUANT_K_IQ2_S/32]; + uint8_t scales[QUANT_K_IQ2_S/32]; +}; + +struct block_iq2_s_packed16 +{ + float16_t d; + uint16_t qs[QUANT_K_IQ2_S/8]; + uint16_t qh[QUANT_K_IQ2_S/64]; + uint16_t scales[QUANT_K_IQ2_S/64]; +}; + +#if defined(DATA_A_IQ2_S) + +const uvec2 iq2s_grid_const[1024] = { + uvec2(0x08080808, 0x08080808), uvec2(0x0808082b, 0x08080808), uvec2(0x08081919, 0x08080808), uvec2(0x08082b08, 0x08080808), + uvec2(0x08082b2b, 0x08080808), uvec2(0x08190819, 0x08080808), uvec2(0x08191908, 0x08080808), uvec2(0x0819192b, 0x08080808), + uvec2(0x08192b19, 0x08080808), uvec2(0x082b0808, 0x08080808), uvec2(0x082b082b, 0x08080808), uvec2(0x082b1919, 0x08080808), + uvec2(0x082b2b08, 0x08080808), uvec2(0x19080819, 0x08080808), uvec2(0x19081908, 0x08080808), uvec2(0x1908192b, 0x08080808), + uvec2(0x19082b19, 0x08080808), uvec2(0x19190808, 0x08080808), uvec2(0x1919082b, 0x08080808), uvec2(0x19191919, 0x08080808), + uvec2(0x19192b08, 0x08080808), uvec2(0x192b0819, 0x08080808), uvec2(0x192b1908, 0x08080808), uvec2(0x192b192b, 0x08080808), + uvec2(0x192b2b19, 0x08080808), uvec2(0x2b080808, 0x08080808), uvec2(0x2b08082b, 0x08080808), uvec2(0x2b081919, 0x08080808), + uvec2(0x2b082b08, 0x08080808), uvec2(0x2b190819, 0x08080808), uvec2(0x2b191908, 0x08080808), uvec2(0x2b2b0808, 0x08080808), + uvec2(0x2b2b1919, 0x08080808), uvec2(0x2b2b2b2b, 0x08080808), uvec2(0x08080819, 0x08080819), uvec2(0x08081908, 0x08080819), + uvec2(0x0808192b, 0x08080819), uvec2(0x08082b19, 0x08080819), uvec2(0x08190808, 0x08080819), uvec2(0x0819082b, 0x08080819), + uvec2(0x08191919, 0x08080819), uvec2(0x08192b08, 0x08080819), uvec2(0x082b0819, 0x08080819), uvec2(0x082b1908, 0x08080819), + uvec2(0x19080808, 0x08080819), uvec2(0x1908082b, 0x08080819), uvec2(0x19081919, 0x08080819), uvec2(0x19082b08, 0x08080819), + uvec2(0x19190819, 0x08080819), uvec2(0x19191908, 0x08080819), uvec2(0x1919192b, 0x08080819), uvec2(0x19192b19, 0x08080819), + uvec2(0x192b0808, 0x08080819), uvec2(0x192b1919, 0x08080819), uvec2(0x192b2b08, 0x08080819), uvec2(0x2b080819, 0x08080819), + uvec2(0x2b081908, 0x08080819), uvec2(0x2b190808, 0x08080819), uvec2(0x2b19082b, 0x08080819), uvec2(0x2b191919, 0x08080819), + uvec2(0x2b2b0819, 0x08080819), uvec2(0x2b2b1908, 0x08080819), uvec2(0x08080808, 0x0808082b), uvec2(0x0808082b, 0x0808082b), + uvec2(0x08081919, 0x0808082b), uvec2(0x08082b08, 0x0808082b), uvec2(0x08190819, 0x0808082b), uvec2(0x08191908, 0x0808082b), + uvec2(0x082b0808, 0x0808082b), uvec2(0x082b2b2b, 0x0808082b), uvec2(0x19080819, 0x0808082b), uvec2(0x19081908, 0x0808082b), + uvec2(0x1908192b, 0x0808082b), uvec2(0x19082b19, 0x0808082b), uvec2(0x19190808, 0x0808082b), uvec2(0x19191919, 0x0808082b), + uvec2(0x2b080808, 0x0808082b), uvec2(0x2b081919, 0x0808082b), uvec2(0x2b082b2b, 0x0808082b), uvec2(0x2b191908, 0x0808082b), + uvec2(0x2b2b082b, 0x0808082b), uvec2(0x08080819, 0x08081908), uvec2(0x08081908, 0x08081908), uvec2(0x0808192b, 0x08081908), + uvec2(0x08082b19, 0x08081908), uvec2(0x08190808, 0x08081908), uvec2(0x0819082b, 0x08081908), uvec2(0x08191919, 0x08081908), + uvec2(0x08192b08, 0x08081908), uvec2(0x082b0819, 0x08081908), uvec2(0x082b1908, 0x08081908), uvec2(0x082b192b, 0x08081908), + uvec2(0x082b2b19, 0x08081908), uvec2(0x19080808, 0x08081908), uvec2(0x1908082b, 0x08081908), uvec2(0x19081919, 0x08081908), + uvec2(0x19082b08, 0x08081908), uvec2(0x19082b2b, 0x08081908), uvec2(0x19190819, 0x08081908), uvec2(0x19191908, 0x08081908), + uvec2(0x1919192b, 0x08081908), uvec2(0x19192b19, 0x08081908), uvec2(0x192b0808, 0x08081908), uvec2(0x192b082b, 0x08081908), + uvec2(0x192b1919, 0x08081908), uvec2(0x2b080819, 0x08081908), uvec2(0x2b081908, 0x08081908), uvec2(0x2b08192b, 0x08081908), + uvec2(0x2b082b19, 0x08081908), uvec2(0x2b190808, 0x08081908), uvec2(0x2b191919, 0x08081908), uvec2(0x2b192b08, 0x08081908), + uvec2(0x2b2b0819, 0x08081908), uvec2(0x2b2b1908, 0x08081908), uvec2(0x08080808, 0x08081919), uvec2(0x0808082b, 0x08081919), + uvec2(0x08081919, 0x08081919), uvec2(0x08082b08, 0x08081919), uvec2(0x08082b2b, 0x08081919), uvec2(0x08190819, 0x08081919), + uvec2(0x08191908, 0x08081919), uvec2(0x0819192b, 0x08081919), uvec2(0x08192b19, 0x08081919), uvec2(0x082b0808, 0x08081919), + uvec2(0x082b1919, 0x08081919), uvec2(0x082b2b08, 0x08081919), uvec2(0x19080819, 0x08081919), uvec2(0x19081908, 0x08081919), + uvec2(0x1908192b, 0x08081919), uvec2(0x19082b19, 0x08081919), uvec2(0x19190808, 0x08081919), uvec2(0x1919082b, 0x08081919), + uvec2(0x19191919, 0x08081919), uvec2(0x19192b08, 0x08081919), uvec2(0x192b0819, 0x08081919), uvec2(0x192b1908, 0x08081919), + uvec2(0x2b080808, 0x08081919), uvec2(0x2b08082b, 0x08081919), uvec2(0x2b081919, 0x08081919), uvec2(0x2b082b08, 0x08081919), + uvec2(0x2b190819, 0x08081919), uvec2(0x2b191908, 0x08081919), uvec2(0x2b2b0808, 0x08081919), uvec2(0x08080819, 0x0808192b), + uvec2(0x08081908, 0x0808192b), uvec2(0x0808192b, 0x0808192b), uvec2(0x08082b19, 0x0808192b), uvec2(0x08190808, 0x0808192b), + uvec2(0x08191919, 0x0808192b), uvec2(0x19080808, 0x0808192b), uvec2(0x19081919, 0x0808192b), uvec2(0x19082b08, 0x0808192b), + uvec2(0x19190819, 0x0808192b), uvec2(0x19191908, 0x0808192b), uvec2(0x192b0808, 0x0808192b), uvec2(0x2b080819, 0x0808192b), + uvec2(0x2b081908, 0x0808192b), uvec2(0x2b190808, 0x0808192b), uvec2(0x08080808, 0x08082b08), uvec2(0x0808082b, 0x08082b08), + uvec2(0x08081919, 0x08082b08), uvec2(0x08082b08, 0x08082b08), uvec2(0x08190819, 0x08082b08), uvec2(0x08191908, 0x08082b08), + uvec2(0x0819192b, 0x08082b08), uvec2(0x08192b19, 0x08082b08), uvec2(0x082b0808, 0x08082b08), uvec2(0x082b1919, 0x08082b08), + uvec2(0x082b2b2b, 0x08082b08), uvec2(0x19080819, 0x08082b08), uvec2(0x19081908, 0x08082b08), uvec2(0x1908192b, 0x08082b08), + uvec2(0x19082b19, 0x08082b08), uvec2(0x19190808, 0x08082b08), uvec2(0x1919082b, 0x08082b08), uvec2(0x19191919, 0x08082b08), + uvec2(0x19192b08, 0x08082b08), uvec2(0x192b0819, 0x08082b08), uvec2(0x192b1908, 0x08082b08), uvec2(0x2b080808, 0x08082b08), + uvec2(0x2b081919, 0x08082b08), uvec2(0x2b191908, 0x08082b08), uvec2(0x2b2b2b2b, 0x08082b08), uvec2(0x08080819, 0x08082b19), + uvec2(0x08081908, 0x08082b19), uvec2(0x08190808, 0x08082b19), uvec2(0x0819082b, 0x08082b19), uvec2(0x08191919, 0x08082b19), + uvec2(0x08192b08, 0x08082b19), uvec2(0x082b0819, 0x08082b19), uvec2(0x19080808, 0x08082b19), uvec2(0x19081919, 0x08082b19), + uvec2(0x19082b08, 0x08082b19), uvec2(0x19190819, 0x08082b19), uvec2(0x19191908, 0x08082b19), uvec2(0x192b0808, 0x08082b19), + uvec2(0x2b080819, 0x08082b19), uvec2(0x2b190808, 0x08082b19), uvec2(0x08080808, 0x08082b2b), uvec2(0x08190819, 0x08082b2b), + uvec2(0x08191908, 0x08082b2b), uvec2(0x082b082b, 0x08082b2b), uvec2(0x082b2b08, 0x08082b2b), uvec2(0x082b2b2b, 0x08082b2b), + uvec2(0x19190808, 0x08082b2b), uvec2(0x2b192b19, 0x08082b2b), uvec2(0x08080819, 0x08190808), uvec2(0x08081908, 0x08190808), + uvec2(0x0808192b, 0x08190808), uvec2(0x08082b19, 0x08190808), uvec2(0x08190808, 0x08190808), uvec2(0x0819082b, 0x08190808), + uvec2(0x08191919, 0x08190808), uvec2(0x08192b08, 0x08190808), uvec2(0x082b0819, 0x08190808), uvec2(0x082b1908, 0x08190808), + uvec2(0x082b192b, 0x08190808), uvec2(0x19080808, 0x08190808), uvec2(0x1908082b, 0x08190808), uvec2(0x19081919, 0x08190808), + uvec2(0x19082b08, 0x08190808), uvec2(0x19190819, 0x08190808), uvec2(0x19191908, 0x08190808), uvec2(0x1919192b, 0x08190808), + uvec2(0x19192b19, 0x08190808), uvec2(0x192b0808, 0x08190808), uvec2(0x192b082b, 0x08190808), uvec2(0x192b1919, 0x08190808), + uvec2(0x192b2b08, 0x08190808), uvec2(0x2b080819, 0x08190808), uvec2(0x2b081908, 0x08190808), uvec2(0x2b08192b, 0x08190808), + uvec2(0x2b190808, 0x08190808), uvec2(0x2b191919, 0x08190808), uvec2(0x2b192b08, 0x08190808), uvec2(0x2b2b0819, 0x08190808), + uvec2(0x2b2b1908, 0x08190808), uvec2(0x08080808, 0x08190819), uvec2(0x0808082b, 0x08190819), uvec2(0x08081919, 0x08190819), + uvec2(0x08082b08, 0x08190819), uvec2(0x08082b2b, 0x08190819), uvec2(0x08190819, 0x08190819), uvec2(0x08191908, 0x08190819), + uvec2(0x0819192b, 0x08190819), uvec2(0x08192b19, 0x08190819), uvec2(0x082b0808, 0x08190819), uvec2(0x082b082b, 0x08190819), + uvec2(0x082b1919, 0x08190819), uvec2(0x082b2b08, 0x08190819), uvec2(0x19080819, 0x08190819), uvec2(0x19081908, 0x08190819), + uvec2(0x1908192b, 0x08190819), uvec2(0x19082b19, 0x08190819), uvec2(0x19190808, 0x08190819), uvec2(0x1919082b, 0x08190819), + uvec2(0x19191919, 0x08190819), uvec2(0x19192b08, 0x08190819), uvec2(0x192b0819, 0x08190819), uvec2(0x192b1908, 0x08190819), + uvec2(0x2b080808, 0x08190819), uvec2(0x2b08082b, 0x08190819), uvec2(0x2b081919, 0x08190819), uvec2(0x2b082b08, 0x08190819), + uvec2(0x2b190819, 0x08190819), uvec2(0x2b191908, 0x08190819), uvec2(0x08080819, 0x0819082b), uvec2(0x08081908, 0x0819082b), + uvec2(0x08082b19, 0x0819082b), uvec2(0x08190808, 0x0819082b), uvec2(0x08191919, 0x0819082b), uvec2(0x082b0819, 0x0819082b), + uvec2(0x082b1908, 0x0819082b), uvec2(0x19080808, 0x0819082b), uvec2(0x19081919, 0x0819082b), uvec2(0x19190819, 0x0819082b), + uvec2(0x19191908, 0x0819082b), uvec2(0x2b080819, 0x0819082b), uvec2(0x2b081908, 0x0819082b), uvec2(0x2b190808, 0x0819082b), + uvec2(0x08080808, 0x08191908), uvec2(0x0808082b, 0x08191908), uvec2(0x08081919, 0x08191908), uvec2(0x08082b08, 0x08191908), + uvec2(0x08190819, 0x08191908), uvec2(0x08191908, 0x08191908), uvec2(0x0819192b, 0x08191908), uvec2(0x08192b19, 0x08191908), + uvec2(0x082b0808, 0x08191908), uvec2(0x082b1919, 0x08191908), uvec2(0x082b2b08, 0x08191908), uvec2(0x19080819, 0x08191908), + uvec2(0x19081908, 0x08191908), uvec2(0x1908192b, 0x08191908), uvec2(0x19082b19, 0x08191908), uvec2(0x19190808, 0x08191908), + uvec2(0x1919082b, 0x08191908), uvec2(0x19191919, 0x08191908), uvec2(0x19192b08, 0x08191908), uvec2(0x192b0819, 0x08191908), + uvec2(0x192b1908, 0x08191908), uvec2(0x2b080808, 0x08191908), uvec2(0x2b08082b, 0x08191908), uvec2(0x2b081919, 0x08191908), + uvec2(0x2b082b08, 0x08191908), uvec2(0x2b190819, 0x08191908), uvec2(0x2b191908, 0x08191908), uvec2(0x2b2b0808, 0x08191908), + uvec2(0x08080819, 0x08191919), uvec2(0x08081908, 0x08191919), uvec2(0x0808192b, 0x08191919), uvec2(0x08082b19, 0x08191919), + uvec2(0x08190808, 0x08191919), uvec2(0x0819082b, 0x08191919), uvec2(0x08191919, 0x08191919), uvec2(0x08192b08, 0x08191919), + uvec2(0x082b0819, 0x08191919), uvec2(0x082b1908, 0x08191919), uvec2(0x19080808, 0x08191919), uvec2(0x1908082b, 0x08191919), + uvec2(0x19081919, 0x08191919), uvec2(0x19082b08, 0x08191919), uvec2(0x19190819, 0x08191919), uvec2(0x19191908, 0x08191919), + uvec2(0x192b0808, 0x08191919), uvec2(0x2b080819, 0x08191919), uvec2(0x2b081908, 0x08191919), uvec2(0x2b190808, 0x08191919), + uvec2(0x08080808, 0x0819192b), uvec2(0x08081919, 0x0819192b), uvec2(0x08082b08, 0x0819192b), uvec2(0x08190819, 0x0819192b), + uvec2(0x08191908, 0x0819192b), uvec2(0x082b0808, 0x0819192b), uvec2(0x19080819, 0x0819192b), uvec2(0x19081908, 0x0819192b), + uvec2(0x19190808, 0x0819192b), uvec2(0x2b080808, 0x0819192b), uvec2(0x2b2b2b2b, 0x0819192b), uvec2(0x08080819, 0x08192b08), + uvec2(0x08081908, 0x08192b08), uvec2(0x0808192b, 0x08192b08), uvec2(0x08082b19, 0x08192b08), uvec2(0x08190808, 0x08192b08), + uvec2(0x08191919, 0x08192b08), uvec2(0x08192b08, 0x08192b08), uvec2(0x082b0819, 0x08192b08), uvec2(0x19080808, 0x08192b08), + uvec2(0x1908082b, 0x08192b08), uvec2(0x19081919, 0x08192b08), uvec2(0x19082b08, 0x08192b08), uvec2(0x19190819, 0x08192b08), + uvec2(0x19191908, 0x08192b08), uvec2(0x192b0808, 0x08192b08), uvec2(0x2b080819, 0x08192b08), uvec2(0x2b081908, 0x08192b08), + uvec2(0x08080808, 0x08192b19), uvec2(0x0808082b, 0x08192b19), uvec2(0x08081919, 0x08192b19), uvec2(0x08082b08, 0x08192b19), + uvec2(0x08190819, 0x08192b19), uvec2(0x08191908, 0x08192b19), uvec2(0x082b0808, 0x08192b19), uvec2(0x19080819, 0x08192b19), + uvec2(0x19081908, 0x08192b19), uvec2(0x19190808, 0x08192b19), uvec2(0x192b2b19, 0x08192b19), uvec2(0x2b2b082b, 0x08192b19), + uvec2(0x08081908, 0x08192b2b), uvec2(0x08190808, 0x08192b2b), uvec2(0x19080808, 0x08192b2b), uvec2(0x1919192b, 0x08192b2b), + uvec2(0x08080808, 0x082b0808), uvec2(0x0808082b, 0x082b0808), uvec2(0x08081919, 0x082b0808), uvec2(0x08082b08, 0x082b0808), + uvec2(0x08190819, 0x082b0808), uvec2(0x08191908, 0x082b0808), uvec2(0x0819192b, 0x082b0808), uvec2(0x08192b19, 0x082b0808), + uvec2(0x082b0808, 0x082b0808), uvec2(0x082b1919, 0x082b0808), uvec2(0x082b2b2b, 0x082b0808), uvec2(0x19080819, 0x082b0808), + uvec2(0x19081908, 0x082b0808), uvec2(0x19190808, 0x082b0808), uvec2(0x1919082b, 0x082b0808), uvec2(0x19191919, 0x082b0808), + uvec2(0x192b1908, 0x082b0808), uvec2(0x2b080808, 0x082b0808), uvec2(0x2b082b2b, 0x082b0808), uvec2(0x2b191908, 0x082b0808), + uvec2(0x2b2b2b2b, 0x082b0808), uvec2(0x08080819, 0x082b0819), uvec2(0x08081908, 0x082b0819), uvec2(0x08190808, 0x082b0819), + uvec2(0x0819082b, 0x082b0819), uvec2(0x08191919, 0x082b0819), uvec2(0x082b0819, 0x082b0819), uvec2(0x19080808, 0x082b0819), + uvec2(0x1908082b, 0x082b0819), uvec2(0x19081919, 0x082b0819), uvec2(0x19190819, 0x082b0819), uvec2(0x19191908, 0x082b0819), + uvec2(0x192b0808, 0x082b0819), uvec2(0x2b080819, 0x082b0819), uvec2(0x2b081908, 0x082b0819), uvec2(0x2b190808, 0x082b0819), + uvec2(0x08080808, 0x082b082b), uvec2(0x08082b2b, 0x082b082b), uvec2(0x082b082b, 0x082b082b), uvec2(0x082b2b08, 0x082b082b), + uvec2(0x082b2b2b, 0x082b082b), uvec2(0x19081908, 0x082b082b), uvec2(0x19190808, 0x082b082b), uvec2(0x2b082b08, 0x082b082b), + uvec2(0x2b082b2b, 0x082b082b), uvec2(0x2b2b2b08, 0x082b082b), uvec2(0x08080819, 0x082b1908), uvec2(0x08081908, 0x082b1908), + uvec2(0x0808192b, 0x082b1908), uvec2(0x08082b19, 0x082b1908), uvec2(0x08190808, 0x082b1908), uvec2(0x08191919, 0x082b1908), + uvec2(0x08192b08, 0x082b1908), uvec2(0x082b0819, 0x082b1908), uvec2(0x082b1908, 0x082b1908), uvec2(0x19080808, 0x082b1908), + uvec2(0x1908082b, 0x082b1908), uvec2(0x19081919, 0x082b1908), uvec2(0x19082b08, 0x082b1908), uvec2(0x19190819, 0x082b1908), + uvec2(0x19191908, 0x082b1908), uvec2(0x192b0808, 0x082b1908), uvec2(0x2b080819, 0x082b1908), uvec2(0x2b081908, 0x082b1908), + uvec2(0x2b190808, 0x082b1908), uvec2(0x08080808, 0x082b1919), uvec2(0x08081919, 0x082b1919), uvec2(0x08082b08, 0x082b1919), + uvec2(0x08190819, 0x082b1919), uvec2(0x08191908, 0x082b1919), uvec2(0x082b0808, 0x082b1919), uvec2(0x19080819, 0x082b1919), + uvec2(0x19081908, 0x082b1919), uvec2(0x19190808, 0x082b1919), uvec2(0x192b192b, 0x082b1919), uvec2(0x2b080808, 0x082b1919), + uvec2(0x08080819, 0x082b192b), uvec2(0x08081908, 0x082b192b), uvec2(0x08190808, 0x082b192b), uvec2(0x19080808, 0x082b192b), + uvec2(0x19192b19, 0x082b192b), uvec2(0x08080808, 0x082b2b08), uvec2(0x08081919, 0x082b2b08), uvec2(0x08190819, 0x082b2b08), + uvec2(0x08191908, 0x082b2b08), uvec2(0x19080819, 0x082b2b08), uvec2(0x19081908, 0x082b2b08), uvec2(0x19190808, 0x082b2b08), + uvec2(0x2b082b2b, 0x082b2b08), uvec2(0x2b2b2b2b, 0x082b2b08), uvec2(0x08080819, 0x082b2b19), uvec2(0x08081908, 0x082b2b19), + uvec2(0x08190808, 0x082b2b19), uvec2(0x2b191919, 0x082b2b19), uvec2(0x08082b2b, 0x082b2b2b), uvec2(0x082b082b, 0x082b2b2b), + uvec2(0x192b1908, 0x082b2b2b), uvec2(0x2b082b08, 0x082b2b2b), uvec2(0x2b082b2b, 0x082b2b2b), uvec2(0x08080819, 0x19080808), + uvec2(0x08081908, 0x19080808), uvec2(0x0808192b, 0x19080808), uvec2(0x08082b19, 0x19080808), uvec2(0x08190808, 0x19080808), + uvec2(0x0819082b, 0x19080808), uvec2(0x08191919, 0x19080808), uvec2(0x08192b08, 0x19080808), uvec2(0x08192b2b, 0x19080808), + uvec2(0x082b0819, 0x19080808), uvec2(0x082b1908, 0x19080808), uvec2(0x082b192b, 0x19080808), uvec2(0x19080808, 0x19080808), + uvec2(0x1908082b, 0x19080808), uvec2(0x19081919, 0x19080808), uvec2(0x19082b08, 0x19080808), uvec2(0x19082b2b, 0x19080808), + uvec2(0x19190819, 0x19080808), uvec2(0x19191908, 0x19080808), uvec2(0x1919192b, 0x19080808), uvec2(0x19192b19, 0x19080808), + uvec2(0x192b0808, 0x19080808), uvec2(0x192b082b, 0x19080808), uvec2(0x192b1919, 0x19080808), uvec2(0x2b080819, 0x19080808), + uvec2(0x2b081908, 0x19080808), uvec2(0x2b190808, 0x19080808), uvec2(0x2b191919, 0x19080808), uvec2(0x2b192b08, 0x19080808), + uvec2(0x2b2b0819, 0x19080808), uvec2(0x2b2b1908, 0x19080808), uvec2(0x08080808, 0x19080819), uvec2(0x0808082b, 0x19080819), + uvec2(0x08081919, 0x19080819), uvec2(0x08082b08, 0x19080819), uvec2(0x08190819, 0x19080819), uvec2(0x08191908, 0x19080819), + uvec2(0x0819192b, 0x19080819), uvec2(0x08192b19, 0x19080819), uvec2(0x082b0808, 0x19080819), uvec2(0x082b082b, 0x19080819), + uvec2(0x082b1919, 0x19080819), uvec2(0x19080819, 0x19080819), uvec2(0x19081908, 0x19080819), uvec2(0x1908192b, 0x19080819), + uvec2(0x19082b19, 0x19080819), uvec2(0x19190808, 0x19080819), uvec2(0x1919082b, 0x19080819), uvec2(0x19191919, 0x19080819), + uvec2(0x19192b08, 0x19080819), uvec2(0x192b0819, 0x19080819), uvec2(0x192b1908, 0x19080819), uvec2(0x2b080808, 0x19080819), + uvec2(0x2b08082b, 0x19080819), uvec2(0x2b081919, 0x19080819), uvec2(0x2b082b08, 0x19080819), uvec2(0x2b190819, 0x19080819), + uvec2(0x2b191908, 0x19080819), uvec2(0x2b2b0808, 0x19080819), uvec2(0x08080819, 0x1908082b), uvec2(0x08081908, 0x1908082b), + uvec2(0x08190808, 0x1908082b), uvec2(0x0819082b, 0x1908082b), uvec2(0x08191919, 0x1908082b), uvec2(0x08192b08, 0x1908082b), + uvec2(0x082b1908, 0x1908082b), uvec2(0x19080808, 0x1908082b), uvec2(0x19081919, 0x1908082b), uvec2(0x19082b08, 0x1908082b), + uvec2(0x19190819, 0x1908082b), uvec2(0x19191908, 0x1908082b), uvec2(0x192b0808, 0x1908082b), uvec2(0x2b080819, 0x1908082b), + uvec2(0x2b081908, 0x1908082b), uvec2(0x08080808, 0x19081908), uvec2(0x0808082b, 0x19081908), uvec2(0x08081919, 0x19081908), + uvec2(0x08082b08, 0x19081908), uvec2(0x08082b2b, 0x19081908), uvec2(0x08190819, 0x19081908), uvec2(0x08191908, 0x19081908), + uvec2(0x0819192b, 0x19081908), uvec2(0x08192b19, 0x19081908), uvec2(0x082b0808, 0x19081908), uvec2(0x082b082b, 0x19081908), + uvec2(0x082b1919, 0x19081908), uvec2(0x082b2b08, 0x19081908), uvec2(0x19080819, 0x19081908), uvec2(0x19081908, 0x19081908), + uvec2(0x1908192b, 0x19081908), uvec2(0x19082b19, 0x19081908), uvec2(0x19190808, 0x19081908), uvec2(0x1919082b, 0x19081908), + uvec2(0x19191919, 0x19081908), uvec2(0x19192b08, 0x19081908), uvec2(0x192b0819, 0x19081908), uvec2(0x192b1908, 0x19081908), + uvec2(0x2b080808, 0x19081908), uvec2(0x2b08082b, 0x19081908), uvec2(0x2b081919, 0x19081908), uvec2(0x2b082b08, 0x19081908), + uvec2(0x2b190819, 0x19081908), uvec2(0x2b191908, 0x19081908), uvec2(0x2b2b0808, 0x19081908), uvec2(0x08080819, 0x19081919), + uvec2(0x08081908, 0x19081919), uvec2(0x0808192b, 0x19081919), uvec2(0x08082b19, 0x19081919), uvec2(0x08190808, 0x19081919), + uvec2(0x0819082b, 0x19081919), uvec2(0x08191919, 0x19081919), uvec2(0x08192b08, 0x19081919), uvec2(0x082b0819, 0x19081919), + uvec2(0x082b1908, 0x19081919), uvec2(0x19080808, 0x19081919), uvec2(0x1908082b, 0x19081919), uvec2(0x19081919, 0x19081919), + uvec2(0x19082b08, 0x19081919), uvec2(0x19190819, 0x19081919), uvec2(0x19191908, 0x19081919), uvec2(0x192b0808, 0x19081919), + uvec2(0x192b2b2b, 0x19081919), uvec2(0x2b080819, 0x19081919), uvec2(0x2b081908, 0x19081919), uvec2(0x2b190808, 0x19081919), + uvec2(0x08080808, 0x1908192b), uvec2(0x0808082b, 0x1908192b), uvec2(0x08081919, 0x1908192b), uvec2(0x08082b08, 0x1908192b), + uvec2(0x08190819, 0x1908192b), uvec2(0x08191908, 0x1908192b), uvec2(0x082b0808, 0x1908192b), uvec2(0x19080819, 0x1908192b), + uvec2(0x19081908, 0x1908192b), uvec2(0x19190808, 0x1908192b), uvec2(0x2b080808, 0x1908192b), uvec2(0x2b2b1919, 0x1908192b), + uvec2(0x08080819, 0x19082b08), uvec2(0x08081908, 0x19082b08), uvec2(0x08082b19, 0x19082b08), uvec2(0x08190808, 0x19082b08), + uvec2(0x0819082b, 0x19082b08), uvec2(0x08191919, 0x19082b08), uvec2(0x08192b08, 0x19082b08), uvec2(0x082b0819, 0x19082b08), + uvec2(0x082b1908, 0x19082b08), uvec2(0x19080808, 0x19082b08), uvec2(0x1908082b, 0x19082b08), uvec2(0x19081919, 0x19082b08), + uvec2(0x19082b08, 0x19082b08), uvec2(0x19190819, 0x19082b08), uvec2(0x19191908, 0x19082b08), uvec2(0x192b0808, 0x19082b08), + uvec2(0x2b081908, 0x19082b08), uvec2(0x2b190808, 0x19082b08), uvec2(0x08080808, 0x19082b19), uvec2(0x0808082b, 0x19082b19), + uvec2(0x08081919, 0x19082b19), uvec2(0x08082b08, 0x19082b19), uvec2(0x08190819, 0x19082b19), uvec2(0x08191908, 0x19082b19), + uvec2(0x082b0808, 0x19082b19), uvec2(0x19080819, 0x19082b19), uvec2(0x19081908, 0x19082b19), uvec2(0x19190808, 0x19082b19), + uvec2(0x2b080808, 0x19082b19), uvec2(0x2b19192b, 0x19082b19), uvec2(0x08080819, 0x19082b2b), uvec2(0x08081908, 0x19082b2b), + uvec2(0x08190808, 0x19082b2b), uvec2(0x19080808, 0x19082b2b), uvec2(0x08080808, 0x19190808), uvec2(0x0808082b, 0x19190808), + uvec2(0x08081919, 0x19190808), uvec2(0x08082b08, 0x19190808), uvec2(0x08190819, 0x19190808), uvec2(0x08191908, 0x19190808), + uvec2(0x0819192b, 0x19190808), uvec2(0x08192b19, 0x19190808), uvec2(0x082b0808, 0x19190808), uvec2(0x082b082b, 0x19190808), + uvec2(0x082b1919, 0x19190808), uvec2(0x082b2b08, 0x19190808), uvec2(0x19080819, 0x19190808), uvec2(0x19081908, 0x19190808), + uvec2(0x1908192b, 0x19190808), uvec2(0x19082b19, 0x19190808), uvec2(0x19190808, 0x19190808), uvec2(0x1919082b, 0x19190808), + uvec2(0x19191919, 0x19190808), uvec2(0x19192b08, 0x19190808), uvec2(0x192b0819, 0x19190808), uvec2(0x192b1908, 0x19190808), + uvec2(0x2b080808, 0x19190808), uvec2(0x2b08082b, 0x19190808), uvec2(0x2b081919, 0x19190808), uvec2(0x2b082b08, 0x19190808), + uvec2(0x2b190819, 0x19190808), uvec2(0x2b191908, 0x19190808), uvec2(0x08080819, 0x19190819), uvec2(0x08081908, 0x19190819), + uvec2(0x0808192b, 0x19190819), uvec2(0x08082b19, 0x19190819), uvec2(0x08190808, 0x19190819), uvec2(0x0819082b, 0x19190819), + uvec2(0x08191919, 0x19190819), uvec2(0x08192b08, 0x19190819), uvec2(0x082b0819, 0x19190819), uvec2(0x082b1908, 0x19190819), + uvec2(0x19080808, 0x19190819), uvec2(0x1908082b, 0x19190819), uvec2(0x19081919, 0x19190819), uvec2(0x19082b08, 0x19190819), + uvec2(0x19190819, 0x19190819), uvec2(0x19191908, 0x19190819), uvec2(0x192b0808, 0x19190819), uvec2(0x2b080819, 0x19190819), + uvec2(0x2b081908, 0x19190819), uvec2(0x2b190808, 0x19190819), uvec2(0x08080808, 0x1919082b), uvec2(0x08081919, 0x1919082b), + uvec2(0x08082b08, 0x1919082b), uvec2(0x08190819, 0x1919082b), uvec2(0x08191908, 0x1919082b), uvec2(0x082b0808, 0x1919082b), + uvec2(0x19080819, 0x1919082b), uvec2(0x19081908, 0x1919082b), uvec2(0x19190808, 0x1919082b), uvec2(0x192b2b19, 0x1919082b), + uvec2(0x2b080808, 0x1919082b), uvec2(0x08080819, 0x19191908), uvec2(0x08081908, 0x19191908), uvec2(0x0808192b, 0x19191908), + uvec2(0x08082b19, 0x19191908), uvec2(0x08190808, 0x19191908), uvec2(0x0819082b, 0x19191908), uvec2(0x08191919, 0x19191908), + uvec2(0x08192b08, 0x19191908), uvec2(0x082b0819, 0x19191908), uvec2(0x082b1908, 0x19191908), uvec2(0x19080808, 0x19191908), + uvec2(0x1908082b, 0x19191908), uvec2(0x19081919, 0x19191908), uvec2(0x19082b08, 0x19191908), uvec2(0x19190819, 0x19191908), + uvec2(0x19191908, 0x19191908), uvec2(0x192b0808, 0x19191908), uvec2(0x2b080819, 0x19191908), uvec2(0x2b081908, 0x19191908), + uvec2(0x2b190808, 0x19191908), uvec2(0x08080808, 0x19191919), uvec2(0x0808082b, 0x19191919), uvec2(0x08081919, 0x19191919), + uvec2(0x08082b08, 0x19191919), uvec2(0x08190819, 0x19191919), uvec2(0x08191908, 0x19191919), uvec2(0x082b0808, 0x19191919), + uvec2(0x19080819, 0x19191919), uvec2(0x19081908, 0x19191919), uvec2(0x19190808, 0x19191919), uvec2(0x2b080808, 0x19191919), + uvec2(0x08080819, 0x1919192b), uvec2(0x08081908, 0x1919192b), uvec2(0x08190808, 0x1919192b), uvec2(0x082b192b, 0x1919192b), + uvec2(0x19080808, 0x1919192b), uvec2(0x08080808, 0x19192b08), uvec2(0x0808082b, 0x19192b08), uvec2(0x08081919, 0x19192b08), + uvec2(0x08082b08, 0x19192b08), uvec2(0x08190819, 0x19192b08), uvec2(0x08191908, 0x19192b08), uvec2(0x082b0808, 0x19192b08), + uvec2(0x19080819, 0x19192b08), uvec2(0x19081908, 0x19192b08), uvec2(0x19190808, 0x19192b08), uvec2(0x19192b2b, 0x19192b08), + uvec2(0x2b080808, 0x19192b08), uvec2(0x08080819, 0x19192b19), uvec2(0x08081908, 0x19192b19), uvec2(0x08190808, 0x19192b19), + uvec2(0x19080808, 0x19192b19), uvec2(0x08080808, 0x19192b2b), uvec2(0x08192b19, 0x19192b2b), uvec2(0x2b081919, 0x19192b2b), + uvec2(0x2b2b2b08, 0x19192b2b), uvec2(0x08080819, 0x192b0808), uvec2(0x08081908, 0x192b0808), uvec2(0x0808192b, 0x192b0808), + uvec2(0x08190808, 0x192b0808), uvec2(0x0819082b, 0x192b0808), uvec2(0x08191919, 0x192b0808), uvec2(0x08192b08, 0x192b0808), + uvec2(0x082b0819, 0x192b0808), uvec2(0x082b1908, 0x192b0808), uvec2(0x19080808, 0x192b0808), uvec2(0x19081919, 0x192b0808), + uvec2(0x19082b08, 0x192b0808), uvec2(0x19190819, 0x192b0808), uvec2(0x19191908, 0x192b0808), uvec2(0x192b0808, 0x192b0808), + uvec2(0x2b081908, 0x192b0808), uvec2(0x2b190808, 0x192b0808), uvec2(0x08080808, 0x192b0819), uvec2(0x0808082b, 0x192b0819), + uvec2(0x08081919, 0x192b0819), uvec2(0x08082b08, 0x192b0819), uvec2(0x08190819, 0x192b0819), uvec2(0x08191908, 0x192b0819), + uvec2(0x082b0808, 0x192b0819), uvec2(0x19080819, 0x192b0819), uvec2(0x19081908, 0x192b0819), uvec2(0x19190808, 0x192b0819), + uvec2(0x2b080808, 0x192b0819), uvec2(0x2b192b19, 0x192b0819), uvec2(0x08081908, 0x192b082b), uvec2(0x08190808, 0x192b082b), + uvec2(0x19080808, 0x192b082b), uvec2(0x1919192b, 0x192b082b), uvec2(0x2b2b0819, 0x192b082b), uvec2(0x08080808, 0x192b1908), + uvec2(0x08081919, 0x192b1908), uvec2(0x08082b08, 0x192b1908), uvec2(0x08190819, 0x192b1908), uvec2(0x08191908, 0x192b1908), + uvec2(0x082b0808, 0x192b1908), uvec2(0x19080819, 0x192b1908), uvec2(0x19081908, 0x192b1908), uvec2(0x19190808, 0x192b1908), + uvec2(0x2b080808, 0x192b1908), uvec2(0x08080819, 0x192b1919), uvec2(0x08081908, 0x192b1919), uvec2(0x08190808, 0x192b1919), + uvec2(0x19080808, 0x192b1919), uvec2(0x19082b2b, 0x192b1919), uvec2(0x192b2b08, 0x192b1919), uvec2(0x2b19082b, 0x192b1919), + uvec2(0x08080808, 0x192b192b), uvec2(0x2b191908, 0x192b192b), uvec2(0x08080819, 0x192b2b08), uvec2(0x08081908, 0x192b2b08), + uvec2(0x08190808, 0x192b2b08), uvec2(0x192b1919, 0x192b2b08), uvec2(0x2b192b08, 0x192b2b08), uvec2(0x08080808, 0x192b2b19), + uvec2(0x082b2b2b, 0x192b2b19), uvec2(0x1908082b, 0x192b2b2b), uvec2(0x2b2b0819, 0x192b2b2b), uvec2(0x08080808, 0x2b080808), + uvec2(0x0808082b, 0x2b080808), uvec2(0x08081919, 0x2b080808), uvec2(0x08082b08, 0x2b080808), uvec2(0x08190819, 0x2b080808), + uvec2(0x08191908, 0x2b080808), uvec2(0x08192b19, 0x2b080808), uvec2(0x082b0808, 0x2b080808), uvec2(0x082b1919, 0x2b080808), + uvec2(0x19080819, 0x2b080808), uvec2(0x19081908, 0x2b080808), uvec2(0x19190808, 0x2b080808), uvec2(0x1919082b, 0x2b080808), + uvec2(0x19191919, 0x2b080808), uvec2(0x19192b08, 0x2b080808), uvec2(0x192b0819, 0x2b080808), uvec2(0x2b080808, 0x2b080808), + uvec2(0x2b081919, 0x2b080808), uvec2(0x2b190819, 0x2b080808), uvec2(0x2b191908, 0x2b080808), uvec2(0x08080819, 0x2b080819), + uvec2(0x08081908, 0x2b080819), uvec2(0x08082b19, 0x2b080819), uvec2(0x08190808, 0x2b080819), uvec2(0x0819082b, 0x2b080819), + uvec2(0x08191919, 0x2b080819), uvec2(0x08192b08, 0x2b080819), uvec2(0x082b0819, 0x2b080819), uvec2(0x082b1908, 0x2b080819), + uvec2(0x19080808, 0x2b080819), uvec2(0x1908082b, 0x2b080819), uvec2(0x19081919, 0x2b080819), uvec2(0x19082b08, 0x2b080819), + uvec2(0x19190819, 0x2b080819), uvec2(0x19191908, 0x2b080819), uvec2(0x2b080819, 0x2b080819), uvec2(0x2b081908, 0x2b080819), + uvec2(0x2b190808, 0x2b080819), uvec2(0x2b2b2b19, 0x2b080819), uvec2(0x08080808, 0x2b08082b), uvec2(0x08081919, 0x2b08082b), + uvec2(0x08082b2b, 0x2b08082b), uvec2(0x08190819, 0x2b08082b), uvec2(0x08191908, 0x2b08082b), uvec2(0x19080819, 0x2b08082b), + uvec2(0x19081908, 0x2b08082b), uvec2(0x19190808, 0x2b08082b), uvec2(0x08080819, 0x2b081908), uvec2(0x08081908, 0x2b081908), + uvec2(0x0808192b, 0x2b081908), uvec2(0x08082b19, 0x2b081908), uvec2(0x08190808, 0x2b081908), uvec2(0x0819082b, 0x2b081908), + uvec2(0x08191919, 0x2b081908), uvec2(0x08192b08, 0x2b081908), uvec2(0x082b0819, 0x2b081908), uvec2(0x19080808, 0x2b081908), + uvec2(0x1908082b, 0x2b081908), uvec2(0x19081919, 0x2b081908), uvec2(0x19082b08, 0x2b081908), uvec2(0x19190819, 0x2b081908), + uvec2(0x19191908, 0x2b081908), uvec2(0x192b0808, 0x2b081908), uvec2(0x2b080819, 0x2b081908), uvec2(0x2b081908, 0x2b081908), + uvec2(0x2b190808, 0x2b081908), uvec2(0x08080808, 0x2b081919), uvec2(0x0808082b, 0x2b081919), uvec2(0x08081919, 0x2b081919), + uvec2(0x08082b08, 0x2b081919), uvec2(0x08190819, 0x2b081919), uvec2(0x08191908, 0x2b081919), uvec2(0x082b0808, 0x2b081919), + uvec2(0x19080819, 0x2b081919), uvec2(0x19081908, 0x2b081919), uvec2(0x19190808, 0x2b081919), uvec2(0x2b080808, 0x2b081919), + uvec2(0x2b082b2b, 0x2b081919), uvec2(0x08080819, 0x2b08192b), uvec2(0x08081908, 0x2b08192b), uvec2(0x08190808, 0x2b08192b), + uvec2(0x082b2b19, 0x2b08192b), uvec2(0x19080808, 0x2b08192b), uvec2(0x08080808, 0x2b082b08), uvec2(0x08081919, 0x2b082b08), + uvec2(0x08190819, 0x2b082b08), uvec2(0x08191908, 0x2b082b08), uvec2(0x19080819, 0x2b082b08), uvec2(0x19081908, 0x2b082b08), + uvec2(0x19190808, 0x2b082b08), uvec2(0x2b2b082b, 0x2b082b08), uvec2(0x08080819, 0x2b082b19), uvec2(0x08081908, 0x2b082b19), + uvec2(0x19080808, 0x2b082b19), uvec2(0x192b1919, 0x2b082b19), uvec2(0x082b082b, 0x2b082b2b), uvec2(0x19192b08, 0x2b082b2b), + uvec2(0x19192b2b, 0x2b082b2b), uvec2(0x2b08082b, 0x2b082b2b), uvec2(0x2b2b082b, 0x2b082b2b), uvec2(0x08080819, 0x2b190808), + uvec2(0x08081908, 0x2b190808), uvec2(0x08082b19, 0x2b190808), uvec2(0x08190808, 0x2b190808), uvec2(0x0819082b, 0x2b190808), + uvec2(0x08191919, 0x2b190808), uvec2(0x08192b08, 0x2b190808), uvec2(0x082b1908, 0x2b190808), uvec2(0x19080808, 0x2b190808), + uvec2(0x1908082b, 0x2b190808), uvec2(0x19081919, 0x2b190808), uvec2(0x19082b08, 0x2b190808), uvec2(0x19190819, 0x2b190808), + uvec2(0x19191908, 0x2b190808), uvec2(0x192b0808, 0x2b190808), uvec2(0x2b080819, 0x2b190808), uvec2(0x2b081908, 0x2b190808), + uvec2(0x2b190808, 0x2b190808), uvec2(0x08080808, 0x2b190819), uvec2(0x08081919, 0x2b190819), uvec2(0x08190819, 0x2b190819), + uvec2(0x08191908, 0x2b190819), uvec2(0x19080819, 0x2b190819), uvec2(0x19081908, 0x2b190819), uvec2(0x19190808, 0x2b190819), + uvec2(0x19192b2b, 0x2b190819), uvec2(0x08080819, 0x2b19082b), uvec2(0x08081908, 0x2b19082b), uvec2(0x08190808, 0x2b19082b), + uvec2(0x19080808, 0x2b19082b), uvec2(0x2b2b192b, 0x2b19082b), uvec2(0x08080808, 0x2b191908), uvec2(0x0808082b, 0x2b191908), + uvec2(0x08081919, 0x2b191908), uvec2(0x08082b08, 0x2b191908), uvec2(0x08190819, 0x2b191908), uvec2(0x08191908, 0x2b191908), + uvec2(0x082b0808, 0x2b191908), uvec2(0x19080819, 0x2b191908), uvec2(0x19081908, 0x2b191908), uvec2(0x19190808, 0x2b191908), + uvec2(0x2b080808, 0x2b191908), uvec2(0x2b19192b, 0x2b191908), uvec2(0x08080819, 0x2b191919), uvec2(0x08081908, 0x2b191919), + uvec2(0x08190808, 0x2b191919), uvec2(0x19080808, 0x2b191919), uvec2(0x2b192b08, 0x2b191919), uvec2(0x2b2b0819, 0x2b191919), + uvec2(0x08080808, 0x2b19192b), uvec2(0x1908192b, 0x2b19192b), uvec2(0x192b1908, 0x2b19192b), uvec2(0x08080819, 0x2b192b08), + uvec2(0x08081908, 0x2b192b08), uvec2(0x08190808, 0x2b192b08), uvec2(0x082b192b, 0x2b192b08), uvec2(0x19080808, 0x2b192b08), + uvec2(0x2b2b2b19, 0x2b192b08), uvec2(0x08080808, 0x2b192b19), uvec2(0x19082b19, 0x2b192b19), uvec2(0x1919082b, 0x2b192b19), + uvec2(0x2b190808, 0x2b192b2b), uvec2(0x08080808, 0x2b2b0808), uvec2(0x08081919, 0x2b2b0808), uvec2(0x08082b2b, 0x2b2b0808), + uvec2(0x08191908, 0x2b2b0808), uvec2(0x082b082b, 0x2b2b0808), uvec2(0x082b2b2b, 0x2b2b0808), uvec2(0x19080819, 0x2b2b0808), + uvec2(0x19081908, 0x2b2b0808), uvec2(0x19190808, 0x2b2b0808), uvec2(0x2b2b082b, 0x2b2b0808), uvec2(0x2b2b2b2b, 0x2b2b0808), + uvec2(0x19080808, 0x2b2b0819), uvec2(0x192b1919, 0x2b2b0819), uvec2(0x0808082b, 0x2b2b082b), uvec2(0x08082b2b, 0x2b2b082b), + uvec2(0x082b082b, 0x2b2b082b), uvec2(0x082b2b08, 0x2b2b082b), uvec2(0x082b2b2b, 0x2b2b082b), uvec2(0x2b08082b, 0x2b2b082b), + uvec2(0x2b082b08, 0x2b2b082b), uvec2(0x2b082b2b, 0x2b2b082b), uvec2(0x2b2b2b08, 0x2b2b082b), uvec2(0x08080819, 0x2b2b1908), + uvec2(0x08081908, 0x2b2b1908), uvec2(0x08190808, 0x2b2b1908), uvec2(0x19080808, 0x2b2b1908), uvec2(0x2b082b19, 0x2b2b1908), + uvec2(0x2b2b1908, 0x2b2b1908), uvec2(0x08080808, 0x2b2b1919), uvec2(0x08192b19, 0x2b2b1919), uvec2(0x19190819, 0x2b2b192b), + uvec2(0x08082b2b, 0x2b2b2b08), uvec2(0x082b2b08, 0x2b2b2b08), uvec2(0x2b2b082b, 0x2b2b2b08), uvec2(0x19191908, 0x2b2b2b19), + uvec2(0x2b08192b, 0x2b2b2b19), uvec2(0x08082b08, 0x2b2b2b2b), uvec2(0x08082b2b, 0x2b2b2b2b), uvec2(0x082b0808, 0x2b2b2b2b), + uvec2(0x082b082b, 0x2b2b2b2b), uvec2(0x082b2b08, 0x2b2b2b2b), uvec2(0x2b082b08, 0x2b2b2b2b), uvec2(0x2b2b2b2b, 0x2b2b2b2b) +}; + +shared uvec2 iq2s_grid[1024]; + +#define NEEDS_INIT_IQ_SHMEM +void init_iq_shmem(uvec3 wgsize) +{ + // copy the table into shared memory and sync + [[unroll]] for (uint i = 0; i < iq2s_grid.length(); i += wgsize.x) { + if (iq2s_grid.length() % wgsize.x == 0 || i + gl_LocalInvocationIndex.x < iq2s_grid_const.length()) { + iq2s_grid[i + gl_LocalInvocationIndex.x] = iq2s_grid_const[i + gl_LocalInvocationIndex.x]; + } + } + barrier(); +} + +#define QUANT_K QUANT_K_IQ2_S +#define QUANT_R QUANT_R_IQ2_S +#define A_TYPE block_iq2_s +#define A_TYPE_PACKED16 block_iq2_s_packed16 +#endif + +#define QUANT_K_IQ3_XXS 256 +#define QUANT_R_IQ3_XXS 1 + +struct block_iq3_xxs +{ + float16_t d; + uint8_t qs[QUANT_K_IQ3_XXS/4 + QUANT_K_IQ3_XXS/8]; +}; + +struct block_iq3_xxs_packed16 +{ + float16_t d; + uint16_t qs[QUANT_K_IQ3_XXS/8 + QUANT_K_IQ3_XXS/16]; +}; + +#if defined(DATA_A_IQ3_XXS) + +const uint32_t iq3xxs_grid_const[256] = { + 0x04040404, 0x04040414, 0x04040424, 0x04040c0c, 0x04040c1c, 0x04040c3e, 0x04041404, 0x04041414, + 0x04041c0c, 0x04042414, 0x04043e1c, 0x04043e2c, 0x040c040c, 0x040c041c, 0x040c0c04, 0x040c0c14, + 0x040c140c, 0x040c142c, 0x040c1c04, 0x040c1c14, 0x040c240c, 0x040c2c24, 0x040c3e04, 0x04140404, + 0x04140414, 0x04140424, 0x04140c0c, 0x04141404, 0x04141414, 0x04141c0c, 0x04141c1c, 0x04141c3e, + 0x04142c0c, 0x04142c3e, 0x04143e2c, 0x041c040c, 0x041c043e, 0x041c0c04, 0x041c0c14, 0x041c142c, + 0x041c3e04, 0x04240c1c, 0x04241c3e, 0x04242424, 0x04242c3e, 0x04243e1c, 0x04243e2c, 0x042c040c, + 0x042c043e, 0x042c1c14, 0x042c2c14, 0x04341c2c, 0x04343424, 0x043e0c04, 0x043e0c24, 0x043e0c34, + 0x043e241c, 0x043e340c, 0x0c04040c, 0x0c04041c, 0x0c040c04, 0x0c040c14, 0x0c04140c, 0x0c04141c, + 0x0c041c04, 0x0c041c14, 0x0c041c24, 0x0c04243e, 0x0c042c04, 0x0c0c0404, 0x0c0c0414, 0x0c0c0c0c, + 0x0c0c1404, 0x0c0c1414, 0x0c14040c, 0x0c14041c, 0x0c140c04, 0x0c140c14, 0x0c14140c, 0x0c141c04, + 0x0c143e14, 0x0c1c0404, 0x0c1c0414, 0x0c1c1404, 0x0c1c1c0c, 0x0c1c2434, 0x0c1c3434, 0x0c24040c, + 0x0c24042c, 0x0c242c04, 0x0c2c1404, 0x0c2c1424, 0x0c2c2434, 0x0c2c3e0c, 0x0c34042c, 0x0c3e1414, + 0x0c3e2404, 0x14040404, 0x14040414, 0x14040c0c, 0x14040c1c, 0x14041404, 0x14041414, 0x14041434, + 0x14041c0c, 0x14042414, 0x140c040c, 0x140c041c, 0x140c042c, 0x140c0c04, 0x140c0c14, 0x140c140c, + 0x140c1c04, 0x140c341c, 0x140c343e, 0x140c3e04, 0x14140404, 0x14140414, 0x14140c0c, 0x14140c3e, + 0x14141404, 0x14141414, 0x14141c3e, 0x14142404, 0x14142c2c, 0x141c040c, 0x141c0c04, 0x141c0c24, + 0x141c3e04, 0x141c3e24, 0x14241c2c, 0x14242c1c, 0x142c041c, 0x142c143e, 0x142c240c, 0x142c3e24, + 0x143e040c, 0x143e041c, 0x143e0c34, 0x143e242c, 0x1c04040c, 0x1c040c04, 0x1c040c14, 0x1c04140c, + 0x1c04141c, 0x1c042c04, 0x1c04342c, 0x1c043e14, 0x1c0c0404, 0x1c0c0414, 0x1c0c1404, 0x1c0c1c0c, + 0x1c0c2424, 0x1c0c2434, 0x1c14040c, 0x1c14041c, 0x1c140c04, 0x1c14142c, 0x1c142c14, 0x1c143e14, + 0x1c1c0c0c, 0x1c1c1c1c, 0x1c241c04, 0x1c24243e, 0x1c243e14, 0x1c2c0404, 0x1c2c0434, 0x1c2c1414, + 0x1c2c2c2c, 0x1c340c24, 0x1c341c34, 0x1c34341c, 0x1c3e1c1c, 0x1c3e3404, 0x24040424, 0x24040c3e, + 0x24041c2c, 0x24041c3e, 0x24042c1c, 0x24042c3e, 0x240c3e24, 0x24141404, 0x24141c3e, 0x24142404, + 0x24143404, 0x24143434, 0x241c043e, 0x241c242c, 0x24240424, 0x24242c0c, 0x24243424, 0x242c142c, + 0x242c241c, 0x242c3e04, 0x243e042c, 0x243e0c04, 0x243e0c14, 0x243e1c04, 0x2c040c14, 0x2c04240c, + 0x2c043e04, 0x2c0c0404, 0x2c0c0434, 0x2c0c1434, 0x2c0c2c2c, 0x2c140c24, 0x2c141c14, 0x2c143e14, + 0x2c1c0414, 0x2c1c2c1c, 0x2c240c04, 0x2c24141c, 0x2c24143e, 0x2c243e14, 0x2c2c0414, 0x2c2c1c0c, + 0x2c342c04, 0x2c3e1424, 0x2c3e2414, 0x34041424, 0x34042424, 0x34042434, 0x34043424, 0x340c140c, + 0x340c340c, 0x34140c3e, 0x34143424, 0x341c1c04, 0x341c1c34, 0x34242424, 0x342c042c, 0x342c2c14, + 0x34341c1c, 0x343e041c, 0x343e140c, 0x3e04041c, 0x3e04042c, 0x3e04043e, 0x3e040c04, 0x3e041c14, + 0x3e042c14, 0x3e0c1434, 0x3e0c2404, 0x3e140c14, 0x3e14242c, 0x3e142c14, 0x3e1c0404, 0x3e1c0c2c, + 0x3e1c1c1c, 0x3e1c3404, 0x3e24140c, 0x3e24240c, 0x3e2c0404, 0x3e2c0414, 0x3e2c1424, 0x3e341c04, +}; + +shared uint32_t iq3xxs_grid[256]; + +#define NEEDS_INIT_IQ_SHMEM +void init_iq_shmem(uvec3 wgsize) +{ + // copy the table into shared memory and sync + [[unroll]] for (uint i = 0; i < iq3xxs_grid.length(); i += wgsize.x) { + if (iq3xxs_grid.length() % wgsize.x == 0 || i + gl_LocalInvocationIndex.x < iq3xxs_grid.length()) { + iq3xxs_grid[i + gl_LocalInvocationIndex.x] = iq3xxs_grid_const[i + gl_LocalInvocationIndex.x]; + } + } + barrier(); +} + +#define QUANT_K QUANT_K_IQ3_XXS +#define QUANT_R QUANT_R_IQ3_XXS +#define A_TYPE block_iq3_xxs +#define A_TYPE_PACKED16 block_iq3_xxs_packed16 +#endif + +#define QUANT_K_IQ3_S 256 +#define QUANT_R_IQ3_S 1 + +struct block_iq3_s +{ + float16_t d; + uint8_t qs[QUANT_K_IQ3_S/4]; + uint8_t qh[QUANT_K_IQ3_S/32]; + uint8_t signs[QUANT_K_IQ3_S/8]; + uint8_t scales[QUANT_K_IQ3_S/64]; +}; + +struct block_iq3_s_packed16 +{ + float16_t d; + uint16_t qs[QUANT_K_IQ3_S/4/2]; + uint16_t qh[QUANT_K_IQ3_S/32/2]; + uint16_t signs[QUANT_K_IQ3_S/8/2]; + uint16_t scales[QUANT_K_IQ3_S/64/2]; +}; + +#if defined(DATA_A_IQ3_S) + +const uint32_t iq3s_grid_const[512] = { + 0x01010101, 0x01010103, 0x01010105, 0x0101010b, 0x0101010f, 0x01010301, 0x01010303, 0x01010305, + 0x01010309, 0x0101030d, 0x01010501, 0x01010503, 0x0101050b, 0x01010707, 0x01010901, 0x01010905, + 0x0101090b, 0x0101090f, 0x01010b03, 0x01010b07, 0x01010d01, 0x01010d05, 0x01010f03, 0x01010f09, + 0x01010f0f, 0x01030101, 0x01030103, 0x01030105, 0x01030109, 0x01030301, 0x01030303, 0x0103030b, + 0x01030501, 0x01030507, 0x0103050f, 0x01030703, 0x0103070b, 0x01030909, 0x01030d03, 0x01030d0b, + 0x01030f05, 0x01050101, 0x01050103, 0x0105010b, 0x0105010f, 0x01050301, 0x01050307, 0x0105030d, + 0x01050503, 0x0105050b, 0x01050701, 0x01050709, 0x01050905, 0x0105090b, 0x0105090f, 0x01050b03, + 0x01050b07, 0x01050f01, 0x01050f07, 0x01070107, 0x01070303, 0x0107030b, 0x01070501, 0x01070505, + 0x01070703, 0x01070707, 0x0107070d, 0x01070909, 0x01070b01, 0x01070b05, 0x01070d0f, 0x01070f03, + 0x01070f0b, 0x01090101, 0x01090307, 0x0109030f, 0x01090503, 0x01090509, 0x01090705, 0x01090901, + 0x01090907, 0x01090b03, 0x01090f01, 0x010b0105, 0x010b0109, 0x010b0501, 0x010b0505, 0x010b050d, + 0x010b0707, 0x010b0903, 0x010b090b, 0x010b090f, 0x010b0d0d, 0x010b0f07, 0x010d010d, 0x010d0303, + 0x010d0307, 0x010d0703, 0x010d0b05, 0x010d0f03, 0x010f0101, 0x010f0105, 0x010f0109, 0x010f0501, + 0x010f0505, 0x010f050d, 0x010f0707, 0x010f0b01, 0x010f0b09, 0x03010101, 0x03010103, 0x03010105, + 0x03010109, 0x03010301, 0x03010303, 0x03010307, 0x0301030b, 0x0301030f, 0x03010501, 0x03010505, + 0x03010703, 0x03010709, 0x0301070d, 0x03010b09, 0x03010b0d, 0x03010d03, 0x03010f05, 0x03030101, + 0x03030103, 0x03030107, 0x0303010d, 0x03030301, 0x03030309, 0x03030503, 0x03030701, 0x03030707, + 0x03030903, 0x03030b01, 0x03030b05, 0x03030f01, 0x03030f0d, 0x03050101, 0x03050305, 0x0305030b, + 0x0305030f, 0x03050501, 0x03050509, 0x03050705, 0x03050901, 0x03050907, 0x03050b0b, 0x03050d01, + 0x03050f05, 0x03070103, 0x03070109, 0x0307010f, 0x03070301, 0x03070307, 0x03070503, 0x0307050f, + 0x03070701, 0x03070709, 0x03070903, 0x03070d05, 0x03070f01, 0x03090107, 0x0309010b, 0x03090305, + 0x03090309, 0x03090703, 0x03090707, 0x03090905, 0x0309090d, 0x03090b01, 0x03090b09, 0x030b0103, + 0x030b0301, 0x030b0307, 0x030b0503, 0x030b0701, 0x030b0705, 0x030b0b03, 0x030d0501, 0x030d0509, + 0x030d050f, 0x030d0909, 0x030d090d, 0x030f0103, 0x030f0107, 0x030f0301, 0x030f0305, 0x030f0503, + 0x030f070b, 0x030f0903, 0x030f0d05, 0x030f0f01, 0x05010101, 0x05010103, 0x05010107, 0x0501010b, + 0x0501010f, 0x05010301, 0x05010305, 0x05010309, 0x0501030d, 0x05010503, 0x05010507, 0x0501050f, + 0x05010701, 0x05010705, 0x05010903, 0x05010907, 0x0501090b, 0x05010b01, 0x05010b05, 0x05010d0f, + 0x05010f01, 0x05010f07, 0x05010f0b, 0x05030101, 0x05030105, 0x05030301, 0x05030307, 0x0503030f, + 0x05030505, 0x0503050b, 0x05030703, 0x05030709, 0x05030905, 0x05030b03, 0x05050103, 0x05050109, + 0x0505010f, 0x05050503, 0x05050507, 0x05050701, 0x0505070f, 0x05050903, 0x05050b07, 0x05050b0f, + 0x05050f03, 0x05050f09, 0x05070101, 0x05070105, 0x0507010b, 0x05070303, 0x05070505, 0x05070509, + 0x05070703, 0x05070707, 0x05070905, 0x05070b01, 0x05070d0d, 0x05090103, 0x0509010f, 0x05090501, + 0x05090507, 0x05090705, 0x0509070b, 0x05090903, 0x05090f05, 0x05090f0b, 0x050b0109, 0x050b0303, + 0x050b0505, 0x050b070f, 0x050b0901, 0x050b0b07, 0x050b0f01, 0x050d0101, 0x050d0105, 0x050d010f, + 0x050d0503, 0x050d0b0b, 0x050d0d03, 0x050f010b, 0x050f0303, 0x050f050d, 0x050f0701, 0x050f0907, + 0x050f0b01, 0x07010105, 0x07010303, 0x07010307, 0x0701030b, 0x0701030f, 0x07010505, 0x07010703, + 0x07010707, 0x0701070b, 0x07010905, 0x07010909, 0x0701090f, 0x07010b03, 0x07010d07, 0x07010f03, + 0x07030103, 0x07030107, 0x0703010b, 0x07030309, 0x07030503, 0x07030507, 0x07030901, 0x07030d01, + 0x07030f05, 0x07030f0d, 0x07050101, 0x07050305, 0x07050501, 0x07050705, 0x07050709, 0x07050b01, + 0x07070103, 0x07070301, 0x07070309, 0x07070503, 0x07070507, 0x0707050f, 0x07070701, 0x07070903, + 0x07070907, 0x0707090f, 0x07070b0b, 0x07070f07, 0x07090107, 0x07090303, 0x0709030d, 0x07090505, + 0x07090703, 0x07090b05, 0x07090d01, 0x07090d09, 0x070b0103, 0x070b0301, 0x070b0305, 0x070b050b, + 0x070b0705, 0x070b0909, 0x070b0b0d, 0x070b0f07, 0x070d030d, 0x070d0903, 0x070f0103, 0x070f0107, + 0x070f0501, 0x070f0505, 0x070f070b, 0x09010101, 0x09010109, 0x09010305, 0x09010501, 0x09010509, + 0x0901050f, 0x09010705, 0x09010903, 0x09010b01, 0x09010f01, 0x09030105, 0x0903010f, 0x09030303, + 0x09030307, 0x09030505, 0x09030701, 0x0903070b, 0x09030907, 0x09030b03, 0x09030b0b, 0x09050103, + 0x09050107, 0x09050301, 0x0905030b, 0x09050503, 0x09050707, 0x09050901, 0x09050b0f, 0x09050d05, + 0x09050f01, 0x09070109, 0x09070303, 0x09070307, 0x09070501, 0x09070505, 0x09070703, 0x0907070b, + 0x09090101, 0x09090105, 0x09090509, 0x0909070f, 0x09090901, 0x09090f03, 0x090b010b, 0x090b010f, + 0x090b0503, 0x090b0d05, 0x090d0307, 0x090d0709, 0x090d0d01, 0x090f0301, 0x090f030b, 0x090f0701, + 0x090f0907, 0x090f0b03, 0x0b010105, 0x0b010301, 0x0b010309, 0x0b010505, 0x0b010901, 0x0b010909, + 0x0b01090f, 0x0b010b05, 0x0b010d0d, 0x0b010f09, 0x0b030103, 0x0b030107, 0x0b03010b, 0x0b030305, + 0x0b030503, 0x0b030705, 0x0b030f05, 0x0b050101, 0x0b050303, 0x0b050507, 0x0b050701, 0x0b05070d, + 0x0b050b07, 0x0b070105, 0x0b07010f, 0x0b070301, 0x0b07050f, 0x0b070909, 0x0b070b03, 0x0b070d0b, + 0x0b070f07, 0x0b090103, 0x0b090109, 0x0b090501, 0x0b090705, 0x0b09090d, 0x0b0b0305, 0x0b0b050d, + 0x0b0b0b03, 0x0b0b0b07, 0x0b0d0905, 0x0b0f0105, 0x0b0f0109, 0x0b0f0505, 0x0d010303, 0x0d010307, + 0x0d01030b, 0x0d010703, 0x0d010707, 0x0d010d01, 0x0d030101, 0x0d030501, 0x0d03050f, 0x0d030d09, + 0x0d050305, 0x0d050709, 0x0d050905, 0x0d050b0b, 0x0d050d05, 0x0d050f01, 0x0d070101, 0x0d070309, + 0x0d070503, 0x0d070901, 0x0d09050b, 0x0d090907, 0x0d090d05, 0x0d0b0101, 0x0d0b0107, 0x0d0b0709, + 0x0d0b0d01, 0x0d0d010b, 0x0d0d0901, 0x0d0f0303, 0x0d0f0307, 0x0f010101, 0x0f010109, 0x0f01010f, + 0x0f010501, 0x0f010505, 0x0f01070d, 0x0f010901, 0x0f010b09, 0x0f010d05, 0x0f030105, 0x0f030303, + 0x0f030509, 0x0f030907, 0x0f03090b, 0x0f050103, 0x0f050109, 0x0f050301, 0x0f05030d, 0x0f050503, + 0x0f050701, 0x0f050b03, 0x0f070105, 0x0f070705, 0x0f07070b, 0x0f070b07, 0x0f090103, 0x0f09010b, + 0x0f090307, 0x0f090501, 0x0f090b01, 0x0f0b0505, 0x0f0b0905, 0x0f0d0105, 0x0f0d0703, 0x0f0f0101, +}; + +shared uint32_t iq3s_grid[512]; + +#define NEEDS_INIT_IQ_SHMEM +void init_iq_shmem(uvec3 wgsize) +{ + // copy the table into shared memory and sync + [[unroll]] for (uint i = 0; i < iq3s_grid.length(); i += wgsize.x) { + if (iq3s_grid.length() % wgsize.x == 0 || i + gl_LocalInvocationIndex.x < iq3s_grid.length()) { + iq3s_grid[i + gl_LocalInvocationIndex.x] = iq3s_grid_const[i + gl_LocalInvocationIndex.x]; + } + } + barrier(); +} + +#define QUANT_K QUANT_K_IQ3_S +#define QUANT_R QUANT_R_IQ3_S +#define A_TYPE block_iq3_s +#define A_TYPE_PACKED16 block_iq3_s_packed16 +#endif + +#define QUANT_K_IQ4_XS 256 +#define QUANT_R_IQ4_XS 1 + +struct block_iq4_xs +{ + float16_t d; + uint16_t scales_h; + uint8_t scales_l[QUANT_K_IQ4_XS/64]; + uint8_t qs[QUANT_K_IQ4_XS/2]; +}; + +#if defined(DATA_A_IQ4_XS) +#define QUANT_K QUANT_K_IQ4_XS +#define QUANT_R QUANT_R_IQ4_XS +#define A_TYPE block_iq4_xs +#endif + +#define QUANT_K_IQ4_NL 32 +#define QUANT_R_IQ4_NL 2 struct block_iq4_nl { float16_t d; - uint8_t qs[QUANT_K/2]; + uint8_t qs[QUANT_K_IQ4_NL/2]; }; -#define A_TYPE block_iq4_nl +struct block_iq4_nl_packed16 +{ + float16_t d; + uint16_t qs[QUANT_K_IQ4_NL/2/2]; +}; -const int8_t kvalues_iq4nl[16] = { +#if defined(DATA_A_IQ4_NL) +#define QUANT_K QUANT_K_IQ4_NL +#define QUANT_R QUANT_R_IQ4_NL +#define A_TYPE block_iq4_nl +#define A_TYPE_PACKED16 block_iq4_nl_packed16 +#endif + +#if defined(DATA_A_IQ4_NL) || defined(DATA_A_IQ4_XS) +const int8_t kvalues_iq4nl_const[16] = { int8_t(-127), int8_t(-104), int8_t(-83), int8_t(-65), int8_t(-49), int8_t(-35), int8_t(-22), int8_t(-10), int8_t(1), int8_t(13), int8_t(25), int8_t(38), int8_t(53), int8_t(69), int8_t(89), int8_t(113) }; + +shared FLOAT_TYPE kvalues_iq4nl[16]; + +#define NEEDS_INIT_IQ_SHMEM +void init_iq_shmem(uvec3 wgsize) +{ + // copy the table into shared memory and sync + for (uint i = gl_LocalInvocationIndex.x; i < kvalues_iq4nl.length(); i += wgsize.x) { + kvalues_iq4nl[i] = FLOAT_TYPE(kvalues_iq4nl_const[i]); + } + barrier(); +} #endif + +// returns the bfloat value in the low 16b. +// See ggml_compute_fp32_to_bf16 +uint32_t fp32_to_bf16(float f) +{ + uint32_t u = floatBitsToUint(f); + u = (u + (0x7fff + ((u >> 16) & 1))) >> 16; + return u; +} + +float bf16_to_fp32(uint32_t u) +{ + return uintBitsToFloat(u << 16); +} + +#endif // !defined(GGML_TYPES_COMP) diff --git a/ggml/src/vulkan-shaders/upscale.comp b/ggml/src/vulkan-shaders/upscale.comp index 511a086e..6f607380 100644 --- a/ggml/src/vulkan-shaders/upscale.comp +++ b/ggml/src/vulkan-shaders/upscale.comp @@ -2,7 +2,7 @@ layout (push_constant) uniform parameter { - uint ne; uint d_offset; + uint ne; uint a_offset; uint d_offset; uint nb00; uint nb01; uint nb02; uint nb03; uint ne10; uint ne11; uint ne12; uint ne13; float sf0; float sf1; float sf2; float sf3; @@ -32,5 +32,5 @@ void main() { const uint i02 = uint(i12 / p.sf2); const uint i03 = uint(i13 / p.sf3); - data_d[p.d_offset + idx] = D_TYPE(data_a[i03 * p.nb03 + i02 * p.nb02 + i01 * p.nb01 + i00 * p.nb00]); + data_d[p.d_offset + idx] = D_TYPE(data_a[p.a_offset + i03 * p.nb03 + i02 * p.nb02 + i01 * p.nb01 + i00 * p.nb00]); } diff --git a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp index a792e203..0f244dea 100644 --- a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp +++ b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp @@ -16,13 +16,14 @@ #include #include #include +#include +#include #include #include #ifdef _WIN32 #include #include // For _mkdir on Windows - #include // For std::replace on w64devkit #else #include #include @@ -54,9 +55,19 @@ const std::vector type_names = { "q4_k", "q5_k", "q6_k", - "iq4_nl" + "iq1_s", + "iq1_m", + "iq2_xxs", + "iq2_xs", + "iq2_s", + "iq3_xxs", + "iq3_s", + "iq4_xs", + "iq4_nl", + "bf16", }; +namespace { void execute_command(const std::string& command, std::string& stdout_str, std::string& stderr_str) { #ifdef _WIN32 HANDLE stdout_read, stdout_write; @@ -74,7 +85,8 @@ void execute_command(const std::string& command, std::string& stdout_str, std::s } PROCESS_INFORMATION pi; - STARTUPINFOA si = { sizeof(STARTUPINFOA) }; + STARTUPINFOA si = {}; + si.cb = sizeof(STARTUPINFOA); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = stdout_write; si.hStdError = stderr_write; @@ -92,11 +104,11 @@ void execute_command(const std::string& command, std::string& stdout_str, std::s std::array buffer; DWORD bytes_read; - while (ReadFile(stdout_read, buffer.data(), buffer.size(), &bytes_read, NULL) && bytes_read > 0) { + while (ReadFile(stdout_read, buffer.data(), (DWORD)buffer.size(), &bytes_read, NULL) && bytes_read > 0) { stdout_str.append(buffer.data(), bytes_read); } - while (ReadFile(stderr_read, buffer.data(), buffer.size(), &bytes_read, NULL) && bytes_read > 0) { + while (ReadFile(stderr_read, buffer.data(), (DWORD)buffer.size(), &bytes_read, NULL) && bytes_read > 0) { stderr_str.append(buffer.data(), bytes_read); } @@ -173,6 +185,13 @@ std::string to_uppercase(const std::string& input) { return result; } +bool string_starts_with(const std::string& str, const std::string& prefix) { + if (prefix.size() > str.size()) { + return false; + } + return std::equal(prefix.begin(), prefix.end(), str.begin()); +} + bool string_ends_with(const std::string& str, const std::string& suffix) { if (suffix.size() > str.size()) { return false; @@ -190,16 +209,31 @@ std::string basename(const std::string &path) { return path.substr(path.find_last_of("/\\") + 1); } -void string_to_spv(const std::string& _name, const std::string& in_fname, const std::map& defines, bool fp16 = true) { - std::string name = _name + (fp16 ? "" : "_fp32"); +// variables to track number of compiles in progress +static uint32_t compile_count = 0; +static std::mutex compile_count_mutex; +static std::condition_variable compile_count_cond; + +void string_to_spv_func(const std::string& _name, const std::string& in_fname, const std::map& defines, bool fp16 = true, bool coopmat = false, bool coopmat2 = false, bool f16acc = false) { + std::string name = _name + (f16acc ? "_f16acc" : "") + (coopmat ? "_cm1" : "") + (coopmat2 ? "_cm2" : (fp16 ? "" : "_fp32")); std::string out_fname = join_paths(output_dir, name + ".spv"); std::string in_path = join_paths(input_dir, in_fname); + std::string target_env = (name.find("_cm2") != std::string::npos) ? "--target-env=vulkan1.3" : "--target-env=vulkan1.2"; + + // disable spirv-opt for coopmat shaders for https://github.com/ggerganov/llama.cpp/issues/10734 + std::string opt_level = coopmat ? "" : "-O"; + #ifdef _WIN32 - std::vector cmd = {GLSLC, "-fshader-stage=compute", "--target-env=vulkan1.2", "-O", "\"" + in_path + "\"", "-o", "\"" + out_fname + "\""}; + std::vector cmd = {GLSLC, "-fshader-stage=compute", target_env, opt_level, "\"" + in_path + "\"", "-o", "\"" + out_fname + "\""}; #else - std::vector cmd = {GLSLC, "-fshader-stage=compute", "--target-env=vulkan1.2", "-O", in_path, "-o", out_fname}; + std::vector cmd = {GLSLC, "-fshader-stage=compute", target_env, opt_level, in_path, "-o", out_fname}; #endif + + #ifdef GGML_VULKAN_SHADER_DEBUG_INFO + cmd.push_back("-g"); + #endif + for (const auto& define : defines) { cmd.push_back("-D" + define.first + "=" + define.second); } @@ -228,6 +262,12 @@ void string_to_spv(const std::string& _name, const std::string& in_fname, const } catch (const std::exception& e) { std::cerr << "Error executing command for " << name << ": " << e.what() << std::endl; } + { + std::lock_guard guard(compile_count_mutex); + assert(compile_count > 0); + compile_count--; + } + compile_count_cond.notify_all(); } std::map merge_maps(const std::map& a, const std::map& b) { @@ -236,12 +276,29 @@ std::map merge_maps(const std::map>& tasks, bool fp16, bool matmul_id) { - std::string load_vec = fp16 ? "8" : "4"; - std::string aligned_b_type_f32 = fp16 ? "mat2x4" : "vec4"; - std::string aligned_b_type_f16 = fp16 ? "f16mat2x4" : "f16vec4"; +static std::vector> compiles; +void string_to_spv(const std::string& _name, const std::string& in_fname, const std::map& defines, bool fp16 = true, bool coopmat = false, bool coopmat2 = false, bool f16acc = false) { + { + // wait until fewer than N compiles are in progress. + // 16 is an arbitrary limit, the goal is to avoid "failed to create pipe" errors. + uint32_t N = 16; + std::unique_lock guard(compile_count_mutex); + while (compile_count >= N) { + compile_count_cond.wait(guard); + } + compile_count++; + } + compiles.push_back(std::async(string_to_spv_func, _name, in_fname, defines, fp16, coopmat, coopmat2, f16acc)); +} - std::map base_dict = {{"FLOAT_TYPE", fp16 ? "float16_t" : "float"}}; +void matmul_shaders(bool fp16, bool matmul_id, bool coopmat, bool coopmat2, bool f16acc) { + std::string load_vec = coopmat2 ? "1" : fp16 ? "8" : "4"; + std::string aligned_b_type_f32 = coopmat2 ? "float" : fp16 ? "mat2x4" : "vec4"; + std::string aligned_b_type_f16 = coopmat2 ? "float16_t" : fp16 ? "f16mat2x4" : "f16vec4"; + + std::map base_dict = { + {"FLOAT_TYPE_VEC2", (coopmat2 || fp16) ? "f16vec2" : "vec2"}, + }; std::string shader_name = "matmul"; if (matmul_id) { @@ -253,225 +310,328 @@ void matmul_shaders(std::vector>& tasks, bool fp16, bool matmu base_dict["FLOAT16"] = "1"; } - // Shaders with f16 B_TYPE - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv(shader_name + "_f32_f16", "mul_mm.comp", merge_maps(base_dict, {{"DATA_A_F32", "1"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}}), fp16); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv(shader_name + "_f32_f16_aligned", "mul_mm.comp", merge_maps(base_dict, {{"DATA_A_F32", "1"}, {"LOAD_VEC_A", load_vec}, {"LOAD_VEC_B", load_vec}, {"B_TYPE", aligned_b_type_f16}, {"D_TYPE", "float"}}), fp16); - })); + base_dict["ACC_TYPE"] = f16acc ? "float16_t" : "float"; - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv(shader_name + "_f16", "mul_mm.comp", merge_maps(base_dict, {{"DATA_A_F16", "1"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}}), fp16); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv(shader_name + "_f16_aligned", "mul_mm.comp", merge_maps(base_dict, {{"DATA_A_F16", "1"}, {"LOAD_VEC_A", load_vec}, {"LOAD_VEC_B", load_vec}, {"B_TYPE", aligned_b_type_f16}, {"D_TYPE", "float"}}), fp16); - })); + if (coopmat) { + base_dict["COOPMAT"] = "1"; + } + + const std::string source_name = coopmat2 ? "mul_mm_cm2.comp" : "mul_mm.comp"; + + auto const &FLOAT_TYPE = [&](const std::string &t) -> std::string { + if (t == "bf16") { + // scalar path promotes to float + if (!coopmat && !coopmat2) { + return "float"; + } + return "bfloat16_t"; + } + if (coopmat2 || fp16) { + return "float16_t"; + } + return "float"; + }; + + // Shaders with f16 B_TYPE + string_to_spv(shader_name + "_f32_f16", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE("f16")}, {"DATA_A_F32", "1"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}, }), fp16, coopmat, coopmat2, f16acc); + string_to_spv(shader_name + "_f32_f16_aligned", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE("f16")}, {"DATA_A_F32", "1"}, {"LOAD_VEC_A", load_vec}, {"LOAD_VEC_B", load_vec}, {"B_TYPE", aligned_b_type_f16}, {"D_TYPE", "float"}, {"ALIGNED", "1"}}), fp16, coopmat, coopmat2, f16acc); + + string_to_spv(shader_name + "_f16_aligned", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE("f16")}, {"DATA_A_F16", "1"}, {"LOAD_VEC_A", load_vec}, {"LOAD_VEC_B", load_vec}, {"B_TYPE", aligned_b_type_f16}, {"D_TYPE", "float"}, {"ALIGNED", "1"}}), fp16, coopmat, coopmat2, f16acc); + string_to_spv(shader_name + "_f16", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE("f16")}, {"DATA_A_F16", "1"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}}), fp16, coopmat, coopmat2, f16acc); + + // bf16 + { + std::string load_vec_a_unaligned = "1"; + // For aligned matmul loads + std::string load_vec_a = coopmat2 ? "1" : "4"; + + // scalar path promotes to float + std::string to_float_type = (coopmat || coopmat2) ? "uintBitsToBFloat16EXT" : "bf16_to_fp32"; + + // If bfloat16 is not supported, then only compile the scalar (promote to fp32) shader +#if !defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT) + if (!(coopmat || coopmat2)) +#endif + { + string_to_spv(shader_name + "_bf16_aligned", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE("bf16")}, {"TO_FLOAT_TYPE", to_float_type}, {"DATA_A_BF16", "1"}, {"LOAD_VEC_A", load_vec_a}, {"LOAD_VEC_B", "4"}, {"B_TYPE", coopmat2 ? "bfloat16_t" : "u16vec4"}, {"D_TYPE", "float"}, {"B_IS_FLOAT", "1"}, {"ALIGNED", "1"}}), fp16, coopmat, coopmat2, f16acc); + string_to_spv(shader_name + "_bf16", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE("bf16")}, {"TO_FLOAT_TYPE", to_float_type}, {"DATA_A_BF16", "1"}, {"LOAD_VEC_A", load_vec_a_unaligned}, {"B_TYPE", coopmat2 ? "bfloat16_t" : "uint16_t"}, {"D_TYPE", "float"}, {"B_IS_FLOAT", "1"}}), fp16, coopmat, coopmat2, f16acc); + } + } for (const auto& tname : type_names) { + std::string load_vec_quant = "2"; + if ((tname == "q4_0") || (tname == "q4_1")) + load_vec_quant = "8"; + else if ((tname == "q5_0") || (tname == "q5_1") || (tname == "q8_0") || (tname == "iq4_nl")) + load_vec_quant = "4"; + + if (tname == "bf16") { + continue; + } + std::string data_a_key = "DATA_A_" + to_uppercase(tname); // For unaligned, load one at a time for f32/f16, or two at a time for quants - std::string load_vec_a_unaligned = (tname == "f32" || tname == "f16") ? "1" : "2"; + std::string load_vec_a_unaligned = (coopmat2 || tname == "f32" || tname == "f16" || tname == "bf16") ? "1" : load_vec_quant; // For aligned matmul loads - std::string load_vec_a = (tname == "f32" || tname == "f16") ? load_vec : "2"; - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv(shader_name + "_" + tname + "_f32", "mul_mm.comp", merge_maps(base_dict, {{data_a_key, "1"}, {"LOAD_VEC_A", load_vec_a_unaligned}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}), fp16); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv(shader_name + "_" + tname + "_f32_aligned", "mul_mm.comp", merge_maps(base_dict, {{data_a_key, "1"}, {"LOAD_VEC_A", load_vec_a}, {"LOAD_VEC_B", load_vec}, {"B_TYPE", aligned_b_type_f32}, {"D_TYPE", "float"}}), fp16); - })); + std::string load_vec_a = (coopmat2 || tname == "f32" || tname == "f16" || tname == "bf16") ? load_vec : load_vec_quant; + + // don't generate f32 variants for coopmat2 + if (!coopmat2) { + string_to_spv(shader_name + "_" + tname + "_f32", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE(tname)}, {data_a_key, "1"}, {"LOAD_VEC_A", load_vec_a_unaligned}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}), fp16, coopmat, coopmat2, f16acc); + string_to_spv(shader_name + "_" + tname + "_f32_aligned", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE(tname)}, {data_a_key, "1"}, {"LOAD_VEC_A", load_vec_a}, {"LOAD_VEC_B", load_vec}, {"B_TYPE", aligned_b_type_f32}, {"D_TYPE", "float"}, {"ALIGNED", "1"}}), fp16, coopmat, coopmat2, f16acc); + } + + if (tname != "f16" && tname != "f32") { + string_to_spv(shader_name + "_" + tname + "_f16", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE(tname)}, {data_a_key, "1"}, {"LOAD_VEC_A", load_vec_a_unaligned}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}}), fp16, coopmat, coopmat2, f16acc); + string_to_spv(shader_name + "_" + tname + "_f16_aligned", source_name, merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE(tname)}, {data_a_key, "1"}, {"LOAD_VEC_A", load_vec_a}, {"LOAD_VEC_B", load_vec}, {"B_TYPE", aligned_b_type_f16}, {"D_TYPE", "float"}, {"ALIGNED", "1"}}), fp16, coopmat, coopmat2, f16acc); + } + +#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT) + if (!coopmat && !coopmat2 && !matmul_id && (tname == "q4_0" || tname == "q4_1" || tname == "q5_0" || tname == "q5_1" || tname == "q8_0")) { + string_to_spv(shader_name + "_" + tname + "_q8_1", "mul_mmq.comp", merge_maps(base_dict, {{"FLOAT_TYPE", FLOAT_TYPE(tname)}, {data_a_key, "1"}, {"D_TYPE", "float"},}), fp16, coopmat, coopmat2, f16acc); + } +#endif } } -void process_shaders(std::vector>& tasks) { +void process_shaders() { std::cout << "ggml_vulkan: Generating and compiling shaders to SPIR-V" << std::endl; std::map base_dict = {{"FLOAT_TYPE", "float"}}; - for (const auto& fp16 : {false, true}) { - matmul_shaders(tasks, fp16, false); - matmul_shaders(tasks, fp16, true); + // matmul + for (const auto& matmul_id : {false, true}) { + // No coopmats + // fp32 + matmul_shaders(false, matmul_id, false, false, false); + + // fp16, fp32acc and fp16acc + matmul_shaders(true, matmul_id, false, false, false); + matmul_shaders(true, matmul_id, false, false, true); + +#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + // Coopmat, fp32acc and fp16acc + matmul_shaders(true, matmul_id, true, false, false); + matmul_shaders(true, matmul_id, true, false, true); +#endif + +#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + // Coopmat2, fp32acc and fp16acc + matmul_shaders(true, matmul_id, false, true, false); + matmul_shaders(true, matmul_id, false, true, true); +#endif + } + + // flash attention + for (const auto& f16acc : {false, true}) { + std::string acctype = f16acc ? "float16_t" : "float"; + std::string acctypev4 = f16acc ? "f16vec4" : "vec4"; + + for (const auto& tname : type_names) { + if (tname == "f32") { + continue; + } + if (tname == "bf16") continue; + +#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT) + if (tname == "f16") { + string_to_spv("flash_attn_f32_f16_" + tname, "flash_attn_cm2.comp", + merge_maps(base_dict, {{"Q_TYPE", "float"}, {"D_TYPE", "float"}, {"ACC_TYPE", acctype}}), true, false, true, f16acc); + } else { + std::string data_a_key = "DATA_A_" + to_uppercase(tname); + string_to_spv("flash_attn_f32_f16_" + tname, "flash_attn_cm2.comp", + merge_maps(base_dict, {{data_a_key, "1"}, {"Q_TYPE", "float"}, {"D_TYPE", "float"}, {"ACC_TYPE", acctype}, {"DEQUANTFUNC", "dequantFunc"+to_uppercase(tname) }, {"BLOCK_SIZE", "QUANT_K_"+to_uppercase(tname) }}), true, false, true, f16acc); + } +#endif +#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT) + if (tname == "f16") { + string_to_spv("flash_attn_f32_f16_" + tname, "flash_attn_cm1.comp", + merge_maps(base_dict, {{"Q_TYPE", "float"}, {"D_TYPE", "float"}, {"ACC_TYPE", acctype}, {"ACC_TYPEV4", acctypev4}, {"COOPMAT", "1"}}), true, true, false, f16acc); + } else if (tname == "q4_0" || tname == "q8_0") { + std::string data_a_key = "DATA_A_" + to_uppercase(tname); + string_to_spv("flash_attn_f32_f16_" + tname, "flash_attn_cm1.comp", + merge_maps(base_dict, {{data_a_key, "1"}, {"Q_TYPE", "float"}, {"D_TYPE", "float"}, {"ACC_TYPE", acctype}, {"ACC_TYPEV4", acctypev4}, {"BLOCK_SIZE", "QUANT_K_"+to_uppercase(tname)}, {"COOPMAT", "1"}}), true, true, false, f16acc); + } +#endif + if (tname == "f16") { + string_to_spv("flash_attn_f32_f16_" + tname, "flash_attn.comp", + merge_maps(base_dict, {{"Q_TYPE", "float"}, {"D_TYPE", "float"}, {"ACC_TYPE", acctype}}), true, false, false, f16acc); + } else if (tname == "q4_0" || tname == "q8_0") { + std::string data_a_key = "DATA_A_" + to_uppercase(tname); + string_to_spv("flash_attn_f32_f16_" + tname, "flash_attn.comp", + merge_maps(base_dict, {{data_a_key, "1"}, {"Q_TYPE", "float"}, {"D_TYPE", "float"}, {"ACC_TYPE", acctype}, {"BLOCK_SIZE", "QUANT_K_"+to_uppercase(tname) }}), true, false, false, f16acc); + } + } } for (const auto& tname : type_names) { // mul mat vec std::string data_a_key = "DATA_A_" + to_uppercase(tname); - std::string shader = (string_ends_with(tname, "_k")) ? "mul_mat_vec_" + tname + ".comp" : "mul_mat_vec.comp"; + std::string shader = (string_ends_with(tname, "_k") || string_starts_with(tname, "iq1_") || string_starts_with(tname, "iq2_") || string_starts_with(tname, "iq3_")) ? "mul_mat_vec_" + tname + ".comp" : "mul_mat_vec.comp"; - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("mul_mat_vec_" + tname + "_f32_f32", shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("mul_mat_vec_" + tname + "_f16_f32", shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}})); - })); + string_to_spv("mul_mat_vec_" + tname + "_f32_f32", shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "float"}, {"B_TYPE_VEC2", "vec2"}, {"B_TYPE_VEC4", "vec4"}, {"D_TYPE", "float"}})); + string_to_spv("mul_mat_vec_" + tname + "_f16_f32", shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "float16_t"}, {"B_TYPE_VEC2", "f16vec2"}, {"B_TYPE_VEC4", "f16vec4"}, {"D_TYPE", "float"}})); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("mul_mat_vec_id_" + tname + "_f32", shader, merge_maps(base_dict, {{"MUL_MAT_ID", "1"}, {data_a_key, "1"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); - })); + string_to_spv("mul_mat_vec_id_" + tname + "_f32", shader, merge_maps(base_dict, {{"MUL_MAT_ID", "1"}, {data_a_key, "1"}, {"B_TYPE", "float"}, {"B_TYPE_VEC2", "vec2"}, {"B_TYPE_VEC4", "vec4"}, {"D_TYPE", "float"}})); // Dequant shaders - if (tname != "f16") { - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("dequant_" + tname, "dequant_" + tname + ".comp", merge_maps(base_dict, {{data_a_key, "1"}, {"D_TYPE", "float16_t"}})); - })); + if (tname != "f16" && tname != "bf16") { + string_to_spv("dequant_" + tname, "dequant_" + tname + ".comp", merge_maps(base_dict, {{data_a_key, "1"}, {"D_TYPE", "float16_t"}})); } if (!string_ends_with(tname, "_k")) { - shader = (tname == "f32" || tname == "f16") ? "get_rows.comp" : "get_rows_quant.comp"; + shader = (tname == "f32" || tname == "f16" || tname == "bf16") ? "get_rows.comp" : "get_rows_quant.comp"; if (tname == "f16") { - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("get_rows_" + tname, shader, {{data_a_key, "1"}, {"B_TYPE", "int"}, {"D_TYPE", "float16_t"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); - })); + string_to_spv("get_rows_" + tname, shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "int"}, {"D_TYPE", "float16_t"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}})); } else { - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("get_rows_" + tname, shader, {{data_a_key, "1"}, {"B_TYPE", "int"}, {"D_TYPE", "float16_t"}}); - })); + string_to_spv("get_rows_" + tname, shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "int"}, {"D_TYPE", "float16_t"}})); } - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("get_rows_" + tname + "_f32", shader, {{data_a_key, "1"}, {"B_TYPE", "int"}, {"D_TYPE", "float"}}); - })); + string_to_spv("get_rows_" + tname + "_f32", shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "int"}, {"D_TYPE", "float"}})); } } - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("mul_mat_vec_p021_f16_f32", "mul_mat_vec_p021.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("mul_mat_vec_nc_f16_f32", "mul_mat_vec_nc.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - })); + string_to_spv("mul_mat_vec_p021_f16_f32_subgroup_add", "mul_mat_vec_p021.comp", {{"A_TYPE", "float16_t"}, {"A_TYPE_VEC4", "f16vec4"}, {"B_TYPE", "float"}, {"B_TYPE_VEC4", "vec4"}, {"D_TYPE", "float"}, {"USE_SUBGROUP_ADD", "1"}}); + string_to_spv("mul_mat_vec_p021_f16_f32", "mul_mat_vec_p021.comp", {{"A_TYPE", "float16_t"}, {"A_TYPE_VEC4", "f16vec4"}, {"B_TYPE", "float"}, {"B_TYPE_VEC4", "vec4"}, {"D_TYPE", "float"}}); + string_to_spv("mul_mat_vec_nc_f16_f32", "mul_mat_vec_nc.comp", {{"A_TYPE", "float16_t"}, {"A_TYPE_VEC4", "f16vec4"}, {"B_TYPE", "float"}, {"B_TYPE_VEC4", "vec4"}, {"D_TYPE", "float"}}); // Norms - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("norm_f32", "norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("group_norm_f32", "group_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("rms_norm_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - })); + string_to_spv("norm_f32", "norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("group_norm_f32", "group_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("rms_norm_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("rms_norm_back_f32", "rms_norm_back.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("cpy_f32_f32", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("cpy_f32_f16", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float16_t"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("cpy_f16_f16", "copy.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); - })); + string_to_spv("cpy_f32_f32", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("cpy_f32_f16", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float16_t"}}); + string_to_spv("cpy_f16_f16", "copy.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); + string_to_spv("cpy_f16_f32", "copy.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); + string_to_spv("cpy_f32_bf16","copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "uint16_t"}, {"DATA_D_BF16", "1"}}); + string_to_spv("contig_cpy_f32_f32", "contig_copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("contig_cpy_f32_f16", "contig_copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float16_t"}}); + string_to_spv("contig_cpy_f16_f16", "contig_copy.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); + string_to_spv("contig_cpy_f16_f32", "contig_copy.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); + string_to_spv("contig_cpy_f32_bf16","contig_copy.comp",{{"A_TYPE", "float"}, {"D_TYPE", "uint16_t"}, {"DATA_D_BF16", "1"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("add_f32", "add.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("add_f16_f32_f16", "add.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float"}, {"D_TYPE", "float16_t"}, {"FLOAT_TYPE", "float"}}); - })); + for (std::string t : {"q4_0", "q4_1", "q5_0", "q5_1", "q8_0", "iq4_nl"}) { + string_to_spv("cpy_f32_" + t, "copy_to_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); + string_to_spv("cpy_f32_" + t + "_rte", "copy_to_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}, {"RTE16", "1"}}); + string_to_spv("cpy_" + t + "_f32", "copy_from_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); + } - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("split_k_reduce", "mul_mat_split_k_reduce.comp", {}); - })); + auto get_type_str = [](bool f16) { + return f16 ? "float16_t" : "float"; + }; + auto get_suffix = [](bool src0_f16, bool src1_f16, bool dst_f16) { + std::string s; + s += std::string(src0_f16 ? "_f16" : "_f32"); + s += std::string(src1_f16 ? "_f16" : "_f32"); + s += std::string(dst_f16 ? "_f16" : "_f32"); + return s; + }; + for (std::string op : {"add", "sub", "mul", "div"}) { + for (auto src0_f16 : {false, true}) { + for (auto src1_f16 : {false, true}) { + for (auto dst_f16 : {false, true}) { + auto name = op + get_suffix(src0_f16, src1_f16, dst_f16); + string_to_spv(name.c_str(), op + ".comp", {{"A_TYPE", get_type_str(src0_f16)}, {"B_TYPE", get_type_str(src1_f16)}, {"D_TYPE", get_type_str(dst_f16)}, {"FLOAT_TYPE", "float"}}); + } + } + } + } - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("mul_f32", "mul.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - })); + string_to_spv("sub_f32", "sub.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("div_f32", "div.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - })); + string_to_spv("acc_f32", "acc.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("scale_f32", "scale.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - })); + string_to_spv("split_k_reduce", "mul_mat_split_k_reduce.comp", {}); + string_to_spv("fa_split_k_reduce", "flash_attn_split_k_reduce.comp", {}); + string_to_spv("quantize_q8_1", "quantize_q8_1.comp", {}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("sqr_f32", "square.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - })); + string_to_spv("mul_f32", "mul.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("clamp_f32", "clamp.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - })); + string_to_spv("div_f32", "div.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("pad_f32", "pad.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); + string_to_spv("repeat_f32", "repeat.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("repeat_back_f32", "repeat_back.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("concat_f32", "concat.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("concat_f16", "concat.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("concat_i32", "concat.comp", {{"A_TYPE", "int"}, {"B_TYPE", "int"}, {"D_TYPE", "int"}}); - })); + string_to_spv("scale_f32", "scale.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("upscale_f32", "upscale.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - })); + string_to_spv("sqr_f32", "square.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("gelu_f32", "gelu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("gelu_quick_f32", "gelu_quick.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("silu_f32", "silu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("relu_f32", "relu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("leaky_relu_f32", "leaky_relu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("tanh_f32", "tanh.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); + string_to_spv("sin_f32", "sin.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("diag_mask_inf_f32", "diag_mask_inf.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); + string_to_spv("cos_f32", "cos.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("soft_max_f32", "soft_max.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("soft_max_f32_f16", "soft_max.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}})); - })); + string_to_spv("clamp_f32", "clamp.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("rope_norm_f32", "rope_norm.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("rope_norm_f16", "rope_norm.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); - })); + string_to_spv("pad_f32", "pad.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("rope_neox_f32", "rope_neox.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - })); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("rope_neox_f16", "rope_neox.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); - })); + string_to_spv("concat_f32", "concat.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("concat_f16", "concat.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"OPTIMIZATION_ERROR_WORKAROUND", "1"}}); + string_to_spv("concat_i32", "concat.comp", {{"A_TYPE", "int"}, {"B_TYPE", "int"}, {"D_TYPE", "int"}}); - tasks.push_back(std::async(std::launch::async, [] { - string_to_spv("argsort_f32", "argsort.comp", {{"A_TYPE", "float"}}); - })); + string_to_spv("upscale_f32", "upscale.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("sum_rows_f32", "sum_rows.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - })); + string_to_spv("gelu_f16", "gelu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("gelu_f32", "gelu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("gelu_quick_f16", "gelu_quick.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("gelu_quick_f32", "gelu_quick.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("silu_f16", "silu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("silu_f32", "silu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("relu_f16", "relu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("relu_f32", "relu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("tanh_f16", "tanh.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("tanh_f32", "tanh.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("sigmoid_f16", "sigmoid.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("sigmoid_f32", "sigmoid.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("im2col_f32", "im2col.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - })); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("im2col_f32_f16", "im2col.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float16_t"}})); - })); + string_to_spv("leaky_relu_f32", "leaky_relu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("silu_back_f32", "silu_back.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - tasks.push_back(std::async(std::launch::async, [=] { - string_to_spv("timestep_embedding_f32", "timestep_embedding.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - })); + string_to_spv("diag_mask_inf_f32", "diag_mask_inf.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + + string_to_spv("soft_max_f32", "soft_max.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("soft_max_f32_f16", "soft_max.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float"}})); + string_to_spv("soft_max_back_f32", "soft_max_back.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); + + string_to_spv("rope_norm_f32", "rope_norm.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("rope_norm_f16", "rope_norm.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("rope_norm_f16_rte", "rope_norm.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"RTE16", "1"}}); + + string_to_spv("rope_neox_f32", "rope_neox.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("rope_neox_f16", "rope_neox.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("rope_neox_f16_rte", "rope_neox.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"RTE16", "1"}}); + + string_to_spv("rope_multi_f32", "rope_multi.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("rope_multi_f16", "rope_multi.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("rope_multi_f16_rte", "rope_multi.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"RTE16", "1"}}); + + string_to_spv("rope_vision_f32", "rope_vision.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("rope_vision_f16", "rope_vision.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("rope_vision_f16_rte", "rope_vision.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}, {"RTE16", "1"}}); + + string_to_spv("argsort_f32", "argsort.comp", {{"A_TYPE", "float"}}); + + string_to_spv("argmax_f32", "argmax.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "int"}})); + string_to_spv("sum_rows_f32", "sum_rows.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("count_equal_i32", "count_equal.comp", merge_maps(base_dict, {{"A_TYPE", "int"}, {"B_TYPE", "int"}, {"D_TYPE", "int"}})); + + string_to_spv("im2col_f32", "im2col.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("im2col_f32_f16", "im2col.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float16_t"}})); + string_to_spv("im2col_f32_f16_rte", "im2col.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float16_t"}, {"RTE16", "1"}})); + + string_to_spv("timestep_embedding_f32", "timestep_embedding.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + + string_to_spv("conv_transpose_1d_f32", "conv_transpose_1d.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + + string_to_spv("pool2d_f32", "pool2d.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + + string_to_spv("rwkv_wkv6_f32", "wkv6.comp", merge_maps(base_dict, {{"A_TYPE", "float"}})); + + string_to_spv("opt_step_adamw_f32", "opt_step_adamw.comp", merge_maps(base_dict, {{"A_TYPE", "float"}})); + + for (auto &c : compiles) { + c.wait(); + } } void write_output_files() { @@ -481,6 +641,7 @@ void write_output_files() { fprintf(hdr, "#include \n\n"); fprintf(src, "#include \"%s\"\n\n", basename(target_hpp).c_str()); + std::sort(shader_fnames.begin(), shader_fnames.end()); for (const auto& pair : shader_fnames) { const std::string& name = pair.first; #ifdef _WIN32 @@ -522,16 +683,28 @@ void write_output_files() { std::remove(path.c_str()); } } - + for (const char *op : {"add", "sub", "mul", "div"}) { + fprintf(hdr, "extern unsigned char *%s_data[2][2][2];\n", op); + fprintf(hdr, "extern uint64_t %s_len[2][2][2];\n", op); + fprintf(src, "unsigned char *%s_data[2][2][2] = {{{%s_f32_f32_f32_data, %s_f32_f32_f16_data}, {%s_f32_f16_f32_data, %s_f32_f16_f16_data}}, {{%s_f16_f32_f32_data, %s_f16_f32_f16_data}, {%s_f16_f16_f32_data, %s_f16_f16_f16_data}}};\n", op, op, op, op, op, op, op, op, op); + fprintf(src, "uint64_t %s_len[2][2][2] = {{{%s_f32_f32_f32_len, %s_f32_f32_f16_len}, {%s_f32_f16_f32_len, %s_f32_f16_f16_len}}, {{%s_f16_f32_f32_len, %s_f16_f32_f16_len}, {%s_f16_f16_f32_len, %s_f16_f16_f16_len}}};\n", op, op, op, op, op, op, op, op, op); + } fclose(hdr); fclose(src); } +} int main(int argc, char** argv) { std::map args; - for (int i = 1; i < argc; i += 2) { - if (i + 1 < argc) { - args[argv[i]] = argv[i + 1]; + for (int i = 1; i < argc; ++i) { + std::string arg = argv[i]; + if (arg.rfind("--", 0) == 0) { + if (i + 1 < argc && argv[i + 1][0] != '-') { + args[arg] = argv[i + 1]; + ++i; + } else { + args[arg] = ""; + } } } @@ -566,12 +739,7 @@ int main(int argc, char** argv) { } } - std::vector> tasks; - process_shaders(tasks); - - for (auto& task : tasks) { - task.get(); - } + process_shaders(); write_output_files(); diff --git a/ggml/src/vulkan-shaders/wkv6.comp b/ggml/src/vulkan-shaders/wkv6.comp new file mode 100644 index 00000000..35cc6c45 --- /dev/null +++ b/ggml/src/vulkan-shaders/wkv6.comp @@ -0,0 +1,87 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : require + +#define BLOCK_SIZE 64 +layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout(push_constant) uniform Parameters { + uint B; + uint T; + uint C; + uint H; +}; + +layout(binding = 0) readonly buffer KBuf { A_TYPE k[]; }; +layout(binding = 1) readonly buffer VBuf { A_TYPE v[]; }; +layout(binding = 2) readonly buffer RBuf { A_TYPE r[]; }; +layout(binding = 3) readonly buffer TimeFBuf { A_TYPE tf[]; }; +layout(binding = 4) readonly buffer TimeDBuf { A_TYPE td[]; }; +layout(binding = 5) readonly buffer StateBuf { A_TYPE state_in[]; }; +layout(binding = 6) buffer DstBuf { A_TYPE dst[]; }; + +shared A_TYPE _k[BLOCK_SIZE], _r[BLOCK_SIZE], _tf[BLOCK_SIZE], _td[BLOCK_SIZE]; + +void main() { + const uint head_size = BLOCK_SIZE; + const uint batch_id = gl_WorkGroupID.x / H; + const uint head_id = gl_WorkGroupID.x % H; + const uint tid = gl_LocalInvocationID.x; + + const uint state_size = C * head_size; + const uint n_seq_tokens = T / B; + + if (batch_id >= B || head_id >= H) { + return; + } + + A_TYPE state[BLOCK_SIZE]; + [[unroll]] for (uint i = 0; i < head_size; i++) { + state[i] = state_in[batch_id * state_size + head_id * head_size * head_size + + i * head_size + tid]; + } + + barrier(); + _tf[tid] = tf[head_id * head_size + tid]; + barrier(); + + const uint start_t = batch_id * n_seq_tokens * C + head_id * head_size + tid; + const uint end_t = (batch_id + 1) * n_seq_tokens * C + head_id * head_size + tid; + + for (uint t = start_t; t < end_t; t += C) { + barrier(); + _k[tid] = k[t]; + _r[tid] = r[t]; + _td[tid] = td[t]; + barrier(); + + const A_TYPE v_val = v[t]; + A_TYPE y = 0.0; + + [[unroll]] for (uint j = 0; j < head_size; j += 4) { + vec4 k_vec = vec4(_k[j], _k[j+1], _k[j+2], _k[j+3]); + vec4 r_vec = vec4(_r[j], _r[j+1], _r[j+2], _r[j+3]); + vec4 tf_vec = vec4(_tf[j], _tf[j+1], _tf[j+2], _tf[j+3]); + vec4 td_vec = vec4(_td[j], _td[j+1], _td[j+2], _td[j+3]); + vec4 s_vec = vec4(state[j], state[j+1], state[j+2], state[j+3]); + + vec4 kv = k_vec * v_val; + + vec4 temp = tf_vec * kv + s_vec; + y += dot(r_vec, temp); + + s_vec = s_vec * td_vec + kv; + state[j] = s_vec.x; + state[j+1] = s_vec.y; + state[j+2] = s_vec.z; + state[j+3] = s_vec.w; + } + + dst[t] = y; + } + + [[unroll]] for (uint i = 0; i < head_size; i++) { + dst[T * C + batch_id * state_size + head_id * head_size * head_size + + i * head_size + tid] = state[i]; + } +} diff --git a/include/llama.h b/include/llama.h index aa0f3980..53adeb94 100644 --- a/include/llama.h +++ b/include/llama.h @@ -117,7 +117,7 @@ extern "C" { enum llama_rope_type { LLAMA_ROPE_TYPE_NONE = -1, LLAMA_ROPE_TYPE_NORM = 0, - LLAMA_ROPE_TYPE_NEOX = 2, + LLAMA_ROPE_TYPE_NEOX = 2, LLAMA_ROPE_TYPE_GLM = 4, }; diff --git a/src/llama.cpp b/src/llama.cpp index 7c10cebd..b06f9d44 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -9595,7 +9595,7 @@ static struct ggml_tensor * llm_build_norm( const llm_build_cb & cb, int il, float scale_eps = 1) { - if (type == LLM_NORM_RMS && mw) { + if (false && type == LLM_NORM_RMS && mw) { cur = ggml_fused_rms_norm(ctx, cur, mw, scale_eps * hparams.f_norm_rms_eps); if (mb) { cb(cur, "fused_norm", il); @@ -9686,7 +9686,7 @@ static struct ggml_tensor * llm_build_ffn( cur = tmp; } - if (type_gate == LLM_FFN_PAR && + if (false && type_gate == LLM_FFN_PAR && (type_op == LLM_FFN_SILU || type_op == LLM_FFN_RELU || (type_op == LLM_FFN_GELU && !act_scales))) { cur = ggml_fused_mul_unary(ctx, cur, tmp, type_op == LLM_FFN_SILU ? GGML_UNARY_OP_SILU : type_op == LLM_FFN_RELU ? GGML_UNARY_OP_RELU : GGML_UNARY_OP_GELU); From b2566759a91966936e192f4ec06284cd8c37cd81 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Wed, 2 Jul 2025 08:59:04 +0200 Subject: [PATCH 04/63] Conditionally disable fused ops when building with Vulkan enabled (#569) Co-authored-by: Iwan Kawrakow --- src/llama.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/llama.cpp b/src/llama.cpp index b06f9d44..1ea2084d 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -9595,7 +9595,12 @@ static struct ggml_tensor * llm_build_norm( const llm_build_cb & cb, int il, float scale_eps = 1) { - if (false && type == LLM_NORM_RMS && mw) { +#ifdef GGML_USE_VULKAN + constexpr bool use_fused_rms_norm = false; +#else + constexpr bool use_fused_rms_norm = true; +#endif + if (use_fused_rms_norm && type == LLM_NORM_RMS && mw) { cur = ggml_fused_rms_norm(ctx, cur, mw, scale_eps * hparams.f_norm_rms_eps); if (mb) { cb(cur, "fused_norm", il); @@ -9686,7 +9691,13 @@ static struct ggml_tensor * llm_build_ffn( cur = tmp; } - if (false && type_gate == LLM_FFN_PAR && +#ifdef GGML_USE_VULKAN + constexpr bool use_fused_mul_unary = false; +#else + constexpr bool use_fused_mul_unary = true; +#endif + + if (use_fused_mul_unary && type_gate == LLM_FFN_PAR && (type_op == LLM_FFN_SILU || type_op == LLM_FFN_RELU || (type_op == LLM_FFN_GELU && !act_scales))) { cur = ggml_fused_mul_unary(ctx, cur, tmp, type_op == LLM_FFN_SILU ? GGML_UNARY_OP_SILU : type_op == LLM_FFN_RELU ? GGML_UNARY_OP_RELU : GGML_UNARY_OP_GELU); From 46f2e5d249568b6395d17a80feb2ba9ab48156e5 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Wed, 2 Jul 2025 09:11:33 +0200 Subject: [PATCH 05/63] Minor CUDA PP speed improvement (#567) * Slightly better q8_0_q8_1 kerneel and iqk_ks tile loading * Minor --------- Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-cuda/mmq.cuh | 186 +++++++++++++++++++++++-------------- 1 file changed, 117 insertions(+), 69 deletions(-) diff --git a/ggml/src/ggml-cuda/mmq.cuh b/ggml/src/ggml-cuda/mmq.cuh index 0a1d779e..6def49ef 100644 --- a/ggml/src/ggml-cuda/mmq.cuh +++ b/ggml/src/ggml-cuda/mmq.cuh @@ -861,61 +861,60 @@ static __device__ __forceinline__ void vec_dot_q8_0_q8_1_mma( const float * y_df = (const float *) y; const half2 * y_ds = (const half2 *) y; - mma_A A[ntx][WARP_SIZE/QI8_0]; - float dA[ntx][mma_C::ne/2][WARP_SIZE/QI8_0]; + mma_A A[ntx]; + float dA[ntx][mma_C::ne/2]; const int i0 = (threadIdx.y/ntx)*rows_per_warp; -#pragma unroll - for (int n = 0; n < ntx; ++n) { -#pragma unroll - for (int k01 = 0; k01 < WARP_SIZE; k01 += QI8_0) { - const int k0 = k00 + k01; - - A[n][k01/QI8_0].load(x_qs + (i0 + n*mma_A::I)*MMQ_MMA_TILE_X_K_Q8_0 + k0, MMQ_MMA_TILE_X_K_Q8_0); - } - -#pragma unroll + #pragma unroll + for (int k01 = 0; k01 < WARP_SIZE; k01 += QI8_0) { + const int k0 = k00 + k01; + mma_B B; + float dB[mma_C::ne/2]; + B.load(y_qs + k01, MMQ_TILE_Y_K); + #pragma unroll for (int l = 0; l < mma_C::ne/2; ++l) { - const int i = i0 + n*mma_A::I + mma_C::get_i(2*l); - -#pragma unroll - for (int k01 = 0; k01 < WARP_SIZE; k01 += QI8_0) { - const int k0 = k00 + k01; - - dA[n][l][k01/QI8_0] = x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + k0/QI8_0]; + const int j = mma_C::get_j(l); + if constexpr (ds_layout == MMQ_Q8_1_DS_LAYOUT_D4) { + dB[l] = y_df[j*MMQ_TILE_Y_K + k01/QI8_1]; + } else { + dB[l] = __low2float(y_ds[j*MMQ_TILE_Y_K + k01/QI8_1]); } } - } - -#pragma unroll - for (int j0 = 0; j0 < mmq_x; j0 += ntx*mma_C::J) { -#pragma unroll - for (int k01 = 0; k01 < WARP_SIZE; k01 += QI8_0) { - mma_B B; - float dB[mma_C::ne/2]; - + #pragma unroll + for (int n = 0; n < ntx; ++n) { + A[n].load(x_qs + (i0 + n*mma_A::I)*MMQ_MMA_TILE_X_K_Q8_0 + k0, MMQ_MMA_TILE_X_K_Q8_0); + #pragma unroll + for (int l = 0; l < mma_C::ne/2; ++l) { + const int i = i0 + n*mma_A::I + mma_C::get_i(2*l); + dA[n][l] = x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + k0/QI8_0]; + } + mma_C C; + C.mma_K8(A[n], B); + #pragma unroll + for (int l = 0; l < mma_C::ne; ++l) { + sum[(n)*mma_C::ne + l] += C.x[l]*dA[n][l/2]*dB[l%2]; + } + } + #pragma unroll + for (int j0 = ntx*mma_C::J; j0 < mmq_x; j0 += ntx*mma_C::J) { B.load(y_qs + j0*MMQ_TILE_Y_K + k01, MMQ_TILE_Y_K); - -#pragma unroll + #pragma unroll for (int l = 0; l < mma_C::ne/2; ++l) { const int j = j0 + mma_C::get_j(l); - - if (ds_layout == MMQ_Q8_1_DS_LAYOUT_D4) { - dB[l] = y_df[j*MMQ_TILE_Y_K + k01/QI8_1]; + if constexpr (ds_layout == MMQ_Q8_1_DS_LAYOUT_D4) { + dB[l] = y_df[j*MMQ_TILE_Y_K + k01/QI8_1]; } else { dB[l] = __low2float(y_ds[j*MMQ_TILE_Y_K + k01/QI8_1]); } } - -#pragma unroll + #pragma unroll for (int n = 0; n < ntx; ++n) { mma_C C; - C.mma_K8(A[n][k01/QI8_0], B); - -#pragma unroll + C.mma_K8(A[n], B); + #pragma unroll for (int l = 0; l < mma_C::ne; ++l) { - sum[(j0/mma_C::J + n)*mma_C::ne + l] += C.x[l]*dA[n][l/2][k01/QI8_0]*dB[l%2]; + sum[(j0/mma_C::J + n)*mma_C::ne + l] += C.x[l]*dA[n][l/2]*dB[l%2]; } } } @@ -2701,6 +2700,64 @@ template static __device__ __forceinlin } } +//template static __device__ __forceinline__ void load_tiles_iq4_ks( +// const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { +// +//#ifdef INT8_MMA_AVAILABLE +// int * x_qs = (int *) x_tile; +// float * x_df = (float *) (x_qs + WARP_SIZE*2); +//#else +// constexpr tile_x_sizes txs = mmq_get_dp4a_tile_x_sizes(GGML_TYPE_IQ4_XS, mmq_y); +// int * x_qs = (int *) x_tile; +// float * x_df = (float *) (x_qs + txs.qs); +//#endif // INT8_MMA_AVAILABLE +// +// const int kbx = 0; // threadIdx.x / QI4_XS +// const int kqsx = threadIdx.x; // threadIdx.x % QI4_XS +// +//#pragma unroll +// for (int i0 = 0; i0 < mmq_y; i0 += nwarps) { +// int i = i0 + threadIdx.y; +// +// if (need_check) { +// i = min(i, i_max); +// } +// +// const block_iq4_ks * bxi = (const block_iq4_ks *)(x + i*stride + sizeof(float)) + kbx0 + kbx; +// +// auto values = iq4k_values + ((bxi->scales[kqsx/4] & 1) << 4); +// const int aux_q4 = get_int_b4(bxi->qs, kqsx); +// const int2 v = get_int_from_table_16(aux_q4, values); +// const int k0 = 8 * (threadIdx.x / 4) + threadIdx.x % 4; +//#ifdef INT8_MMA_AVAILABLE +// x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 0] = v.x; +// x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 4] = v.y; +//#else +// x_qs[i*(2*WARP_SIZE + 1) + k0 + 0] = v.x; +// x_qs[i*(2*WARP_SIZE + 1) + k0 + 4] = v.y; +//#endif // INT8_MMA_AVAILABLE +// } +// +//#pragma unroll +// for (int i0 = 0; i0 < mmq_y; i0 += nwarps * 4) { +// int i = i0 + threadIdx.y * 4 + threadIdx.x / (WARP_SIZE/4); +// +// if (need_check) { +// i = min(i, i_max); +// } +// +// const float * dptr = (const float *)(x + i*stride); +// const block_iq4_ks * bxi = (const block_iq4_ks *)(dptr + 1) + kbx0; +// const int ls = (bxi->scales[threadIdx.x % 8] & 254) - 127; +// +//#ifdef INT8_MMA_AVAILABLE +// x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + threadIdx.x % 8] = dptr[0] * ls; +//#else +// x_df[i*(WARP_SIZE/4) + i/4 + threadIdx.x % 8] = dptr[0] * ls; +//#endif // INT8_MMA_AVAILABLE +// } +//} + template static __device__ __forceinline__ void load_tiles_iq4_ks( const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { @@ -2713,35 +2770,11 @@ template static __device__ __forceinlin float * x_df = (float *) (x_qs + txs.qs); #endif // INT8_MMA_AVAILABLE - const int kbx = 0; // threadIdx.x / QI4_XS - const int kqsx = threadIdx.x; // threadIdx.x % QI4_XS + const int kqsx = threadIdx.x / 4; #pragma unroll - for (int i0 = 0; i0 < mmq_y; i0 += nwarps) { - int i = i0 + threadIdx.y; - - if (need_check) { - i = min(i, i_max); - } - - const block_iq4_ks * bxi = (const block_iq4_ks *)(x + i*stride + sizeof(float)) + kbx0 + kbx; - - auto values = iq4k_values + ((bxi->scales[kqsx/4] & 1) << 4); - const int aux_q4 = get_int_b4(bxi->qs, kqsx); - const int2 v = get_int_from_table_16(aux_q4, values); - const int k0 = 8 * (threadIdx.x / 4) + threadIdx.x % 4; -#ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 0] = v.x; - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 4] = v.y; -#else - x_qs[i*(2*WARP_SIZE + 1) + k0 + 0] = v.x; - x_qs[i*(2*WARP_SIZE + 1) + k0 + 4] = v.y; -#endif // INT8_MMA_AVAILABLE - } - -#pragma unroll - for (int i0 = 0; i0 < mmq_y; i0 += nwarps * 4) { - int i = i0 + threadIdx.y * 4 + threadIdx.x / (WARP_SIZE/4); + for (int i0 = 0; i0 < mmq_y; i0 += 4*nwarps) { + int i = i0 + 4*threadIdx.y + threadIdx.x%4; if (need_check) { i = min(i, i_max); @@ -2749,16 +2782,31 @@ template static __device__ __forceinlin const float * dptr = (const float *)(x + i*stride); const block_iq4_ks * bxi = (const block_iq4_ks *)(dptr + 1) + kbx0; - const int ls = (bxi->scales[threadIdx.x % 8] & 254) - 127; + const int ls = (bxi->scales[kqsx] & 254) - 127; + auto values = iq4k_values + ((bxi->scales[kqsx] & 1) << 4); + #pragma unroll + for (int j = 0; j < 4; ++j) { + const int aux_q4 = get_int_b4(bxi->qs, 4*kqsx+j); + const int2 v = get_int_from_table_16(aux_q4, values); #ifdef INT8_MMA_AVAILABLE - x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + threadIdx.x % 8] = dptr[0] * ls; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*kqsx + j + 0] = v.x; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*kqsx + j + 4] = v.y; #else - x_df[i*(WARP_SIZE/4) + i/4 + threadIdx.x % 8] = dptr[0] * ls; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + j + 0] = v.x; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + j + 4] = v.y; +#endif // INT8_MMA_AVAILABLE + } +#ifdef INT8_MMA_AVAILABLE + x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx] = dptr[0] * ls; +#else + x_df[i*(WARP_SIZE/4) + i/4 + kqsx] = dptr[0] * ls; #endif // INT8_MMA_AVAILABLE } + } + template static __device__ __forceinline__ void load_tiles_iq4_ks_r4( const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { From 3248a3599275c3d2a98bc41d512e1d3ba66e32ba Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Wed, 2 Jul 2025 09:27:47 +0200 Subject: [PATCH 06/63] Adding IQ3_KS quants (#566) * iq3_ks: basics * iq3_ks: CUDA dequantize * iq3_ks: CUDA mmvq * iq3_ks: mmq * iq3_ks: faster mmq * iq3_ks: Zen4 * iq3_ks: AVX2 convert to q8_k_r8 This gives usPP-512 = 360 t/s. * iq3_ks: AVX2 GEMM/GEMV * iq3_ks: NEON GEMM/GEMV * iq3_ks: NEON convert to q8_k_r8 This gives us PP-512 = 164 t/s. * iq3_ks: Metal dequantize * iq3_ks: Metal gemv - pathetic performance --------- Co-authored-by: Iwan Kawrakow --- examples/quantize/quantize.cpp | 1 + ggml/include/ggml.h | 2 + ggml/src/ggml-common.h | 8 + ggml/src/ggml-cuda.cu | 1 + ggml/src/ggml-cuda/common.cuh | 7 + ggml/src/ggml-cuda/convert.cu | 59 ++++ ggml/src/ggml-cuda/iqk_mmvq.cu | 75 +++++ ggml/src/ggml-cuda/iqk_mmvq.cuh | 5 + ggml/src/ggml-cuda/mmq.cu | 4 + ggml/src/ggml-cuda/mmq.cuh | 152 ++++++---- ggml/src/ggml-cuda/mmvq.cu | 4 + .../template-instances/mmq-instance-iq3_ks.cu | 5 + ggml/src/ggml-metal.m | 38 ++- ggml/src/ggml-metal.metal | 180 +++++++++++ ggml/src/ggml-quants.c | 1 + ggml/src/ggml.c | 22 ++ ggml/src/iqk/iqk_gemm_iqk_quants.cpp | 284 +++++++++++++++++- ggml/src/iqk/iqk_mul_mat.cpp | 5 + ggml/src/iqk/iqk_quantize.cpp | 231 ++++++++++++++ ggml/src/iqk/iqk_quantize.h | 6 + include/llama.h | 1 + src/llama.cpp | 14 +- 22 files changed, 1040 insertions(+), 65 deletions(-) create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_ks.cu diff --git a/examples/quantize/quantize.cpp b/examples/quantize/quantize.cpp index 85ceabfd..fd657373 100644 --- a/examples/quantize/quantize.cpp +++ b/examples/quantize/quantize.cpp @@ -76,6 +76,7 @@ static const std::vector QUANT_OPTIONS = { { "IQ2_K_R4", LLAMA_FTYPE_MOSTLY_IQ2_K_R4, "IQ2_K repacked",}, { "IQ2_KS", LLAMA_FTYPE_MOSTLY_IQ2_KS, " 2.1875 bpw non-linear quantization",}, { "IQ2_KT", LLAMA_FTYPE_MOSTLY_IQ2_KT, " 2.125 bpw trellis quantization", }, + { "IQ3_KS", LLAMA_FTYPE_MOSTLY_IQ3_KS, " 3.19 bpw non-linear quantization", }, { "IQ3_K", LLAMA_FTYPE_MOSTLY_IQ3_K, " 3.44 bpw non-linear quantization", }, { "IQ3_K_R4", LLAMA_FTYPE_MOSTLY_IQ3_K_R4, "IQ3_K repacked", }, { "IQ3_KL", LLAMA_FTYPE_MOSTLY_IQ3_KL, " 4 bpw non-linear quantization mix",}, diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index 67551eb2..aea0fac5 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -429,6 +429,7 @@ extern "C" { GGML_TYPE_IQ2_KT = 153, GGML_TYPE_IQ3_KT = 154, GGML_TYPE_IQ4_KT = 155, + GGML_TYPE_IQ3_KS = 156, GGML_TYPE_Q4_0_R8 = 202, GGML_TYPE_Q5_0_R4 = 206, @@ -521,6 +522,7 @@ extern "C" { GGML_FTYPE_MOSTLY_IQ2_KT = 142, // except 1d tensors GGML_FTYPE_MOSTLY_IQ3_KT = 143, // except 1d tensors GGML_FTYPE_MOSTLY_IQ4_KT = 144, // except 1d tensors + GGML_FTYPE_MOSTLY_IQ3_KS = 145, // except 1d tensors // GGML_FTYPE_MOSTLY_Q4_0_R8 = 202, // except 1d tensors GGML_FTYPE_MOSTLY_Q8_0_R8 = 207, // except 1d tensors diff --git a/ggml/src/ggml-common.h b/ggml/src/ggml-common.h index 2bfe5d39..a1f97911 100644 --- a/ggml/src/ggml-common.h +++ b/ggml/src/ggml-common.h @@ -649,6 +649,14 @@ typedef struct { } block_iq3_k; static_assert(sizeof(block_iq3_k) == sizeof(ggml_half) + 2*sizeof(uint16_t) + QK_K/32 + QK_K/4 + QK_K/8, "wrong iq3_k block size/padding"); +typedef struct { + uint16_t extra; + uint8_t scales[QK_K/64]; + uint8_t qs[QK_K/4]; + uint8_t qh[QK_K/8]; +} block_iq3_ks; +static_assert(sizeof(block_iq3_ks) == sizeof(uint16_t) + QK_K/64 + QK_K/4 + QK_K/8, "wrong iq3_ks block size/padding"); + typedef struct { ggml_half d[4]; uint8_t extra[8]; diff --git a/ggml/src/ggml-cuda.cu b/ggml/src/ggml-cuda.cu index ae7a55c6..e0035c7a 100644 --- a/ggml/src/ggml-cuda.cu +++ b/ggml/src/ggml-cuda.cu @@ -3465,6 +3465,7 @@ GGML_CALL static bool ggml_backend_cuda_supports_op(ggml_backend_t backend, cons case GGML_TYPE_IQ3_XXS: case GGML_TYPE_IQ4_NL: case GGML_TYPE_IQ4_XS: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ4_KSS: case GGML_TYPE_IQ5_KS: diff --git a/ggml/src/ggml-cuda/common.cuh b/ggml/src/ggml-cuda/common.cuh index e2690cb3..973af2b8 100644 --- a/ggml/src/ggml-cuda/common.cuh +++ b/ggml/src/ggml-cuda/common.cuh @@ -599,6 +599,13 @@ struct ggml_cuda_type_traits { static constexpr int qi = QI4_XS; }; +template<> +struct ggml_cuda_type_traits { + static constexpr int qk = QK_K; + static constexpr int qr = QR4_XS; + static constexpr int qi = QI4_XS; +}; + template<> struct ggml_cuda_type_traits { static constexpr int qk = QK_K; diff --git a/ggml/src/ggml-cuda/convert.cu b/ggml/src/ggml-cuda/convert.cu index b40079a3..61c09481 100644 --- a/ggml/src/ggml-cuda/convert.cu +++ b/ggml/src/ggml-cuda/convert.cu @@ -1333,6 +1333,51 @@ static __global__ void dequantize_block_iq3_k(const void * __restrict__ vx, dst_ } } +template +static __global__ void dequantize_block_iq3_ks(const void * __restrict__ vx, dst_t * __restrict__ yy, int64_t n_per_row, int64_t row_size) { + + int64_t ii = blockIdx.x; + int64_t row = (QK_K * ii) / n_per_row; + const char * cx = (const char *)vx + row * row_size; + float scale = *(const ggml_half *)cx; + const block_iq3_ks * x = (const block_iq3_ks *)(cx + sizeof(ggml_half)); + const int64_t i = ii - (row*n_per_row)/QK_K; + + const int64_t tid = threadIdx.x; + const int64_t is = tid/16; + const int64_t il = tid%16; + dst_t * y = yy + ii*QK_K + 128*is + 2*il; + const uint8_t * qs = x[i].qs + 32*is + 2*il; + const uint8_t * qh = x[i].qh + 2*il; + uint16_t extra = x[i].extra >> 4*is; + const float d0 = scale * (int(((x[i].scales[0] >> 4*is) & 0xf) | ((extra << 4) & 0x10)) - 16); + const float d1 = scale * (int(((x[i].scales[1] >> 4*is) & 0xf) | ((extra << 3) & 0x10)) - 16); + const float d2 = scale * (int(((x[i].scales[2] >> 4*is) & 0xf) | ((extra << 2) & 0x10)) - 16); + const float d3 = scale * (int(((x[i].scales[3] >> 4*is) & 0xf) | ((extra << 1) & 0x10)) - 16); + extra >>= 8; + const int8_t * values0 = iq3nl_values + ((extra & 1) << 3); + const int8_t * values1 = iq3nl_values + ((extra & 2) << 2); + const int8_t * values2 = iq3nl_values + ((extra & 4) << 1); + const int8_t * values3 = iq3nl_values + ((extra & 8) << 0); + if constexpr (std::is_same_v) { + for (int j = 0; j < 2; ++j) { + uint8_t h = qh[j] >> 4*is; + y[j+ 0] = __float2bfloat16(d0 * values0[((qs[j] >> 0) & 3) | ((h << 2) & 4)]); + y[j+32] = __float2bfloat16(d1 * values1[((qs[j] >> 2) & 3) | ((h << 1) & 4)]); + y[j+64] = __float2bfloat16(d2 * values2[((qs[j] >> 4) & 3) | ((h >> 0) & 4)]); + y[j+96] = __float2bfloat16(d3 * values3[((qs[j] >> 6) & 3) | ((h >> 1) & 4)]); + } + } else { + for (int j = 0; j < 2; ++j) { + uint8_t h = qh[j] >> 4*is; + y[j+ 0] = d0 * values0[((qs[j] >> 0) & 3) | ((h << 2) & 4)]; + y[j+32] = d1 * values1[((qs[j] >> 2) & 3) | ((h << 1) & 4)]; + y[j+64] = d2 * values2[((qs[j] >> 4) & 3) | ((h >> 0) & 4)]; + y[j+96] = d3 * values3[((qs[j] >> 6) & 3) | ((h >> 1) & 4)]; + } + } +} + template static void dequantize_block_cuda(const void * __restrict__ vx, dst_t * __restrict__ y, const int64_t nrows, const int64_t n_per_row, cudaStream_t stream) { const int64_t k = nrows * n_per_row; @@ -1573,6 +1618,14 @@ static void dequantize_row_iq3_k_cuda(const void * vx, dst_t * y, const int64_t dequantize_block_iq3_k<<>>(vx, y); } +template +static void dequantize_row_iq3_ks_cuda(const void * vx, dst_t * y, const int64_t nrows, const int64_t n_per_row, cudaStream_t stream) { + const int64_t k = nrows * n_per_row; + const int64_t row_size = ggml_row_size(GGML_TYPE_IQ3_KS, n_per_row); + const int nb = (k + QK_K - 1) / QK_K; + dequantize_block_iq3_ks<<>>(vx, y, n_per_row, row_size); +} + template static void dequantize_row_iq3_k_r4_cuda(const void * vx, dst_t * y, const int64_t nrows, const int64_t n_per_row, cudaStream_t stream) { const int64_t k = nrows * n_per_row; @@ -1719,6 +1772,8 @@ to_bf16_cuda_t ggml_get_to_bf16_cuda(ggml_type type) { return dequantize_row_iq2_k_cuda; case GGML_TYPE_IQ3_K: return dequantize_row_iq3_k_cuda; + case GGML_TYPE_IQ3_KS: + return dequantize_row_iq3_ks_cuda; case GGML_TYPE_IQ4_KSS: return dequantize_row_iq4_kss_cuda; case GGML_TYPE_IQ4_KS: @@ -1821,6 +1876,8 @@ to_fp16_cuda_t ggml_get_to_fp16_cuda(ggml_type type) { return dequantize_row_iq2_k_cuda; case GGML_TYPE_IQ3_K: return dequantize_row_iq3_k_cuda; + case GGML_TYPE_IQ3_KS: + return dequantize_row_iq3_ks_cuda; case GGML_TYPE_IQ4_K: return dequantize_row_iq4_k_cuda; case GGML_TYPE_IQ5_K: @@ -1916,6 +1973,8 @@ to_fp32_cuda_t ggml_get_to_fp32_cuda(ggml_type type) { return dequantize_row_iq2_k_cuda; case GGML_TYPE_IQ3_K: return dequantize_row_iq3_k_cuda; + case GGML_TYPE_IQ3_KS: + return dequantize_row_iq3_ks_cuda; case GGML_TYPE_IQ4_K: return dequantize_row_iq4_k_cuda; case GGML_TYPE_IQ5_K: diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cu b/ggml/src/ggml-cuda/iqk_mmvq.cu index e69bcc4a..3b1f6acb 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cu +++ b/ggml/src/ggml-cuda/iqk_mmvq.cu @@ -1104,6 +1104,73 @@ __device__ __forceinline__ void vec_dot_iq3_k_q8_1( } +__device__ __forceinline__ void vec_dot_iq3_ks_q8_1( + const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iiqs, float * result) { + + float d = __half2float(*(const half *)vbq); + const block_iq3_ks * bq3 = (const block_iq3_ks *)((const char *)vbq + sizeof(half)) + kbx; + + int iqs = iiqs/4; + const int ib128 = iqs/4; // 0 or 1. 0 works on quants 0...127, 1 on quants 128...255 + // Each thread processes 8 quants in each of the 4 32-blocks + const int il8 = iqs%4; // 0...3. 0 works on quants 0...7, 1 on quants 8...15, 2 on 16...23, 3 on 24...31 + const int shift = 4*(il8/2); + + const uint16_t * ql = (const uint16_t *)bq3->qs + 16*ib128 + 4*il8; + const uint16_t * qh = (const uint16_t *)bq3->qh + 4*il8; + + int32_t aux32; + const uint8_t * aux8 = (const uint8_t *)&aux32; + + uint16_t extra = bq3->extra >> 4*ib128; + uint16_t extra_v = extra >> 8; + + const uint16_t * values1 = iq3k_table + ((extra_v << 6) & 0x40); + const uint16_t * values2 = iq3k_table + ((extra_v << 5) & 0x40); + const uint16_t * values3 = iq3k_table + ((extra_v << 4) & 0x40); + const uint16_t * values4 = iq3k_table + ((extra_v << 3) & 0x40); + + const int * q8; + int sumi[4] = {0, 0, 0, 0}; + int v; + for (int i = 0; i < 2; ++i) { + uint32_t vl = ql[2*i+0] | (ql[2*i+1] << 16); + uint32_t vh = ((qh[2*i+0] | (qh[2*i+1] << 16)) >> 4*ib128) << 2; + + q8 = (const int *)bq8_1[4*ib128+0].qs + 2*il8; + aux32 = (vl & 0x03030303) | (vh & 0x04040404); + v = int_from_table_2(aux8, values1); + sumi[0] = ggml_cuda_dp4a(v, q8[i], sumi[0]); + vl >>= 2; vh >>= 1; + + q8 += sizeof(block_q8_1)/4; + aux32 = (vl & 0x03030303) | (vh & 0x04040404); + v = int_from_table_2(aux8, values2); + sumi[1] = ggml_cuda_dp4a(v, q8[i], sumi[1]); + vl >>= 2; vh >>= 1; + + q8 += sizeof(block_q8_1)/4; + aux32 = (vl & 0x03030303) | (vh & 0x04040404); + v = int_from_table_2(aux8, values3); + sumi[2] = ggml_cuda_dp4a(v, q8[i], sumi[2]); + vl >>= 2; vh >>= 1; + + q8 += sizeof(block_q8_1)/4; + aux32 = (vl & 0x03030303) | (vh & 0x04040404); + v = int_from_table_2(aux8, values4); + sumi[3] = ggml_cuda_dp4a(v, q8[i], sumi[3]); + + } + const uint16_t * sl16 = (const uint16_t *)bq3->scales; + aux32 = __vsub4(((sl16[0] | (sl16[1] << 16)) >> 4*ib128) & 0x0f0f0f0f, 0x10101010); + const int8_t * a8 = (const int8_t *)&aux32; + *result += d * (__low2float(bq8_1[4*ib128+0].ds) * (a8[0] + ((extra << 4) & 0x10)) * sumi[0] + + __low2float(bq8_1[4*ib128+1].ds) * (a8[1] + ((extra << 3) & 0x10)) * sumi[1] + + __low2float(bq8_1[4*ib128+2].ds) * (a8[2] + ((extra << 2) & 0x10)) * sumi[2] + + __low2float(bq8_1[4*ib128+3].ds) * (a8[3] + ((extra << 1) & 0x10)) * sumi[3]); + +} + __device__ __forceinline__ void vec_dot_iq1_bn_q8_1( const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iqs, float * result) { @@ -1302,6 +1369,14 @@ void mul_mat_vec_iq4_ks_q8_1_cuda( iqk_mul_mat_vec_q_cuda(vx, vy, dst, ids_data, ncols_x, nrows_x, nrows_y, ncols_y, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); } +void mul_mat_vec_iq3_ks_q8_1_cuda( + const void * vx, const void * vy, float * dst, const char * ids_data, + const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, + const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, int64_t ids_nb0, cudaStream_t stream) { + + iqk_mul_mat_vec_q_cuda(vx, vy, dst, ids_data, ncols_x, nrows_x, nrows_y, ncols_y, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); +} + void mul_mat_vec_iq4_kt_q8_1_cuda( const void * vx, const void * vy, float * dst, const char * ids_data, const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cuh b/ggml/src/ggml-cuda/iqk_mmvq.cuh index e7c6e1d2..c2416b1e 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cuh +++ b/ggml/src/ggml-cuda/iqk_mmvq.cuh @@ -16,6 +16,11 @@ void mul_mat_vec_iq3_k_q8_1_cuda( const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, const int64_t ids_nb0, cudaStream_t stream); +void mul_mat_vec_iq3_ks_q8_1_cuda( + const void * vx, const void * vy, float * dst, const char * ids_data, + const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, + const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, const int64_t ids_nb0, cudaStream_t stream); + void mul_mat_vec_iq4_k_q8_1_cuda( const void * vx, const void * vy, float * dst, const char * ids_data, const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, diff --git a/ggml/src/ggml-cuda/mmq.cu b/ggml/src/ggml-cuda/mmq.cu index deac4d8c..9c206e50 100644 --- a/ggml/src/ggml-cuda/mmq.cu +++ b/ggml/src/ggml-cuda/mmq.cu @@ -94,6 +94,9 @@ void ggml_cuda_op_mul_mat_q( case GGML_TYPE_IQ4_NL: mul_mat_q_case(ctx, args, stream); break; + case GGML_TYPE_IQ3_KS: + mul_mat_q_case(ctx, args, stream); + break; case GGML_TYPE_IQ4_KS: mul_mat_q_case(ctx, args, stream); break; @@ -196,6 +199,7 @@ bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11) { case GGML_TYPE_IQ1_S_R4: case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ4_KS_R4: case GGML_TYPE_IQ5_KS: diff --git a/ggml/src/ggml-cuda/mmq.cuh b/ggml/src/ggml-cuda/mmq.cuh index 6def49ef..d6f4cf3a 100644 --- a/ggml/src/ggml-cuda/mmq.cuh +++ b/ggml/src/ggml-cuda/mmq.cuh @@ -87,6 +87,7 @@ static mmq_q8_1_ds_layout mmq_get_q8_1_ds_layout(const ggml_type type_x) { case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ4_KS_R4: @@ -199,6 +200,7 @@ static constexpr __host__ __device__ tile_x_sizes mmq_get_dp4a_tile_x_sizes(ggml case GGML_TYPE_IQ1_S_R4: return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_XS : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_NL : return MMQ_DP4A_TXS_Q8_0; + case GGML_TYPE_IQ3_KS : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_KS : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_KS_R4 : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ5_KS : return MMQ_DP4A_TXS_Q8_0; @@ -254,6 +256,7 @@ static constexpr __host__ __device__ int mmq_get_mma_tile_x_k(ggml_type type) { case GGML_TYPE_IQ1_S_R4: return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_XS : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_NL : return MMQ_MMA_TILE_X_K_Q8_0; + case GGML_TYPE_IQ3_KS : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_KS : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_KS_R4 : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ5_KS : return MMQ_MMA_TILE_X_K_Q8_0; @@ -2700,63 +2703,90 @@ template static __device__ __forceinlin } } -//template static __device__ __forceinline__ void load_tiles_iq4_ks( -// const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { -// -//#ifdef INT8_MMA_AVAILABLE -// int * x_qs = (int *) x_tile; -// float * x_df = (float *) (x_qs + WARP_SIZE*2); -//#else -// constexpr tile_x_sizes txs = mmq_get_dp4a_tile_x_sizes(GGML_TYPE_IQ4_XS, mmq_y); -// int * x_qs = (int *) x_tile; -// float * x_df = (float *) (x_qs + txs.qs); -//#endif // INT8_MMA_AVAILABLE -// -// const int kbx = 0; // threadIdx.x / QI4_XS -// const int kqsx = threadIdx.x; // threadIdx.x % QI4_XS -// -//#pragma unroll -// for (int i0 = 0; i0 < mmq_y; i0 += nwarps) { -// int i = i0 + threadIdx.y; -// -// if (need_check) { -// i = min(i, i_max); -// } -// -// const block_iq4_ks * bxi = (const block_iq4_ks *)(x + i*stride + sizeof(float)) + kbx0 + kbx; -// -// auto values = iq4k_values + ((bxi->scales[kqsx/4] & 1) << 4); -// const int aux_q4 = get_int_b4(bxi->qs, kqsx); -// const int2 v = get_int_from_table_16(aux_q4, values); -// const int k0 = 8 * (threadIdx.x / 4) + threadIdx.x % 4; -//#ifdef INT8_MMA_AVAILABLE -// x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 0] = v.x; -// x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 4] = v.y; -//#else -// x_qs[i*(2*WARP_SIZE + 1) + k0 + 0] = v.x; -// x_qs[i*(2*WARP_SIZE + 1) + k0 + 4] = v.y; -//#endif // INT8_MMA_AVAILABLE -// } -// -//#pragma unroll -// for (int i0 = 0; i0 < mmq_y; i0 += nwarps * 4) { -// int i = i0 + threadIdx.y * 4 + threadIdx.x / (WARP_SIZE/4); -// -// if (need_check) { -// i = min(i, i_max); -// } -// -// const float * dptr = (const float *)(x + i*stride); -// const block_iq4_ks * bxi = (const block_iq4_ks *)(dptr + 1) + kbx0; -// const int ls = (bxi->scales[threadIdx.x % 8] & 254) - 127; -// -//#ifdef INT8_MMA_AVAILABLE -// x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + threadIdx.x % 8] = dptr[0] * ls; -//#else -// x_df[i*(WARP_SIZE/4) + i/4 + threadIdx.x % 8] = dptr[0] * ls; -//#endif // INT8_MMA_AVAILABLE -// } -//} +static const __device__ uint16_t iq3k_table[128] = { + 0xc1c1, 0xc1d8, 0xc1e9, 0xc1f6, 0xc101, 0xc10d, 0xc11c, 0xc12f, 0xd8c1, 0xd8d8, 0xd8e9, 0xd8f6, 0xd801, 0xd80d, 0xd81c, 0xd82f, + 0xe9c1, 0xe9d8, 0xe9e9, 0xe9f6, 0xe901, 0xe90d, 0xe91c, 0xe92f, 0xf6c1, 0xf6d8, 0xf6e9, 0xf6f6, 0xf601, 0xf60d, 0xf61c, 0xf62f, + 0x01c1, 0x01d8, 0x01e9, 0x01f6, 0x0101, 0x010d, 0x011c, 0x012f, 0x0dc1, 0x0dd8, 0x0de9, 0x0df6, 0x0d01, 0x0d0d, 0x0d1c, 0x0d2f, + 0x1cc1, 0x1cd8, 0x1ce9, 0x1cf6, 0x1c01, 0x1c0d, 0x1c1c, 0x1c2f, 0x2fc1, 0x2fd8, 0x2fe9, 0x2ff6, 0x2f01, 0x2f0d, 0x2f1c, 0x2f2f, + 0xc5c5, 0xc5dc, 0xc5ed, 0xc5fa, 0xc505, 0xc511, 0xc520, 0xc533, 0xdcc5, 0xdcdc, 0xdced, 0xdcfa, 0xdc05, 0xdc11, 0xdc20, 0xdc33, + 0xedc5, 0xeddc, 0xeded, 0xedfa, 0xed05, 0xed11, 0xed20, 0xed33, 0xfac5, 0xfadc, 0xfaed, 0xfafa, 0xfa05, 0xfa11, 0xfa20, 0xfa33, + 0x05c5, 0x05dc, 0x05ed, 0x05fa, 0x0505, 0x0511, 0x0520, 0x0533, 0x11c5, 0x11dc, 0x11ed, 0x11fa, 0x1105, 0x1111, 0x1120, 0x1133, + 0x20c5, 0x20dc, 0x20ed, 0x20fa, 0x2005, 0x2011, 0x2020, 0x2033, 0x33c5, 0x33dc, 0x33ed, 0x33fa, 0x3305, 0x3311, 0x3320, 0x3333, +}; + +__device__ __forceinline__ int int_from_table_2(const uint8_t * a8, const uint16_t * values) { + return values[a8[0] | (a8[1] << 3)] | (values[a8[2] | (a8[3] << 3)] << 16); +} + +template static __device__ __forceinline__ void load_tiles_iq3_ks( + const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { + +#ifdef INT8_MMA_AVAILABLE + int * x_qs = (int *) x_tile; + float * x_df = (float *) (x_qs + WARP_SIZE*2); +#else + constexpr tile_x_sizes txs = MMQ_DP4A_TXS_Q8_0_16; + int * x_qs = (int *) x_tile; + float * x_df = (float *) (x_qs + txs.qs); +#endif // INT8_MMA_AVAILABLE + + constexpr int qstep = 8; + const int kqsx = threadIdx.x % qstep; + + uint32_t aux32[4]; + const uint8_t * aux8 = (const uint8_t *)aux32; +#pragma unroll + for (int i0 = 0; i0 < mmq_y; i0 += nwarps * WARP_SIZE/qstep) { + int i = i0 + threadIdx.y*(WARP_SIZE/qstep) + threadIdx.x/qstep; + + if (need_check) { + i = min(i, i_max); + } + + const half * dptr = (const half *)(x + i*stride); + const float d = __half2float(dptr[0]); + const block_iq3_ks * bxi = (const block_iq3_ks *)(dptr + 1) + kbx0; + + uint16_t extra = bxi->extra >> 8; + int qh = get_int_b2(bxi->qh, kqsx); + + #pragma unroll + for (int l = 0; l < qstep/4; ++l) { + + const int ql = get_int_b2(bxi->qs, kqsx + qstep*l); + aux32[0] = ((ql >> 0) & 0x03030303) | ((qh << 2) & 0x04040404); + aux32[1] = ((ql >> 2) & 0x03030303) | ((qh << 1) & 0x04040404); + aux32[2] = ((ql >> 4) & 0x03030303) | ((qh >> 0) & 0x04040404); + aux32[3] = ((ql >> 6) & 0x03030303) | ((qh >> 1) & 0x04040404); + + const int val0 = int_from_table_2(aux8+ 0, iq3k_table + ((extra << 6) & 0x40)); + const int val1 = int_from_table_2(aux8+ 4, iq3k_table + ((extra << 5) & 0x40)); + const int val2 = int_from_table_2(aux8+ 8, iq3k_table + ((extra << 4) & 0x40)); + const int val3 = int_from_table_2(aux8+12, iq3k_table + ((extra << 3) & 0x40)); + + extra >>= 4; + qh >>= 4; + +#ifdef INT8_MMA_AVAILABLE + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx + 32*l + 0] = val0; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx + 32*l + 8] = val1; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx + 32*l + 16] = val2; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx + 32*l + 24] = val3; +#else + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 0] = val0; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 8] = val1; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 16] = val2; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 24] = val3; +#endif // INT8_MMA_AVAILABLE + } + +#ifdef INT8_MMA_AVAILABLE + x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx] = d * (int(((bxi->scales[kqsx%4] >> 4*(kqsx/4)) & 0xf) | (((bxi->extra >> kqsx) & 1) << 4)) - 16); +#else + x_df[i*(WARP_SIZE/4) + i/4 + kqsx] = d * (int(((bxi->scales[kqsx%4] >> 4*(kqsx/4)) & 0xf) | (((bxi->extra >> kqsx) & 1) << 4)) - 16); +#endif // INT8_MMA_AVAILABLE + } +} template static __device__ __forceinline__ void load_tiles_iq4_ks( const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { @@ -3657,6 +3687,13 @@ struct mmq_type_traits { static constexpr vec_dot_mmq_t vec_dot_dp4a = vec_dot_q8_0_q8_1_dp4a; }; +template +struct mmq_type_traits { + static constexpr load_tiles_mmq_t load_tiles = load_tiles_iq3_ks; + static constexpr vec_dot_mmq_t vec_dot_mma = vec_dot_q8_0_q8_1_mma; + static constexpr vec_dot_mmq_t vec_dot_dp4a = vec_dot_q8_0_q8_1_dp4a; +}; + template struct mmq_type_traits { static constexpr load_tiles_mmq_t load_tiles = load_tiles_iq4_ks; @@ -4142,6 +4179,7 @@ extern DECL_MMQ_CASE(GGML_TYPE_IQ3_S); extern DECL_MMQ_CASE(GGML_TYPE_IQ1_S); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_NL); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_XS); +extern DECL_MMQ_CASE(GGML_TYPE_IQ3_KS); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_KS); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_KS_R4); extern DECL_MMQ_CASE(GGML_TYPE_IQ5_KS_R4); diff --git a/ggml/src/ggml-cuda/mmvq.cu b/ggml/src/ggml-cuda/mmvq.cu index 6412be30..2b619f67 100644 --- a/ggml/src/ggml-cuda/mmvq.cu +++ b/ggml/src/ggml-cuda/mmvq.cu @@ -518,6 +518,9 @@ static void ggml_cuda_op_mul_mat_vec_q_impl(ggml_backend_cuda_context & ctx, ggm case GGML_TYPE_IQ3_K: mul_mat_vec_iq3_k_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); break; + case GGML_TYPE_IQ3_KS: + mul_mat_vec_iq3_ks_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); + break; case GGML_TYPE_IQ4_K: mul_mat_vec_iq4_k_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); break; @@ -679,6 +682,7 @@ bool ggml_cuda_mmvq_type_supported(ggml_type src0_type) { case GGML_TYPE_IQ4_NL: case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ4_KS: diff --git a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_ks.cu b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_ks.cu new file mode 100644 index 00000000..b8afe899 --- /dev/null +++ b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_ks.cu @@ -0,0 +1,5 @@ +// This file has been autogenerated by generate_cu_files.py, do not edit manually. + +#include "../mmq.cuh" + +DECL_MMQ_CASE(GGML_TYPE_IQ3_KS); diff --git a/ggml/src/ggml-metal.m b/ggml/src/ggml-metal.m index ff68ee19..e1e49fcb 100644 --- a/ggml/src/ggml-metal.m +++ b/ggml/src/ggml-metal.m @@ -106,6 +106,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_BN, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_NL, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_XS, + GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ3_KS, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_KS, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_KS, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_KSS, @@ -152,6 +153,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_BN_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_NL_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_XS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MV_IQ3_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_KSS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ5_KS_F32, @@ -192,6 +194,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_BN_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_NL_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_XS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ3_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_KSS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ5_KS_F32, @@ -229,6 +232,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_BN_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_NL_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_XS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KSS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F32, @@ -266,6 +270,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_BN_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_NL_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_XS_F16, + GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_KS_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KS_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KSS_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F16, @@ -303,6 +308,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_BN_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_NL_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_XS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ3_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_KSS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_KS_F32, @@ -756,6 +762,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_BN, get_rows_iq2_bn, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_NL, get_rows_iq4_nl, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_XS, get_rows_iq4_xs, true); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ3_KS, get_rows_iq3_ks, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_KS, get_rows_iq4_ks, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_KSS, get_rows_iq4_kss, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_KS, get_rows_iq5_ks, true); @@ -802,6 +809,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_BN_F32, mul_mv_iq2_bn_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_NL_F32, mul_mv_iq4_nl_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_XS_F32, mul_mv_iq4_xs_f32, ctx->support_simdgroup_reduction); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ3_KS_F32, mul_mv_iq3_ks_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_KS_F32, mul_mv_iq4_ks_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_KSS_F32, mul_mv_iq4_kss_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ5_KS_F32, mul_mv_iq5_ks_f32, ctx->support_simdgroup_reduction); @@ -842,6 +850,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_BN_F32, mul_mv_id_iq2_bn_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_NL_F32, mul_mv_id_iq4_nl_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_XS_F32, mul_mv_id_iq4_xs_f32, ctx->support_simdgroup_reduction); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ3_KS_F32, mul_mv_id_iq3_ks_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_KS_F32, mul_mv_id_iq4_ks_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_KSS_F32, mul_mv_id_iq4_kss_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ5_KS_F32, mul_mv_id_iq5_ks_f32, ctx->support_simdgroup_reduction); @@ -879,6 +888,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_BN_F32, mul_mm_iq2_bn_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_NL_F32, mul_mm_iq4_nl_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_XS_F32, mul_mm_iq4_xs_f32, ctx->support_simdgroup_mm); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_KS_F32, mul_mm_iq3_ks_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KS_F32, mul_mm_iq4_ks_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KSS_F32, mul_mm_iq4_kss_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F32, mul_mm_iq5_ks_f32, ctx->support_simdgroup_mm); @@ -916,6 +926,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_BN_F16, mul_mm_iq2_bn_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_NL_F16, mul_mm_iq4_nl_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_XS_F16, mul_mm_iq4_xs_f16, ctx->support_simdgroup_mm); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_KS_F16, mul_mm_iq3_ks_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KS_F16, mul_mm_iq4_ks_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KSS_F16, mul_mm_iq4_kss_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F16, mul_mm_iq5_ks_f16, ctx->support_simdgroup_mm); @@ -953,6 +964,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_BN_F32, mul_mm_id_iq2_bn_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_NL_F32, mul_mm_id_iq4_nl_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_XS_F32, mul_mm_id_iq4_xs_f32, ctx->support_simdgroup_mm); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ3_KS_F32, mul_mm_id_iq3_ks_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_KS_F32, mul_mm_id_iq4_ks_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_KSS_F32, mul_mm_id_iq4_kss_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_KS_F32, mul_mm_id_iq5_ks_f32, ctx->support_simdgroup_mm); @@ -2169,6 +2181,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ2_BN: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_BN_F32 ].pipeline; break; case GGML_TYPE_IQ4_NL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_NL_F32 ].pipeline; break; case GGML_TYPE_IQ4_XS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_XS_F32 ].pipeline; break; + case GGML_TYPE_IQ3_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_KS_F32 ].pipeline; break; case GGML_TYPE_IQ4_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KS_F32 ].pipeline; break; case GGML_TYPE_IQ4_KSS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KSS_F32].pipeline; break; case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F32 ].pipeline; break; @@ -2211,6 +2224,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ2_BN: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_BN_F16 ].pipeline; break; case GGML_TYPE_IQ4_NL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_NL_F16 ].pipeline; break; case GGML_TYPE_IQ4_XS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_XS_F16 ].pipeline; break; + case GGML_TYPE_IQ3_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_KS_F16 ].pipeline; break; case GGML_TYPE_IQ4_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KS_F16 ].pipeline; break; case GGML_TYPE_IQ4_KSS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_KSS_F16].pipeline; break; case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F16 ].pipeline; break; @@ -2428,6 +2442,12 @@ static void ggml_metal_encode_node( nth1 = 16; pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_XS_F32].pipeline; } break; + case GGML_TYPE_IQ3_KS: + { + nth0 = 4; + nth1 = 16; + pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_IQ3_KS_F32].pipeline; + } break; case GGML_TYPE_IQ4_KS: { nth0 = 4; @@ -2535,8 +2555,9 @@ static void ggml_metal_encode_node( src0t == GGML_TYPE_IQ2_KT|| src0t == GGML_TYPE_IQ3_KT) { //|| src0t == GGML_TYPE_IQ4_KT) { [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, ne11, ne12*ne13) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; } - else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K) { - const int mem_size = src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) : src0t == GGML_TYPE_IQ3_K ? 32*sizeof(float) : 16*sizeof(float); + else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS) { + const int mem_size = src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) + : src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS ? 32*sizeof(float) : 16*sizeof(float); [encoder setThreadgroupMemoryLength:mem_size atIndex:0]; [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, ne11, ne12*ne13) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; } @@ -2648,6 +2669,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ2_BN: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_BN_F32 ].pipeline; break; case GGML_TYPE_IQ4_NL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_NL_F32 ].pipeline; break; case GGML_TYPE_IQ4_XS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_XS_F32 ].pipeline; break; + case GGML_TYPE_IQ3_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ3_KS_F32 ].pipeline; break; case GGML_TYPE_IQ4_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_KS_F32 ].pipeline; break; case GGML_TYPE_IQ4_KSS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_KSS_F32].pipeline; break; case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_KS_F32 ].pipeline; break; @@ -2849,6 +2871,12 @@ static void ggml_metal_encode_node( nth1 = 2; pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_XS_F32].pipeline; } break; + case GGML_TYPE_IQ3_KS: + { + nth0 = 4; + nth1 = 16; + pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ3_KS_F32].pipeline; + } break; case GGML_TYPE_IQ4_KS: { nth0 = 4; @@ -2967,8 +2995,9 @@ static void ggml_metal_encode_node( src0t == GGML_TYPE_IQ2_KT|| src0t == GGML_TYPE_IQ3_KT) { //|| src0t == GGML_TYPE_IQ4_KT) { [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, _ne1, tgz) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; } - else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K) { - const int mem_size = src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) : src0t == GGML_TYPE_IQ3_K ? 32*sizeof(float) : 16*sizeof(float); + else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS) { + const int mem_size = src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) + : src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS ? 32*sizeof(float) : 16*sizeof(float); [encoder setThreadgroupMemoryLength:mem_size atIndex:0]; [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, _ne1, tgz) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; } @@ -3036,6 +3065,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ2_BN: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_BN ].pipeline; break; case GGML_TYPE_IQ4_NL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_NL ].pipeline; break; case GGML_TYPE_IQ4_XS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_XS ].pipeline; break; + case GGML_TYPE_IQ3_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ3_KS ].pipeline; break; case GGML_TYPE_IQ4_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_KS ].pipeline; break; case GGML_TYPE_IQ4_KSS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_KSS].pipeline; break; case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_KS ].pipeline; break; diff --git a/ggml/src/ggml-metal.metal b/ggml/src/ggml-metal.metal index e3bd070d..baaac407 100644 --- a/ggml/src/ggml-metal.metal +++ b/ggml/src/ggml-metal.metal @@ -7371,6 +7371,158 @@ kernel void kernel_mul_mv_iq3_k_f32( kernel_mul_mv_iq3_k_f32_impl(src0, src1, dst, ne00, ne01, ne02, ne10, ne12, ne0, ne1, r2, r3, shared_values, tgpig, tiisg, sgitg); } +// TODO +void kernel_mul_mv_iq3_ks_f32_impl( + device const void * src0, + device const float * src1, + device float * dst, + int64_t ne00, + int64_t ne01, + int64_t ne02, + int64_t ne10, + int64_t ne12, + int64_t ne0, + int64_t ne1, + uint r2, + uint r3, + threadgroup int8_t * shared_values, + uint3 tgpig, + uint tiisg, + uint sgitg) { + + const int nb = ne00/QK_K; + const int r0 = tgpig.x; + const int r1 = tgpig.y; + const int im = tgpig.z; + + const int first_row = (r0 * N_SIMDGROUP + sgitg) * N_DST; + + const uint i12 = im%ne12; + const uint i13 = im/ne12; + + const uint offset0 = (i12/r2)*(nb*ne01) + (i13/r3)*(nb*ne01*ne02); + + const uint row_size = sizeof(half) + nb*sizeof(block_iq3_ks); + device const char * cx = (device const char *)src0 + (first_row + offset0)*row_size; + device const float * y = (device const float *)src1 + r1*ne10 + im*ne00*ne1; + + threadgroup float * all_values = (threadgroup float *)shared_values + 16*sgitg; + { + if (tiisg < 16) all_values[tiisg] = kvalues_iq3k_f[tiisg]; + simdgroup_barrier(mem_flags::mem_none); + } + + float yl[32]; + float sumf[N_DST]={0.f}; + float d[N_DST]; + + const int ix = tiisg/8; // 0...3 + const int it = tiisg%8; // 0...7 + const int iq = it/4; // 0 or 1 + const int ir = it%4; // 0...3 + + device const half * dptr = (device const half *)cx; + d[0] = (float)dptr[0]; + for (int i = 1; i < N_DST; ++i) { + dptr += row_size/2; + d[i] = (float)dptr[0]; + } + + device const float * y4 = y + ix * QK_K + 128 * iq + 8 * ir; + + uint32_t vl[2], vh[2]; + uint32_t aux32[2]; + thread const uint8_t * aux8 = (thread const uint8_t *)aux32; + + for (int ib = ix; ib < nb; ib += 4) { + + for (int i = 0; i < 8; ++i) { + yl[i+ 0] = y4[i+ 0]; + yl[i+ 8] = y4[i+32]; + yl[i+16] = y4[i+64]; + yl[i+24] = y4[i+96]; + } + + for (int row = 0; row < N_DST; row++) { + + device const block_iq3_ks * x = (device const block_iq3_ks *)(cx + row_size*row + sizeof(half)); + device const block_iq3_ks & xb = x[ib]; + device const uint16_t * ql16 = (device const uint16_t *)xb.qs + 16*iq + 4*ir; + device const uint16_t * qh16 = (device const uint16_t *)xb.qh + 4*ir; + device const uint16_t * sc16 = (device const uint16_t *)xb.scales; + + uint8_t extra_s = (xb.extra & 0xff) >> 4*iq; + uint8_t extra_v = xb.extra >> (8 + 4*iq); + + uint32_t scales32 = sc16[0] | (sc16[1] << 16); + scales32 = (scales32 >> 4*iq) & 0x0f0f0f0f; + thread int8_t * s8 = (thread int8_t *)&scales32; + s8[0] += ((extra_s << 4) & 0x10) - 16; + s8[1] += ((extra_s << 3) & 0x10) - 16; + s8[2] += ((extra_s << 2) & 0x10) - 16; + s8[3] += ((extra_s << 1) & 0x10) - 16; + + vl[0] = ql16[0] | ql16[1] << 16; + vl[1] = ql16[2] | ql16[3] << 16; + vh[0] = ((qh16[0] | (qh16[1] << 16)) << 4*(1-iq)) >> 2; + vh[1] = ((qh16[2] | (qh16[3] << 16)) << 4*(1-iq)) >> 2; + + float4 acc = {0.f}; + for (int l = 0; l < 4; ++l) { + threadgroup const float * values = all_values + ((extra_v & 1) << 3); + aux32[0] = (vl[0] & 0x03030303) | (vh[0] & 0x04040404); + aux32[1] = (vl[1] & 0x03030303) | (vh[1] & 0x04040404); + for (int j = 0; j < 8; ++j) acc[l] += yl[8*l+j] * values[aux8[j]]; + vl[0] >>= 2; vl[1] >>= 2; + vh[0] >>= 1; vh[1] >>= 1; + extra_v >>= 1; + } + + sumf[row] += d[row] * (acc[0] * s8[0] + acc[1] * s8[1] + acc[2] * s8[2] + acc[3] * s8[3]); + + } + + y4 += 4 * QK_K; + } + + for (int row = 0; row < N_DST; row += 2) { + float2 tmp{sumf[row], sumf[row+1]}; + tmp = simd_sum(tmp); + if (tiisg < 2) { + dst[r1*ne0 + im*ne0*ne1 + first_row + row + tiisg] = tmp[tiisg]; + } + } +} + +[[host_name("kernel_mul_mv_iq3_ks_f32")]] +kernel void kernel_mul_mv_iq3_ks_f32( + device const void * src0, + device const float * 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 int64_t & ne12, + constant uint64_t & nb10, + constant uint64_t & nb11, + constant uint64_t & nb12, + constant int64_t & ne0, + constant int64_t & ne1, + constant uint & r2, + constant uint & r3, + threadgroup int8_t * shared_values [[threadgroup(0)]], + uint3 tgpig[[threadgroup_position_in_grid]], + uint tiisg[[thread_index_in_simdgroup]], + uint sgitg[[simdgroup_index_in_threadgroup]]) { + + kernel_mul_mv_iq3_ks_f32_impl(src0, src1, dst, ne00, ne01, ne02, ne10, ne12, ne0, ne1, r2, r3, shared_values, tgpig, tiisg, sgitg); +} + void kernel_mul_mv_iq4_k_f32_impl( device const void * src0, device const float * src1, @@ -8688,6 +8840,29 @@ void dequantize_iq3_k(device const block_iq3_k * xb, short il, thread type4x4 & } } +template +void dequantize_iq3_ks(device const block_iq3_ks * xb, short il, thread type4x4 & reg) { + // il is 0...15 for QK_K = 256 + int ib32 = il/2; + device const uint16_t * q16l = (device const uint16_t *)xb->qs + 16*(il/8) + 8*(il&1); + device const uint16_t * q16h = (device const uint16_t *)xb->qh + 8*(il&1); + + int8_t ls = int8_t(((xb->scales[ib32%4] >> 4*(ib32/4)) & 0xf) | (((xb->extra >> ib32) & 1) << 4)) - 16; + half d = ls; + + constant half * values = kvalues_iq3k_h + 8*((xb->extra >> (8+ib32)) & 1); + + const int shift = 2*((il%8)/2); + uint32_t aux32; + thread const uint8_t * aux8 = (thread const uint8_t *)&aux32; + for (int i = 0; i < 4; ++i) { + uint32_t vl = q16l[2*i+0] | (q16l[2*i+1] << 16); + uint32_t vh = q16h[2*i+0] | (q16h[2*i+1] << 16); + aux32 = ((vl >> shift) & 0x03030303) | (((vh >> ((il/2)%8)) << 2) & 0x04040404); + for (int j = 0; j < 4; ++j) reg[i][j] = d * values[aux8[j]]; + } +} + template void dequantize_iq4_k(device const block_iq4_k * xb, short il, thread type4x4 & reg) { // il is 0...15 for QK_K = 256 => index of block of 32 is il/2 @@ -9416,6 +9591,7 @@ template [[host_name("kernel_get_rows_iq5_k")]] kernel get_rows_q_t kernel_get template [[host_name("kernel_get_rows_iq6_k")]] kernel get_rows_q_t kernel_get_rows_q; template [[host_name("kernel_get_rows_iq1_bn")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq2_bn")]] kernel get_rows_q_t kernel_get_rows_q2>; +template [[host_name("kernel_get_rows_iq3_ks")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq4_ks")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq5_ks")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq4_kss")]] kernel get_rows_q_t kernel_get_rows_q2>; @@ -9463,6 +9639,7 @@ template [[host_name("kernel_mul_mm_iq5_k_f32")]] kernel mat_mm_t kernel_mul_m template [[host_name("kernel_mul_mm_iq6_k_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq1_bn_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq2_bn_f32")]] kernel mat_mm_t kernel_mul_mm, float>; +template [[host_name("kernel_mul_mm_iq3_ks_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq4_ks_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq5_ks_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq4_kss_f32")]] kernel mat_mm_t kernel_mul_mm, float>; @@ -9501,6 +9678,7 @@ template [[host_name("kernel_mul_mm_iq5_k_f16")]] kernel mat_mm_t kernel_mul_m template [[host_name("kernel_mul_mm_iq6_k_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq1_bn_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq2_bn_f16")]] kernel mat_mm_t kernel_mul_mm, half>; +template [[host_name("kernel_mul_mm_iq3_ks_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq4_ks_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq5_ks_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq4_kss_f16")]] kernel mat_mm_t kernel_mul_mm, half>; @@ -9546,6 +9724,7 @@ template [[host_name("kernel_mul_mm_id_iq5_k_f32")]] kernel mat_mm_id_t kernel template [[host_name("kernel_mul_mm_id_iq6_k_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq1_bn_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq2_bn_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; +template [[host_name("kernel_mul_mm_id_iq3_ks_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq4_ks_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq5_ks_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq4_kss_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; @@ -9766,6 +9945,7 @@ template [[host_name("kernel_mul_mv_id_iq3_s_f32")]] kernel kernel_mul_mv_id_t template [[host_name("kernel_mul_mv_id_iq2_s_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq4_nl_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq4_xs_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; +template [[host_name("kernel_mul_mv_id_iq3_ks_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq4_ks_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq5_ks_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq4_kss_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; diff --git a/ggml/src/ggml-quants.c b/ggml/src/ggml-quants.c index 220c0c99..96242727 100644 --- a/ggml/src/ggml-quants.c +++ b/ggml/src/ggml-quants.c @@ -15425,6 +15425,7 @@ bool ggml_validate_row_data(enum ggml_type type, const void * data, size_t nbyte case GGML_TYPE_IQ3_KT: break; case GGML_TYPE_IQ4_KT: break; case GGML_TYPE_IQ3_K: break; + case GGML_TYPE_IQ3_KS: break; case GGML_TYPE_IQ4_K: break; case GGML_TYPE_IQ5_K: break; case GGML_TYPE_IQ6_K: break; diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index 97b5bff7..2e6983df 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -1656,6 +1656,19 @@ static const ggml_type_traits_t type_traits[GGML_TYPE_COUNT] = { .nrows = 1, .row_meta_size = 0, }, + [GGML_TYPE_IQ3_KS] = { + .type_name = "iq3_ks", + .blck_size = QK_K, + .type_size = sizeof(block_iq3_ks), + .is_quantized = true, + .to_float = (ggml_to_float_t) dequantize_row_iq3_ks, + .from_float = quantize_row_iq3_ks, + .from_float_ref = (ggml_from_float_t)quantize_row_iq3_ks_ref, + .vec_dot = vec_dot_iq3_ks_q8_k, + .vec_dot_type = GGML_TYPE_Q8_K, + .nrows = 1, + .row_meta_size = 2, + }, [GGML_TYPE_IQ4_K] = { .type_name = "iq4_k", .blck_size = QK_K, @@ -4578,6 +4591,7 @@ enum ggml_type ggml_ftype_to_ggml_type(enum ggml_ftype ftype) { case GGML_FTYPE_MOSTLY_IQ3_KT: wtype = GGML_TYPE_IQ3_KT; break; case GGML_FTYPE_MOSTLY_IQ4_KT: wtype = GGML_TYPE_IQ4_KT; break; case GGML_FTYPE_MOSTLY_IQ3_K: wtype = GGML_TYPE_IQ3_K; break; + case GGML_FTYPE_MOSTLY_IQ3_KS: wtype = GGML_TYPE_IQ3_KS; break; case GGML_FTYPE_MOSTLY_IQ4_K: wtype = GGML_TYPE_IQ4_K; break; case GGML_FTYPE_MOSTLY_IQ3_K_R4: wtype = GGML_TYPE_IQ3_K_R4; break; case GGML_FTYPE_MOSTLY_IQ4_K_R4: wtype = GGML_TYPE_IQ4_K_R4; break; @@ -11347,6 +11361,7 @@ static void ggml_compute_forward_add( case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -11824,6 +11839,7 @@ static void ggml_compute_forward_add1( case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -11998,6 +12014,7 @@ static void ggml_compute_forward_acc( case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -15499,6 +15516,7 @@ static void ggml_compute_forward_out_prod( case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -15913,6 +15931,7 @@ static void ggml_compute_forward_set( case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -16233,6 +16252,7 @@ static void ggml_compute_forward_get_rows( case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -16870,6 +16890,7 @@ static void ggml_compute_forward_clamp( case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -23943,6 +23964,7 @@ size_t ggml_quantize_chunk( case GGML_TYPE_IQ3_KT: result = quantize_iq3_kt (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ4_KT: result = quantize_iq4_kt (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ3_K: result = quantize_iq3_k (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; + case GGML_TYPE_IQ3_KS: result = quantize_iq3_ks (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ4_K: result = quantize_iq4_k (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ3_K_R4:result = quantize_iq3_k_r4(src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ4_K_R4:result = quantize_iq4_k_r4(src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; diff --git a/ggml/src/iqk/iqk_gemm_iqk_quants.cpp b/ggml/src/iqk/iqk_gemm_iqk_quants.cpp index 2105ac00..57038d0c 100644 --- a/ggml/src/iqk/iqk_gemm_iqk_quants.cpp +++ b/ggml/src/iqk/iqk_gemm_iqk_quants.cpp @@ -1,4 +1,5 @@ #include "iqk_gemm_iqk_quants.h" +#include #ifdef IQK_IMPLEMENT @@ -214,6 +215,68 @@ struct DequantizerIQ3K final : public BaseDequantizer { constexpr static uint8_t k_shuff[16] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; }; +struct DequantizerIQ3KS final : public BaseDequantizer { + DequantizerIQ3KS(const void * vx, size_t bx) : BaseDequantizer(vx, bx), values(load_values()) {} + template + inline void compute_block(int i, const Q8& q8, __m512 * acc) { + uint32_t aux32; std::memcpy(&aux32, x[i].scales, 4); + auto scl = _mm_srlv_epi32(_mm_set1_epi32(aux32), _mm_set_epi32(0, 0, 4, 0)); + auto scales128 = _mm_cvtepu8_epi16(_mm_and_si128(scl, _mm_set1_epi8(0xf))); + scales128 = _mm_mask_add_epi16(scales128, __mmask8(x[i].extra & 0xff), scales128, _mm_set1_epi16(16)); + scales128 = _mm_sub_epi16(scales128, _mm_set1_epi16(16)); + auto shifts = _mm_mask_add_epi16(m64, __mmask8(x[i].extra >> 8), m64, _mm_set1_epi16(4)); + auto mins128 = _mm_mullo_epi16(scales128, shifts); + auto mins = MM256_SET_M128I(_mm_shuffle_epi8(mins128, s8k.shuffles[1]), _mm_shuffle_epi8(mins128, s8k.shuffles[0])); + auto scales256 = MM256_SET_M128I(scales128, scales128); + auto all_scales = _mm512_inserti32x8(_mm512_castsi256_si512(scales256), scales256, 1); + __m512i scales[4]; + for (int k = 0; k < 4; ++k) scales[k] = _mm512_shuffle_epi8(all_scales, shuffles[k]); + prepare(x[i].qs, x[i].qh); + for (int iy = 0; iy < Q8::nrc_y; ++iy) { + auto q8s = q8.load_bsums(iy, i); + auto prod = _mm256_madd_epi16(mins, q8s); + auto sumi = _mm512_inserti32x8(_mm512_setzero_si512(), prod, 0); + for (int k = 0; k < 4; ++k) { + auto p = _mm512_maddubs_epi16(bits.values[k], q8.load_quants64(iy, i, k)); + sumi = _mm512_dpwssd_epi32(sumi, p, scales[k]); + } + acc[iy] = _mm512_fmadd_ps(_mm512_set1_ps(d*q8.scale(iy, i)), _mm512_cvtepi32_ps(sumi), acc[iy]); + } + } + inline void prepare(const uint8_t * q2, const uint8_t * qh) { + bits.prepare(q2); + auto h256 = _mm256_loadu_si256((const __m256i *)qh); + auto hbits = _mm512_inserti32x8(_mm512_castsi256_si512(h256), _mm256_srli_epi16(h256, 1), 1); + bits.values[0] = _mm512_or_si512(bits.values[0], _mm512_and_si512(_mm512_slli_epi16(hbits, 2), hmask)); + bits.values[1] = _mm512_or_si512(bits.values[1], _mm512_and_si512(hbits, hmask)); + bits.values[2] = _mm512_or_si512(bits.values[2], _mm512_and_si512(_mm512_srli_epi16(hbits, 2), hmask)); + bits.values[3] = _mm512_or_si512(bits.values[3], _mm512_and_si512(_mm512_srli_epi16(hbits, 4), hmask)); + bits.values[0] = _mm512_shuffle_epi8(values, bits.values[0]); + bits.values[1] = _mm512_shuffle_epi8(values, bits.values[1]); + bits.values[2] = _mm512_shuffle_epi8(values, bits.values[2]); + bits.values[3] = _mm512_shuffle_epi8(values, bits.values[3]); + } + static inline __m512i load_values() { + static const uint8_t kvalues_iq3nl[16] = {1, 24, 41, 54, 65, 77, 92, 111, 5, 28, 45, 58, 69, 81, 96, 115}; + auto val128 = _mm_loadu_si128((const __m128i *)kvalues_iq3nl); + auto val256 = MM256_SET_M128I(val128, val128); + return _mm512_inserti32x8(_mm512_castsi256_si512(val256), val256, 1); + } + + Q2Bits bits; + Scales8KBase s8k; + + const __m128i m64 = _mm_set1_epi16(-64); + const __m512i values; + const __m512i hmask = _mm512_set1_epi8(4); + const __m512i shuffles[4] = { + _mm512_inserti32x8(_mm512_set1_epi16(0x0100), _mm256_set1_epi16(0x0302), 1), + _mm512_inserti32x8(_mm512_set1_epi16(0x0504), _mm256_set1_epi16(0x0706), 1), + _mm512_inserti32x8(_mm512_set1_epi16(0x0908), _mm256_set1_epi16(0x0b0a), 1), + _mm512_inserti32x8(_mm512_set1_epi16(0x0d0c), _mm256_set1_epi16(0x0f0e), 1), + }; +}; + struct DequantizerIQ4KSS final : public BaseDequantizer { DequantizerIQ4KSS(const void * vx, size_t bx) : BaseDequantizer(vx, bx), values(load_iq4nl_values_512()) {} template @@ -922,6 +985,40 @@ struct DequantizerIQ3K final : public BaseDequantizer { constexpr static uint8_t k_shuff[16] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; }; +struct DequantizerIQ3KS final : public BaseDequantizer { + DequantizerIQ3KS(const void * vx, size_t bx) : BaseDequantizer(vx, bx), values(load_values()) {} + template + inline __m256i new_block(int i, [[maybe_unused]] const Q8& q8, [[maybe_unused]] __m256 * accd) { + uint32_t aux32; std::memcpy(&aux32, x[i].scales, 4); + auto scl = _mm_cvtepi8_epi16(_mm_and_si128(_mm_srlv_epi32(_mm_set1_epi32(aux32), _mm_set_epi32(0, 0, 4, 0)), _mm_set1_epi8(0xf))); + auto sch = _mm_cmpeq_epi16(_mm_and_si128(_mm_set1_epi16(x[i].extra), mask), mask); + auto scales128 = _mm_add_epi16(scl, _mm_and_si128(sch, _mm_set1_epi16(16))); + scales128 = _mm_sub_epi16(scales128, _mm_set1_epi16(16)); + return MM256_SET_M128I(scales128, scales128); + } + inline void prepare(int i, int j) { + uint8_t extra = x[i].extra >> (8 + 4*j); + hbits = j == 0 ? _mm256_loadu_si256((const __m256i *)x[i].qh) : _mm256_srli_epi16(hbits, 4); + bits.prepare(x[i].qs, j); + bits.values[0] = _mm256_add_epi8(_mm256_set1_epi8((extra << 3) & 8), _mm256_or_si256(bits.values[0], _mm256_and_si256(_mm256_slli_epi16(hbits, 2), mh))); + bits.values[1] = _mm256_add_epi8(_mm256_set1_epi8((extra << 2) & 8), _mm256_or_si256(bits.values[1], _mm256_and_si256(_mm256_slli_epi16(hbits, 1), mh))); + bits.values[2] = _mm256_add_epi8(_mm256_set1_epi8((extra << 1) & 8), _mm256_or_si256(bits.values[2], _mm256_and_si256(hbits, mh))); + bits.values[3] = _mm256_add_epi8(_mm256_set1_epi8((extra << 0) & 8), _mm256_or_si256(bits.values[3], _mm256_and_si256(_mm256_srli_epi16(hbits, 1), mh))); + for (int k = 0; k < 4; ++k) bits.values[k] = _mm256_shuffle_epi8(values, bits.values[k]); + } + inline __m256i load_values() { + auto v = _mm_loadu_si128((const __m128i *)iq3nl_values); + return MM256_SET_M128I(v, v); + } + + + Q2Bits bits; + __m256i hbits; + const __m256i values; + const __m256i mh = _mm256_set1_epi8(4); + const __m128i mask = _mm_setr_epi16(0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80); +}; + struct DequantizerIQ4KSS final : public BaseDequantizer { DequantizerIQ4KSS(const void * vx, size_t bx) : BaseDequantizer(vx, bx), values(load_iq4nl_values_256()) {} template @@ -1286,7 +1383,7 @@ static void mul_mat_qX_K_q8_K_T(int n, const void * vx, size_t bx, const DataInf set_scales_8(all_scales, j, scales); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { multiply_add_avx2(deq.bits, scales, j, i, q8, sumi); } else { multiply_add(deq.bits, scales, j, i, q8, sumi); @@ -2030,6 +2127,7 @@ static void mul_mat_iq5_ks_r4_q8_k(int n, const void * vx, size_t bx, const Data template void set_functions(std::array& funcs) { #ifdef HAVE_FANCY_SIMD if constexpr (std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v) { IQK_SET_MUL_MAT_FUNCTIONS_T(mul_mat_iqX_k_q8_K_AVX512_new, Dequantizer, funcs) @@ -2307,6 +2405,65 @@ void iqk_convert_iq3_k_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int } } +void iqk_convert_iq3_ks_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { + GGML_ASSERT(n%QK_K == 0); + GGML_ASSERT(nrc_x%8 == 0); + + int nb = n/QK_K; + + const block_iq3_ks * x8[8]; + + block_q8_k_r8 * y = (block_q8_k_r8 *)vy; + + __m256i values; + { + auto v = _mm_loadu_si128((const __m128i *)iq3nl_values); + values = MM256_SET_M128I(v, v); + } + + ggml_half drow[8]; + float dnew[8]; + int16_t ls[16]; + + __m256i xv[8]; + uint32_t block[8]; + + for (int ix = 0; ix < nrc_x; ix += 8) { + for (int k = 0; k < 8; ++k) { + const ggml_half * dptr = (const ggml_half *)((const char *)vx + (ix + k)*bx); + drow[k] = dptr[0]; + x8[k] = (const block_iq3_ks *)(dptr + 1); + } + auto vd = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)drow)); + for (int i = 0; i < nb; ++i) { + for (int k = 0; k < 8; ++k) { + auto hbits = _mm256_loadu_si256((const __m256i *)x8[k][i].qh); + auto extra = x8[k][i].extra; + uint8_t extra_v = extra >> 8; + for (int j = 0; j < 4; ++j) { + ls[2*j+0] = ls[2*j+1] = ((x8[k][i].scales[j] & 0xf) | ((extra << 4) & 0x10)) - 16; + ls[2*j+8] = ls[2*j+9] = ((x8[k][i].scales[j] >> 4) | ((extra << 0) & 0x10)) - 16; + extra >>= 1; + } + for (int i128 = 0; i128 < QK_K/128; ++i128) { + auto lbits = _mm256_loadu_si256((const __m256i *)x8[k][i].qs + i128); + for (int j = 0; j < 4; ++j) { + xv[4*i128+j] = _mm256_or_si256(_mm256_and_si256(lbits, _mm256_set1_epi8(3)), _mm256_and_si256(_mm256_slli_epi16(hbits, 2), _mm256_set1_epi8(4))); + xv[4*i128+j] = _mm256_add_epi8(xv[4*i128+j], _mm256_set1_epi8((extra_v & 1) << 3)); + xv[4*i128+j] = _mm256_shuffle_epi8(values, xv[4*i128+j]); + extra_v >>= 1; + lbits = _mm256_srli_epi16(lbits, 2); + hbits = _mm256_srli_epi16(hbits, 1); + } + } + dnew[k] = convert_to_q8_k_r8(k, 1.f/127, xv, ls, block, y[i].qs); + } + _mm_storeu_si128((__m128i *)y[i].d, _mm256_cvtps_ph(_mm256_mul_ps(vd, _mm256_loadu_ps(dnew)), _MM_ROUND_NEAREST)); + } + y += nb; + } +} + void iqk_convert_iq4_ks_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { GGML_ASSERT(n%QK_K == 0); GGML_ASSERT(nrc_x%8 == 0); @@ -2730,6 +2887,7 @@ bool iqk_convert_iqk_quants_q80_r8(int type, int n, const void * vx, size_t bx, switch (ggml_type(type)) { case GGML_TYPE_IQ2_KS : iqk_convert_iq2_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ2_K : iqk_convert_iq2_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; + case GGML_TYPE_IQ3_KS : iqk_convert_iq3_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ3_K : iqk_convert_iq3_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ4_KS : iqk_convert_iq4_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ4_K : iqk_convert_iq4_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; @@ -2758,6 +2916,9 @@ bool iqk_set_kernels_iqk_quants(int ne00, int typeA, int typeB, std::array(kernels); break; + case GGML_TYPE_IQ3_KS: + set_functions(kernels); + break; case GGML_TYPE_IQ3_K: set_functions(kernels); break; @@ -3080,6 +3241,58 @@ struct DequantizerIQ3K final : public BaseDequantizer { }; +struct DequantizerIQ3KS final : public BaseDequantizer { + + DequantizerIQ3KS(const void * vx, size_t bx, int nrc) : BaseDequantizer(vx, bx, nrc), values(load_values()) {} + + constexpr static int num_blocks() { return 8; } + constexpr static bool should_scale_quants() { return false; } + + template + inline int32x4x2_t new_block(int i, const Q8& q8, float32x4_t * acc) { + (void)q8; + (void)acc; + uint32_t aux32; std::memcpy(&aux32, x[i].scales, 4); + auto scl8 = vand_s8(vreinterpret_s8_u32(uint32x2_t{aux32, aux32 >> 4}), vdup_n_s8(0xf)); + auto sch8 = vdup_n_u8(x[i].extra & 0xff); + sch8 = vand_u8(vceq_u8(vand_u8(sch8, shmask), shmask), vdup_n_u8(16)); + scl8 = vsub_s8(vadd_s8(scl8, vreinterpret_s8_u8(sch8)), vdup_n_s8(16)); + auto scales16 = vmovl_s8(scl8); + int32x4x2_t scales = {vmovl_s16(vget_low_s16(scales16)), vmovl_s16(vget_high_s16(scales16))}; + return scales; + } + inline void prepare(int i, int j) { + bits.prepare(x[i].qs+32*j); + if (j == 0) { + hbits = vld1q_u8_x2(x[i].qh); + } + else { + hbits.val[0] = vshrq_n_u8(hbits.val[0], 4); + hbits.val[1] = vshrq_n_u8(hbits.val[1], 4); + } + uint8_t extra = x[i].extra >> (8 + 4*j); + bits.b1.val[0] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b1.val[0], vandq_u8(vshlq_n_u8(hbits.val[0], 2), hmask))); + bits.b1.val[1] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b1.val[1], vandq_u8(vshlq_n_u8(hbits.val[1], 2), hmask))); extra >>= 1; + bits.b1.val[2] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b1.val[2], vandq_u8(vshlq_n_u8(hbits.val[0], 1), hmask))); + bits.b1.val[3] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b1.val[3], vandq_u8(vshlq_n_u8(hbits.val[1], 1), hmask))); extra >>= 1; + bits.b2.val[0] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b2.val[0], vandq_u8(hbits.val[0], hmask))); + bits.b2.val[1] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b2.val[1], vandq_u8(hbits.val[1], hmask))); extra >>= 1; + bits.b2.val[2] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b2.val[2], vandq_u8(vshrq_n_u8(hbits.val[0], 1), hmask))); + bits.b2.val[3] = vqtbl1q_s8(values.val[extra & 1], vorrq_u8(bits.b2.val[3], vandq_u8(vshrq_n_u8(hbits.val[1], 1), hmask))); + } + static int8x16x2_t load_values() { + auto v1 = vld1_s8(iq3nl_values + 0); + auto v2 = vld1_s8(iq3nl_values + 8); + return { vcombine_s8(v1, v1), vcombine_s8(v2, v2) }; + } + + Q2bits bits; + uint8x16x2_t hbits; + const int8x16x2_t values; + const uint8x16_t hmask = vdupq_n_u8(4); + const uint8x8_t shmask = vreinterpret_u8_u64(vdup_n_u64(0x8040201008040201)); +}; + struct DequantizerIQ4KS final : public BaseDequantizer { DequantizerIQ4KS(const void * vx, size_t bx, int nrc) : BaseDequantizer(vx, bx, nrc), values(vld1q_s8_x2(iq4k_values)) {} @@ -4196,6 +4409,71 @@ void iqk_convert_iq2_k_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int } } +void iqk_convert_iq3_ks_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { + GGML_ASSERT(n%QK_K == 0); + GGML_ASSERT(nrc_x%8 == 0); + + int nb = n/QK_K; + + const block_iq3_ks * x8[8]; + + block_q8_k_r8 * y = (block_q8_k_r8 *)vy; + + int8x16x2_t values; + { + auto v1 = vld1_s8(iq3nl_values+0); + auto v2 = vld1_s8(iq3nl_values+8); + values.val[0] = vcombine_s8(v1, v1); + values.val[1] = vcombine_s8(v2, v2); + } + + ggml_half dh[8]; + int8x16x2_t xv[8]; + uint32_t block[8]; + int8_t ls[16]; + + auto ml = vdupq_n_u8(0x03); + auto mh = vdupq_n_u8(0x04); + + for (int ix = 0; ix < nrc_x; ix += 8) { + for (int k = 0; k < 8; ++k) { + auto dptr = (const ggml_half *)((const char *)vx + (ix+k)*bx); + dh[k] = dptr[0]; + x8[k] = (const block_iq3_ks *)(dptr + 1); + } + for (int i = 0; i < nb; ++i) { + for (int k = 0; k < 8; ++k) { + auto extra = x8[k][i].extra; + auto extra_v = extra >> 8; + auto hbits = vld1q_u8_x2(x8[k][i].qh); + for (int i128 = 0; i128 < 2; ++i128) { + + ls[8*i128+0] = ls[8*i128+1] = int8_t(((x8[k][i].scales[0] >> 4*i128) & 0xf) | ((extra << 4) & 0x10)) - 16; + ls[8*i128+2] = ls[8*i128+3] = int8_t(((x8[k][i].scales[1] >> 4*i128) & 0xf) | ((extra << 3) & 0x10)) - 16; + ls[8*i128+4] = ls[8*i128+5] = int8_t(((x8[k][i].scales[2] >> 4*i128) & 0xf) | ((extra << 2) & 0x10)) - 16; + ls[8*i128+6] = ls[8*i128+7] = int8_t(((x8[k][i].scales[3] >> 4*i128) & 0xf) | ((extra << 1) & 0x10)) - 16; + + auto bits = vld1q_u8_x2(x8[k][i].qs+32*i128); + xv[4*i128+0].val[0] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vandq_u8(bits.val[0], ml), vandq_u8(vshlq_n_u8(hbits.val[0], 2), mh))); + xv[4*i128+0].val[1] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vandq_u8(bits.val[1], ml), vandq_u8(vshlq_n_u8(hbits.val[1], 2), mh))); extra_v >>= 1; + xv[4*i128+1].val[0] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vandq_u8(vshrq_n_u8(bits.val[0], 2), ml), vandq_u8(vshlq_n_u8(hbits.val[0], 1), mh))); + xv[4*i128+1].val[1] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vandq_u8(vshrq_n_u8(bits.val[1], 2), ml), vandq_u8(vshlq_n_u8(hbits.val[1], 1), mh))); extra_v >>= 1; + xv[4*i128+2].val[0] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vandq_u8(vshrq_n_u8(bits.val[0], 4), ml), vandq_u8(hbits.val[0], mh))); + xv[4*i128+2].val[1] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vandq_u8(vshrq_n_u8(bits.val[1], 4), ml), vandq_u8(hbits.val[1], mh))); extra_v >>= 1; + xv[4*i128+3].val[0] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vshrq_n_u8(bits.val[0], 6), vandq_u8(vshrq_n_u8(hbits.val[0], 1), mh))); + xv[4*i128+3].val[1] = vqtbl1q_s8(values.val[extra_v & 1], vorrq_u8(vshrq_n_u8(bits.val[1], 6), vandq_u8(vshrq_n_u8(hbits.val[1], 1), mh))); extra_v >>= 1; + hbits.val[0] = vshrq_n_u8(hbits.val[0], 4); + hbits.val[1] = vshrq_n_u8(hbits.val[1], 4); + extra >>= 4; + } + float dnew = convert_to_q8_k_r8(1.f/127, xv, ls, block, (uint32_t *)y[i].qs + k); + y[i].d[k] = GGML_FP32_TO_FP16(GGML_FP16_TO_FP32(dh[k])*dnew); + } + } + y += nb; + } +} + void iqk_convert_iq3_k_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { GGML_ASSERT(n%QK_K == 0); GGML_ASSERT(nrc_x%8 == 0); @@ -4405,6 +4683,7 @@ bool iqk_convert_iqk_quants_q80_r8(int type, int n, const void * vx, size_t bx, switch (ggml_type(type)) { case GGML_TYPE_IQ2_KS : iqk_convert_iq2_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ2_K : iqk_convert_iq2_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; + case GGML_TYPE_IQ3_KS : iqk_convert_iq3_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ3_K : iqk_convert_iq3_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ4_KS : iqk_convert_iq4_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ4_K : iqk_convert_iq4_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; @@ -4431,6 +4710,9 @@ bool iqk_set_kernels_iqk_quants(int ne00, int typeA, int typeB, std::array= 64 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ2_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ2_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; + case GGML_TYPE_IQ3_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ3_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ4_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ4_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; @@ -295,6 +296,7 @@ struct MulMat { case GGML_TYPE_IQ3_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ4_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ2_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; + case GGML_TYPE_IQ3_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ4_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ5_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ2_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; @@ -422,6 +424,7 @@ bool iqk_convert_repack(int typeA, int n, const void * vx, size_t bx, void * vy, return iqk_convert_iquants_q80_r8(typeA, n, vx, bx, vy, nrc_x); case GGML_TYPE_IQ2_KS: case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ4_KSS: case GGML_TYPE_IQ4_KS: @@ -824,6 +827,7 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& mm, int Ny) { case GGML_TYPE_IQ3_XXS_R4: case GGML_TYPE_IQ3_S_R4: return iqk_set_kernels_iquants(ne00, typeA, typeB, mm.funcs, mm.func16); + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ5_KS: case GGML_TYPE_IQ4_KSS: @@ -905,6 +909,7 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& m, int /*Ny*/) { return iqk_set_kernels_kquants(ne00, typeA, typeB, m.funcs, m.func16); case GGML_TYPE_IQ2_KS: case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ4_KSS: case GGML_TYPE_IQ4_KS: diff --git a/ggml/src/iqk/iqk_quantize.cpp b/ggml/src/iqk/iqk_quantize.cpp index 0384e49a..9095cda4 100644 --- a/ggml/src/iqk/iqk_quantize.cpp +++ b/ggml/src/iqk/iqk_quantize.cpp @@ -1819,6 +1819,237 @@ void vec_dot_iq3_k_q8_k(int n, float * s, size_t bs, const void * vx, size_t bx, GGML_ABORT("not implemented"); } +// +// ============================================== iq3_ks +// +namespace { +static void quantize_row_iq3_ks_impl(const int super_block_size, const int block_size, + int n_per_row, const float * x, char * cy, + float * all_scales, float * weight, + const int8_t * values, + const float * quant_weights, + const int ntry) { + + ggml_half * dptr = (ggml_half *)cy; + block_iq3_ks * y = (block_iq3_ks *)(dptr + 1); + + const int8_t * shifted_values = values + 8; + + float amax_scale = 0; + float max_scale = 0; + + for (int ibl = 0; ibl < n_per_row/super_block_size; ++ibl) { + memset(&y[ibl], 0, sizeof(block_iq3_ks)); + const float * xbl = x + ibl*super_block_size; + auto scales = all_scales + ibl*(super_block_size/block_size); + float sigma2 = 0; + for (int j = 0; j < super_block_size; ++j) sigma2 += xbl[j]*xbl[j]; + sigma2 *= 2.f/super_block_size; + for (int ib = 0; ib < super_block_size/block_size; ++ib) { + const float * xb = xbl + ib*block_size; + if (quant_weights) { + const float * qw = quant_weights + ibl*super_block_size + ib*block_size; + for (int j = 0; j < block_size; ++j) weight[j] = qw[j] * sqrtf(sigma2 + xb[j]*xb[j]); + } else { + for (int j = 0; j < block_size; ++j) weight[j] = xb[j]*xb[j]; + } + float amax = 0, max = 0; + for (int j = 0; j < block_size; ++j) { + float ax = fabsf(xb[j]); + if (ax > amax) { + amax = ax; max = xb[j]; + } + } + if (!amax) { + scales[ib] = 0; + continue; + } + float d = ntry > 0 ? -max/values[0] : max/values[0]; + float id = 1/d; + float sumqx_p = 0, sumq2_p = 0; + float sumqx_m = 0, sumq2_m = 0; + for (int j = 0; j < block_size; ++j) { + float w = weight[j]; + float al = id*xb[j]; + int l = best_index_iq3nl(values, al); + float q = values[l]; + sumqx_p += w*q*xb[j]; + sumq2_p += w*q*q; + l = best_index_iq3nl(values, -al); + q = values[l]; + sumqx_m += w*q*xb[j]; + sumq2_m += w*q*q; + } + d = sumqx_p/sumq2_p; + bool is_shifted = false; + float best = d*sumqx_p; + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d*sumqx_m; + } + for (int itry = -ntry; itry <= ntry; ++itry) { + id = (itry + values[0])/max; + sumqx_p = sumq2_p = 0; + sumqx_m = sumq2_m = 0; + for (int j = 0; j < block_size; ++j) { + float w = weight[j]; + float al = id*xb[j]; + int l = best_index_iq3nl(values, al); + float q = values[l]; + sumqx_p += w*q*xb[j]; + sumq2_p += w*q*q; + l = best_index_iq3nl(values, -al); + q = values[l]; + sumqx_m += w*q*xb[j]; + sumq2_m += w*q*q; + } + if (sumq2_p > 0 && sumqx_p*sumqx_p > best*sumq2_p) { + d = sumqx_p/sumq2_p; best = d * sumqx_p; is_shifted = false; + } + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d * sumqx_m; is_shifted = false; + } + id = (itry + shifted_values[0])/max; + sumqx_p = sumq2_p = 0; + sumqx_m = sumq2_m = 0; + for (int j = 0; j < block_size; ++j) { + float w = weight[j]; + float al = id*xb[j]; + int l = best_index_iq3nl(shifted_values, al); + float q = shifted_values[l]; + sumqx_p += w*q*xb[j]; + sumq2_p += w*q*q; + l = best_index_iq3nl(shifted_values, -al); + q = shifted_values[l]; + sumqx_m += w*q*xb[j]; + sumq2_m += w*q*q; + } + if (sumq2_p > 0 && sumqx_p*sumqx_p > best*sumq2_p) { + d = sumqx_p/sumq2_p; best = d * sumqx_p; is_shifted = true; + } + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d * sumqx_m; is_shifted = true; + } + } + if (is_shifted) y[ibl].extra |= (1 << (8 + ib)); + scales[ib] = d; + float ascale = std::abs(d); + if (ascale > amax_scale) { + amax_scale = ascale; max_scale = d; + } + } + } + float d = -max_scale/16; + *dptr = GGML_FP32_TO_FP16(d); + if (!d) return; + float id = d ? 1/d : 0.f; + float sumqx = 0, sumq2 = 0; + for (int ibl = 0; ibl < n_per_row/super_block_size; ++ibl) { + const float * xbl = x + ibl*super_block_size; + float sigma2 = 0; + for (int j = 0; j < super_block_size; ++j) sigma2 += xbl[j]*xbl[j]; + sigma2 *= 2.f/super_block_size; + auto scales = all_scales + (super_block_size/block_size)*ibl; + for (int ib = 0; ib < super_block_size/block_size; ++ib) { + const int8_t * block_values = (y[ibl].extra >> (8 + ib)) & 0x01 ? shifted_values : values; + int l = nearest_int(id*scales[ib]); + l = std::max(-16, std::min(15, l)); + uint8_t ul = l + 16; + y[ibl].scales[ib%4] |= (ul & 0xf) << 4*(ib/4); + y[ibl].extra |= (ul >> 4) << ib; + float dl = d * l; + float idl = dl ? 1/dl : 0.f; + const float * xb = xbl + ib*block_size; + if (quant_weights) { + const float * qw = quant_weights + ibl*super_block_size + ib*block_size; + for (int j = 0; j < block_size; ++j) weight[j] = qw[j] * sqrtf(sigma2 + xb[j]*xb[j]); + } else { + for (int j = 0; j < block_size; ++j) weight[j] = xb[j]*xb[j]; + } + auto qs = y[ibl].qs + (ib/4)*block_size; + auto qh = y[ibl].qh + (ib/8)*block_size; + for (int j = 0; j < block_size; ++j) { + uint8_t i = best_index_iq3nl(block_values, idl*xb[j]); + qs[j] |= ((i & 3) << 2*(ib%4)); + qh[j] |= ((i >> 2) << (ib%8)); + float w = weight[j]; + float q = block_values[i]*l; + sumqx += w*q*xb[j]; + sumq2 += w*q*q; + } + } + } + if (sumq2 > 0) *dptr = GGML_FP32_TO_FP16(sumqx/sumq2); +} +} + +void quantize_row_iq3_ks_ref(const float * x, block_iq3_ks * y, int64_t k) { + quantize_iq3_ks(x, (void *)y, 1, k, nullptr); +} + +void quantize_row_iq3_ks(const float * x, void * y, int64_t k) { + quantize_iq3_ks(x, (void *)y, 1, k, nullptr); +} + +size_t quantize_iq3_ks(const float * src, void * dst, int64_t nrows, int64_t n_per_row, const float * imatrix) { + constexpr int kBlockSize = 32; + GGML_ASSERT(n_per_row%QK_K == 0); + auto row_size = ggml_row_size(GGML_TYPE_IQ3_KS, n_per_row); + char * qrow = (char *)dst; + float weight[kBlockSize]; + std::vector all_scales(n_per_row/kBlockSize); + for (int64_t row = 0; row < nrows; ++row) { + quantize_row_iq3_ks_impl(QK_K, kBlockSize, n_per_row, src, qrow, all_scales.data(), weight, iq3nl_values, imatrix, 5); + src += n_per_row; + qrow += row_size; + } + return nrows * row_size; +} + +void dequantize_row_iq3_ks(const block_iq3_ks * x, float * y, int64_t k) { + constexpr int kBlockSize = 32; + static_assert(QK_K/kBlockSize == 8); + GGML_ASSERT(k%QK_K == 0); + const ggml_half * dptr = (const ggml_half *)x; + float d = GGML_FP16_TO_FP32(*dptr); + x = (const block_iq3_ks *)(dptr + 1); + float dl[8]; + int nblock = k/QK_K; + for (int ibl = 0; ibl < nblock; ++ibl) { + for (int j = 0; j < 4; ++j) { + int ls1 = (x[ibl].scales[j] & 0xf) | (((x[ibl].extra >> (j+0)) & 1) << 4); + int ls2 = (x[ibl].scales[j] >> 4) | (((x[ibl].extra >> (j+4)) & 1) << 4); + dl[j+0] = d*(ls1 - 16); + dl[j+4] = d*(ls2 - 16); + } + auto qs = x[ibl].qs; + auto qh = x[ibl].qh; + for (int i128 = 0; i128 < QK_K/128; ++i128) { + for (int ib = 0; ib < 4; ++ib) { + const int8_t * values = iq3nl_values + ((x[ibl].extra >> (8 + (4*i128+ib)) & 1) << 3); + for (int j = 0; j < kBlockSize; ++j) { + y[j] = dl[4*i128 + ib] * values[((qs[j] >> 2*ib) & 3) | (((qh[j] >> (4*i128+ib)) & 1) << 2)]; + } + y += kBlockSize; + } + qs += kBlockSize; + } + } +} + +void vec_dot_iq3_ks_q8_k(int n, float * s, size_t bs, const void * vx, size_t bx, const void * vy, size_t by, int nrc) { +#if GGML_USE_IQK_MULMAT + if (iqk_mul_mat(1, 1, n, GGML_TYPE_IQ3_KS, vx, 0, GGML_TYPE_Q8_K, vy, 0, s, 0, 0, 1)) { + return; + } +#endif + GGML_ASSERT(n%QK_K == 0); + GGML_ASSERT(nrc == 1); + GGML_UNUSED(bs); + GGML_UNUSED(bx); + GGML_UNUSED(by); + GGML_ABORT("Not implemented"); +} + // // ============================================== iq4_K // diff --git a/ggml/src/iqk/iqk_quantize.h b/ggml/src/iqk/iqk_quantize.h index 70918a65..3fc02a5e 100644 --- a/ggml/src/iqk/iqk_quantize.h +++ b/ggml/src/iqk/iqk_quantize.h @@ -31,6 +31,12 @@ size_t quantize_iq3_k(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, void dequantize_row_iq3_k(const block_iq3_k * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k); void vec_dot_iq3_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); +void quantize_row_iq3_ks_ref(const float * GGML_RESTRICT x, block_iq3_ks * GGML_RESTRICT y, int64_t k); +void quantize_row_iq3_ks(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k); +size_t quantize_iq3_ks(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix); +void dequantize_row_iq3_ks(const block_iq3_ks * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k); +void vec_dot_iq3_ks_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); + void quantize_row_iq4_k_ref(const float * GGML_RESTRICT x, block_iq4_k * GGML_RESTRICT y, int64_t k); void quantize_row_iq4_k(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k); size_t quantize_iq4_k(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix); diff --git a/include/llama.h b/include/llama.h index 53adeb94..6c8bff95 100644 --- a/include/llama.h +++ b/include/llama.h @@ -201,6 +201,7 @@ extern "C" { LLAMA_FTYPE_MOSTLY_IQ2_KT = 151, // except 1d tensors LLAMA_FTYPE_MOSTLY_IQ3_KT = 152, // except 1d tensors LLAMA_FTYPE_MOSTLY_IQ4_KT = 153, // except 1d tensors + LLAMA_FTYPE_MOSTLY_IQ3_KS = 154, // except 1d tensors // LLAMA_FTYPE_MOSTLY_Q4_0_R8 = 202, // except 1d tensors LLAMA_FTYPE_MOSTLY_Q8_0_R8 = 207, // except 1d tensors diff --git a/src/llama.cpp b/src/llama.cpp index 1ea2084d..8823ab5b 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -4374,6 +4374,7 @@ struct llama_model_loader { case GGML_TYPE_IQ5_KS: ftype = LLAMA_FTYPE_MOSTLY_IQ5_KS; break; case GGML_TYPE_IQ2_K: ftype = LLAMA_FTYPE_MOSTLY_IQ2_K; break; case GGML_TYPE_IQ2_K_R4:ftype = LLAMA_FTYPE_MOSTLY_IQ2_K_R4;break; + case GGML_TYPE_IQ3_KS: ftype = LLAMA_FTYPE_MOSTLY_IQ3_KS; break; case GGML_TYPE_IQ3_K: ftype = LLAMA_FTYPE_MOSTLY_IQ3_K; break; case GGML_TYPE_IQ3_K_R4:ftype = LLAMA_FTYPE_MOSTLY_IQ3_K_R4;break; case GGML_TYPE_IQ4_K: ftype = LLAMA_FTYPE_MOSTLY_IQ4_K; break; @@ -5115,6 +5116,7 @@ static std::string llama_model_ftype_name(llama_ftype ftype) { case LLAMA_FTYPE_MOSTLY_IQ5_KS: return "IQ5_KS - 5.25 bpw"; case LLAMA_FTYPE_MOSTLY_IQ2_K: return "IQ2_K - 2.375 bpw"; case LLAMA_FTYPE_MOSTLY_IQ2_K_R4: return "IQ2_K_R4 - 2.375 bpw"; + case LLAMA_FTYPE_MOSTLY_IQ3_KS: return "IQ3_KS - 3.1875 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_K: return "IQ3_K - 3.4325 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_K_R4: return "IQ3_K_R4 - 3.4325 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_KL: return "IQ3_KL - 4 bpw"; @@ -18642,7 +18644,7 @@ static ggml_type change_type_if_necessary(ggml_type new_type, int nx, int ny) { new_type == GGML_TYPE_IQ4_K_R4|| new_type == GGML_TYPE_Q8_K_R8 || new_type == GGML_TYPE_IQ3_K_R4|| new_type == GGML_TYPE_IQ2_K_R4|| new_type == GGML_TYPE_IQ5_K_R4|| new_type == GGML_TYPE_IQ4_KS_R4 || new_type == GGML_TYPE_IQ3_XXS_R4 || new_type == GGML_TYPE_IQ2_XXS_R4 || new_type == GGML_TYPE_IQ2_XS_R4 || - new_type == GGML_TYPE_IQ2_S_R4|| new_type == GGML_TYPE_IQ3_S_R4|| + new_type == GGML_TYPE_IQ2_S_R4|| new_type == GGML_TYPE_IQ3_S_R4|| new_type == GGML_TYPE_IQ3_KS || new_type == GGML_TYPE_IQ2_KT || new_type == GGML_TYPE_IQ3_KT || new_type == GGML_TYPE_IQ4_KT || new_type == GGML_TYPE_IQ5_KS || new_type == GGML_TYPE_IQ5_KS_R4) { if (nx % QK_K != 0) { @@ -18676,6 +18678,7 @@ static ggml_type change_type_if_necessary(ggml_type new_type, int nx, int ny) { case GGML_TYPE_Q3_K_R4: case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_KSS: @@ -18810,7 +18813,7 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n else if (ftype == LLAMA_FTYPE_MOSTLY_IQ2_XXS || ftype == LLAMA_FTYPE_MOSTLY_IQ2_XS || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS || ftype == LLAMA_FTYPE_MOSTLY_IQ1_S || ftype == LLAMA_FTYPE_MOSTLY_IQ2_S || ftype == LLAMA_FTYPE_MOSTLY_IQ2_M || ftype == LLAMA_FTYPE_MOSTLY_IQ1_M || ftype == LLAMA_FTYPE_MOSTLY_IQ2_K || ftype == LLAMA_FTYPE_MOSTLY_IQ3_K || - ftype == LLAMA_FTYPE_MOSTLY_IQ2_KS || ftype == LLAMA_FTYPE_MOSTLY_IQ3_K_R4 || + ftype == LLAMA_FTYPE_MOSTLY_IQ2_KS || ftype == LLAMA_FTYPE_MOSTLY_IQ3_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KS || ftype == LLAMA_FTYPE_MOSTLY_IQ2_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_M_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ1_S_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ1_M_R4 || @@ -19003,6 +19006,9 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n else if (ftype == LLAMA_FTYPE_MOSTLY_IQ3_K && qs.model.hparams.n_gqa() >= 2) { new_type = GGML_TYPE_IQ4_K; } + else if (ftype == LLAMA_FTYPE_MOSTLY_IQ3_KS && qs.model.hparams.n_gqa() >= 2) { + new_type = GGML_TYPE_IQ4_KS; + } else if (ftype == LLAMA_FTYPE_MOSTLY_IQ3_K_R4 && qs.model.hparams.n_gqa() >= 2) { new_type = GGML_TYPE_IQ4_K_R4; } @@ -19059,6 +19065,7 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n else if (new_type == GGML_TYPE_Q2_K_R4 || new_type == GGML_TYPE_IQ3_XXS_R4) new_type = GGML_TYPE_IQ3_K_R4; else if (new_type == GGML_TYPE_Q3_K || new_type == GGML_TYPE_IQ3_S) new_type = GGML_TYPE_Q4_K; else if (new_type == GGML_TYPE_IQ3_K) new_type = GGML_TYPE_IQ4_K; + else if (new_type == GGML_TYPE_IQ3_KS) new_type = GGML_TYPE_IQ4_KS; else if (new_type == GGML_TYPE_IQ3_S_R4) new_type = GGML_TYPE_Q4_K_R4; else if (new_type == GGML_TYPE_Q3_K_R4) new_type = GGML_TYPE_Q4_K_R4; else if (new_type == GGML_TYPE_Q4_K || new_type == GGML_TYPE_IQ4_XS) new_type = GGML_TYPE_Q5_K; @@ -19185,7 +19192,7 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n ftype == LLAMA_FTYPE_MOSTLY_IQ5_KS || ftype == LLAMA_FTYPE_MOSTLY_IQ5_KS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_K || ftype == LLAMA_FTYPE_MOSTLY_IQ3_K || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KL || ftype == LLAMA_FTYPE_MOSTLY_Q4_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ4_NL_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ4_XS_R8 || - ftype == LLAMA_FTYPE_MOSTLY_Q3_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KT || + ftype == LLAMA_FTYPE_MOSTLY_Q3_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KT || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KS || ftype == LLAMA_FTYPE_MOSTLY_Q2_K_R4|| ftype == LLAMA_FTYPE_MOSTLY_IQ4_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_S_R4) { new_type = GGML_TYPE_Q5_K; // should the IQ_K quants be applied here as the new type for the IQ_K ftypes ? @@ -19427,6 +19434,7 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s case LLAMA_FTYPE_MOSTLY_IQ5_KS: default_type = GGML_TYPE_IQ5_KS; break; case LLAMA_FTYPE_MOSTLY_IQ2_K: default_type = GGML_TYPE_IQ2_K; break; case LLAMA_FTYPE_MOSTLY_IQ2_K_R4:default_type = GGML_TYPE_IQ2_K_R4;break; + case LLAMA_FTYPE_MOSTLY_IQ3_KS: default_type = GGML_TYPE_IQ3_KS; break; case LLAMA_FTYPE_MOSTLY_IQ3_K: default_type = GGML_TYPE_IQ3_K; break; case LLAMA_FTYPE_MOSTLY_IQ3_K_R4:default_type = GGML_TYPE_IQ3_K_R4;break; case LLAMA_FTYPE_MOSTLY_IQ3_KL: default_type = GGML_TYPE_IQ3_K; break; From c9148ba0b4724033f369636d31bc17aeed090f7e Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Wed, 2 Jul 2025 16:11:56 +0200 Subject: [PATCH 07/63] Fix CMakeLists (#571) * Move Vulkan stuff inside if (GGML_VULKAN) * Minor --------- Co-authored-by: Iwan Kawrakow --- ggml/src/CMakeLists.txt | 231 ++++++++++++++++++++-------------------- ggml/src/ggml-backend.c | 2 +- 2 files changed, 114 insertions(+), 119 deletions(-) diff --git a/ggml/src/CMakeLists.txt b/ggml/src/CMakeLists.txt index 4f9428f9..1a3c1ff6 100644 --- a/ggml/src/CMakeLists.txt +++ b/ggml/src/CMakeLists.txt @@ -643,8 +643,6 @@ if (GGML_RPC) set(GGML_SOURCES_RPC ggml-rpc.cpp) endif() -find_package(Vulkan COMPONENTS glslc REQUIRED) - function(detect_host_compiler) if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") find_program(HOST_C_COMPILER NAMES cl gcc clang NO_CMAKE_FIND_ROOT_PATH) @@ -657,71 +655,68 @@ function(detect_host_compiler) set(HOST_CXX_COMPILER "${HOST_CXX_COMPILER}" PARENT_SCOPE) endfunction() -# Function to test shader extension support -# Parameters: -# EXTENSION_NAME - Name of the extension to test (e.g., "GL_EXT_integer_dot_product") -# TEST_SHADER_FILE - Path to the test shader file -# RESULT_VARIABLE - Name of the variable to set (ON/OFF) based on test result -function(test_shader_extension_support EXTENSION_NAME TEST_SHADER_FILE RESULT_VARIABLE) - execute_process( - COMMAND ${Vulkan_GLSLC_EXECUTABLE} -o - -fshader-stage=compute --target-env=vulkan1.3 "${TEST_SHADER_FILE}" - OUTPUT_VARIABLE glslc_output - ERROR_VARIABLE glslc_error - ) - - if (${glslc_error} MATCHES ".*extension not supported: ${EXTENSION_NAME}.*") - message(STATUS "${EXTENSION_NAME} not supported by glslc") - set(${RESULT_VARIABLE} OFF PARENT_SCOPE) - else() - message(STATUS "${EXTENSION_NAME} supported by glslc") - set(${RESULT_VARIABLE} ON PARENT_SCOPE) - add_compile_definitions(${RESULT_VARIABLE}) - - # Ensure the extension support is forwarded to vulkan-shaders-gen - list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -D${RESULT_VARIABLE}=ON) - set(VULKAN_SHADER_GEN_CMAKE_ARGS "${VULKAN_SHADER_GEN_CMAKE_ARGS}" PARENT_SCOPE) - endif() -endfunction() - if (GGML_VULKAN) find_package(Vulkan COMPONENTS glslc REQUIRED) if (Vulkan_FOUND) message(STATUS "Vulkan found") - # add vulkan test - - set(VULKAN_SHADER_GEN_CMAKE_ARGS "") + # Function to test shader extension support + # Parameters: + # EXTENSION_NAME - Name of the extension to test (e.g., "GL_EXT_integer_dot_product") + # TEST_SHADER_FILE - Path to the test shader file + # RESULT_VARIABLE - Name of the variable to set (ON/OFF) based on test result + function(test_shader_extension_support EXTENSION_NAME TEST_SHADER_FILE RESULT_VARIABLE) + execute_process( + COMMAND ${Vulkan_GLSLC_EXECUTABLE} -o - -fshader-stage=compute --target-env=vulkan1.3 "${TEST_SHADER_FILE}" + OUTPUT_VARIABLE glslc_output + ERROR_VARIABLE glslc_error + ) - # Test all shader extensions - test_shader_extension_support( - "GL_KHR_cooperative_matrix" - "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat_support.comp" - "GGML_VULKAN_COOPMAT_GLSLC_SUPPORT" - ) + if (${glslc_error} MATCHES ".*extension not supported: ${EXTENSION_NAME}.*") + message(STATUS "${EXTENSION_NAME} not supported by glslc") + set(${RESULT_VARIABLE} OFF PARENT_SCOPE) + else() + message(STATUS "${EXTENSION_NAME} supported by glslc") + set(${RESULT_VARIABLE} ON PARENT_SCOPE) + add_compile_definitions(${RESULT_VARIABLE}) - test_shader_extension_support( - "GL_NV_cooperative_matrix2" - "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat2_support.comp" - "GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT" - ) + # Ensure the extension support is forwarded to vulkan-shaders-gen + list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -D${RESULT_VARIABLE}=ON) + set(VULKAN_SHADER_GEN_CMAKE_ARGS "${VULKAN_SHADER_GEN_CMAKE_ARGS}" PARENT_SCOPE) + endif() + endfunction() - test_shader_extension_support( - "GL_EXT_integer_dot_product" - "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_integer_dot_support.comp" - "GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT" - ) + # add vulkan test - test_shader_extension_support( - "GL_EXT_bfloat16" - "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_bfloat16_support.comp" - "GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT" - ) - - - - - # end vulkan test + set(VULKAN_SHADER_GEN_CMAKE_ARGS "") + + # Test all shader extensions + test_shader_extension_support( + "GL_KHR_cooperative_matrix" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat_support.comp" + "GGML_VULKAN_COOPMAT_GLSLC_SUPPORT" + ) + + test_shader_extension_support( + "GL_NV_cooperative_matrix2" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat2_support.comp" + "GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT" + ) + + test_shader_extension_support( + "GL_EXT_integer_dot_product" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_integer_dot_support.comp" + "GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT" + ) + + test_shader_extension_support( + "GL_EXT_bfloat16" + "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_bfloat16_support.comp" + "GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT" + ) + + # end vulkan test list(APPEND GGML_CDEF_PUBLIC GGML_USE_VULKAN) # Workaround to the "can't dereference invalidated vector iterator" bug in clang-cl debug build @@ -758,79 +753,79 @@ if (GGML_VULKAN) add_compile_definitions(GGML_VULKAN_RUN_TESTS) endif() - # Set up toolchain for host compilation whether cross-compiling or not - if (CMAKE_CROSSCOMPILING) - if (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN) - set(HOST_CMAKE_TOOLCHAIN_FILE ${GGML_VULKAN_SHADERS_GEN_TOOLCHAIN}) - else() - detect_host_compiler() - if (NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER) - message(FATAL_ERROR "Host compiler not found") - else() - message(STATUS "Host compiler: ${HOST_C_COMPILER} ${HOST_CXX_COMPILER}") - endif() - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/host-toolchain.cmake.in ${CMAKE_BINARY_DIR}/host-toolchain.cmake @ONLY) - set(HOST_CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/host-toolchain.cmake) - endif() - else() - # For non-cross-compiling, use empty toolchain (use host compiler) - set(HOST_CMAKE_TOOLCHAIN_FILE "") - endif() + # Set up toolchain for host compilation whether cross-compiling or not + if (CMAKE_CROSSCOMPILING) + if (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN) + set(HOST_CMAKE_TOOLCHAIN_FILE ${GGML_VULKAN_SHADERS_GEN_TOOLCHAIN}) + else() + detect_host_compiler() + if (NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER) + message(FATAL_ERROR "Host compiler not found") + else() + message(STATUS "Host compiler: ${HOST_C_COMPILER} ${HOST_CXX_COMPILER}") + endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/host-toolchain.cmake.in ${CMAKE_BINARY_DIR}/host-toolchain.cmake @ONLY) + set(HOST_CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/host-toolchain.cmake) + endif() + else() + # For non-cross-compiling, use empty toolchain (use host compiler) + set(HOST_CMAKE_TOOLCHAIN_FILE "") + endif() - include(ExternalProject) + include(ExternalProject) - if (CMAKE_CROSSCOMPILING) - list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${HOST_CMAKE_TOOLCHAIN_FILE}) - message(STATUS "vulkan-shaders-gen toolchain file: ${HOST_CMAKE_TOOLCHAIN_FILE}") - endif() + if (CMAKE_CROSSCOMPILING) + list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${HOST_CMAKE_TOOLCHAIN_FILE}) + message(STATUS "vulkan-shaders-gen toolchain file: ${HOST_CMAKE_TOOLCHAIN_FILE}") + endif() - ExternalProject_Add( - vulkan-shaders-gen - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/$ - -DCMAKE_INSTALL_BINDIR=. - -DCMAKE_BUILD_TYPE=$ - ${VULKAN_SHADER_GEN_CMAKE_ARGS} + ExternalProject_Add( + vulkan-shaders-gen + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/$ + -DCMAKE_INSTALL_BINDIR=. + -DCMAKE_BUILD_TYPE=$ + ${VULKAN_SHADER_GEN_CMAKE_ARGS} - BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $ + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $ - # NOTE: When DESTDIR is set using Makefile generators and - # "make install" triggers the build step, vulkan-shaders-gen - # would be installed into the DESTDIR prefix, so it is unset - # to ensure that does not happen. + # NOTE: When DESTDIR is set using Makefile generators and + # "make install" triggers the build step, vulkan-shaders-gen + # would be installed into the DESTDIR prefix, so it is unset + # to ensure that does not happen. - INSTALL_COMMAND ${CMAKE_COMMAND} -E env --unset=DESTDIR - ${CMAKE_COMMAND} --install . --config $ - ) + INSTALL_COMMAND ${CMAKE_COMMAND} -E env --unset=DESTDIR + ${CMAKE_COMMAND} --install . --config $ + ) - set (_ggml_vk_host_suffix $,.exe,>) - set (_ggml_vk_genshaders_dir "${CMAKE_BINARY_DIR}/$") - set (_ggml_vk_genshaders_cmd "${_ggml_vk_genshaders_dir}/vulkan-shaders-gen${_ggml_vk_host_suffix}") - set (_ggml_vk_header "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp") - set (_ggml_vk_source "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.cpp") - set (_ggml_vk_input_dir "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders") - set (_ggml_vk_output_dir "${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv") + set (_ggml_vk_host_suffix $,.exe,>) + set (_ggml_vk_genshaders_dir "${CMAKE_BINARY_DIR}/$") + set (_ggml_vk_genshaders_cmd "${_ggml_vk_genshaders_dir}/vulkan-shaders-gen${_ggml_vk_host_suffix}") + set (_ggml_vk_header "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp") + set (_ggml_vk_source "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.cpp") + set (_ggml_vk_input_dir "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders") + set (_ggml_vk_output_dir "${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv") - file(GLOB _ggml_vk_shader_files CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.comp") + file(GLOB _ggml_vk_shader_files CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.comp") - add_custom_command( - OUTPUT ${_ggml_vk_header} - ${_ggml_vk_source} + add_custom_command( + OUTPUT ${_ggml_vk_header} + ${_ggml_vk_source} - COMMAND ${_ggml_vk_genshaders_cmd} - --glslc ${Vulkan_GLSLC_EXECUTABLE} - --input-dir ${_ggml_vk_input_dir} - --output-dir ${_ggml_vk_output_dir} - --target-hpp ${_ggml_vk_header} - --target-cpp ${_ggml_vk_source} - --no-clean + COMMAND ${_ggml_vk_genshaders_cmd} + --glslc ${Vulkan_GLSLC_EXECUTABLE} + --input-dir ${_ggml_vk_input_dir} + --output-dir ${_ggml_vk_output_dir} + --target-hpp ${_ggml_vk_header} + --target-cpp ${_ggml_vk_source} + --no-clean - DEPENDS ${_ggml_vk_shader_files} - ${_ggml_vk_shader_gens_sources} - vulkan-shaders-gen + DEPENDS ${_ggml_vk_shader_files} + ${_ggml_vk_shader_gens_sources} + vulkan-shaders-gen - COMMENT "Generate vulkan shaders" - ) + COMMENT "Generate vulkan shaders" + ) set(GGML_HEADERS_VULKAN ${CMAKE_CURRENT_SOURCE_DIR}/../include/ggml-vulkan.h ${_ggml_vk_header}) set(GGML_SOURCES_VULKAN ggml-vulkan.cpp ${_ggml_vk_source}) diff --git a/ggml/src/ggml-backend.c b/ggml/src/ggml-backend.c index 28850e0d..19dcb9bc 100644 --- a/ggml/src/ggml-backend.c +++ b/ggml/src/ggml-backend.c @@ -266,7 +266,7 @@ GGML_CALL void ggml_backend_tensor_get(const struct ggml_tensor * tensor, void * #endif } -GGML_CALL void ggml_backend_tensor_memset(struct ggml_tensor* tensor, uint8_t value, size_t offset, size_t size) { +static void ggml_backend_tensor_memset(struct ggml_tensor* tensor, uint8_t value, size_t offset, size_t size) { ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer; if (size == 0) { From de7a4403b0d8e17814ed562b9754e86aca1fbe22 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Thu, 3 Jul 2025 10:43:27 +0200 Subject: [PATCH 08/63] Chnage KQ mask padding to 64 (#574) Co-authored-by: Iwan Kawrakow --- ggml/include/ggml.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index aea0fac5..655170a6 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -1957,7 +1957,7 @@ extern "C" { int min_entries, float thresh); -#define GGML_KQ_MASK_PAD 32 +#define GGML_KQ_MASK_PAD 64 // q: [n_embd, n_batch, n_head, 1] // k: [n_embd, n_kv, n_head_kv, 1] From ab22474d77ecc846eaf102011f866b1d767f3ad5 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Thu, 3 Jul 2025 15:26:28 +0200 Subject: [PATCH 09/63] Fix debug build failure with RPC off (#579) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-backend.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ggml/src/ggml-backend.c b/ggml/src/ggml-backend.c index 19dcb9bc..07b879f1 100644 --- a/ggml/src/ggml-backend.c +++ b/ggml/src/ggml-backend.c @@ -971,12 +971,14 @@ GGML_CALL static ggml_backend_t ggml_backend_reg_cpu_init(const char * params, v GGML_UNUSED(user_data); } +#ifdef GGML_USE_RPC GGML_CALL static ggml_backend_t ggml_backend_reg_rpc_init(const char* params, void* user_data) { return ggml_backend_rpc_init((const char*)user_data); GGML_UNUSED(params); GGML_UNUSED(user_data); } +#endif // multi-buffer buffer From db8dee50516d1437f94017de196f87dcf54be12d Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Thu, 3 Jul 2025 15:26:52 +0200 Subject: [PATCH 10/63] Do not crash when there is no DRY sampler (#578) Co-authored-by: Iwan Kawrakow --- common/sampling.cpp | 6 ++++-- src/llama.cpp | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/common/sampling.cpp b/common/sampling.cpp index 4b983e5f..08a19b45 100644 --- a/common/sampling.cpp +++ b/common/sampling.cpp @@ -55,7 +55,7 @@ struct llama_sampling_context * llama_sampling_init(const struct llama_vocab* vo c_breakers.push_back(str.c_str()); } result->smpl=llama_sampler_init_dry(vocab, params.dry_multiplier, params.dry_base, params.dry_allowed_length, params.dry_penalty_last_n, c_breakers.data(), c_breakers.size()); - + break; } default: @@ -502,5 +502,7 @@ void llama_sampling_accept( if (ctx_sampling->grammar != NULL && apply_grammar) { llama_grammar_accept_token(ctx_sampling->grammar, ctx_main, id); } - llama_sampler_dry_accept(ctx_sampling->smpl, id); + if (ctx_sampling->smpl) { + llama_sampler_dry_accept(ctx_sampling->smpl, id); + } } diff --git a/src/llama.cpp b/src/llama.cpp index 8823ab5b..c2769e32 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -23401,6 +23401,9 @@ struct llama_sampler_dry* llama_sampler_dry_clone(struct llama_sampler_dry* smpl } void llama_sampler_dry_accept(struct llama_sampler_dry* smpl, llama_token token) { + if (!smpl) { + return; + } if (smpl->dry_multiplier == 0.0f || smpl->dry_base < 1.0f || smpl->dry_penalty_last_n == 0) { return; } From 9534461c01e132672821e53ce6e5e560dc58e829 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Thu, 3 Jul 2025 15:36:52 +0200 Subject: [PATCH 11/63] Vulkan: fused rms norm (#577) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-vulkan.cpp | 40 ++++++++++++++ ggml/src/vulkan-shaders/fused_rms_norm.comp | 54 +++++++++++++++++++ .../src/vulkan-shaders/vulkan-shaders-gen.cpp | 1 + src/llama.cpp | 7 +-- 4 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 ggml/src/vulkan-shaders/fused_rms_norm.comp diff --git a/ggml/src/ggml-vulkan.cpp b/ggml/src/ggml-vulkan.cpp index c0bdfb7b..bd17fb26 100644 --- a/ggml/src/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan.cpp @@ -431,6 +431,7 @@ struct vk_device_struct { vk_pipeline pipeline_norm_f32; vk_pipeline pipeline_group_norm_f32; vk_pipeline pipeline_rms_norm_f32; + vk_pipeline pipeline_fused_rms_norm_f32; vk_pipeline pipeline_rms_norm_back_f32; // [src/dst 0=fp32,1=fp16] @@ -2653,6 +2654,7 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_norm_f32, "norm_f32", norm_f32_len, norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_group_norm_f32, "group_norm_f32", group_norm_f32_len, group_norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_rms_norm_f32, "rms_norm_f32", rms_norm_f32_len, rms_norm_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_rms_norm_f32, "fused_rms_norm_f32", fused_rms_norm_f32_len, fused_rms_norm_f32_data, "main", 3, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_rms_norm_back_f32, "rms_norm_back_f32", rms_norm_back_f32_len, rms_norm_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_f32, "cpy_f32_f32", cpy_f32_f32_len, cpy_f32_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); @@ -6381,6 +6383,11 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_rms_norm_f32; } return nullptr; + case GGML_OP_FUSED_RMS_NORM: + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_fused_rms_norm_f32; + } + return nullptr; case GGML_OP_RMS_NORM_BACK: if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_rms_norm_back_f32; @@ -6521,6 +6528,7 @@ static bool ggml_vk_op_supports_incontiguous(ggml_op op) { case GGML_OP_REPEAT_BACK: case GGML_OP_ROPE: case GGML_OP_RMS_NORM: + case GGML_OP_FUSED_RMS_NORM: case GGML_OP_IM2COL: return true; default: @@ -6751,6 +6759,10 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co elements = { (uint32_t)ne01, (uint32_t)ne02, (uint32_t)ne03 }; break; + case GGML_OP_FUSED_RMS_NORM: + elements = { (uint32_t)ne01, (uint32_t)ne02, (uint32_t)ne03 }; + break; + case GGML_OP_SUM: // We use GGML_OP_SUM_ROWS with 1 row. elements = { 1, 1, 1 }; @@ -7173,6 +7185,24 @@ static void ggml_vk_rms_norm(ggml_backend_vk_context * ctx, vk_context& subctx, }, dryrun); } +static void ggml_vk_fused_rms_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + float * op_params = (float *)dst->op_params; + const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t src1_type_size = ggml_type_size(src1->type); + const uint32_t dst_type_size = ggml_type_size(dst->type); + GGML_ASSERT(src1->ne[1] == 1 && src1->ne[2] == 1 && src1->ne[3] == 1); + GGML_ASSERT(src1->ne[0] == src0->ne[0]); + + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_FUSED_RMS_NORM, { + (uint32_t)ggml_nelements(src0), + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t)src1->ne[0], 1u, 1u, 1u, (uint32_t)src1->nb[0] / src1_type_size, 0u, 0u, 0u, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, + 0, + op_params[0], 0.0f, 0, + }, dryrun); +} + static void ggml_vk_rms_norm_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { float * op_params = (float *)dst->op_params; ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_RMS_NORM_BACK, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }, dryrun); @@ -8386,6 +8416,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: + case GGML_OP_FUSED_RMS_NORM: case GGML_OP_RMS_NORM_BACK: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: @@ -8444,6 +8475,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: + case GGML_OP_FUSED_RMS_NORM: case GGML_OP_RMS_NORM_BACK: case GGML_OP_UNARY: case GGML_OP_DIAG_MASK_INF: @@ -8550,6 +8582,10 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_RMS_NORM: ggml_vk_rms_norm(ctx, compute_ctx, src0, node, dryrun); + break; + case GGML_OP_FUSED_RMS_NORM: + ggml_vk_fused_rms_norm(ctx, compute_ctx, src0, src1, node, dryrun); + break; case GGML_OP_RMS_NORM_BACK: ggml_vk_rms_norm_back(ctx, compute_ctx, src0, src1, node, dryrun); @@ -8703,6 +8739,7 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: + case GGML_OP_FUSED_RMS_NORM: case GGML_OP_RMS_NORM_BACK: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: @@ -9625,6 +9662,7 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const case GGML_OP_PERMUTE: case GGML_OP_TRANSPOSE: case GGML_OP_RMS_NORM: + case GGML_OP_FUSED_RMS_NORM: return true; case GGML_OP_NORM: case GGML_OP_GROUP_NORM: @@ -10064,6 +10102,8 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { tensor_clone = ggml_group_norm(ggml_ctx, src_clone[0], tensor->op_params[0], float_params[1]); } else if (tensor->op == GGML_OP_RMS_NORM) { tensor_clone = ggml_rms_norm(ggml_ctx, src_clone[0], *(float *)tensor->op_params); + } else if (tensor->op == GGML_OP_FUSED_RMS_NORM) { + tensor_clone = ggml_fused_rms_norm(ggml_ctx, src_clone[0], src_clone[1], *(float *)tensor->op_params); } else if (tensor->op == GGML_OP_RMS_NORM_BACK) { const float eps = ((float *) tensor->op_params)[0]; tensor_clone = ggml_rms_norm_back(ggml_ctx, src_clone[0], src_clone[1], eps); diff --git a/ggml/src/vulkan-shaders/fused_rms_norm.comp b/ggml/src/vulkan-shaders/fused_rms_norm.comp new file mode 100644 index 00000000..fcea166c --- /dev/null +++ b/ggml/src/vulkan-shaders/fused_rms_norm.comp @@ -0,0 +1,54 @@ +#version 450 + +#include "generic_binary_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable +#define BLOCK_SIZE 512 + +layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; + +shared FLOAT_TYPE sum[BLOCK_SIZE]; + +void main() { + const uint ncols = p.ne00; + const uint nrows = gl_NumWorkGroups.x; + const uint nchannels = gl_NumWorkGroups.y; + + const uint row = gl_WorkGroupID.x; + const uint channel = gl_WorkGroupID.y; + const uint samp = gl_WorkGroupID.z; + const uint tid = gl_LocalInvocationID.x; + + const uint stride_row_a = p.nb01; + const uint stride_channel_a = p.nb02; + const uint stride_sample_a = p.nb03; + + uint32_t a_offset = samp*stride_sample_a + channel*stride_channel_a + row*stride_row_a; + uint32_t d_offset = ((samp*nchannels + channel)*nrows + row)*ncols + get_doffset(); + + FLOAT_TYPE sumf = FLOAT_TYPE(0.0f); + + [[unroll]] for (uint col = tid; col < ncols; col += BLOCK_SIZE) { + const FLOAT_TYPE xi = FLOAT_TYPE(data_a[a_offset + col]); + sumf += xi * xi; + } + + sum[tid] = sumf; + + // sum up partial sums and write back result + barrier(); + [[unroll]] for (int s = BLOCK_SIZE / 2; s > 0; s >>= 1) { + if (tid < s) { + sum[tid] += sum[tid + s]; + } + barrier(); + } + + const FLOAT_TYPE mean = sum[0] / FLOAT_TYPE(ncols); + const FLOAT_TYPE scale = inversesqrt(mean + FLOAT_TYPE(p.param1)); + + [[unroll]] for (uint col = tid; col < ncols; col += BLOCK_SIZE) { + data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[col])); + } +} diff --git a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp index 0f244dea..d622f1bd 100644 --- a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp +++ b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp @@ -498,6 +498,7 @@ void process_shaders() { string_to_spv("norm_f32", "norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); string_to_spv("group_norm_f32", "group_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); string_to_spv("rms_norm_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("fused_rms_norm_f32", "fused_rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); string_to_spv("rms_norm_back_f32", "rms_norm_back.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); string_to_spv("cpy_f32_f32", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); diff --git a/src/llama.cpp b/src/llama.cpp index c2769e32..794dcca6 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -9597,12 +9597,7 @@ static struct ggml_tensor * llm_build_norm( const llm_build_cb & cb, int il, float scale_eps = 1) { -#ifdef GGML_USE_VULKAN - constexpr bool use_fused_rms_norm = false; -#else - constexpr bool use_fused_rms_norm = true; -#endif - if (use_fused_rms_norm && type == LLM_NORM_RMS && mw) { + if (type == LLM_NORM_RMS && mw) { cur = ggml_fused_rms_norm(ctx, cur, mw, scale_eps * hparams.f_norm_rms_eps); if (mb) { cb(cur, "fused_norm", il); From 8a0c38f496f60bb0f627521823de604ce10fdc16 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Thu, 3 Jul 2025 18:03:23 +0200 Subject: [PATCH 12/63] Vulkan: add GGML_OP_FUSED_MUL_UNARY (#580) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-vulkan.cpp | 61 +++++++++++++++++++ ggml/src/vulkan-shaders/fused_mul_gelu.comp | 27 ++++++++ ggml/src/vulkan-shaders/fused_mul_relu.comp | 22 +++++++ ggml/src/vulkan-shaders/fused_mul_silu.comp | 24 ++++++++ .../src/vulkan-shaders/vulkan-shaders-gen.cpp | 7 +++ src/llama.cpp | 8 +-- 6 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 ggml/src/vulkan-shaders/fused_mul_gelu.comp create mode 100644 ggml/src/vulkan-shaders/fused_mul_relu.comp create mode 100644 ggml/src/vulkan-shaders/fused_mul_silu.comp diff --git a/ggml/src/ggml-vulkan.cpp b/ggml/src/ggml-vulkan.cpp index bd17fb26..7c25f3b5 100644 --- a/ggml/src/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan.cpp @@ -442,6 +442,11 @@ struct vk_device_struct { vk_pipeline pipeline_tanh[2]; vk_pipeline pipeline_sigmoid[2]; + // [src/dst 0=fp32,1=fp16] + vk_pipeline pipeline_fused_mul_gelu[2]; + vk_pipeline pipeline_fused_mul_silu[2]; + vk_pipeline pipeline_fused_mul_relu[2]; + vk_pipeline pipeline_leaky_relu_f32; vk_pipeline pipeline_silu_back_f32; vk_pipeline pipeline_diag_mask_inf_f32; @@ -2747,6 +2752,13 @@ static void ggml_vk_load_shaders(vk_device& device) { CREATE_UNARY(sigmoid) #undef CREATE_UNARY + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_silu[0], "fused_mul_silu_f32", fused_mul_silu_f32_len, fused_mul_silu_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_silu[1], "fused_mul_silu_f16", fused_mul_silu_f16_len, fused_mul_silu_f16_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_gelu[0], "fused_mul_gelu_f32", fused_mul_gelu_f32_len, fused_mul_gelu_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_gelu[1], "fused_mul_gelu_f16", fused_mul_gelu_f16_len, fused_mul_gelu_f16_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[0], "fused_mul_relu_f32", fused_mul_relu_f32_len, fused_mul_relu_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[1], "fused_mul_relu_f16", fused_mul_relu_f16_len, fused_mul_relu_f16_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_leaky_relu_f32, "leaky_relu_f32", leaky_relu_f32_len, leaky_relu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_silu_back_f32, "silu_back_f32", silu_back_f32_len, silu_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); @@ -6393,6 +6405,26 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_rms_norm_back_f32; } return nullptr; + case GGML_OP_FUSED_MUL_UNARY: + if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || + (src1->type != GGML_TYPE_F32 && src1->type != GGML_TYPE_F16) || + (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16) || + (src0->type != dst->type) || (src1->type != dst->type)) { + return nullptr; + } else { + ggml_unary_op unary_op = (ggml_unary_op)dst->op_params[0]; + switch (unary_op) { + case GGML_UNARY_OP_SILU: + return ctx->device->pipeline_fused_mul_silu[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_GELU: + return ctx->device->pipeline_fused_mul_gelu[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_RELU: + return ctx->device->pipeline_fused_mul_relu[dst->type == GGML_TYPE_F16]; + default: + break; + } + return nullptr; + } case GGML_OP_UNARY: if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16) || @@ -6830,6 +6862,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co case GGML_OP_CPY: case GGML_OP_CONCAT: case GGML_OP_UPSCALE: + case GGML_OP_FUSED_MUL_UNARY: case GGML_OP_UNARY: { uint32_t ne = ggml_nelements(dst); @@ -7212,6 +7245,13 @@ static void ggml_vk_unary(ggml_backend_vk_context * ctx, vk_context& subctx, con ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); } +static void ggml_vk_fused_mul_unary(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + GGML_ASSERT(ggml_is_contiguous(src0)); + GGML_ASSERT(ggml_are_same_shape(src0, src1)); + GGML_ASSERT(ggml_are_same_shape(src0, dst)); + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_FUSED_MUL_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); +} + static void ggml_vk_diag_mask_inf(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { int32_t * op_params = (int32_t *)dst->op_params; ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_DIAG_MASK_INF, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0] }, dryrun); @@ -8396,6 +8436,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod return false; } break; + case GGML_OP_FUSED_MUL_UNARY: case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: case GGML_OP_GET_ROWS: @@ -8478,6 +8519,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_FUSED_RMS_NORM: case GGML_OP_RMS_NORM_BACK: case GGML_OP_UNARY: + case GGML_OP_FUSED_MUL_UNARY: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: case GGML_OP_SOFT_MAX_BACK: @@ -8590,6 +8632,9 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_RMS_NORM_BACK: ggml_vk_rms_norm_back(ctx, compute_ctx, src0, src1, node, dryrun); + break; + case GGML_OP_FUSED_MUL_UNARY: + ggml_vk_fused_mul_unary(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_UNARY: switch (ggml_get_unary_op(node)) { @@ -8762,6 +8807,7 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * case GGML_OP_LEAKY_RELU: case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: + case GGML_OP_FUSED_MUL_UNARY: buf = tensor->buffer; break; @@ -9445,6 +9491,19 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const return false; } break; + case GGML_OP_FUSED_MUL_UNARY: + switch ((ggml_unary_op)op->op_params[0]) { + case GGML_UNARY_OP_GELU: + case GGML_UNARY_OP_SILU: + case GGML_UNARY_OP_RELU: + return ggml_is_contiguous(op->src[0]) && ggml_are_same_shape(op->src[0], op->src[1]) && + (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) && + (op->src[1]->type == GGML_TYPE_F32 || op->src[1]->type == GGML_TYPE_F16) && + (op->src[0]->type == op->type) && (op->src[1]->type == op->type); + default: + return false; + } + break; case GGML_OP_MUL_MAT: case GGML_OP_MUL_MAT_ID: { @@ -10169,6 +10228,8 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { std::cerr << "Missing vk_check_results OP: " << ggml_op_name(tensor->op) << std::endl; GGML_ABORT("fatal error"); } + } else if (tensor->op == GGML_OP_FUSED_MUL_UNARY) { + tensor_clone = ggml_fused_mul_unary(ggml_ctx, src_clone[0], src_clone[1], (ggml_unary_op)tensor->op_params[0]); } else if (tensor->op == GGML_OP_CPY || tensor->op == GGML_OP_DUP) { if (src1 == nullptr) { tensor_clone = ggml_dup(ggml_ctx, src_clone[0]); diff --git a/ggml/src/vulkan-shaders/fused_mul_gelu.comp b/ggml/src/vulkan-shaders/fused_mul_gelu.comp new file mode 100644 index 00000000..65e2e662 --- /dev/null +++ b/ggml/src/vulkan-shaders/fused_mul_gelu.comp @@ -0,0 +1,27 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) readonly buffer Y {B_TYPE data_b[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + const float GELU_COEF_A = 0.044715f; + const float SQRT_2_OVER_PI = 0.79788456080286535587989211986876f; + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.KX) { + return; + } + + const float xi = float(data_a[i]); + const float yi = float(data_b[i]); + const float val = SQRT_2_OVER_PI*xi*(1.0f + GELU_COEF_A*xi*xi); + data_d[i] = D_TYPE(0.5f*xi*yi*(2.0f - 2.0f / (exp(2 * val) + 1))); +} diff --git a/ggml/src/vulkan-shaders/fused_mul_relu.comp b/ggml/src/vulkan-shaders/fused_mul_relu.comp new file mode 100644 index 00000000..01a3107f --- /dev/null +++ b/ggml/src/vulkan-shaders/fused_mul_relu.comp @@ -0,0 +1,22 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) readonly buffer Y {B_TYPE data_b[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.KX) { + return; + } + + data_d[i] = D_TYPE(float(data_b[i])*max(float(data_a[i]), 0)); +} diff --git a/ggml/src/vulkan-shaders/fused_mul_silu.comp b/ggml/src/vulkan-shaders/fused_mul_silu.comp new file mode 100644 index 00000000..0d59b64e --- /dev/null +++ b/ggml/src/vulkan-shaders/fused_mul_silu.comp @@ -0,0 +1,24 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) readonly buffer Y {B_TYPE data_b[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.KX) { + return; + } + + const float xi = float(data_a[i]); + const float yi = float(data_b[i]); + data_d[i] = D_TYPE(xi * yi / (1.0f + exp(-xi))); +} diff --git a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp index d622f1bd..281d98c6 100644 --- a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp +++ b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp @@ -572,6 +572,13 @@ void process_shaders() { string_to_spv("upscale_f32", "upscale.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("fused_mul_gelu_f16", "fused_mul_gelu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("fused_mul_gelu_f32", "fused_mul_gelu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("fused_mul_silu_f16", "fused_mul_silu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("fused_mul_silu_f32", "fused_mul_silu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("fused_mul_relu_f16", "fused_mul_relu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("fused_mul_relu_f32", "fused_mul_relu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("gelu_f16", "gelu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); string_to_spv("gelu_f32", "gelu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); string_to_spv("gelu_quick_f16", "gelu_quick.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); diff --git a/src/llama.cpp b/src/llama.cpp index 794dcca6..11a7060c 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -9688,13 +9688,7 @@ static struct ggml_tensor * llm_build_ffn( cur = tmp; } -#ifdef GGML_USE_VULKAN - constexpr bool use_fused_mul_unary = false; -#else - constexpr bool use_fused_mul_unary = true; -#endif - - if (use_fused_mul_unary && type_gate == LLM_FFN_PAR && + if (type_gate == LLM_FFN_PAR && (type_op == LLM_FFN_SILU || type_op == LLM_FFN_RELU || (type_op == LLM_FFN_GELU && !act_scales))) { cur = ggml_fused_mul_unary(ctx, cur, tmp, type_op == LLM_FFN_SILU ? GGML_UNARY_OP_SILU : type_op == LLM_FFN_RELU ? GGML_UNARY_OP_RELU : GGML_UNARY_OP_GELU); From 3e024de1dae45d17110a7dfe02cadea2eb111f51 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Thu, 3 Jul 2025 18:31:48 +0200 Subject: [PATCH 13/63] Vulkan: Disable multi-add for now (#581) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-vulkan.cpp | 44 ++++++++++++++++++++++++++++++++---- src/llama.cpp | 48 +++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/ggml/src/ggml-vulkan.cpp b/ggml/src/ggml-vulkan.cpp index 7c25f3b5..e8b5403c 100644 --- a/ggml/src/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan.cpp @@ -5520,6 +5520,9 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t nei0 = ids->ne[0]; const uint64_t nei1 = ids->ne[1]; + if (nei0*nei1 > 4096) { + fprintf(stderr, "%s: nei0 = %d, nei1 = %d\n", __func__, (int)nei0, (int)nei1); + } GGML_ASSERT(nei0 * nei1 <= 4096); const uint32_t nbi1 = ids->nb[1]; @@ -5915,7 +5918,30 @@ static void ggml_vk_mul_mat_id(ggml_backend_vk_context * ctx, vk_context& subctx if (src2->ne[1] == 1 && (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || ggml_is_quantized(src0->type))) { ggml_vk_mul_mat_vec_id_q_f16(ctx, subctx, src0, src1, src2, dst, dryrun); } else { - ggml_vk_mul_mat_id_q_f16(ctx, subctx, src0, src1, src2, dst, dryrun); + // Split based on number of ids, to fit in shared memory + const uint32_t nei0 = (uint32_t)src2->ne[0]; + const uint32_t nei1 = (uint32_t)src2->ne[1]; + + GGML_ASSERT(nei0 <= 4096); + const uint32_t split_size = std::min(nei1, 4096u / nei0); + + ggml_tensor src1_copy = *src1; + ggml_tensor src2_copy = *src2; + ggml_tensor dst_copy = *dst; + + for (uint32_t token_start = 0; token_start < nei1; token_start += split_size) { + const uint32_t n_tokens = std::min(split_size, nei1 - token_start); + + src1_copy.view_offs = src1->view_offs + token_start * src1_copy.nb[2]; + src2_copy.view_offs = src2->view_offs + token_start * src2_copy.nb[1]; + dst_copy.view_offs = dst->view_offs + token_start * dst_copy.nb[2]; + + src1_copy.ne[2] = n_tokens; + src2_copy.ne[1] = n_tokens; + dst_copy.ne[2] = n_tokens; + + ggml_vk_mul_mat_id_q_f16(ctx, subctx, src0, &src1_copy, &src2_copy, &dst_copy, dryrun); + } } } @@ -9510,9 +9536,15 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const ggml_type src0_type = op->src[0]->type; ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; const vk_device& device = ctx->device; - if (op->op == GGML_OP_MUL_MAT_ID && !device->mul_mat_id_s[src0_type] && !device->mul_mat_id_m[src0_type] && !device->mul_mat_id_l[src0_type]) { - // If there's not enough shared memory for row_ids and the result tile, fallback to CPU - return false; + if (op->op == GGML_OP_MUL_MAT_ID) { + if (!device->mul_mat_id_s[src0_type] && !device->mul_mat_id_m[src0_type] && !device->mul_mat_id_l[src0_type]) { + // If there's not enough shared memory for row_ids and the result tile, fallback to CPU + return false; + } + // Check against size of shared memory variable + if (op->src[2]->ne[0] > 4096) { + return false; + } } switch (src0_type) { case GGML_TYPE_F32: @@ -9580,6 +9612,10 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const default: return false; } + if (op->src[1]->ne[0] != op->src[2]->ne[0]) { + // different head sizes of K and V are not supported yet + return false; + } if (op->src[0]->type != GGML_TYPE_F32) { return false; } diff --git a/src/llama.cpp b/src/llama.cpp index 11a7060c..a1821d2d 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -9870,6 +9870,28 @@ llm_expert_gating_func_type gating_op, cb(cur, "ffn_moe_weighted", il); } +#ifdef GGML_USE_VULKAN + // aggregate experts + ggml_tensor * moe_out = nullptr; + //ggml_tensor * first_expert = 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; +#else if (n_expert_used == 1) { return ggml_cont(ctx, ggml_view_2d(ctx, experts, n_embd, n_tokens, experts->nb[2], 0)); } @@ -9878,32 +9900,8 @@ llm_expert_gating_func_type gating_op, ggml_view_2d(ctx, experts, n_embd, n_tokens, experts->nb[2], experts->nb[1])); } return ggml_multi_add(ctx, ggml_view_2d(ctx, experts, n_embd, n_tokens, experts->nb[2], 0), n_expert_used); +#endif - //// aggregate experts - //ggml_tensor * moe_out = nullptr; - ////ggml_tensor * first_expert = 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; - // //first_expert = cur_expert; - // //printf("%s: %d: %d x %d x %d x %d | %d x %d x %d x %d\n", __func__, ggml_is_contiguous(first_expert), - // // (int)cur_expert->ne[0], (int)cur_expert->ne[1], (int)cur_expert->ne[2], (int)cur_expert->ne[3], - // // (int)cur_expert->nb[0], (int)cur_expert->nb[1], (int)cur_expert->nb[2], (int)cur_expert->nb[3]); - // } else { - // moe_out = ggml_add(ctx, moe_out, cur_expert); - // //printf("%s: %d %d\n", __func__, ggml_is_contiguous(cur_expert), ggml_are_same_shape(cur_expert, first_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( From 235c989e398ef38c8c29c76017807705ddfa3a88 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Fri, 4 Jul 2025 08:33:43 +0200 Subject: [PATCH 14/63] Vulkan: adding GGML_OP_MULTI_ADD implementation (#582) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-vulkan.cpp | 35 ++++++++++++++ .../src/vulkan-shaders/vulkan-shaders-gen.cpp | 2 + src/llama.cpp | 46 +++++++++---------- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/ggml/src/ggml-vulkan.cpp b/ggml/src/ggml-vulkan.cpp index e8b5403c..758e6e6d 100644 --- a/ggml/src/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan.cpp @@ -447,6 +447,8 @@ struct vk_device_struct { vk_pipeline pipeline_fused_mul_silu[2]; vk_pipeline pipeline_fused_mul_relu[2]; + vk_pipeline pipeline_multi_add_f32; + vk_pipeline pipeline_leaky_relu_f32; vk_pipeline pipeline_silu_back_f32; vk_pipeline pipeline_diag_mask_inf_f32; @@ -683,6 +685,13 @@ struct vk_op_unary_push_constants { }; static_assert(sizeof(vk_op_unary_push_constants) <= 128, "sizeof(vk_op_unary_push_constants) must be <= 128"); +struct vk_op_multiadd_push_constants { + uint32_t ne; + uint32_t ne0, ne1; + uint32_t nb0, nb01; + uint32_t nadd; +}; + // See https://gmplib.org/~tege/divcnst-pldi94.pdf figure 4.1. // Precompute mp (m' in the paper) and L such that division // can be computed using a multiply (high 32b of 64b result) @@ -2759,6 +2768,8 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[0], "fused_mul_relu_f32", fused_mul_relu_f32_len, fused_mul_relu_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[1], "fused_mul_relu_f16", fused_mul_relu_f16_len, fused_mul_relu_f16_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_multi_add_f32, "multi_add_f32", multi_add_f32_len, multi_add_f32_data, "main", 2, sizeof(vk_op_multiadd_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_leaky_relu_f32, "leaky_relu_f32", leaky_relu_f32_len, leaky_relu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_silu_back_f32, "silu_back_f32", silu_back_f32_len, silu_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); @@ -6451,6 +6462,12 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const } return nullptr; } + case GGML_OP_MULTI_ADD: + if (src0->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F32 || + dst->ne[2] == 1 || dst->ne[3] == 1) { + return ctx->device->pipeline_multi_add_f32; + } + return nullptr; case GGML_OP_UNARY: if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16) || @@ -6588,6 +6605,7 @@ static bool ggml_vk_op_supports_incontiguous(ggml_op op) { case GGML_OP_RMS_NORM: case GGML_OP_FUSED_RMS_NORM: case GGML_OP_IM2COL: + case GGML_OP_MULTI_ADD: return true; default: return false; @@ -6889,6 +6907,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co case GGML_OP_CONCAT: case GGML_OP_UPSCALE: case GGML_OP_FUSED_MUL_UNARY: + case GGML_OP_MULTI_ADD: case GGML_OP_UNARY: { uint32_t ne = ggml_nelements(dst); @@ -7278,6 +7297,12 @@ static void ggml_vk_fused_mul_unary(ggml_backend_vk_context * ctx, vk_context& s ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_FUSED_MUL_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); } +static void ggml_vk_multi_add(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + uint32_t nadd = (uint32_t)dst->op_params[0]; + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_MULTI_ADD, + { (uint32_t)ggml_nelements(dst), (uint32_t)dst->ne[0], (uint32_t)dst->ne[1], (uint32_t)(dst->nb[1]/sizeof(float)), (uint32_t)(src0->nb[1]/sizeof(float)), nadd }, dryrun); +} + static void ggml_vk_diag_mask_inf(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { int32_t * op_params = (int32_t *)dst->op_params; ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_DIAG_MASK_INF, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0] }, dryrun); @@ -8463,6 +8488,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod } break; case GGML_OP_FUSED_MUL_UNARY: + case GGML_OP_MULTI_ADD: case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: case GGML_OP_GET_ROWS: @@ -8546,6 +8572,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_RMS_NORM_BACK: case GGML_OP_UNARY: case GGML_OP_FUSED_MUL_UNARY: + case GGML_OP_MULTI_ADD: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: case GGML_OP_SOFT_MAX_BACK: @@ -8662,6 +8689,9 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_FUSED_MUL_UNARY: ggml_vk_fused_mul_unary(ctx, compute_ctx, src0, src1, node, dryrun); break; + case GGML_OP_MULTI_ADD: + ggml_vk_multi_add(ctx, compute_ctx, src0, node, dryrun); + break; case GGML_OP_UNARY: switch (ggml_get_unary_op(node)) { case GGML_UNARY_OP_SILU: @@ -8834,6 +8864,7 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: case GGML_OP_FUSED_MUL_UNARY: + case GGML_OP_MULTI_ADD: buf = tensor->buffer; break; @@ -9530,6 +9561,8 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const return false; } break; + case GGML_OP_MULTI_ADD: + return op->src[0]->type == GGML_TYPE_F32 && op->type == GGML_TYPE_F32 && op->ne[2] == 1 && op->ne[3] == 1; case GGML_OP_MUL_MAT: case GGML_OP_MUL_MAT_ID: { @@ -10266,6 +10299,8 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { } } else if (tensor->op == GGML_OP_FUSED_MUL_UNARY) { tensor_clone = ggml_fused_mul_unary(ggml_ctx, src_clone[0], src_clone[1], (ggml_unary_op)tensor->op_params[0]); + } else if (tensor->op == GGML_OP_MULTI_ADD) { + tensor_clone = ggml_multi_add(ggml_ctx, src_clone[0], tensor->op_params[0]); } else if (tensor->op == GGML_OP_CPY || tensor->op == GGML_OP_DUP) { if (src1 == nullptr) { tensor_clone = ggml_dup(ggml_ctx, src_clone[0]); diff --git a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp index 281d98c6..65dd82de 100644 --- a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp +++ b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp @@ -579,6 +579,8 @@ void process_shaders() { string_to_spv("fused_mul_relu_f16", "fused_mul_relu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); string_to_spv("fused_mul_relu_f32", "fused_mul_relu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("multi_add_f32", "multi_add.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("gelu_f16", "gelu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); string_to_spv("gelu_f32", "gelu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); string_to_spv("gelu_quick_f16", "gelu_quick.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); diff --git a/src/llama.cpp b/src/llama.cpp index a1821d2d..8c16e778 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -9870,28 +9870,28 @@ llm_expert_gating_func_type gating_op, cb(cur, "ffn_moe_weighted", il); } -#ifdef GGML_USE_VULKAN - // aggregate experts - ggml_tensor * moe_out = nullptr; - //ggml_tensor * first_expert = 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; -#else +//#ifdef GGML_USE_VULKAN +// // aggregate experts +// ggml_tensor * moe_out = nullptr; +// //ggml_tensor * first_expert = 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; +//#else if (n_expert_used == 1) { return ggml_cont(ctx, ggml_view_2d(ctx, experts, n_embd, n_tokens, experts->nb[2], 0)); } @@ -9900,7 +9900,7 @@ llm_expert_gating_func_type gating_op, ggml_view_2d(ctx, experts, n_embd, n_tokens, experts->nb[2], experts->nb[1])); } return ggml_multi_add(ctx, ggml_view_2d(ctx, experts, n_embd, n_tokens, experts->nb[2], 0), n_expert_used); -#endif +//#endif } From 0678427f82686e9bb37d02bf5842e451bb742808 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Fri, 4 Jul 2025 08:39:04 +0200 Subject: [PATCH 15/63] Adding forgotten file (#583) Co-authored-by: Iwan Kawrakow --- ggml/src/vulkan-shaders/multi_add.comp | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 ggml/src/vulkan-shaders/multi_add.comp diff --git a/ggml/src/vulkan-shaders/multi_add.comp b/ggml/src/vulkan-shaders/multi_add.comp new file mode 100644 index 00000000..50f14c20 --- /dev/null +++ b/ggml/src/vulkan-shaders/multi_add.comp @@ -0,0 +1,37 @@ +#version 450 + +#include "types.comp" + +#extension GL_EXT_shader_16bit_storage : require +#extension GL_EXT_control_flow_attributes : enable + +layout (push_constant) uniform parameter +{ + uint ne; + uint ne0; + uint ne1; + uint nb1; + uint nb01; + uint nadd; +} p; + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.ne) { + return; + } + + uint i1 = i / p.ne0; + uint i0 = i % p.ne0; + + float sum = data_a[i1*p.nb01 + i0] + data_a[i1*p.nb01 + i0 + p.ne0]; + for (int j = 2; j < p.nadd; ++j) sum += data_a[i1*p.nb01 + i0 + j*p.ne0]; + + data_d[i1*p.nb1 + i0] = D_TYPE(sum); +} From 4622fadc2a2665b731a5887f93e295f0331ed80e Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Sat, 5 Jul 2025 15:14:12 +0200 Subject: [PATCH 16/63] Vulkan: flash attention for DeepSeek models (#584) * vulkan: support mixed/deepseekR1 FA head sizes (#14509) * vulkan: better parameterize FA by head sizes * vulkan: support mixed/deepseekR1 FA head sizes * Fix the FA cherry-pick --------- Co-authored-by: Jeff Bolz Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-vulkan.cpp | 230 ++++++++++--------- ggml/src/vulkan-shaders/flash_attn.comp | 43 ++-- ggml/src/vulkan-shaders/flash_attn_base.comp | 8 +- ggml/src/vulkan-shaders/flash_attn_cm1.comp | 62 ++--- ggml/src/vulkan-shaders/flash_attn_cm2.comp | 50 ++-- 5 files changed, 209 insertions(+), 184 deletions(-) diff --git a/ggml/src/ggml-vulkan.cpp b/ggml/src/ggml-vulkan.cpp index 758e6e6d..4091c89f 100644 --- a/ggml/src/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan.cpp @@ -232,6 +232,21 @@ enum vk_device_architecture { INTEL_XE2, }; +// HSK x HSV +enum FaHeadSizes { + FA_HEAD_SIZE_64, + FA_HEAD_SIZE_80, + FA_HEAD_SIZE_96, + FA_HEAD_SIZE_112, + FA_HEAD_SIZE_128, + FA_HEAD_SIZE_192, + FA_HEAD_SIZE_192_128, + FA_HEAD_SIZE_256, + FA_HEAD_SIZE_576_512, + FA_HEAD_SIZE_UNSUPPORTED, + FA_HEAD_SIZE_COUNT = FA_HEAD_SIZE_UNSUPPORTED, +}; + static vk_device_architecture get_device_architecture(const vk::PhysicalDevice& device) { vk::PhysicalDeviceProperties props = device.getProperties(); @@ -471,26 +486,11 @@ struct vk_device_struct { vk_pipeline pipeline_opt_step_adamw_f32; // [2][2][2] is for {f16acc,f32acc}x{large,small_rows}x{unaligned, aligned} - vk_pipeline pipeline_flash_attn_f32_f16_D64_cm2[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D80_cm2[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D96_cm2[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D112_cm2[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D128_cm2[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D256_cm2[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_cm2[GGML_TYPE_COUNT][FA_HEAD_SIZE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D64_cm1[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D80_cm1[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D96_cm1[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D112_cm1[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D128_cm1[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D256_cm1[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16_cm1[GGML_TYPE_COUNT][FA_HEAD_SIZE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D64[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D80[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D96[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D112[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D128[GGML_TYPE_COUNT][2][2][2]; - vk_pipeline pipeline_flash_attn_f32_f16_D256[GGML_TYPE_COUNT][2][2][2]; + vk_pipeline pipeline_flash_attn_f32_f16[GGML_TYPE_COUNT][FA_HEAD_SIZE_COUNT][2][2][2]; vk_pipeline pipeline_flash_attn_split_k_reduce; @@ -1685,6 +1685,35 @@ enum FaCodePath { FA_COOPMAT2, }; +static FaHeadSizes fa_get_head_sizes(uint32_t hsk, uint32_t hsv) { + if (hsk != 192 && hsk != 576 && hsk != hsv) { + return FA_HEAD_SIZE_UNSUPPORTED; + } + switch (hsk) { + case 64: return FA_HEAD_SIZE_64; + case 80: return FA_HEAD_SIZE_80; + case 96: return FA_HEAD_SIZE_96; + case 112: return FA_HEAD_SIZE_112; + case 128: return FA_HEAD_SIZE_128; + case 192: + if (hsv == 192) { + return FA_HEAD_SIZE_192; + } else if (hsv == 128) { + return FA_HEAD_SIZE_192_128; + } else { + return FA_HEAD_SIZE_UNSUPPORTED; + } + case 256: return FA_HEAD_SIZE_256; + case 576: + if (hsv == 512) { + return FA_HEAD_SIZE_576_512; + } else { + return FA_HEAD_SIZE_UNSUPPORTED; + } + default: return FA_HEAD_SIZE_UNSUPPORTED; + } +} + // number of rows/cols for flash attention shader static constexpr uint32_t flash_attention_num_small_rows = 32; static constexpr uint32_t scalar_flash_attention_num_small_rows = 1; @@ -1705,8 +1734,9 @@ static uint32_t get_fa_num_small_rows(FaCodePath path) { } } -static std::array fa_rows_cols(FaCodePath path, uint32_t D, uint32_t clamp, ggml_type type, bool small_rows) { +static std::array fa_rows_cols(FaCodePath path, uint32_t hsk, uint32_t hsv, uint32_t clamp, ggml_type type, bool small_rows) { GGML_UNUSED(clamp); + GGML_UNUSED(hsv); if (path == FA_SCALAR) { if (small_rows) { @@ -1730,7 +1760,7 @@ static std::array fa_rows_cols(FaCodePath path, uint32_t D, uint32_ } // small cols to reduce register count - if (ggml_is_quantized(type) || D == 256) { + if (ggml_is_quantized(type) || hsk >= 256) { return {64, 32}; } return {64, 64}; @@ -2023,19 +2053,21 @@ static void ggml_vk_load_shaders(vk_device& device) { parameter_count, wg_denoms, specialization_constants, disable_robustness, require_full_subgroups, required_subgroup_size)); }; - auto const &fa_wg_denoms = [&](FaCodePath path, uint32_t D, uint32_t clamp, ggml_type type, bool small_rows) -> std::array { - return {fa_rows_cols(path, D, clamp, type, small_rows)[0], 1, 1}; + auto const &fa_wg_denoms = [&](FaCodePath path, uint32_t hsk, uint32_t hsv, uint32_t clamp, ggml_type type, bool small_rows) -> std::array { + return {fa_rows_cols(path, hsk, hsv, clamp, type, small_rows)[0], 1, 1}; }; - auto const &fa_spec_constants = [&](FaCodePath path, uint32_t D, uint32_t clamp, ggml_type type, bool small_rows) -> std::vector { + auto const &fa_spec_constants = [&](FaCodePath path, uint32_t hsk, uint32_t hsv, uint32_t clamp, ggml_type type, bool small_rows) -> std::vector { // For large number of rows, 128 invocations seems to work best. // For small number of rows (e.g. N==1), 256 works better. But matrix granularity for 256 is 32, so we // can't use 256 for D==80. // For scalar, use 128 (arbitrary) + // The same D_split value is used for both HSK and HSV, so just base it on the union of the LSBs. + const uint32_t D = (hsk|hsv); uint32_t wg_size = (path == FA_SCALAR || path == FA_COOPMAT1) ? scalar_flash_attention_workgroup_size : ((small_rows && (D % 32) == 0) ? 256 : 128); - auto rows_cols = fa_rows_cols(path, D, clamp, type, small_rows); + auto rows_cols = fa_rows_cols(path, hsk, hsv, clamp, type, small_rows); // D_split can't be larger than a subgroup because we use subgroupShuffle to reduce it. // D_split can't be larger than the LSB of D divided by 4 due to vectorization in the shader. @@ -2044,26 +2076,29 @@ static void ggml_vk_load_shaders(vk_device& device) { // mask dim1 is padded to 64, we rely on this to avoid clamping mask loads GGML_ASSERT((GGML_KQ_MASK_PAD % rows_cols[0]) == 0); - return {wg_size, rows_cols[0], rows_cols[1], (D), clamp, D_split}; + return {wg_size, rows_cols[0], rows_cols[1], hsk, hsv, clamp, D_split}; }; -#define CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, D) \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][0][0], "flash_attn_f32_f16_D" #D "_f16acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,false), fa_spec_constants(FAPATH, D,1,TYPE,false), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][0][1], "flash_attn_f32_f16_D" #D "_aligned_f16acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,false), fa_spec_constants(FAPATH, D,0,TYPE,false), fa_rows_cols(FAPATH,D,0,TYPE,false)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][0][0], "flash_attn_f32_f16_D" #D "_f32acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,false), fa_spec_constants(FAPATH, D,1,TYPE,false), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][0][1], "flash_attn_f32_f16_D" #D "_aligned_f32acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,false), fa_spec_constants(FAPATH, D,0,TYPE,false), fa_rows_cols(FAPATH,D,0,TYPE,false)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][1][0], "flash_attn_f32_f16_D" #D "_f16acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,true), fa_spec_constants(FAPATH, D,1,TYPE,true), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][0][1][1], "flash_attn_f32_f16_D" #D "_aligned_f16acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,true), fa_spec_constants(FAPATH, D,0,TYPE,true), fa_rows_cols(FAPATH,D,0,TYPE,true)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][1][0], "flash_attn_f32_f16_D" #D "_f32acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,1,TYPE,true), fa_spec_constants(FAPATH, D,1,TYPE,true), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16_D ## D ## SUFFIX[TYPE][1][1][1], "flash_attn_f32_f16_D" #D "_aligned_f32acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, D,0,TYPE,true), fa_spec_constants(FAPATH, D,0,TYPE,true), fa_rows_cols(FAPATH,D,0,TYPE,true)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ +#define CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, HSK, HSV, HEAD_SIZES) \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][0][0][0], "flash_attn_f32_f16_" #HEAD_SIZES "_f16acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,1,TYPE,false), fa_spec_constants(FAPATH, HSK,HSV,1,TYPE,false), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][0][0][1], "flash_attn_f32_f16_" #HEAD_SIZES "_aligned_f16acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,0,TYPE,false), fa_spec_constants(FAPATH, HSK,HSV,0,TYPE,false), fa_rows_cols(FAPATH,HSK,HSV,0,TYPE,false)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][1][0][0], "flash_attn_f32_f16_" #HEAD_SIZES "_f32acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,1,TYPE,false), fa_spec_constants(FAPATH, HSK,HSV,1,TYPE,false), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][1][0][1], "flash_attn_f32_f16_" #HEAD_SIZES "_aligned_f32acc" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,0,TYPE,false), fa_spec_constants(FAPATH, HSK,HSV,0,TYPE,false), fa_rows_cols(FAPATH,HSK,HSV,0,TYPE,false)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][0][1][0], "flash_attn_f32_f16_" #HEAD_SIZES "_f16acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,1,TYPE,true), fa_spec_constants(FAPATH, HSK,HSV,1,TYPE,true), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][0][1][1], "flash_attn_f32_f16_" #HEAD_SIZES "_aligned_f16acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## _f16acc ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,0,TYPE,true), fa_spec_constants(FAPATH, HSK,HSV,0,TYPE,true), fa_rows_cols(FAPATH,HSK,HSV,0,TYPE,true)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][1][1][0], "flash_attn_f32_f16_" #HEAD_SIZES "_f32acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,1,TYPE,true), fa_spec_constants(FAPATH, HSK,HSV,1,TYPE,true), 1, true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_f32_f16 ## SUFFIX[TYPE][FA_HEAD_SIZE_##HEAD_SIZES][1][1][1], "flash_attn_f32_f16_" #HEAD_SIZES "_aligned_f32acc_smallrows" #NAMELC #SUFFIX, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _len, flash_attn_f32_f16_ ## NAMELC ## SUFFIX ## _data, "main", 5, sizeof(vk_flash_attn_push_constants), fa_wg_denoms(FAPATH, HSK,HSV,0,TYPE,true), fa_spec_constants(FAPATH, HSK,HSV,0,TYPE,true), fa_rows_cols(FAPATH,HSK,HSV,0,TYPE,true)[1], true, FAPATH==FA_COOPMAT1, (FAPATH==FA_COOPMAT1 ? 32 : 0)); \ #define CREATE_FA(TYPE, NAMELC, FAPATH, SUFFIX) \ - CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 64) \ - CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 80) \ - CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 96) \ - CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 112) \ - CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 128) \ - CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 256) + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 64, 64, 64) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 80, 80, 80) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 96, 96, 96) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 112, 112, 112) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 128, 128, 128) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 192, 192, 192) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 192, 128, 192_128) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 256, 256, 256) \ + CREATE_FA2(TYPE, NAMELC, FAPATH, SUFFIX, 576, 512, 576_512) CREATE_FA(GGML_TYPE_F16, f16, FA_SCALAR, ) CREATE_FA(GGML_TYPE_Q4_0, q4_0, FA_SCALAR, ) @@ -3665,7 +3700,6 @@ GGML_CALL void ggml_vk_instance_init() { } - size_t num_available_devices = vk_instance.instance.enumeratePhysicalDevices().size(); vk_perf_logger_enabled = getenv("GGML_VK_PERF_LOGGER") != nullptr; // Emulate behavior of CUDA_VISIBLE_DEVICES for Vulkan @@ -5956,24 +5990,47 @@ static void ggml_vk_mul_mat_id(ggml_backend_vk_context * ctx, vk_context& subctx } } -static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, const uint32_t D, bool f32acc) { +static bool ggml_vk_flash_attn_scalar_shmem_support(const vk_device& device, const uint32_t hsk, uint32_t hsv) { // Needs to be kept up to date on shader changes + GGML_UNUSED(hsv); const uint32_t wg_size = scalar_flash_attention_workgroup_size; const uint32_t Br = scalar_flash_attention_num_large_rows; const uint32_t Bc = scalar_flash_attention_Bc; + const uint32_t tmpsh = wg_size * sizeof(float); + const uint32_t tmpshv4 = wg_size * 4 * sizeof(float); + + const uint32_t masksh = Bc * Br * sizeof(float); + + const uint32_t Qf = Br * (hsk / 4 + 2) * 4 * sizeof(float); + + const uint32_t total_size = tmpsh + tmpshv4 + masksh + Qf; + const bool supported = total_size <= device->properties.limits.maxComputeSharedMemorySize; + + VK_LOG_DEBUG("ggml_vk_flash_attn_coopmat_shmem_support(HSK=" << hsk << ", HSV=" << hsv << ", total_size=" << total_size << ", supported=" << supported); + + return supported; +} + +static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, const uint32_t hsk, uint32_t hsv, bool f32acc) { + // Needs to be kept up to date on shader changes + GGML_UNUSED(hsv); + const uint32_t wg_size = scalar_flash_attention_workgroup_size; + const uint32_t Br = coopmat1_flash_attention_num_large_rows; + const uint32_t Bc = scalar_flash_attention_Bc; + const uint32_t acctype = f32acc ? 4 : 2; const uint32_t f16vec4 = 8; const uint32_t tmpsh = wg_size * sizeof(float); const uint32_t tmpshv4 = wg_size * 4 * acctype; - const uint32_t Qf = Br * (D / 4 + 2) * f16vec4; + const uint32_t Qf = Br * (hsk / 4 + 2) * f16vec4; - const uint32_t sfshstride = (D <= 128) ? (Br + 8) : Br; + const uint32_t sfshstride = (hsk <= 128) ? (Br + 8) : Br; const uint32_t sfsh = Bc * sfshstride * acctype; - const uint32_t kshstride = D / 4 + 2; + const uint32_t kshstride = hsk / 4 + 2; const uint32_t ksh = Bc * kshstride * f16vec4; const uint32_t slope = Br * sizeof(float); @@ -5981,7 +6038,7 @@ static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, co const uint32_t total_size = tmpsh + tmpshv4 + Qf + sfsh + ksh + slope; const bool supported = total_size <= device->properties.limits.maxComputeSharedMemorySize; - VK_LOG_DEBUG("ggml_vk_flash_attn_coopmat_shmem_support(D=" << D << ", f32acc=" << f32acc << ", total_size=" << total_size << ", supported=" << supported); + VK_LOG_DEBUG("ggml_vk_flash_attn_coopmat_shmem_support(HSK=" << hsk << ", HSV=" << hsv << ", f32acc=" << f32acc << ", total_size=" << total_size << ", supported=" << supported); return supported; } @@ -6005,11 +6062,12 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx const uint32_t nem1 = mask ? mask->ne[1] : 0; const uint32_t nbm1 = mask ? mask->nb[1] : 0; - const uint32_t D = neq0; + const uint32_t HSK = nek0; + const uint32_t HSV = nev0; uint32_t N = neq1; const uint32_t KV = nek1; - GGML_ASSERT(ne0 == D); + GGML_ASSERT(ne0 == HSV); GGML_ASSERT(ne2 == N); // input tensor rows must be contiguous @@ -6017,12 +6075,9 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx GGML_ASSERT(nbk0 == ggml_type_size(k->type)); GGML_ASSERT(nbv0 == ggml_type_size(v->type)); - GGML_ASSERT(neq0 == D); - GGML_ASSERT(nek0 == D); - GGML_ASSERT(nev0 == D); + GGML_ASSERT(neq0 == HSK); GGML_ASSERT(neq1 == N); - GGML_ASSERT(nev0 == D); GGML_ASSERT(nev1 == nek1); @@ -6043,7 +6098,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx const bool coopmat_shape_supported = (dst->op_params[3] == GGML_PREC_F32 && ctx->device->coopmat_support_16x16x16_f32acc) || (dst->op_params[3] != GGML_PREC_F32 && ctx->device->coopmat_support_16x16x16_f16acc); - const bool coopmat_shmem_supported = ggml_vk_flash_attn_coopmat_shmem_support(ctx->device, D, dst->op_params[3] == GGML_PREC_F32); + const bool coopmat_shmem_supported = ggml_vk_flash_attn_coopmat_shmem_support(ctx->device, HSK, HSV, dst->op_params[3] == GGML_PREC_F32); if (!coopmat_shape_supported || !coopmat_shmem_supported) { path = FA_SCALAR; @@ -6096,47 +6151,25 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx path = FA_SCALAR; } + // with large hsk/hsv, scalar path may need to use small_rows to fit in shared memory + if (path == FA_SCALAR && + !ggml_vk_flash_attn_scalar_shmem_support(ctx->device, HSK, HSV)) { + small_rows = true; + } + bool f32acc = path == FA_SCALAR || dst->op_params[3] == GGML_PREC_F32; + FaHeadSizes head_sizes = fa_get_head_sizes(k->ne[0], v->ne[0]); + switch (path) { case FA_SCALAR: - switch (D) { - case 64: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D64[k->type][f32acc][small_rows][0]; break; - case 80: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D80[k->type][f32acc][small_rows][0]; break; - case 96: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D96[k->type][f32acc][small_rows][0]; break; - case 112: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D112[k->type][f32acc][small_rows][0]; break; - case 128: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D128[k->type][f32acc][small_rows][0]; break; - case 256: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D256[k->type][f32acc][small_rows][0]; break; - default: - GGML_ASSERT(!"unsupported D value"); - return; - } + pipelines = &ctx->device->pipeline_flash_attn_f32_f16[k->type][head_sizes][f32acc][small_rows][0]; break; case FA_COOPMAT1: - switch (D) { - case 64: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D64_cm1[k->type][f32acc][small_rows][0]; break; - case 80: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D80_cm1[k->type][f32acc][small_rows][0]; break; - case 96: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D96_cm1[k->type][f32acc][small_rows][0]; break; - case 112: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D112_cm1[k->type][f32acc][small_rows][0]; break; - case 128: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D128_cm1[k->type][f32acc][small_rows][0]; break; - case 256: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D256_cm1[k->type][f32acc][small_rows][0]; break; - default: - GGML_ASSERT(!"unsupported D value"); - return; - } + pipelines = &ctx->device->pipeline_flash_attn_f32_f16_cm1[k->type][head_sizes][f32acc][small_rows][0]; break; case FA_COOPMAT2: - switch (D) { - case 64: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D64_cm2[k->type][f32acc][small_rows][0]; break; - case 80: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D80_cm2[k->type][f32acc][small_rows][0]; break; - case 96: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D96_cm2[k->type][f32acc][small_rows][0]; break; - case 112: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D112_cm2[k->type][f32acc][small_rows][0]; break; - case 128: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D128_cm2[k->type][f32acc][small_rows][0]; break; - case 256: pipelines = &ctx->device->pipeline_flash_attn_f32_f16_D256_cm2[k->type][f32acc][small_rows][0]; break; - default: - GGML_ASSERT(!"unsupported D value"); - return; - } + pipelines = &ctx->device->pipeline_flash_attn_f32_f16_cm2[k->type][head_sizes][f32acc][small_rows][0]; break; default: GGML_ASSERT(0); @@ -6166,7 +6199,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx // Try to use split_k when KV is large enough to be worth the overhead if (workgroups_x == 1 && shader_core_count > 0 && KV >= 512) { // Try to run two workgroups per SM. - split_k = ctx->device->shader_core_count * 2 / workgroups_y; + split_k = shader_core_count * 2 / (workgroups_y * workgroups_z); if (split_k > 1) { // Try to evenly split KV into split_k chunks, but it needs to be a multiple // of "align", so recompute split_k based on that. @@ -6176,9 +6209,9 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx } } - // Reserve space for split_k temporaries. For each split, we need to store the O matrix (D x ne1) - // and the per-row m and L values (ne1 rows). - const uint64_t split_k_size = split_k > 1 ? (D * ne1 * sizeof(float) + ne1 * sizeof(float) * 2) * split_k : 0; + // Reserve space for split_k temporaries. For each split x batch, we need to store the O matrix (D x ne1) + // and the per-row m and L values (ne1 rows). We store all the matrices first, followed by the rows. + const uint64_t split_k_size = split_k > 1 ? (HSV * ne1 * sizeof(float) + ne1 * sizeof(float) * 2) * split_k * ne3 : 0; if (split_k_size > ctx->device->max_memory_allocation_size) { GGML_ABORT("Requested preallocation size is too large"); } @@ -6297,7 +6330,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx sizeof(vk_flash_attn_push_constants), &pc, { workgroups_x * pipeline->wg_denoms[0], workgroups_y, workgroups_z }); ggml_vk_sync_buffers(subctx); - const std::array pc2 = { D, (uint32_t)ne1, split_k }; + const std::array pc2 = { HSV, (uint32_t)ne1, (uint32_t)ne3, split_k }; ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_flash_attn_split_k_reduce, { vk_subbuffer{ctx->prealloc_split_k, 0, VK_WHOLE_SIZE}, @@ -9634,19 +9667,8 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const { ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; bool coopmat2 = ctx->device->coopmat2; - switch (op->src[0]->ne[0]) { - case 64: - case 80: - case 96: - case 112: - case 128: - case 256: - break; - default: - return false; - } - if (op->src[1]->ne[0] != op->src[2]->ne[0]) { - // different head sizes of K and V are not supported yet + FaHeadSizes head_sizes = fa_get_head_sizes(op->src[1]->ne[0], op->src[2]->ne[0]); + if (head_sizes == FA_HEAD_SIZE_UNSUPPORTED) { return false; } if (op->src[0]->type != GGML_TYPE_F32) { diff --git a/ggml/src/vulkan-shaders/flash_attn.comp b/ggml/src/vulkan-shaders/flash_attn.comp index ce230a8f..454b3411 100644 --- a/ggml/src/vulkan-shaders/flash_attn.comp +++ b/ggml/src/vulkan-shaders/flash_attn.comp @@ -11,7 +11,8 @@ #include "types.comp" #include "flash_attn_base.comp" -const uint32_t D_per_thread = D / D_split; +const uint32_t HSK_per_thread = HSK / D_split; +const uint32_t HSV_per_thread = HSV / D_split; const uint32_t cols_per_iter = WorkGroupSize / D_split; const uint32_t cols_per_thread = Bc / cols_per_iter; @@ -29,7 +30,7 @@ layout (binding = 3) readonly buffer M {float16_t data_m[];}; // Rows index by Q's dimension 2, and the first N rows are valid. D_TYPE perElemOpGqaStore(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t o_offset, const in uint32_t iq2, const in uint32_t N) { - uint32_t offset = (iq2 + r) * D + c; + uint32_t offset = (iq2 + r) * HSV + c; data_o[o_offset + offset] = D_TYPE(elem); return elem; } @@ -38,7 +39,7 @@ shared FLOAT_TYPE tmpsh[WorkGroupSize]; shared vec4 tmpshv4[WorkGroupSize]; shared float masksh[Bc][Br]; -shared vec4 Qf[Br][D / 4]; +shared vec4 Qf[Br][HSK / 4]; void main() { #ifdef NEEDS_INIT_IQ_SHMEM @@ -53,18 +54,18 @@ void main() { uint32_t q_offset = (iq2*p.nb02+iq3*p.nb03) / 4; - [[unroll]] for (uint32_t idx = 0; idx < Br * D / 4; idx += gl_WorkGroupSize.x) { - uint32_t d = (idx + tid) % (D / 4); - uint32_t r = (idx + tid) / (D / 4); - if (r < Br && d < D / 4 && + [[unroll]] for (uint32_t idx = 0; idx < Br * HSK / 4; idx += gl_WorkGroupSize.x) { + uint32_t d = (idx + tid) % (HSK / 4); + uint32_t r = (idx + tid) / (HSK / 4); + if (r < Br && d < HSK / 4 && i * Br + r < N) { Qf[r][d] = vec4(data_qv4[q_offset / 4 + (i * Br + r) * q_stride / 4 + d]) * p.scale; } } barrier(); - vec4 Of[Br][D_per_thread / 4]; - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + vec4 Of[Br][HSV_per_thread / 4]; + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t r = 0; r < Br; ++r) { Of[r][d] = vec4(0.0); } @@ -112,7 +113,7 @@ void main() { [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSK_per_thread / 4; ++d) { #if BLOCK_SIZE > 1 uint coord = (j * Bc + c * cols_per_iter + col_tid) * k_stride * BLOCK_SIZE + 4 * (d * D_split + d_tid); uint ib = coord / BLOCK_SIZE; @@ -191,14 +192,14 @@ void main() { Lf[r] = eMf[r]*Lf[r] + rowsumf[r]; } - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t r = 0; r < Br; ++r) { Of[r][d] = eMf[r] * Of[r][d]; } } [[unroll]] for (uint32_t c = 0; c < cols_per_thread; ++c) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { #if BLOCK_SIZE > 1 uint coord = (j * Bc + c * cols_per_iter + col_tid) * v_stride * BLOCK_SIZE + 4 * (d * D_split + d_tid); uint ib = coord / BLOCK_SIZE; @@ -255,7 +256,7 @@ void main() { Lf[r] = tmpsh[d_tid]; barrier(); - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { Of[r][d] = eMf * Of[r][d]; tmpshv4[tid] = Of[r][d]; @@ -277,11 +278,11 @@ void main() { // If there is split_k, then the split_k resolve shader does the final // division by L. Store the intermediate O value and per-row m and L values. if (p.k_num > 1) { - uint32_t o_offset = D * p.ne1 * split_k_index; + uint32_t o_offset = HSV * p.ne1 * (split_k_index + iq3 * p.k_num); [[unroll]] for (uint32_t r = 0; r < Br; ++r) { if (r < N) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { perElemOpGqaStore(r, 4*(d * D_split + d_tid) + comp, Of[r][d][comp], o_offset, iq2, N); } @@ -289,7 +290,7 @@ void main() { } } - o_offset = D * p.ne1 * p.k_num + p.ne1 * split_k_index * 2; + o_offset = HSV * p.ne1 * p.ne3 * p.k_num + p.ne1 * (split_k_index + iq3 * p.k_num) * 2; [[unroll]] for (uint32_t r = 0; r < Br; ++r) { if (r < N) { perElemOpStoreCol0(r, 0u, ACC_TYPE(Lf[r]), o_offset, iq2, N); @@ -305,18 +306,18 @@ void main() { Lfrcp[r] = 1.0 / Lf[r]; } - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t r = 0; r < Br; ++r) { Of[r][d] *= Lfrcp[r]; } } - uint32_t o_offset = iq3*p.ne2*p.ne1; + uint32_t o_offset = iq3*p.ne2*p.ne1*HSV; if (p.gqa_ratio > 1) { [[unroll]] for (uint32_t r = 0; r < Br; ++r) { if (r < N) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { perElemOpGqaStore(r, 4*(d * D_split + d_tid) + comp, Of[r][d][comp], o_offset, iq2, N); } @@ -326,9 +327,9 @@ void main() { } else { [[unroll]] for (uint32_t r = 0; r < Br; ++r) { if (i * Br + r < N) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { - data_o[o_offset + iq2 * D + (i * Br + r) * p.ne1 * D + 4*(d * D_split + d_tid) + comp] = D_TYPE(Of[r][d][comp]); + data_o[o_offset + iq2 * HSV + (i * Br + r) * p.ne1 * HSV + 4*(d * D_split + d_tid) + comp] = D_TYPE(Of[r][d][comp]); } } } diff --git a/ggml/src/vulkan-shaders/flash_attn_base.comp b/ggml/src/vulkan-shaders/flash_attn_base.comp index 61d90e2d..1d3e6387 100644 --- a/ggml/src/vulkan-shaders/flash_attn_base.comp +++ b/ggml/src/vulkan-shaders/flash_attn_base.comp @@ -4,10 +4,10 @@ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; layout (constant_id = 0) const uint32_t WorkGroupSize = 128; layout (constant_id = 1) const uint32_t Br = 1; layout (constant_id = 2) const uint32_t Bc = 32; -layout (constant_id = 3) const uint32_t D = 32; -layout (constant_id = 4) const uint32_t Clamp = 0; -layout (constant_id = 5) const uint32_t D_split = 16; - +layout (constant_id = 3) const uint32_t HSK = 32; +layout (constant_id = 4) const uint32_t HSV = 32; +layout (constant_id = 5) const uint32_t Clamp = 0; +layout (constant_id = 6) const uint32_t D_split = 16; layout (push_constant) uniform parameter { uint32_t N; diff --git a/ggml/src/vulkan-shaders/flash_attn_cm1.comp b/ggml/src/vulkan-shaders/flash_attn_cm1.comp index da478be2..ad7594fe 100644 --- a/ggml/src/vulkan-shaders/flash_attn_cm1.comp +++ b/ggml/src/vulkan-shaders/flash_attn_cm1.comp @@ -13,7 +13,9 @@ #include "types.comp" #include "flash_attn_base.comp" -const uint32_t D_per_thread = D / D_split; +const uint32_t HSK_per_thread = HSK / D_split; +const uint32_t HSV_per_thread = HSV / D_split; + const uint32_t row_split = 4; const uint32_t rows_per_thread = Br / row_split; const uint32_t cols_per_iter = gl_WorkGroupSize.x / D_split / row_split; @@ -32,7 +34,7 @@ layout (binding = 3) readonly buffer M {float16_t data_m[];}; // Rows index by Q's dimension 2, and the first N rows are valid. D_TYPE perElemOpGqaStore(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t o_offset, const in uint32_t iq2, const in uint32_t N) { - uint32_t offset = (iq2 + r) * D + c; + uint32_t offset = (iq2 + r) * HSV + c; data_o[o_offset + offset] = D_TYPE(elem); return elem; } @@ -44,14 +46,14 @@ const uint32_t MatBc = 16; shared FLOAT_TYPE tmpsh[gl_WorkGroupSize.x]; shared ACC_TYPEV4 tmpshv4[gl_WorkGroupSize.x]; -const uint32_t qstride = D / 4 + 2; // in units of f16vec4 +const uint32_t qstride = HSK / 4 + 2; // in units of f16vec4 shared f16vec4 Qf[Br * qstride]; -// Avoid padding for D==256 to make it fit in 48KB shmem. -const uint32_t sfshstride = (D <= 128) ? (Br + 8) : Br; +// Avoid padding for hsk==256 to make it fit in 48KB shmem. +const uint32_t sfshstride = (HSK <= 128) ? (Br + 8) : Br; shared ACC_TYPE sfsh[Bc * sfshstride]; -const uint32_t kshstride = D / 4 + 2; // in units of f16vec4 +const uint32_t kshstride = HSK / 4 + 2; // in units of f16vec4 shared f16vec4 ksh[Bc * kshstride]; shared float slope[Br]; @@ -74,18 +76,18 @@ void main() { uint32_t q_offset = (iq2*p.nb02+iq3*p.nb03) / 4; - [[unroll]] for (uint32_t idx = 0; idx < Br * D / 4; idx += gl_WorkGroupSize.x) { - uint32_t d = (idx + tid) % (D / 4); - uint32_t r = (idx + tid) / (D / 4); - if (r < Br && d < D / 4 && + [[unroll]] for (uint32_t idx = 0; idx < Br * HSK / 4; idx += gl_WorkGroupSize.x) { + uint32_t d = (idx + tid) % (HSK / 4); + uint32_t r = (idx + tid) / (HSK / 4); + if (r < Br && d < HSK / 4 && i * Br + r < N) { Qf[r * qstride + d] = f16vec4(data_qv4[q_offset / 4 + (i * Br + r) * q_stride / 4 + d] * p.scale); } } barrier(); - ACC_TYPEV4 Of[rows_per_thread][D_per_thread / 4]; - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + ACC_TYPEV4 Of[rows_per_thread][HSV_per_thread / 4]; + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { Of[r][d] = ACC_TYPEV4(0.0); } @@ -127,10 +129,10 @@ void main() { [[dont_unroll]] for (uint32_t j = start_j; j < end_j; ++j) { - [[unroll]] for (uint32_t idx = 0; idx < Bc * D / 4; idx += gl_WorkGroupSize.x) { - uint32_t d = (idx + tid) % (D / 4); - uint32_t c = (idx + tid) / (D / 4); - if (c < Bc && d < D / 4) { + [[unroll]] for (uint32_t idx = 0; idx < Bc * HSK / 4; idx += gl_WorkGroupSize.x) { + uint32_t d = (idx + tid) % (HSK / 4); + uint32_t c = (idx + tid) / (HSK / 4); + if (c < Bc && d < HSK / 4) { #if BLOCK_SIZE > 1 uint coord = (j * Bc + c) * k_stride * BLOCK_SIZE + 4 * d; uint ib = coord / BLOCK_SIZE; @@ -145,14 +147,14 @@ void main() { } barrier(); - // K * Q^T -> S^T: Bc x D * D x Br -> Bc x Br - // Bc split across workgroup (four subgroups), loop over D in chunks of 16: 16 x 16 * 16 x 16 -> 16 x 16 + // K * Q^T -> S^T: Bc x HSK * HSK x Br -> Bc x Br + // Bc split across workgroup (four subgroups), loop over HSK in chunks of 16: 16 x 16 * 16 x 16 -> 16 x 16 // This is written transposed in order to allow for N being 8 if implementations need it coopmat SfMat = coopmat(0); coopmat KMat; coopmat QMat; - for (uint32_t d = 0; d < D / 16; ++d) { + for (uint32_t d = 0; d < HSK / 16; ++d) { coopMatLoad(QMat, Qf, d * 16 / 4, qstride, gl_CooperativeMatrixLayoutColumnMajor); uint coord = (gl_SubgroupID * MatBc) * kshstride + d * 16 / 4; @@ -202,7 +204,7 @@ void main() { eMf[r] = exp(Moldf - Mf[r]); } - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { Of[r][d] = float16_t(eMf[r]) * Of[r][d]; } @@ -217,7 +219,7 @@ void main() { Pf[r] = exp(sfsh[tile_row(r) + (c * cols_per_iter + col_tid) * sfshstride] - Mf[r]); Lf[r] += Pf[r]; } - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { #if BLOCK_SIZE > 1 uint coord = (j * Bc + c * cols_per_iter + col_tid) * v_stride * BLOCK_SIZE + 4 * (d * D_split + d_tid); uint ib = coord / BLOCK_SIZE; @@ -280,7 +282,7 @@ void main() { } [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { Of[r][d] = float16_t(eMf[r]) * Of[r][d]; tmpshv4[tid] = Of[r][d]; @@ -300,11 +302,11 @@ void main() { // If there is split_k, then the split_k resolve shader does the final // division by L. Store the intermediate O value and per-row m and L values. if (p.k_num > 1) { - uint32_t o_offset = D * p.ne1 * split_k_index; + uint32_t o_offset = HSV * p.ne1 * (split_k_index + iq3 * p.k_num); [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { if (tile_row(r) < N) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { perElemOpGqaStore(tile_row(r), 4*(d * D_split + d_tid) + comp, float(Of[r][d][comp]), o_offset, iq2, N); } @@ -312,7 +314,7 @@ void main() { } } - o_offset = D * p.ne1 * p.k_num + p.ne1 * split_k_index * 2; + o_offset = HSV * p.ne1 * p.ne3 * p.k_num + p.ne1 * (split_k_index + iq3 * p.k_num) * 2; [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { if (tile_row(r) < N) { perElemOpStoreCol0(tile_row(r), 0u, ACC_TYPE(Lf[r]), o_offset, iq2, N); @@ -328,18 +330,18 @@ void main() { Lfrcp[r] = 1.0 / Lf[r]; } - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { Of[r][d] *= float16_t(Lfrcp[r]); } } - uint32_t o_offset = iq3*p.ne2*p.ne1; + uint32_t o_offset = iq3*p.ne2*p.ne1*HSV; if (p.gqa_ratio > 1) { [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { if (tile_row(r) < N) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { perElemOpGqaStore(tile_row(r), 4*(d * D_split + d_tid) + comp, float(Of[r][d][comp]), o_offset, iq2, N); } @@ -349,9 +351,9 @@ void main() { } else { [[unroll]] for (uint32_t r = 0; r < rows_per_thread; ++r) { if (i * Br + tile_row(r) < N) { - [[unroll]] for (uint32_t d = 0; d < D_per_thread / 4; ++d) { + [[unroll]] for (uint32_t d = 0; d < HSV_per_thread / 4; ++d) { [[unroll]] for (uint32_t comp = 0; comp < 4; ++comp) { - data_o[o_offset + iq2 * D + (i * Br + tile_row(r)) * p.ne1 * D + 4*(d * D_split + d_tid) + comp] = D_TYPE(Of[r][d][comp]); + data_o[o_offset + iq2 * HSV + (i * Br + tile_row(r)) * p.ne1 * HSV + 4*(d * D_split + d_tid) + comp] = D_TYPE(Of[r][d][comp]); } } } diff --git a/ggml/src/vulkan-shaders/flash_attn_cm2.comp b/ggml/src/vulkan-shaders/flash_attn_cm2.comp index 6acf67a0..91caa184 100644 --- a/ggml/src/vulkan-shaders/flash_attn_cm2.comp +++ b/ggml/src/vulkan-shaders/flash_attn_cm2.comp @@ -61,8 +61,8 @@ ACC_TYPE Max(const in uint32_t row, const in uint32_t col, const in ACC_TYPE ele // Rows index by Q's dimension 2, and the first N rows are valid. D_TYPE perElemOpGqaStore(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t o_offset, const in uint32_t iq2, const in uint32_t N) { - if (r < N && c < D) { - uint32_t offset = (iq2 + r) * D + c; + if (r < N && c < HSV) { + uint32_t offset = (iq2 + r) * HSV + c; data_o[o_offset + offset] = D_TYPE(elem); } return elem; @@ -86,9 +86,9 @@ void main() { tensorLayoutV = setTensorLayoutBlockSizeNV(tensorLayoutV, 1, BLOCK_SIZE); #endif - tensorLayoutQ = setTensorLayoutDimensionNV(tensorLayoutQ, N, D); - tensorLayoutK = setTensorLayoutDimensionNV(tensorLayoutK, KV, D); - tensorLayoutV = setTensorLayoutDimensionNV(tensorLayoutV, KV, D); + tensorLayoutQ = setTensorLayoutDimensionNV(tensorLayoutQ, N, HSK); + tensorLayoutK = setTensorLayoutDimensionNV(tensorLayoutK, KV, HSK); + tensorLayoutV = setTensorLayoutDimensionNV(tensorLayoutV, KV, HSV); // hint to the compiler that strides are aligned for the aligned variant of the shader if (Clamp != gl_CooperativeMatrixClampModeConstantNV) @@ -104,16 +104,16 @@ void main() { tensorLayoutK = setTensorLayoutStrideNV(tensorLayoutK, k_stride, 1); tensorLayoutV = setTensorLayoutStrideNV(tensorLayoutV, v_stride, 1); - coopmat Q; - coopmat Qf16; + coopmat Q; + coopmat Qf16; uint32_t q_offset = iq2*p.nb02+iq3*p.nb03; - coopMatLoadTensorNV(Q, data_q, q_offset, sliceTensorLayoutNV(tensorLayoutQ, i * Br, Br, 0, D)); + coopMatLoadTensorNV(Q, data_q, q_offset, sliceTensorLayoutNV(tensorLayoutQ, i * Br, Br, 0, HSK)); - Qf16 = coopmat(Q); + Qf16 = coopmat(Q); Qf16 *= float16_t(p.scale); - coopmat O = coopmat(0); + coopmat O = coopmat(0); coopmat L, M; @@ -135,10 +135,10 @@ void main() { coopmat S = coopmat(0); - coopmat K_T; + coopmat K_T; uint32_t k_offset = ik2*p.nb12 + ik3*p.nb13; - coopMatLoadTensorNV(K_T, data_k, k_offset, sliceTensorLayoutNV(tensorLayoutK, j * Bc, Bc, 0, D), tensorViewTranspose DECODEFUNC); + coopMatLoadTensorNV(K_T, data_k, k_offset, sliceTensorLayoutNV(tensorLayoutK, j * Bc, Bc, 0, HSK), tensorViewTranspose DECODEFUNC); S = coopMatMulAdd(Qf16, K_T, S); if (p.logit_softcap != 0.0f) { @@ -203,42 +203,42 @@ void main() { rowsum = coopmat(0.0); rowsum = coopMatMulAdd(P_A, One, rowsum); - coopmat V; + coopmat V; uint32_t v_offset = iv2*p.nb22 + iv3*p.nb23; - coopMatLoadTensorNV(V, data_v, v_offset, sliceTensorLayoutNV(tensorLayoutV, j * Bc, Bc, 0, D) DECODEFUNC); + coopMatLoadTensorNV(V, data_v, v_offset, sliceTensorLayoutNV(tensorLayoutV, j * Bc, Bc, 0, HSV) DECODEFUNC); L = eM*L + rowsum; // This is the "diagonal" matrix in the paper, but since we do componentwise // multiply rather than matrix multiply it has the diagonal element smeared // across the row - coopmat eMdiag; + coopmat eMdiag; // resize eM by using smear/reduce coopMatReduceNV(eMdiag, eM, gl_CooperativeMatrixReduceRowNV, smearReduce); // multiply with fp16 accumulation, then add to O. - coopmat PV = coopmat(0); + coopmat PV = coopmat(0); PV = coopMatMulAdd(P_A, V, PV); - O = eMdiag * O + coopmat(PV); + O = eMdiag * O + coopmat(PV); } // If there is split_k, then the split_k resolve shader does the final // division by L. Store the intermediate O value and per-row m and L values. if (p.k_num > 1) { - coopmat O_D = coopmat(O); + coopmat O_D = coopmat(O); - uint32_t o_offset = D * p.ne1 * split_k_index; + uint32_t o_offset = HSV * p.ne1 * (split_k_index + iq3 * p.k_num); coopMatPerElementNV(O_D, O_D, perElemOpGqaStore, o_offset, iq2, N); - o_offset = D * p.ne1 * p.k_num + p.ne1 * split_k_index * 2; + o_offset = HSV * p.ne1 * p.ne3 * p.k_num + p.ne1 * (split_k_index + iq3 * p.k_num) * 2; coopMatPerElementNV(L, L, perElemOpStoreCol0, o_offset, iq2, N); coopMatPerElementNV(M, M, perElemOpStoreCol0, o_offset + p.ne1, iq2, N); return; } - coopmat Ldiag; + coopmat Ldiag; // resize L by using smear/reduce coopMatReduceNV(Ldiag, L, gl_CooperativeMatrixReduceRowNV, smearReduce); @@ -250,18 +250,18 @@ void main() { O = Ldiag*O; - uint32_t o_offset = iq3*p.ne2*p.ne1; + uint32_t o_offset = iq3*p.ne2*p.ne1*HSV; - coopmat O_D = coopmat(O); + coopmat O_D = coopmat(O); if (p.gqa_ratio > 1) { coopMatPerElementNV(O_D, O_D, perElemOpGqaStore, o_offset, iq2, N); } else { tensorLayoutNV<3, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutD = createTensorLayoutNV(3, gl_CooperativeMatrixClampModeConstantNV); - tensorLayoutD = setTensorLayoutDimensionNV(tensorLayoutD, p.ne2, p.ne1, D); + tensorLayoutD = setTensorLayoutDimensionNV(tensorLayoutD, p.ne2, p.ne1, HSV); // permute dimensions tensorViewNV<3, false, 1, 0, 2> tensorViewPermute = createTensorViewNV(3, false, 1, 0, 2); - coopMatStoreTensorNV(O_D, data_o, o_offset, sliceTensorLayoutNV(tensorLayoutD, i * Br, Br, iq2, N, 0, D), tensorViewPermute); + coopMatStoreTensorNV(O_D, data_o, o_offset, sliceTensorLayoutNV(tensorLayoutD, i * Br, Br, iq2, N, 0, HSV), tensorViewPermute); } } From 22f67917f63bd222b73a4581e9892d2b2a427bde Mon Sep 17 00:00:00 2001 From: firecoperana Date: Sun, 6 Jul 2025 00:51:36 -0500 Subject: [PATCH 17/63] Fix server crash when there is no DRY sampler (#588) Co-authored-by: firecoperana --- src/llama.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/llama.cpp b/src/llama.cpp index 8c16e778..3ee95939 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -23363,6 +23363,9 @@ struct llama_sampler_dry * llama_sampler_init_dry(const struct llama_vocab* voca } void llama_sampler_dry_reset(struct llama_sampler_dry* smpl) { + if (!smpl) { + return; + } smpl->last_tokens.clear(); smpl->dry_repeat_count.clear(); smpl->dry_max_token_repeat.clear(); From 6f3a3ba7e249cd689cb1ab0376e6504fb6cd49e7 Mon Sep 17 00:00:00 2001 From: Fizz~ <168598314+fizzAI@users.noreply.github.com> Date: Sun, 6 Jul 2025 06:13:55 -0400 Subject: [PATCH 18/63] Special handling of Seed Coder FIM tokens (#585) * Special handling of Seed Coder FIM tokens * vocab: Add Seed Coder pretokenizer * Formatting fix * Update llama.h --- convert_hf_to_gguf.py | 14 ++++++++++++++ convert_hf_to_gguf_update.py | 1 + include/llama.h | 1 + src/llama-vocab.cpp | 7 +++++++ src/llama.cpp | 4 ++++ 5 files changed, 27 insertions(+) diff --git a/convert_hf_to_gguf.py b/convert_hf_to_gguf.py index 1754e486..33be63fa 100644 --- a/convert_hf_to_gguf.py +++ b/convert_hf_to_gguf.py @@ -636,6 +636,9 @@ class Model: if chkhsh == "877081d19cf6996e2c4ff0e1236341e9b7bde288f5311a56a937f0afbbb3aeb5": # ref: https://huggingface.co/deepseek-ai/DeepSeek-V3 res = "deepseek-v3" + if chkhsh == "d5f1dd6f980fec569fb218a81a7658ac45fc56b38c5a0adeb1c232fbe04ef5ec": + # ref: https://huggingface.co/ByteDance-Seed/Seed-Coder-8B-Base + res = "seed-coder" if res is None: logger.warning("\n") @@ -1520,6 +1523,17 @@ class LlamaModel(Model): special_vocab._set_special_token("eot", 32010) special_vocab.add_to_gguf(self.gguf_writer) + # Apply to Seed-Coder only (and ignore otherwise) + if self.hparams.get("vocab_size", 32000) == 155136: + special_vocab = gguf.SpecialVocab( + self.dir_model, load_merges=False, + special_token_types = ['prefix', 'suffix', 'middle', 'eot'] + ) + special_vocab._set_special_token("prefix", 124) + special_vocab._set_special_token("suffix", 125) + special_vocab._set_special_token("middle", 126) + special_vocab.add_to_gguf(self.gguf_writer) + def set_gguf_parameters(self): super().set_gguf_parameters() hparams = self.hparams diff --git a/convert_hf_to_gguf_update.py b/convert_hf_to_gguf_update.py index 40af02f4..f2e6cc37 100755 --- a/convert_hf_to_gguf_update.py +++ b/convert_hf_to_gguf_update.py @@ -95,6 +95,7 @@ models = [ {"name": "tekken", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/mistralai/Mistral-Nemo-Base-2407", }, {"name": "smollm", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/HuggingFaceTB/SmolLM-135M", }, {"name": "deepseek-v3", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/deepseek-ai/DeepSeek-V3"}, + {"name": "seed-coder", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/ByteDance-Seed/Seed-Coder-8B-Base", }, ] diff --git a/include/llama.h b/include/llama.h index 6c8bff95..51db3eab 100644 --- a/include/llama.h +++ b/include/llama.h @@ -110,6 +110,7 @@ extern "C" { LLAMA_VOCAB_PRE_TYPE_LLAMA4 = 33, LLAMA_VOCAB_PRE_TYPE_FALCON_3 = 34, LLAMA_VOCAB_PRE_TYPE_FALCON_E = 35, + LLAMA_VOCAB_PRE_TYPE_SEED_CODER = 36, //llama.cpp lists this as 35 }; // note: these values should be synchronized with ggml_rope diff --git a/src/llama-vocab.cpp b/src/llama-vocab.cpp index 65ca5e38..474cbd8c 100644 --- a/src/llama-vocab.cpp +++ b/src/llama-vocab.cpp @@ -477,6 +477,13 @@ struct llm_tokenizer_bpe { "'(?:[sSdDmMtT]|[lL][lL]|[vV][eE]|[rR][eE])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]|\\s+(?!\\S)|\\s+", }; break; + case LLAMA_VOCAB_PRE_TYPE_SEED_CODER: + regex_exprs = { + // original regex from tokenizer.json + // "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1}| ?[^\\s\\p{L}\\p{N}\r\n]+|\\s*[\r\n]+|\\s+(?!\\S)|\\s+" + "(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1}| ?[^\\s\\p{L}\\p{N}\\r\\n]+|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+", + }; + break; default: // default regex for BPE tokenization pre-processing regex_exprs = { diff --git a/src/llama.cpp b/src/llama.cpp index 3ee95939..564304f6 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -6302,6 +6302,10 @@ static void llm_load_vocab( tokenizer_pre == "bailingmoe") { vocab.type_pre = LLAMA_VOCAB_PRE_TYPE_BAILINGMOE; vocab.tokenizer_clean_spaces = false; + } else if ( + tokenizer_pre == "seed-coder") { + vocab.type_pre = LLAMA_VOCAB_PRE_TYPE_SEED_CODER; + vocab.tokenizer_clean_spaces = false; } else { throw std::runtime_error(format("unknown pre-tokenizer type: '%s'", tokenizer_pre.c_str())); } From 4c0b66026619cf51f45249181bf2cc1de8cd6884 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Mon, 7 Jul 2025 07:23:12 +0200 Subject: [PATCH 19/63] CUDA: small PP performance improvement for MoE models (#589) * Trying to implement quantized fmoe - not working yet * This works, but is slower than the non-working version * quantize_mmq_q8_1_id * Minor --------- Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-cuda.cu | 44 +++++++++--- ggml/src/ggml-cuda/quantize.cu | 121 ++++++++++++++++++++++++++++++++ ggml/src/ggml-cuda/quantize.cuh | 4 ++ 3 files changed, 161 insertions(+), 8 deletions(-) diff --git a/ggml/src/ggml-cuda.cu b/ggml/src/ggml-cuda.cu index e0035c7a..7fb67738 100644 --- a/ggml/src/ggml-cuda.cu +++ b/ggml/src/ggml-cuda.cu @@ -2186,6 +2186,7 @@ struct mmid_row_mapping { int32_t i2; }; +template static __global__ void k_copy_src_to_contiguous(const char * __restrict__ src_original, char * __restrict__ src_contiguous, const mmid_row_mapping * __restrict__ row_mapping, int64_t ne10, int64_t ne11, size_t nb11, size_t nb12) { @@ -2194,8 +2195,8 @@ static __global__ void k_copy_src_to_contiguous(const char * __restrict__ src_or const int32_t i11 = row_mapping[i].i1 % ne11; const int32_t i12 = row_mapping[i].i2; - float * src_row_contiguous = (float *)(src_contiguous + i*nb11); - const float * src_row_original = (const float *)(src_original + i11*nb11 + i12*nb12); + data_t * src_row_contiguous = (data_t *)(src_contiguous + i*nb11); + const data_t * src_row_original = (const data_t *)(src_original + i11*nb11 + i12*nb12); for (int j = threadIdx.x; j < ne10; j += blockDim.x) { src_row_contiguous[j] = src_row_original[j]; @@ -2673,6 +2674,17 @@ static bool ggml_cuda_up_gate_unary(ggml_backend_cuda_context & ctx, ggml_tensor } } } else { + //printf("ne10 = %ld, ne11 = %ld, ne12 = %ld, nb10 = %zu nb11 = %zu nb12 = %zu\n", src1->ne[0], src1->ne[1], src1->ne[2], src1->nb[0], src1->nb[1], src1->nb[2]); + ggml_cuda_pool_alloc src1_quantized(ctx.pool()); + bool use_quantized_src1 = false; + int64_t src1_padded_num_cols = 0, src1_padded_row_size = 0, src1_quantized_size = 0; + if (ggml_is_quantized(src0_1->type) && src0_1->type == src0_2->type && src1->ne[1] == 1 && src1->ne[3] == 1) { + src1_padded_num_cols = GGML_PAD(src1->ne[0], MATRIX_ROW_PADDING); + src1_padded_row_size = src1_padded_num_cols/ggml_blck_size(GGML_TYPE_Q8_1)*ggml_type_size(GGML_TYPE_Q8_1); + src1_quantized_size = src1_padded_row_size*src1->ne[2] + get_mmq_x_max_host(ggml_cuda_info().devices[ctx.device].cc)*sizeof(block_q8_1_mmq); + src1_quantized.alloc(src1_quantized_size); + use_quantized_src1 = true; + } ggml_cuda_pool_alloc src1_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(src1)); ggml_cuda_pool_alloc dst_up_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(dst)); ggml_cuda_pool_alloc dst_gate_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(dst)); @@ -2704,7 +2716,13 @@ static bool ggml_cuda_up_gate_unary(ggml_backend_cuda_context & ctx, ggml_tensor if (num_src1_rows == 0) continue; size_t mapping_offset = cum_moe_counts[i02]; - { + if (use_quantized_src1) { + quantize_mmq_q8_1_id_cuda((const float *)src1->data, src1_quantized.get(), (const char *)(dev_row_mapping.get() + mapping_offset), + src1->ne[0], num_src1_rows, src1_padded_num_cols, src0_1->type, stream); + CUDA_CHECK(cudaGetLastError()); + src1_row.data = src1_quantized.get(); + } + else { dim3 block_dims(std::min((unsigned int)ne10, 768u)); dim3 grid_dims(num_src1_rows); k_copy_src_to_contiguous<<>>( @@ -2719,9 +2737,9 @@ static bool ggml_cuda_up_gate_unary(ggml_backend_cuda_context & ctx, ggml_tensor GGML_ASSERT(nb1 == sizeof(float)*ne0); src1_row.ne[1] = num_src1_rows; - src1_row.nb[1] = nb11; - src1_row.nb[2] = num_src1_rows*nb11; - src1_row.nb[3] = num_src1_rows*nb11; + src1_row.nb[1] = use_quantized_src1 ? src1_padded_row_size : nb11; + src1_row.nb[2] = num_src1_rows*src1_row.nb[1]; + src1_row.nb[3] = num_src1_rows*src1_row.nb[1]; dst_row.ne[1] = num_src1_rows; dst_row.nb[1] = nb1; @@ -2729,11 +2747,21 @@ static bool ggml_cuda_up_gate_unary(ggml_backend_cuda_context & ctx, ggml_tensor dst_row.nb[3] = num_src1_rows*nb1; dst_row.data = dst_up_contiguous.get(); - ggml_cuda_mul_mat(ctx, &src0_1_row, &src1_row, &dst_row); + if (use_quantized_src1) { + ggml_cuda_op_mul_mat_q(ctx, &src0_1_row, &src1_row, &dst_row, (const char *)src0_1_row.data, nullptr, src1_quantized.get(), (float *)dst_row.data, + 0, src0_1_row.ne[1], num_src1_rows, src1_padded_num_cols, stream); + } else { + ggml_cuda_mul_mat(ctx, &src0_1_row, &src1_row, &dst_row); + } CUDA_CHECK(cudaGetLastError()); dst_row.data = dst_gate_contiguous.get(); - ggml_cuda_mul_mat(ctx, &src0_2_row, &src1_row, &dst_row); + if (use_quantized_src1) { + ggml_cuda_op_mul_mat_q(ctx, &src0_2_row, &src1_row, &dst_row, (const char *)src0_2_row.data, nullptr, src1_quantized.get(), (float *)dst_row.data, + 0, src0_2_row.ne[1], num_src1_rows, src1_padded_num_cols, stream); + } else { + ggml_cuda_mul_mat(ctx, &src0_2_row, &src1_row, &dst_row); + } CUDA_CHECK(cudaGetLastError()); ggml_fused_mul_unary(ctx, (ggml_unary_op)dst->op_params[0], ggml_nelements(&dst_row), diff --git a/ggml/src/ggml-cuda/quantize.cu b/ggml/src/ggml-cuda/quantize.cu index 953eb9d9..52d8787d 100644 --- a/ggml/src/ggml-cuda/quantize.cu +++ b/ggml/src/ggml-cuda/quantize.cu @@ -166,6 +166,98 @@ static __global__ void quantize_mmq_q8_1( } } +struct mmid_row_mapping { + int32_t i1; + int32_t i2; +}; + +template +static __global__ void quantize_mmq_q8_1_id( + const float * __restrict__ x, void * __restrict__ vy, const char * row_mapping, const int64_t kx0, const int64_t kx1, const int64_t kx0_padded) { + + constexpr int vals_per_scale = ds_layout == MMQ_Q8_1_DS_LAYOUT_D2S6 ? 64 : 32; + constexpr int vals_per_sum = ds_layout == MMQ_Q8_1_DS_LAYOUT_D2S6 ? 16 : 32; + + const int64_t ix0 = ((int64_t)blockDim.x*blockIdx.x + threadIdx.x)*4; + + if (ix0 >= kx0_padded) { + return; + } + + const float4 * x4 = (const float4 *) x; + + const mmid_row_mapping * mapping = (const mmid_row_mapping *)row_mapping; + const int64_t ii = mapping[blockIdx.y].i2; + + block_q8_1_mmq * y = (block_q8_1_mmq *) vy; + + const int64_t ib0 = blockIdx.z*((int64_t)gridDim.y*gridDim.x*blockDim.x/QK8_1); // first block of channel + const int64_t ib = ib0 + (ix0 / (4*QK8_1))*kx1 + blockIdx.y; // block index in channel + const int64_t iqs = ix0 % (4*QK8_1); // quant index in block + + // Load 4 floats per thread and calculate max. abs. value between them: + const float4 xi = ix0 < kx0 ? x4[(ii*kx0 + ix0)/4] : make_float4(0.0f, 0.0f, 0.0f, 0.0f); + float amax = fabsf(xi.x); + amax = fmaxf(amax, fabsf(xi.y)); + amax = fmaxf(amax, fabsf(xi.z)); + amax = fmaxf(amax, fabsf(xi.w)); + + // Exchange max. abs. value between vals_per_scale/4 threads. +#pragma unroll + for (int mask = vals_per_scale/8; mask > 0; mask >>= 1) { + amax = fmaxf(amax, __shfl_xor_sync(0xFFFFFFFF, amax, mask, WARP_SIZE)); + } + + float sum; + if (ds_layout != MMQ_Q8_1_DS_LAYOUT_D4) { + sum = xi.x + xi.y + xi.z + xi.w; + + // Exchange calculate sum across vals_per_sum/4 threads. +#pragma unroll + for (int mask = vals_per_sum/8; mask > 0; mask >>= 1) { + sum += __shfl_xor_sync(0xFFFFFFFF, sum, mask, WARP_SIZE); + } + } + + const float d = amax/127.f; + const float d_inv = d > 0 ? 1/d : 0.f; + char4 q; + q.x = roundf(xi.x*d_inv); + q.y = roundf(xi.y*d_inv); + q.z = roundf(xi.z*d_inv); + q.w = roundf(xi.w*d_inv); + + // Write back 4 int8 values as a single 32 bit value for better memroy bandwidth: + char4 * yqs4 = (char4 *) y[ib].qs; + yqs4[iqs/4] = q; + + if (ds_layout == MMQ_Q8_1_DS_LAYOUT_D2S6) { + if (iqs % 16 != 0 || iqs >= 96) { + return; + } + + y[ib].d2s6[2 + iqs/16] = sum; + + if (iqs % 64 != 0) { + return; + } + + y[ib].d2s6[iqs/64] = d; + + return; + } + + if (iqs % 32 != 0) { + return; + } + + if (ds_layout == MMQ_Q8_1_DS_LAYOUT_DS4) { + y[ib].ds4[iqs/32] = make_half2(d, sum); + } else { + y[ib].d4[iqs/32] = d; + } +} + void quantize_row_q8_1_cuda( const float * x, void * vy, const int64_t kx0, const int64_t kx1, const int64_t channels, const int64_t kx0_padded, const ggml_type type_x, cudaStream_t stream) { @@ -208,6 +300,35 @@ void quantize_mmq_q8_1_cuda( } } +void quantize_mmq_q8_1_id_cuda( + const float * x, void * vy, const char * row_mapping, const int64_t kx0, const int64_t kx1, const int64_t kx0_padded, + const ggml_type type_x, cudaStream_t stream) { + + GGML_ASSERT(kx0_padded % (4*QK8_1) == 0); + + const int64_t block_num_x = (kx0_padded + 4*CUDA_QUANTIZE_BLOCK_SIZE_MMQ - 1) / (4*CUDA_QUANTIZE_BLOCK_SIZE_MMQ); + const dim3 num_blocks(block_num_x, kx1, 1); + const dim3 block_size(CUDA_QUANTIZE_BLOCK_SIZE_MMQ, 1, 1); + switch (mmq_get_q8_1_ds_layout(type_x)) { + case MMQ_Q8_1_DS_LAYOUT_D4: + quantize_mmq_q8_1_id + <<>>(x, vy, row_mapping, kx0, kx1, kx0_padded); + break; + case MMQ_Q8_1_DS_LAYOUT_DS4: + quantize_mmq_q8_1_id + <<>>(x, vy, row_mapping, kx0, kx1, kx0_padded); + break; + case MMQ_Q8_1_DS_LAYOUT_D2S6: + quantize_mmq_q8_1_id + <<>>(x, vy, row_mapping, kx0, kx1, kx0_padded); + break; + default: + GGML_ABORT("fatal error"); + break; + } +} + + void quantize_tensor_q8_1_cuda(const struct ggml_tensor * src, void * vy, const enum ggml_type type, cudaStream_t stream) { GGML_ASSERT(src->ne[1] == 1 && src->ne[3] == 1); GGML_ASSERT(src->type == GGML_TYPE_F32); diff --git a/ggml/src/ggml-cuda/quantize.cuh b/ggml/src/ggml-cuda/quantize.cuh index 0be5bf0e..e1106164 100644 --- a/ggml/src/ggml-cuda/quantize.cuh +++ b/ggml/src/ggml-cuda/quantize.cuh @@ -30,5 +30,9 @@ void quantize_mmq_q8_1_cuda( const float * x, void * vy, const int64_t kx0, const int64_t kx1, const int64_t channels, const int64_t kx0_padded, const ggml_type type_x, cudaStream_t stream); +void quantize_mmq_q8_1_id_cuda( + const float * x, void * vy, const char * row_mapping, const int64_t kx0, const int64_t kx1, const int64_t kx0_padded, + const ggml_type type_x, cudaStream_t stream); + // For now only applicable for tensors with ne[1] = 1, ne[3] = 1, and useful if ne[2] > 1 void quantize_tensor_q8_1_cuda(const struct ggml_tensor * src, void * vy, const enum ggml_type type, cudaStream_t stream); From 97c34f4056067e167ed4508366f74b49e60202f7 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Tue, 8 Jul 2025 19:44:48 +0200 Subject: [PATCH 20/63] Faster prompt processing for IQ2_KS, IQ2_K, IQ2_K_R4 (#593) * cuda: faster MMQ for iq2_ks, iq2_k, iq2_k_r4 * Lookup is still beter for MMQ if we get 4 values at once * Minor --------- Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-cuda/iqk_cuda_common.h | 75 +++++++++++ ggml/src/ggml-cuda/iqk_mmvq.cu | 116 ++++-------------- ggml/src/ggml-cuda/mmq.cu | 4 +- ggml/src/ggml-cuda/mmq.cuh | 67 ++++------ .../mmq-instance-iq2_k_r4.cu | 31 ++--- 5 files changed, 133 insertions(+), 160 deletions(-) create mode 100644 ggml/src/ggml-cuda/iqk_cuda_common.h diff --git a/ggml/src/ggml-cuda/iqk_cuda_common.h b/ggml/src/ggml-cuda/iqk_cuda_common.h new file mode 100644 index 00000000..95d9b40e --- /dev/null +++ b/ggml/src/ggml-cuda/iqk_cuda_common.h @@ -0,0 +1,75 @@ +#pragma once + +#include "common.cuh" + +static const __device__ uint32_t iq2k_table[512] = { + 0xe1e1e1e1, 0xe1e1e1f3, 0xe1e1e101, 0xe1e1e111, 0xe1e1f3e1, 0xe1e1f3f3, 0xe1e1f301, 0xe1e1f311, + 0xe1e101e1, 0xe1e101f3, 0xe1e10101, 0xe1e10111, 0xe1e111e1, 0xe1e111f3, 0xe1e11101, 0xe1e11111, + 0xe1f3e1e1, 0xe1f3e1f3, 0xe1f3e101, 0xe1f3e111, 0xe1f3f3e1, 0xe1f3f3f3, 0xe1f3f301, 0xe1f3f311, + 0xe1f301e1, 0xe1f301f3, 0xe1f30101, 0xe1f30111, 0xe1f311e1, 0xe1f311f3, 0xe1f31101, 0xe1f31111, + 0xe101e1e1, 0xe101e1f3, 0xe101e101, 0xe101e111, 0xe101f3e1, 0xe101f3f3, 0xe101f301, 0xe101f311, + 0xe10101e1, 0xe10101f3, 0xe1010101, 0xe1010111, 0xe10111e1, 0xe10111f3, 0xe1011101, 0xe1011111, + 0xe111e1e1, 0xe111e1f3, 0xe111e101, 0xe111e111, 0xe111f3e1, 0xe111f3f3, 0xe111f301, 0xe111f311, + 0xe11101e1, 0xe11101f3, 0xe1110101, 0xe1110111, 0xe11111e1, 0xe11111f3, 0xe1111101, 0xe1111111, + 0xf3e1e1e1, 0xf3e1e1f3, 0xf3e1e101, 0xf3e1e111, 0xf3e1f3e1, 0xf3e1f3f3, 0xf3e1f301, 0xf3e1f311, + 0xf3e101e1, 0xf3e101f3, 0xf3e10101, 0xf3e10111, 0xf3e111e1, 0xf3e111f3, 0xf3e11101, 0xf3e11111, + 0xf3f3e1e1, 0xf3f3e1f3, 0xf3f3e101, 0xf3f3e111, 0xf3f3f3e1, 0xf3f3f3f3, 0xf3f3f301, 0xf3f3f311, + 0xf3f301e1, 0xf3f301f3, 0xf3f30101, 0xf3f30111, 0xf3f311e1, 0xf3f311f3, 0xf3f31101, 0xf3f31111, + 0xf301e1e1, 0xf301e1f3, 0xf301e101, 0xf301e111, 0xf301f3e1, 0xf301f3f3, 0xf301f301, 0xf301f311, + 0xf30101e1, 0xf30101f3, 0xf3010101, 0xf3010111, 0xf30111e1, 0xf30111f3, 0xf3011101, 0xf3011111, + 0xf311e1e1, 0xf311e1f3, 0xf311e101, 0xf311e111, 0xf311f3e1, 0xf311f3f3, 0xf311f301, 0xf311f311, + 0xf31101e1, 0xf31101f3, 0xf3110101, 0xf3110111, 0xf31111e1, 0xf31111f3, 0xf3111101, 0xf3111111, + 0x01e1e1e1, 0x01e1e1f3, 0x01e1e101, 0x01e1e111, 0x01e1f3e1, 0x01e1f3f3, 0x01e1f301, 0x01e1f311, + 0x01e101e1, 0x01e101f3, 0x01e10101, 0x01e10111, 0x01e111e1, 0x01e111f3, 0x01e11101, 0x01e11111, + 0x01f3e1e1, 0x01f3e1f3, 0x01f3e101, 0x01f3e111, 0x01f3f3e1, 0x01f3f3f3, 0x01f3f301, 0x01f3f311, + 0x01f301e1, 0x01f301f3, 0x01f30101, 0x01f30111, 0x01f311e1, 0x01f311f3, 0x01f31101, 0x01f31111, + 0x0101e1e1, 0x0101e1f3, 0x0101e101, 0x0101e111, 0x0101f3e1, 0x0101f3f3, 0x0101f301, 0x0101f311, + 0x010101e1, 0x010101f3, 0x01010101, 0x01010111, 0x010111e1, 0x010111f3, 0x01011101, 0x01011111, + 0x0111e1e1, 0x0111e1f3, 0x0111e101, 0x0111e111, 0x0111f3e1, 0x0111f3f3, 0x0111f301, 0x0111f311, + 0x011101e1, 0x011101f3, 0x01110101, 0x01110111, 0x011111e1, 0x011111f3, 0x01111101, 0x01111111, + 0x11e1e1e1, 0x11e1e1f3, 0x11e1e101, 0x11e1e111, 0x11e1f3e1, 0x11e1f3f3, 0x11e1f301, 0x11e1f311, + 0x11e101e1, 0x11e101f3, 0x11e10101, 0x11e10111, 0x11e111e1, 0x11e111f3, 0x11e11101, 0x11e11111, + 0x11f3e1e1, 0x11f3e1f3, 0x11f3e101, 0x11f3e111, 0x11f3f3e1, 0x11f3f3f3, 0x11f3f301, 0x11f3f311, + 0x11f301e1, 0x11f301f3, 0x11f30101, 0x11f30111, 0x11f311e1, 0x11f311f3, 0x11f31101, 0x11f31111, + 0x1101e1e1, 0x1101e1f3, 0x1101e101, 0x1101e111, 0x1101f3e1, 0x1101f3f3, 0x1101f301, 0x1101f311, + 0x110101e1, 0x110101f3, 0x11010101, 0x11010111, 0x110111e1, 0x110111f3, 0x11011101, 0x11011111, + 0x1111e1e1, 0x1111e1f3, 0x1111e101, 0x1111e111, 0x1111f3e1, 0x1111f3f3, 0x1111f301, 0x1111f311, + 0x111101e1, 0x111101f3, 0x11110101, 0x11110111, 0x111111e1, 0x111111f3, 0x11111101, 0x11111111, + 0xe6e6e6e6, 0xe6e6e6f8, 0xe6e6e606, 0xe6e6e616, 0xe6e6f8e6, 0xe6e6f8f8, 0xe6e6f806, 0xe6e6f816, + 0xe6e606e6, 0xe6e606f8, 0xe6e60606, 0xe6e60616, 0xe6e616e6, 0xe6e616f8, 0xe6e61606, 0xe6e61616, + 0xe6f8e6e6, 0xe6f8e6f8, 0xe6f8e606, 0xe6f8e616, 0xe6f8f8e6, 0xe6f8f8f8, 0xe6f8f806, 0xe6f8f816, + 0xe6f806e6, 0xe6f806f8, 0xe6f80606, 0xe6f80616, 0xe6f816e6, 0xe6f816f8, 0xe6f81606, 0xe6f81616, + 0xe606e6e6, 0xe606e6f8, 0xe606e606, 0xe606e616, 0xe606f8e6, 0xe606f8f8, 0xe606f806, 0xe606f816, + 0xe60606e6, 0xe60606f8, 0xe6060606, 0xe6060616, 0xe60616e6, 0xe60616f8, 0xe6061606, 0xe6061616, + 0xe616e6e6, 0xe616e6f8, 0xe616e606, 0xe616e616, 0xe616f8e6, 0xe616f8f8, 0xe616f806, 0xe616f816, + 0xe61606e6, 0xe61606f8, 0xe6160606, 0xe6160616, 0xe61616e6, 0xe61616f8, 0xe6161606, 0xe6161616, + 0xf8e6e6e6, 0xf8e6e6f8, 0xf8e6e606, 0xf8e6e616, 0xf8e6f8e6, 0xf8e6f8f8, 0xf8e6f806, 0xf8e6f816, + 0xf8e606e6, 0xf8e606f8, 0xf8e60606, 0xf8e60616, 0xf8e616e6, 0xf8e616f8, 0xf8e61606, 0xf8e61616, + 0xf8f8e6e6, 0xf8f8e6f8, 0xf8f8e606, 0xf8f8e616, 0xf8f8f8e6, 0xf8f8f8f8, 0xf8f8f806, 0xf8f8f816, + 0xf8f806e6, 0xf8f806f8, 0xf8f80606, 0xf8f80616, 0xf8f816e6, 0xf8f816f8, 0xf8f81606, 0xf8f81616, + 0xf806e6e6, 0xf806e6f8, 0xf806e606, 0xf806e616, 0xf806f8e6, 0xf806f8f8, 0xf806f806, 0xf806f816, + 0xf80606e6, 0xf80606f8, 0xf8060606, 0xf8060616, 0xf80616e6, 0xf80616f8, 0xf8061606, 0xf8061616, + 0xf816e6e6, 0xf816e6f8, 0xf816e606, 0xf816e616, 0xf816f8e6, 0xf816f8f8, 0xf816f806, 0xf816f816, + 0xf81606e6, 0xf81606f8, 0xf8160606, 0xf8160616, 0xf81616e6, 0xf81616f8, 0xf8161606, 0xf8161616, + 0x06e6e6e6, 0x06e6e6f8, 0x06e6e606, 0x06e6e616, 0x06e6f8e6, 0x06e6f8f8, 0x06e6f806, 0x06e6f816, + 0x06e606e6, 0x06e606f8, 0x06e60606, 0x06e60616, 0x06e616e6, 0x06e616f8, 0x06e61606, 0x06e61616, + 0x06f8e6e6, 0x06f8e6f8, 0x06f8e606, 0x06f8e616, 0x06f8f8e6, 0x06f8f8f8, 0x06f8f806, 0x06f8f816, + 0x06f806e6, 0x06f806f8, 0x06f80606, 0x06f80616, 0x06f816e6, 0x06f816f8, 0x06f81606, 0x06f81616, + 0x0606e6e6, 0x0606e6f8, 0x0606e606, 0x0606e616, 0x0606f8e6, 0x0606f8f8, 0x0606f806, 0x0606f816, + 0x060606e6, 0x060606f8, 0x06060606, 0x06060616, 0x060616e6, 0x060616f8, 0x06061606, 0x06061616, + 0x0616e6e6, 0x0616e6f8, 0x0616e606, 0x0616e616, 0x0616f8e6, 0x0616f8f8, 0x0616f806, 0x0616f816, + 0x061606e6, 0x061606f8, 0x06160606, 0x06160616, 0x061616e6, 0x061616f8, 0x06161606, 0x06161616, + 0x16e6e6e6, 0x16e6e6f8, 0x16e6e606, 0x16e6e616, 0x16e6f8e6, 0x16e6f8f8, 0x16e6f806, 0x16e6f816, + 0x16e606e6, 0x16e606f8, 0x16e60606, 0x16e60616, 0x16e616e6, 0x16e616f8, 0x16e61606, 0x16e61616, + 0x16f8e6e6, 0x16f8e6f8, 0x16f8e606, 0x16f8e616, 0x16f8f8e6, 0x16f8f8f8, 0x16f8f806, 0x16f8f816, + 0x16f806e6, 0x16f806f8, 0x16f80606, 0x16f80616, 0x16f816e6, 0x16f816f8, 0x16f81606, 0x16f81616, + 0x1606e6e6, 0x1606e6f8, 0x1606e606, 0x1606e616, 0x1606f8e6, 0x1606f8f8, 0x1606f806, 0x1606f816, + 0x160606e6, 0x160606f8, 0x16060606, 0x16060616, 0x160616e6, 0x160616f8, 0x16061606, 0x16061616, + 0x1616e6e6, 0x1616e6f8, 0x1616e606, 0x1616e616, 0x1616f8e6, 0x1616f8f8, 0x1616f806, 0x1616f816, + 0x161606e6, 0x161606f8, 0x16160606, 0x16160616, 0x161616e6, 0x161616f8, 0x16161606, 0x16161616, +}; + +__device__ __forceinline__ int int_from_table_4(const uint32_t idx, const int * values) { + return values[ggml_cuda_dp4a(idx, 0x40100401, 0)]; +} + diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cu b/ggml/src/ggml-cuda/iqk_mmvq.cu index 3b1f6acb..54d03f78 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cu +++ b/ggml/src/ggml-cuda/iqk_mmvq.cu @@ -5,6 +5,7 @@ // #include "iqk_mmvq.cuh" +#include "iqk_cuda_common.h" typedef void (*vec_dot_q_cuda_t)(const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iqs, float *); @@ -785,77 +786,6 @@ __device__ __forceinline__ void vec_dot_iq6_k_q8_1( *result += d6 * (__low2float(bq8_1[2*(i4/2)+0].ds) * sumi1 * bq6->scales[4*(i4/2)+(i4%2)] + __low2float(bq8_1[2*(i4/2)+1].ds) * sumi2 * bq6->scales[4*(i4/2)+(i4%2)+2]); } -static const __device__ uint32_t iq2k_table[512] = { - 0xe1e1e1e1, 0xe1e1e1f3, 0xe1e1e101, 0xe1e1e111, 0xe1e1f3e1, 0xe1e1f3f3, 0xe1e1f301, 0xe1e1f311, - 0xe1e101e1, 0xe1e101f3, 0xe1e10101, 0xe1e10111, 0xe1e111e1, 0xe1e111f3, 0xe1e11101, 0xe1e11111, - 0xe1f3e1e1, 0xe1f3e1f3, 0xe1f3e101, 0xe1f3e111, 0xe1f3f3e1, 0xe1f3f3f3, 0xe1f3f301, 0xe1f3f311, - 0xe1f301e1, 0xe1f301f3, 0xe1f30101, 0xe1f30111, 0xe1f311e1, 0xe1f311f3, 0xe1f31101, 0xe1f31111, - 0xe101e1e1, 0xe101e1f3, 0xe101e101, 0xe101e111, 0xe101f3e1, 0xe101f3f3, 0xe101f301, 0xe101f311, - 0xe10101e1, 0xe10101f3, 0xe1010101, 0xe1010111, 0xe10111e1, 0xe10111f3, 0xe1011101, 0xe1011111, - 0xe111e1e1, 0xe111e1f3, 0xe111e101, 0xe111e111, 0xe111f3e1, 0xe111f3f3, 0xe111f301, 0xe111f311, - 0xe11101e1, 0xe11101f3, 0xe1110101, 0xe1110111, 0xe11111e1, 0xe11111f3, 0xe1111101, 0xe1111111, - 0xf3e1e1e1, 0xf3e1e1f3, 0xf3e1e101, 0xf3e1e111, 0xf3e1f3e1, 0xf3e1f3f3, 0xf3e1f301, 0xf3e1f311, - 0xf3e101e1, 0xf3e101f3, 0xf3e10101, 0xf3e10111, 0xf3e111e1, 0xf3e111f3, 0xf3e11101, 0xf3e11111, - 0xf3f3e1e1, 0xf3f3e1f3, 0xf3f3e101, 0xf3f3e111, 0xf3f3f3e1, 0xf3f3f3f3, 0xf3f3f301, 0xf3f3f311, - 0xf3f301e1, 0xf3f301f3, 0xf3f30101, 0xf3f30111, 0xf3f311e1, 0xf3f311f3, 0xf3f31101, 0xf3f31111, - 0xf301e1e1, 0xf301e1f3, 0xf301e101, 0xf301e111, 0xf301f3e1, 0xf301f3f3, 0xf301f301, 0xf301f311, - 0xf30101e1, 0xf30101f3, 0xf3010101, 0xf3010111, 0xf30111e1, 0xf30111f3, 0xf3011101, 0xf3011111, - 0xf311e1e1, 0xf311e1f3, 0xf311e101, 0xf311e111, 0xf311f3e1, 0xf311f3f3, 0xf311f301, 0xf311f311, - 0xf31101e1, 0xf31101f3, 0xf3110101, 0xf3110111, 0xf31111e1, 0xf31111f3, 0xf3111101, 0xf3111111, - 0x01e1e1e1, 0x01e1e1f3, 0x01e1e101, 0x01e1e111, 0x01e1f3e1, 0x01e1f3f3, 0x01e1f301, 0x01e1f311, - 0x01e101e1, 0x01e101f3, 0x01e10101, 0x01e10111, 0x01e111e1, 0x01e111f3, 0x01e11101, 0x01e11111, - 0x01f3e1e1, 0x01f3e1f3, 0x01f3e101, 0x01f3e111, 0x01f3f3e1, 0x01f3f3f3, 0x01f3f301, 0x01f3f311, - 0x01f301e1, 0x01f301f3, 0x01f30101, 0x01f30111, 0x01f311e1, 0x01f311f3, 0x01f31101, 0x01f31111, - 0x0101e1e1, 0x0101e1f3, 0x0101e101, 0x0101e111, 0x0101f3e1, 0x0101f3f3, 0x0101f301, 0x0101f311, - 0x010101e1, 0x010101f3, 0x01010101, 0x01010111, 0x010111e1, 0x010111f3, 0x01011101, 0x01011111, - 0x0111e1e1, 0x0111e1f3, 0x0111e101, 0x0111e111, 0x0111f3e1, 0x0111f3f3, 0x0111f301, 0x0111f311, - 0x011101e1, 0x011101f3, 0x01110101, 0x01110111, 0x011111e1, 0x011111f3, 0x01111101, 0x01111111, - 0x11e1e1e1, 0x11e1e1f3, 0x11e1e101, 0x11e1e111, 0x11e1f3e1, 0x11e1f3f3, 0x11e1f301, 0x11e1f311, - 0x11e101e1, 0x11e101f3, 0x11e10101, 0x11e10111, 0x11e111e1, 0x11e111f3, 0x11e11101, 0x11e11111, - 0x11f3e1e1, 0x11f3e1f3, 0x11f3e101, 0x11f3e111, 0x11f3f3e1, 0x11f3f3f3, 0x11f3f301, 0x11f3f311, - 0x11f301e1, 0x11f301f3, 0x11f30101, 0x11f30111, 0x11f311e1, 0x11f311f3, 0x11f31101, 0x11f31111, - 0x1101e1e1, 0x1101e1f3, 0x1101e101, 0x1101e111, 0x1101f3e1, 0x1101f3f3, 0x1101f301, 0x1101f311, - 0x110101e1, 0x110101f3, 0x11010101, 0x11010111, 0x110111e1, 0x110111f3, 0x11011101, 0x11011111, - 0x1111e1e1, 0x1111e1f3, 0x1111e101, 0x1111e111, 0x1111f3e1, 0x1111f3f3, 0x1111f301, 0x1111f311, - 0x111101e1, 0x111101f3, 0x11110101, 0x11110111, 0x111111e1, 0x111111f3, 0x11111101, 0x11111111, - 0xe6e6e6e6, 0xe6e6e6f8, 0xe6e6e606, 0xe6e6e616, 0xe6e6f8e6, 0xe6e6f8f8, 0xe6e6f806, 0xe6e6f816, - 0xe6e606e6, 0xe6e606f8, 0xe6e60606, 0xe6e60616, 0xe6e616e6, 0xe6e616f8, 0xe6e61606, 0xe6e61616, - 0xe6f8e6e6, 0xe6f8e6f8, 0xe6f8e606, 0xe6f8e616, 0xe6f8f8e6, 0xe6f8f8f8, 0xe6f8f806, 0xe6f8f816, - 0xe6f806e6, 0xe6f806f8, 0xe6f80606, 0xe6f80616, 0xe6f816e6, 0xe6f816f8, 0xe6f81606, 0xe6f81616, - 0xe606e6e6, 0xe606e6f8, 0xe606e606, 0xe606e616, 0xe606f8e6, 0xe606f8f8, 0xe606f806, 0xe606f816, - 0xe60606e6, 0xe60606f8, 0xe6060606, 0xe6060616, 0xe60616e6, 0xe60616f8, 0xe6061606, 0xe6061616, - 0xe616e6e6, 0xe616e6f8, 0xe616e606, 0xe616e616, 0xe616f8e6, 0xe616f8f8, 0xe616f806, 0xe616f816, - 0xe61606e6, 0xe61606f8, 0xe6160606, 0xe6160616, 0xe61616e6, 0xe61616f8, 0xe6161606, 0xe6161616, - 0xf8e6e6e6, 0xf8e6e6f8, 0xf8e6e606, 0xf8e6e616, 0xf8e6f8e6, 0xf8e6f8f8, 0xf8e6f806, 0xf8e6f816, - 0xf8e606e6, 0xf8e606f8, 0xf8e60606, 0xf8e60616, 0xf8e616e6, 0xf8e616f8, 0xf8e61606, 0xf8e61616, - 0xf8f8e6e6, 0xf8f8e6f8, 0xf8f8e606, 0xf8f8e616, 0xf8f8f8e6, 0xf8f8f8f8, 0xf8f8f806, 0xf8f8f816, - 0xf8f806e6, 0xf8f806f8, 0xf8f80606, 0xf8f80616, 0xf8f816e6, 0xf8f816f8, 0xf8f81606, 0xf8f81616, - 0xf806e6e6, 0xf806e6f8, 0xf806e606, 0xf806e616, 0xf806f8e6, 0xf806f8f8, 0xf806f806, 0xf806f816, - 0xf80606e6, 0xf80606f8, 0xf8060606, 0xf8060616, 0xf80616e6, 0xf80616f8, 0xf8061606, 0xf8061616, - 0xf816e6e6, 0xf816e6f8, 0xf816e606, 0xf816e616, 0xf816f8e6, 0xf816f8f8, 0xf816f806, 0xf816f816, - 0xf81606e6, 0xf81606f8, 0xf8160606, 0xf8160616, 0xf81616e6, 0xf81616f8, 0xf8161606, 0xf8161616, - 0x06e6e6e6, 0x06e6e6f8, 0x06e6e606, 0x06e6e616, 0x06e6f8e6, 0x06e6f8f8, 0x06e6f806, 0x06e6f816, - 0x06e606e6, 0x06e606f8, 0x06e60606, 0x06e60616, 0x06e616e6, 0x06e616f8, 0x06e61606, 0x06e61616, - 0x06f8e6e6, 0x06f8e6f8, 0x06f8e606, 0x06f8e616, 0x06f8f8e6, 0x06f8f8f8, 0x06f8f806, 0x06f8f816, - 0x06f806e6, 0x06f806f8, 0x06f80606, 0x06f80616, 0x06f816e6, 0x06f816f8, 0x06f81606, 0x06f81616, - 0x0606e6e6, 0x0606e6f8, 0x0606e606, 0x0606e616, 0x0606f8e6, 0x0606f8f8, 0x0606f806, 0x0606f816, - 0x060606e6, 0x060606f8, 0x06060606, 0x06060616, 0x060616e6, 0x060616f8, 0x06061606, 0x06061616, - 0x0616e6e6, 0x0616e6f8, 0x0616e606, 0x0616e616, 0x0616f8e6, 0x0616f8f8, 0x0616f806, 0x0616f816, - 0x061606e6, 0x061606f8, 0x06160606, 0x06160616, 0x061616e6, 0x061616f8, 0x06161606, 0x06161616, - 0x16e6e6e6, 0x16e6e6f8, 0x16e6e606, 0x16e6e616, 0x16e6f8e6, 0x16e6f8f8, 0x16e6f806, 0x16e6f816, - 0x16e606e6, 0x16e606f8, 0x16e60606, 0x16e60616, 0x16e616e6, 0x16e616f8, 0x16e61606, 0x16e61616, - 0x16f8e6e6, 0x16f8e6f8, 0x16f8e606, 0x16f8e616, 0x16f8f8e6, 0x16f8f8f8, 0x16f8f806, 0x16f8f816, - 0x16f806e6, 0x16f806f8, 0x16f80606, 0x16f80616, 0x16f816e6, 0x16f816f8, 0x16f81606, 0x16f81616, - 0x1606e6e6, 0x1606e6f8, 0x1606e606, 0x1606e616, 0x1606f8e6, 0x1606f8f8, 0x1606f806, 0x1606f816, - 0x160606e6, 0x160606f8, 0x16060606, 0x16060616, 0x160616e6, 0x160616f8, 0x16061606, 0x16061616, - 0x1616e6e6, 0x1616e6f8, 0x1616e606, 0x1616e616, 0x1616f8e6, 0x1616f8f8, 0x1616f806, 0x1616f816, - 0x161606e6, 0x161606f8, 0x16160606, 0x16160616, 0x161616e6, 0x161616f8, 0x16161606, 0x16161616, -}; - -__device__ __forceinline__ int int_from_table_4(const uint8_t * a8, const int * values) { - return values[a8[0] | (a8[1] << 2) | (a8[2] << 4) | (a8[3] << 6)]; -} - #define VDR_IQ2_K_Q8_1_MMVQ 4 #define VDR_IQ2_K_Q8_1_MMQ 4 @@ -881,7 +811,6 @@ __device__ __forceinline__ void vec_dot_iq2_k_q8_1( uint32_t val1 = q2[0], val2 = q2[1]; uint32_t aux32[2]; - const uint8_t * a8 = (const uint8_t *)&aux32; int v1, v2; // Block of 16: (32*(4*(i4/4)+k)+8*(i4%4))/16 = 8*(i4/4) + 2*k + (i4%4)/2 @@ -892,23 +821,23 @@ __device__ __forceinline__ void vec_dot_iq2_k_q8_1( const int8_t * s8 = (const int8_t *)&s32; aux32[0] = ((val1 >> 0) & 0x03030303); aux32[1] = ((val2 >> 0) & 0x03030303); values = all_values + ((extra & 0x01) << 8); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi1 = ggml_cuda_dp4a(v2, q8_1[1], ggml_cuda_dp4a(v1, q8_1[0], 0)) * s8[0]; aux32[0] = ((val1 >> 2) & 0x03030303); aux32[1] = ((val2 >> 2) & 0x03030303); values = all_values + ((extra & 0x04) << 6); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi2 = ggml_cuda_dp4a(v2, q8_2[1], ggml_cuda_dp4a(v1, q8_2[0], 0)) * s8[1]; aux32[0] = ((val1 >> 4) & 0x03030303); aux32[1] = ((val2 >> 4) & 0x03030303); values = all_values + ((extra & 0x10) << 4); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi3 = ggml_cuda_dp4a(v2, q8_3[1], ggml_cuda_dp4a(v1, q8_3[0], 0)) * s8[2]; aux32[0] = ((val1 >> 6) & 0x03030303); aux32[1] = ((val2 >> 6) & 0x03030303); values = all_values + ((extra & 0x40) << 2); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi4 = ggml_cuda_dp4a(v2, q8_4[1], ggml_cuda_dp4a(v1, q8_4[0], 0)) * s8[3]; *result += __half2float(bq2->d) * (__low2float(bq8_1[4*(i4/4)+0].ds) * sumi1 @@ -941,7 +870,6 @@ __device__ __forceinline__ void vec_dot_iq2_ks_q8_1( uint32_t val1 = q2[0] | (q2[1] << 16), val2 = q2[2] | (q2[3] << 16); uint32_t aux32[2]; - const uint8_t * a8 = (const uint8_t *)&aux32; int v1, v2; int32_t scales32; @@ -954,23 +882,23 @@ __device__ __forceinline__ void vec_dot_iq2_ks_q8_1( s8[3] += ((extra >> 7) & 0x10); aux32[0] = ((val1 >> 0) & 0x03030303); aux32[1] = ((val2 >> 0) & 0x03030303); values = all_values + ((extra & 0x01) << 8); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi1 = ggml_cuda_dp4a(v2, q8_1[1], ggml_cuda_dp4a(v1, q8_1[0], 0)) * s8[0]; aux32[0] = ((val1 >> 2) & 0x03030303); aux32[1] = ((val2 >> 2) & 0x03030303); values = all_values + ((extra & 0x02) << 7); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi2 = ggml_cuda_dp4a(v2, q8_2[1], ggml_cuda_dp4a(v1, q8_2[0], 0)) * s8[2]; aux32[0] = ((val1 >> 4) & 0x03030303); aux32[1] = ((val2 >> 4) & 0x03030303); values = all_values + ((extra & 0x04) << 6); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi3 = ggml_cuda_dp4a(v2, q8_3[1], ggml_cuda_dp4a(v1, q8_3[0], 0)) * s8[1]; aux32[0] = ((val1 >> 6) & 0x03030303); aux32[1] = ((val2 >> 6) & 0x03030303); values = all_values + ((extra & 0x08) << 5); - v1 = int_from_table_4(a8 + 0, values); - v2 = int_from_table_4(a8 + 4, values); + v1 = int_from_table_4(aux32[0], values); + v2 = int_from_table_4(aux32[1], values); int sumi4 = ggml_cuda_dp4a(v2, q8_4[1], ggml_cuda_dp4a(v1, q8_4[0], 0)) * s8[3]; *result += scale * (__low2float(bq8_1[4*(i4/4)+0].ds) * sumi1 @@ -1000,20 +928,19 @@ __device__ __forceinline__ void vec_dot_iq2_k_r4_q8_1( int2 val1; const int * q2 = (const int *)bq2->qs + 8*ib32 + 4*is; int aux32[2]; - const uint8_t * aux8 = (const uint8_t *)aux32; #pragma unroll for (int i = 0; i < 4; ++i) { auto values1 = all_values + (((bq2->extra[i+4*is] >> ib32) & 1) << 8); int sumi1 = 0; aux32[0] = ((q2[i] >> 0) & 0x03030303); aux32[1] = ((q2[i] >> 2) & 0x03030303); - val1.x = int_from_table_4(aux8+0, values1); - val1.y = int_from_table_4(aux8+4, values1); + val1.x = int_from_table_4(aux32[0], values1); + val1.y = int_from_table_4(aux32[1], values1); sumi1 = ggml_cuda_dp4a(val1.x, q8[0], ggml_cuda_dp4a(val1.y, q8[1], sumi1)); aux32[0] = ((q2[i] >> 4) & 0x03030303); aux32[1] = ((q2[i] >> 6) & 0x03030303); - val1.x = int_from_table_4(aux8+0, values1); - val1.y = int_from_table_4(aux8+4, values1); + val1.x = int_from_table_4(aux32[0], values1); + val1.y = int_from_table_4(aux32[1], values1); sumi1 = ggml_cuda_dp4a(val1.x, q8[2], ggml_cuda_dp4a(val1.y, q8[3], sumi1)); const float d = __half2float(bq2->d[i]) * d8; result[i] += d * sumi1 * s8[i]; @@ -1114,7 +1041,6 @@ __device__ __forceinline__ void vec_dot_iq3_ks_q8_1( const int ib128 = iqs/4; // 0 or 1. 0 works on quants 0...127, 1 on quants 128...255 // Each thread processes 8 quants in each of the 4 32-blocks const int il8 = iqs%4; // 0...3. 0 works on quants 0...7, 1 on quants 8...15, 2 on 16...23, 3 on 24...31 - const int shift = 4*(il8/2); const uint16_t * ql = (const uint16_t *)bq3->qs + 16*ib128 + 4*il8; const uint16_t * qh = (const uint16_t *)bq3->qh + 4*il8; diff --git a/ggml/src/ggml-cuda/mmq.cu b/ggml/src/ggml-cuda/mmq.cu index 9c206e50..231c4a41 100644 --- a/ggml/src/ggml-cuda/mmq.cu +++ b/ggml/src/ggml-cuda/mmq.cu @@ -174,11 +174,13 @@ bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11) { mmq_supported = ne11 < 1536; break; case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ2_K_R4: + mmq_supported = ne11 < 2048; + break; case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ5_K: case GGML_TYPE_IQ6_K: - case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: case GGML_TYPE_IQ5_K_R4: diff --git a/ggml/src/ggml-cuda/mmq.cuh b/ggml/src/ggml-cuda/mmq.cuh index d6f4cf3a..8a87e3e8 100644 --- a/ggml/src/ggml-cuda/mmq.cuh +++ b/ggml/src/ggml-cuda/mmq.cuh @@ -10,6 +10,7 @@ #include "common.cuh" #include "vecdotq.cuh" #include "mma.cuh" +#include "iqk_cuda_common.h" #include #include @@ -2492,12 +2493,10 @@ template static __device__ __forceinlin float * x_df = (float *) (x_qs + txs.qs); #endif // INT8_MMA_AVAILABLE + const int * all_values = (const int *)iq2k_table; + const int kqsx = threadIdx.x%16; - auto values = iq2nl_values; - - uint32_t aux32[4]; - const uint8_t * aux8 = (const uint8_t *)aux32; #pragma unroll for (int i0 = 0; i0 < mmq_y; i0 += 2*nwarps) { int i = i0 + 2*threadIdx.y + threadIdx.x/16; @@ -2511,26 +2510,16 @@ template static __device__ __forceinlin uint16_t extra = bxi->extra >> 4*(kqsx/8); int q2 = get_int_b2(bxi->qs, kqsx); - aux32[0] = ((q2 >> 0) & 0x03030303) | (((extra << 2) & 4) * 0x01010101); - aux32[1] = ((q2 >> 2) & 0x03030303) | (((extra << 1) & 4) * 0x01010101); - aux32[2] = ((q2 >> 4) & 0x03030303) | (((extra >> 0) & 4) * 0x01010101); - aux32[3] = ((q2 >> 6) & 0x03030303) | (((extra >> 1) & 4) * 0x01010101); - - const char4 val0 = make_char4(values[aux8[ 0]], values[aux8[ 1]], values[aux8[ 2]], values[aux8[ 3]]); - const char4 val1 = make_char4(values[aux8[ 4]], values[aux8[ 5]], values[aux8[ 6]], values[aux8[ 7]]); - const char4 val2 = make_char4(values[aux8[ 8]], values[aux8[ 9]], values[aux8[10]], values[aux8[11]]); - const char4 val3 = make_char4(values[aux8[12]], values[aux8[13]], values[aux8[14]], values[aux8[15]]); - #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 0] = *(const int *)&val0; - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 8] = *(const int *)&val1; - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 16] = *(const int *)&val2; - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 24] = *(const int *)&val3; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 0] = int_from_table_4((q2 >> 0) & 0x03030303, all_values + ((extra & 1) << 8)); + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 8] = int_from_table_4((q2 >> 2) & 0x03030303, all_values + ((extra & 2) << 7)); + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 16] = int_from_table_4((q2 >> 4) & 0x03030303, all_values + ((extra & 4) << 6)); + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx%8 + 32*(kqsx/8) + 24] = int_from_table_4((q2 >> 6) & 0x03030303, all_values + ((extra & 8) << 5)); #else - x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 0] = *(const int *)&val0; - x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 8] = *(const int *)&val1; - x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 16] = *(const int *)&val2; - x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 24] = *(const int *)&val3; + x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 0] = int_from_table_4((q2 >> 0) & 0x03030303, all_values + ((extra & 1) << 8)); + x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 8] = int_from_table_4((q2 >> 2) & 0x03030303, all_values + ((extra & 2) << 7)); + x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 16] = int_from_table_4((q2 >> 4) & 0x03030303, all_values + ((extra & 4) << 6)); + x_qs[i*(2*WARP_SIZE + 1) + kqsx%8 + 32*(kqsx/8) + 24] = int_from_table_4((q2 >> 6) & 0x03030303, all_values + ((extra & 8) << 5)); #endif // INT8_MMA_AVAILABLE } @@ -2573,10 +2562,6 @@ template static __device__ __forceinlin constexpr int qstep = 8; const int kqsx = threadIdx.x % qstep; - auto values = iq2nl_values; - - uint32_t aux32[4]; - const uint8_t * aux8 = (const uint8_t *)aux32; #pragma unroll for (int i0 = 0; i0 < mmq_y; i0 += nwarps * WARP_SIZE/qstep) { int i = i0 + threadIdx.y*(WARP_SIZE/qstep) + threadIdx.x/qstep; @@ -2587,6 +2572,8 @@ template static __device__ __forceinlin const block_iq2_k * bxi = (const block_iq2_k *)(x + i*stride) + kbx0; + auto all_values = (const int *)iq2k_table; + const float d = bxi->d; uint16_t extra = bxi->extra >> (kqsx/4); @@ -2595,28 +2582,20 @@ template static __device__ __forceinlin for (int l = 0; l < qstep/4; ++l) { const int ql = get_int_b4(bxi->qs, kqsx + qstep*l); - aux32[0] = ((ql >> 0) & 0x03030303) | (((extra << 2) & 4) * 0x01010101); - aux32[1] = ((ql >> 2) & 0x03030303) | (((extra << 0) & 4) * 0x01010101); - aux32[2] = ((ql >> 4) & 0x03030303) | (((extra >> 2) & 4) * 0x01010101); - aux32[3] = ((ql >> 6) & 0x03030303) | (((extra >> 4) & 4) * 0x01010101); - extra >>= 8; - - const char4 val0 = make_char4(values[aux8[ 0]], values[aux8[ 1]], values[aux8[ 2]], values[aux8[ 3]]); - const char4 val1 = make_char4(values[aux8[ 4]], values[aux8[ 5]], values[aux8[ 6]], values[aux8[ 7]]); - const char4 val2 = make_char4(values[aux8[ 8]], values[aux8[ 9]], values[aux8[10]], values[aux8[11]]); - const char4 val3 = make_char4(values[aux8[12]], values[aux8[13]], values[aux8[14]], values[aux8[15]]); #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 0] = *(const int *)&val0; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 8] = *(const int *)&val1; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 16] = *(const int *)&val2; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 24] = *(const int *)&val3; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 0] = int_from_table_4((ql >> 0) & 0x03030303, all_values + ((extra & 0x01) << 8)); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 8] = int_from_table_4((ql >> 2) & 0x03030303, all_values + ((extra & 0x04) << 6)); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 16] = int_from_table_4((ql >> 4) & 0x03030303, all_values + ((extra & 0x10) << 4)); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 24] = int_from_table_4((ql >> 6) & 0x03030303, all_values + ((extra & 0x40) << 2)); #else - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 0] = *(const int *)&val0; - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 8] = *(const int *)&val1; - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 16] = *(const int *)&val2; - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 24] = *(const int *)&val3; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 0] = int_from_table_4((ql >> 0) & 0x03030303, all_values + ((extra & 0x01) << 8)); + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 8] = int_from_table_4((ql >> 2) & 0x03030303, all_values + ((extra & 0x04) << 6)); + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 16] = int_from_table_4((ql >> 4) & 0x03030303, all_values + ((extra & 0x10) << 4)); + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 24] = int_from_table_4((ql >> 6) & 0x03030303, all_values + ((extra & 0x40) << 2)); #endif // INT8_MMA_AVAILABLE + + extra >>= 8; } #ifdef INT8_MMA_AVAILABLE diff --git a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_k_r4.cu b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_k_r4.cu index d7b5a18e..e40d55a0 100644 --- a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_k_r4.cu +++ b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_k_r4.cu @@ -14,10 +14,10 @@ template static __device__ __forceinlin float * x_df = (float *) (x_qs + txs.qs); #endif // INT8_MMA_AVAILABLE + const int * all_values = (const int *)iq2k_table; + const int kqsx = threadIdx.x/4; // 0...7 -> block of 32 - uint32_t aux32[4]; - const uint8_t * aux8 = (const uint8_t *)aux32; #pragma unroll for (int i0 = 0; i0 < mmq_y; i0 += 4*nwarps) { int i = i0 + 4*threadIdx.y + threadIdx.x%4; @@ -35,29 +35,20 @@ template static __device__ __forceinlin #pragma unroll for (int l = 0; l < 2; ++l) { - auto values_l = iq2nl_values + (((bxi->extra[ir+4*l] >> kqsx) & 1) << 2); + auto values_l = all_values + (((bxi->extra[ir+4*l] >> kqsx) & 1) << 8); const int ql = get_int_b4(bxi->qs, 8*kqsx + ir + 4*l); - aux32[0] = (ql >> 0) & 0x03030303; - aux32[1] = (ql >> 2) & 0x03030303; - aux32[2] = (ql >> 4) & 0x03030303; - aux32[3] = (ql >> 6) & 0x03030303; - - const char4 val0 = make_char4(values_l[aux8[ 0]], values_l[aux8[ 1]], values_l[aux8[ 2]], values_l[aux8[ 3]]); - const char4 val1 = make_char4(values_l[aux8[ 4]], values_l[aux8[ 5]], values_l[aux8[ 6]], values_l[aux8[ 7]]); - const char4 val2 = make_char4(values_l[aux8[ 8]], values_l[aux8[ 9]], values_l[aux8[10]], values_l[aux8[11]]); - const char4 val3 = make_char4(values_l[aux8[12]], values_l[aux8[13]], values_l[aux8[14]], values_l[aux8[15]]); #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 0] = *(const int *)&val0; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 1] = *(const int *)&val1; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 2] = *(const int *)&val2; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 3] = *(const int *)&val3; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 0] = int_from_table_4((ql >> 0) & 0x03030303, values_l); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 1] = int_from_table_4((ql >> 2) & 0x03030303, values_l); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 2] = int_from_table_4((ql >> 4) & 0x03030303, values_l); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 3] = int_from_table_4((ql >> 6) & 0x03030303, values_l); #else - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 0] = *(const int *)&val0; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 1] = *(const int *)&val1; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 2] = *(const int *)&val2; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 3] = *(const int *)&val3; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 0] = int_from_table_4((ql >> 0) & 0x03030303, values_l); + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 1] = int_from_table_4((ql >> 2) & 0x03030303, values_l); + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 2] = int_from_table_4((ql >> 4) & 0x03030303, values_l); + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 3] = int_from_table_4((ql >> 6) & 0x03030303, values_l); #endif // INT8_MMA_AVAILABLE } From 5446ccc8ac87037484ba63f91941de35e0bd58ca Mon Sep 17 00:00:00 2001 From: ubergarm Date: Wed, 9 Jul 2025 04:29:40 -0400 Subject: [PATCH 21/63] add hunyuan moe support for 561 (#565) * add hunyuan moe * Don't reshape Vcur * Apply chat template fix from mainline PR14584 --- include/llama.h | 1 + src/llama-vocab.cpp | 1 + src/llama.cpp | 256 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) diff --git a/include/llama.h b/include/llama.h index 51db3eab..96895afa 100644 --- a/include/llama.h +++ b/include/llama.h @@ -111,6 +111,7 @@ extern "C" { LLAMA_VOCAB_PRE_TYPE_FALCON_3 = 34, LLAMA_VOCAB_PRE_TYPE_FALCON_E = 35, LLAMA_VOCAB_PRE_TYPE_SEED_CODER = 36, //llama.cpp lists this as 35 + LLAMA_VOCAB_PRE_TYPE_HUNYUAN = 37, //llama.cpp lists this as 36 }; // note: these values should be synchronized with ggml_rope diff --git a/src/llama-vocab.cpp b/src/llama-vocab.cpp index 474cbd8c..7bae4fec 100644 --- a/src/llama-vocab.cpp +++ b/src/llama-vocab.cpp @@ -427,6 +427,7 @@ struct llm_tokenizer_bpe { break; case LLAMA_VOCAB_PRE_TYPE_STABLELM2: case LLAMA_VOCAB_PRE_TYPE_QWEN2: + case LLAMA_VOCAB_PRE_TYPE_HUNYUAN: regex_exprs = { // original regex from tokenizer.json // "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+" diff --git a/src/llama.cpp b/src/llama.cpp index 564304f6..92403f6a 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -235,6 +235,7 @@ enum llm_arch { LLM_ARCH_GRANITE, LLM_ARCH_GRANITE_MOE, LLM_ARCH_COHERE2, + LLM_ARCH_HUNYUAN_MOE, LLM_ARCH_UNKNOWN, }; @@ -291,6 +292,7 @@ static const std::map LLM_ARCH_NAMES = { { LLM_ARCH_GRANITE, "granite" }, { LLM_ARCH_GRANITE_MOE, "granitemoe" }, { LLM_ARCH_COHERE2, "cohere2" }, + { LLM_ARCH_HUNYUAN_MOE, "hunyuan-moe" }, { LLM_ARCH_UNKNOWN, "(unknown)" }, }; @@ -1595,6 +1597,29 @@ static const std::map> LLM_TENSOR_NA { LLM_TENSOR_FFN_UP, "blk.%d.ffn_up" }, }, }, + { + LLM_ARCH_HUNYUAN_MOE, + { + { LLM_TENSOR_TOKEN_EMBD, "token_embd" }, + { LLM_TENSOR_OUTPUT_NORM, "output_norm" }, + { LLM_TENSOR_OUTPUT, "output" }, + { 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_FFN_GATE_INP, "blk.%d.ffn_gate_inp" }, + { LLM_TENSOR_FFN_NORM, "blk.%d.ffn_norm" }, + { LLM_TENSOR_FFN_GATE_SHEXP, "blk.%d.ffn_gate_shexp" }, + { LLM_TENSOR_FFN_DOWN_SHEXP, "blk.%d.ffn_down_shexp" }, + { LLM_TENSOR_FFN_UP_SHEXP, "blk.%d.ffn_up_shexp" }, + { LLM_TENSOR_FFN_GATE_EXPS, "blk.%d.ffn_gate_exps" }, + { LLM_TENSOR_FFN_DOWN_EXPS, "blk.%d.ffn_down_exps" }, + { LLM_TENSOR_FFN_UP_EXPS, "blk.%d.ffn_up_exps" }, + }, + }, { LLM_ARCH_UNKNOWN, { @@ -1638,6 +1663,7 @@ enum llm_chat_template { LLM_CHAT_TEMPLATE_MEGREZ, LLM_CHAT_TEMPLATE_LLAMA4, LLM_CHAT_TEMPLATE_BITNET, + LLM_CHAT_TEMPLATE_HUNYUAN_MOE, LLM_CHAT_TEMPLATE_UNKNOWN, }; @@ -1675,6 +1701,7 @@ static const std::map LLM_CHAT_TEMPLATES = { { "gigachat", LLM_CHAT_TEMPLATE_GIGACHAT }, { "megrez", LLM_CHAT_TEMPLATE_MEGREZ }, { "llama4", LLM_CHAT_TEMPLATE_LLAMA4 }, + { "hunyuan-moe", LLM_CHAT_TEMPLATE_HUNYUAN_MOE }, { "bitnet", LLM_CHAT_TEMPLATE_BITNET }, }; @@ -2570,6 +2597,7 @@ enum e_model { MODEL_27B, MODEL_17B_16E, MODEL_17B_128E, + MODEL_80B_A13B, }; static const size_t kiB = 1024; @@ -5203,6 +5231,7 @@ static const char * llama_model_type_name(e_model type) { case MODEL_27B: return "27B"; case MODEL_17B_16E: return "17Bx16E (Scout)"; case MODEL_17B_128E: return "17Bx128E (Maverick)"; + case MODEL_80B_A13B: return "80B.A13B"; default: return "?B"; } } @@ -6037,6 +6066,17 @@ static void llm_load_hparams( default: model.type = e_model::MODEL_UNKNOWN; } } break; + case LLM_ARCH_HUNYUAN_MOE: + { + ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps); + ml.get_key(LLM_KV_EXPERT_FEED_FORWARD_LENGTH, hparams.n_ff_exp); + ml.get_key(LLM_KV_EXPERT_SHARED_FEED_FORWARD_LENGTH, hparams.n_ff_shexp); + + switch (hparams.n_layer) { + case 32: model.type = e_model::MODEL_80B_A13B; break; + default: model.type = e_model::MODEL_UNKNOWN; + } + } break; default: (void)0; } @@ -6306,6 +6346,10 @@ static void llm_load_vocab( tokenizer_pre == "seed-coder") { vocab.type_pre = LLAMA_VOCAB_PRE_TYPE_SEED_CODER; vocab.tokenizer_clean_spaces = false; + } else if ( + tokenizer_pre == "hunyuan") { + vocab.type_pre = LLAMA_VOCAB_PRE_TYPE_HUNYUAN; + vocab.tokenizer_clean_spaces = false; } else { throw std::runtime_error(format("unknown pre-tokenizer type: '%s'", tokenizer_pre.c_str())); } @@ -9164,6 +9208,47 @@ static bool llm_load_tensors( layer.ffn_post_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_FFN_POST_NORM, "weight", i), {n_embd}, 0); } } break; + case LLM_ARCH_HUNYUAN_MOE: + { + model.tok_embd = create_tensor(ctx_input, tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0); + + // output + model.output_norm = create_tensor(ctx_output, tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0); + model.output = create_tensor(ctx_output_split, tn(LLM_TENSOR_OUTPUT, "weight"), {n_embd, n_vocab}, llama_model_loader::TENSOR_NOT_REQUIRED); + + // if output is NULL, init from the input tok embed + if (model.output == NULL) { + model.output = create_tensor(ctx_output_split, tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, llama_model_loader::TENSOR_DUPLICATED); + } + + for (int i = 0; i < n_layer; ++i) { + ggml_context * ctx_layer = ctx_for_layer(i); + ggml_context * ctx_split = ctx_for_layer_split(i); + + auto & layer = model.layers[i]; + + layer.attn_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0); + + layer.wq = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_Q, "weight", i), {n_embd, n_embd_head_k * n_head}, 0); + layer.wk = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_K, "weight", i), {n_embd, n_embd_k_gqa}, 0); + layer.wv = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_V, "weight", i), {n_embd, n_embd_v_gqa}, 0); + layer.wo = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head_k * n_head, n_embd}, 0); + + layer.attn_k_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_ATTN_K_NORM, "weight", i), {n_embd_head_k}, 0); + layer.attn_q_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_ATTN_Q_NORM, "weight", i), {n_embd_head_k}, 0); + + layer.ffn_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0); + + layer.ffn_gate_inp = create_tensor(ctx_layer, tn(LLM_TENSOR_FFN_GATE_INP, "weight", i), {n_embd, n_expert}, 0); + layer.ffn_gate_exps = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_GATE_EXPS, "weight", i), {n_embd, n_ff, n_expert}, 0); + layer.ffn_down_exps = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_DOWN_EXPS, "weight", i), { n_ff, n_embd, n_expert}, 0); + layer.ffn_up_exps = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_UP_EXPS, "weight", i), {n_embd, n_ff, n_expert}, 0); + + layer.ffn_gate_shexp = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_GATE_SHEXP, "weight", i), {n_embd, hparams.n_ff_shexp}, 0); + layer.ffn_up_shexp = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_UP_SHEXP, "weight", i), {n_embd, hparams.n_ff_shexp}, 0); + layer.ffn_down_shexp = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_DOWN_SHEXP, "weight", i), {hparams.n_ff_shexp, n_embd}, 0); + } + } break; default: throw std::runtime_error("unknown architecture"); } @@ -16862,6 +16947,158 @@ struct llm_build_context { return gf; } + + struct ggml_cgraph * build_hunyuan_moe() { + struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, llama_model_max_nodes(model), 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); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = llm_build_inp_embd(ctx0, lctx, hparams, batch, model.tok_embd, cb); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); + + const float kq_scale = 1.0f / sqrtf(float(n_embd_head)); + + ggml_tensor * inp_out_ids = build_inp_out_ids(); + + for (int il = 0; il < n_layer; ++il) { + 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 + 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); + } + + 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); + } + + 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); + 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); + cb(Kcur, "Kcur", il); + cb(Vcur, "Vcur", 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 + ); + + Kcur = llm_build_norm(ctx0, Kcur, hparams, model.layers[il].attn_k_norm, nullptr, LLM_NORM_RMS, cb, il); + cb(Kcur, "Kcur_norm", il); + + Qcur = llm_build_norm(ctx0, Qcur, hparams, model.layers[il].attn_q_norm, nullptr, LLM_NORM_RMS, cb, il); + cb(Qcur, "Qcur_norm", 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); + cb(cur, "attn_out", il); + } + + if (il == n_layer - 1 && 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 = llm_build_norm(ctx0,ffn_inp, hparams, model.layers[il].ffn_norm, NULL, LLM_NORM_RMS, cb, il); + cb(cur, "ffn_norm", il); + + // feed-forward network (non-MoE) + ggml_tensor * cur_mlp = 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_mlp, "ffn_mlp", il); + + // MoE branch + ggml_tensor * cur_moe = 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, // norm_topk_prob + false, + 0.0, + LLM_EXPERT_GATING_FUNC_SOFTMAX, + cb, + il); + cb(cur_moe, "ffn_moe_out", il); + + ggml_tensor * ffn_out = ggml_add(ctx0, cur_moe, cur_mlp); + cb(ffn_out, "ffn_out", il); + + cur = ggml_add(ctx0, ffn_out, 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); + //res->t_embd = cur; + + // lm_head + cur = llm_build_lora_mm(lctx, ctx0, model.output, cur); + + cb(cur, "result_output", -1); + //res->t_logits = cur; + + ggml_build_forward_expand(gf, cur); + + return gf; + } }; static struct ggml_cgraph * llama_build_graph_defrag(llama_context & lctx, const std::vector & ids) { @@ -17157,6 +17394,10 @@ static struct ggml_cgraph * llama_build_graph( { result = llm.build_jais(); } break; + case LLM_ARCH_HUNYUAN_MOE: + { + result = llm.build_hunyuan_moe(); + } break; default: GGML_ABORT("fatal error"); } @@ -20929,6 +21170,7 @@ enum llama_rope_type llama_rope_type(const struct llama_model * model) { case LLM_ARCH_OPENELM: case LLM_ARCH_GPTNEOX: case LLM_ARCH_CODESHELL: + case LLM_ARCH_HUNYUAN_MOE: return LLAMA_ROPE_TYPE_NEOX; // all model arches should be listed explicitly here @@ -22742,6 +22984,8 @@ static llm_chat_template llama_chat_detect_template(const std::string & tmpl) { return LLM_CHAT_TEMPLATE_MEGREZ; } else if (tmpl_contains("<|header_start|>") && tmpl_contains("<|header_end|>")) { return LLM_CHAT_TEMPLATE_LLAMA4; + } else if (tmpl_contains("<|startoftext|>") && tmpl_contains("<|extra_4|>")) { + return LLM_CHAT_TEMPLATE_HUNYUAN_MOE; } return LLM_CHAT_TEMPLATE_UNKNOWN; } @@ -23160,6 +23404,18 @@ static int32_t llama_chat_apply_template_internal( ss << message->content; } } + } else if (tmpl == LLM_CHAT_TEMPLATE_HUNYUAN_MOE) { + // tencent/Hunyuan-A13B-Instruct + for (auto message : chat) { + std::string role(message->role); + if (role == "system") { + ss << "<|startoftext|>" << message->content << "<|extra_4|>"; + } else if (role == "assistant") { + ss << "<|startoftext|>" << message->content << "<|eos|>"; + } else { + ss << "<|startoftext|>" << message->content << "<|extra_0|>"; + } + } } else { // template not supported return -1; From 283753cabcabd30eb2cfb93739d9c1679200bf1f Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Thu, 10 Jul 2025 09:27:28 +0200 Subject: [PATCH 22/63] CUDA: Faster prompt processing for several quantization types (#595) * cuda: slightly faster MMQ for iq3_k, iq3_k_r4 * cuda: slightly faster MMQ for iq4_k, iq4_k_r4 * cuda: slightly faster MMQ for iq4_ks_r4 * cuda: slightly faster MMQ for iq4_ks * cuda: slightly faster MMQ for iq4_xs --------- Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-cuda/iqk_cuda_common.h | 54 ++++++++ ggml/src/ggml-cuda/iqk_mmvq.cu | 15 -- ggml/src/ggml-cuda/mmq.cuh | 128 +++++++++--------- .../mmq-instance-iq3_k_r4.cu | 26 ++-- .../mmq-instance-iq4_k_r4.cu | 23 ++-- 5 files changed, 139 insertions(+), 107 deletions(-) diff --git a/ggml/src/ggml-cuda/iqk_cuda_common.h b/ggml/src/ggml-cuda/iqk_cuda_common.h index 95d9b40e..fbe655c4 100644 --- a/ggml/src/ggml-cuda/iqk_cuda_common.h +++ b/ggml/src/ggml-cuda/iqk_cuda_common.h @@ -73,3 +73,57 @@ __device__ __forceinline__ int int_from_table_4(const uint32_t idx, const int * return values[ggml_cuda_dp4a(idx, 0x40100401, 0)]; } +static const __device__ uint16_t iq3k_table[128] = { + 0xc1c1, 0xc1d8, 0xc1e9, 0xc1f6, 0xc101, 0xc10d, 0xc11c, 0xc12f, 0xd8c1, 0xd8d8, 0xd8e9, 0xd8f6, 0xd801, 0xd80d, 0xd81c, 0xd82f, + 0xe9c1, 0xe9d8, 0xe9e9, 0xe9f6, 0xe901, 0xe90d, 0xe91c, 0xe92f, 0xf6c1, 0xf6d8, 0xf6e9, 0xf6f6, 0xf601, 0xf60d, 0xf61c, 0xf62f, + 0x01c1, 0x01d8, 0x01e9, 0x01f6, 0x0101, 0x010d, 0x011c, 0x012f, 0x0dc1, 0x0dd8, 0x0de9, 0x0df6, 0x0d01, 0x0d0d, 0x0d1c, 0x0d2f, + 0x1cc1, 0x1cd8, 0x1ce9, 0x1cf6, 0x1c01, 0x1c0d, 0x1c1c, 0x1c2f, 0x2fc1, 0x2fd8, 0x2fe9, 0x2ff6, 0x2f01, 0x2f0d, 0x2f1c, 0x2f2f, + 0xc5c5, 0xc5dc, 0xc5ed, 0xc5fa, 0xc505, 0xc511, 0xc520, 0xc533, 0xdcc5, 0xdcdc, 0xdced, 0xdcfa, 0xdc05, 0xdc11, 0xdc20, 0xdc33, + 0xedc5, 0xeddc, 0xeded, 0xedfa, 0xed05, 0xed11, 0xed20, 0xed33, 0xfac5, 0xfadc, 0xfaed, 0xfafa, 0xfa05, 0xfa11, 0xfa20, 0xfa33, + 0x05c5, 0x05dc, 0x05ed, 0x05fa, 0x0505, 0x0511, 0x0520, 0x0533, 0x11c5, 0x11dc, 0x11ed, 0x11fa, 0x1105, 0x1111, 0x1120, 0x1133, + 0x20c5, 0x20dc, 0x20ed, 0x20fa, 0x2005, 0x2011, 0x2020, 0x2033, 0x33c5, 0x33dc, 0x33ed, 0x33fa, 0x3305, 0x3311, 0x3320, 0x3333, +}; + +__device__ __forceinline__ int int_from_table_2(const uint8_t * a8, const uint16_t * values) { + return values[a8[0] | (a8[1] << 3)] | (values[a8[2] | (a8[3] << 3)] << 16); +} + +static const __device__ uint16_t iq4k_table[512] = { + 0x8181, 0x8198, 0x81ad, 0x81bf, 0x81cf, 0x81dd, 0x81ea, 0x81f6, 0x8101, 0x810d, 0x8119, 0x8126, 0x8135, 0x8145, 0x8159, 0x8171, + 0x9881, 0x9898, 0x98ad, 0x98bf, 0x98cf, 0x98dd, 0x98ea, 0x98f6, 0x9801, 0x980d, 0x9819, 0x9826, 0x9835, 0x9845, 0x9859, 0x9871, + 0xad81, 0xad98, 0xadad, 0xadbf, 0xadcf, 0xaddd, 0xadea, 0xadf6, 0xad01, 0xad0d, 0xad19, 0xad26, 0xad35, 0xad45, 0xad59, 0xad71, + 0xbf81, 0xbf98, 0xbfad, 0xbfbf, 0xbfcf, 0xbfdd, 0xbfea, 0xbff6, 0xbf01, 0xbf0d, 0xbf19, 0xbf26, 0xbf35, 0xbf45, 0xbf59, 0xbf71, + 0xcf81, 0xcf98, 0xcfad, 0xcfbf, 0xcfcf, 0xcfdd, 0xcfea, 0xcff6, 0xcf01, 0xcf0d, 0xcf19, 0xcf26, 0xcf35, 0xcf45, 0xcf59, 0xcf71, + 0xdd81, 0xdd98, 0xddad, 0xddbf, 0xddcf, 0xdddd, 0xddea, 0xddf6, 0xdd01, 0xdd0d, 0xdd19, 0xdd26, 0xdd35, 0xdd45, 0xdd59, 0xdd71, + 0xea81, 0xea98, 0xeaad, 0xeabf, 0xeacf, 0xeadd, 0xeaea, 0xeaf6, 0xea01, 0xea0d, 0xea19, 0xea26, 0xea35, 0xea45, 0xea59, 0xea71, + 0xf681, 0xf698, 0xf6ad, 0xf6bf, 0xf6cf, 0xf6dd, 0xf6ea, 0xf6f6, 0xf601, 0xf60d, 0xf619, 0xf626, 0xf635, 0xf645, 0xf659, 0xf671, + 0x0181, 0x0198, 0x01ad, 0x01bf, 0x01cf, 0x01dd, 0x01ea, 0x01f6, 0x0101, 0x010d, 0x0119, 0x0126, 0x0135, 0x0145, 0x0159, 0x0171, + 0x0d81, 0x0d98, 0x0dad, 0x0dbf, 0x0dcf, 0x0ddd, 0x0dea, 0x0df6, 0x0d01, 0x0d0d, 0x0d19, 0x0d26, 0x0d35, 0x0d45, 0x0d59, 0x0d71, + 0x1981, 0x1998, 0x19ad, 0x19bf, 0x19cf, 0x19dd, 0x19ea, 0x19f6, 0x1901, 0x190d, 0x1919, 0x1926, 0x1935, 0x1945, 0x1959, 0x1971, + 0x2681, 0x2698, 0x26ad, 0x26bf, 0x26cf, 0x26dd, 0x26ea, 0x26f6, 0x2601, 0x260d, 0x2619, 0x2626, 0x2635, 0x2645, 0x2659, 0x2671, + 0x3581, 0x3598, 0x35ad, 0x35bf, 0x35cf, 0x35dd, 0x35ea, 0x35f6, 0x3501, 0x350d, 0x3519, 0x3526, 0x3535, 0x3545, 0x3559, 0x3571, + 0x4581, 0x4598, 0x45ad, 0x45bf, 0x45cf, 0x45dd, 0x45ea, 0x45f6, 0x4501, 0x450d, 0x4519, 0x4526, 0x4535, 0x4545, 0x4559, 0x4571, + 0x5981, 0x5998, 0x59ad, 0x59bf, 0x59cf, 0x59dd, 0x59ea, 0x59f6, 0x5901, 0x590d, 0x5919, 0x5926, 0x5935, 0x5945, 0x5959, 0x5971, + 0x7181, 0x7198, 0x71ad, 0x71bf, 0x71cf, 0x71dd, 0x71ea, 0x71f6, 0x7101, 0x710d, 0x7119, 0x7126, 0x7135, 0x7145, 0x7159, 0x7171, + 0x8585, 0x859c, 0x85b1, 0x85c3, 0x85d3, 0x85e1, 0x85ee, 0x85fa, 0x8505, 0x8511, 0x851d, 0x852a, 0x8539, 0x8549, 0x855d, 0x8575, + 0x9c85, 0x9c9c, 0x9cb1, 0x9cc3, 0x9cd3, 0x9ce1, 0x9cee, 0x9cfa, 0x9c05, 0x9c11, 0x9c1d, 0x9c2a, 0x9c39, 0x9c49, 0x9c5d, 0x9c75, + 0xb185, 0xb19c, 0xb1b1, 0xb1c3, 0xb1d3, 0xb1e1, 0xb1ee, 0xb1fa, 0xb105, 0xb111, 0xb11d, 0xb12a, 0xb139, 0xb149, 0xb15d, 0xb175, + 0xc385, 0xc39c, 0xc3b1, 0xc3c3, 0xc3d3, 0xc3e1, 0xc3ee, 0xc3fa, 0xc305, 0xc311, 0xc31d, 0xc32a, 0xc339, 0xc349, 0xc35d, 0xc375, + 0xd385, 0xd39c, 0xd3b1, 0xd3c3, 0xd3d3, 0xd3e1, 0xd3ee, 0xd3fa, 0xd305, 0xd311, 0xd31d, 0xd32a, 0xd339, 0xd349, 0xd35d, 0xd375, + 0xe185, 0xe19c, 0xe1b1, 0xe1c3, 0xe1d3, 0xe1e1, 0xe1ee, 0xe1fa, 0xe105, 0xe111, 0xe11d, 0xe12a, 0xe139, 0xe149, 0xe15d, 0xe175, + 0xee85, 0xee9c, 0xeeb1, 0xeec3, 0xeed3, 0xeee1, 0xeeee, 0xeefa, 0xee05, 0xee11, 0xee1d, 0xee2a, 0xee39, 0xee49, 0xee5d, 0xee75, + 0xfa85, 0xfa9c, 0xfab1, 0xfac3, 0xfad3, 0xfae1, 0xfaee, 0xfafa, 0xfa05, 0xfa11, 0xfa1d, 0xfa2a, 0xfa39, 0xfa49, 0xfa5d, 0xfa75, + 0x0585, 0x059c, 0x05b1, 0x05c3, 0x05d3, 0x05e1, 0x05ee, 0x05fa, 0x0505, 0x0511, 0x051d, 0x052a, 0x0539, 0x0549, 0x055d, 0x0575, + 0x1185, 0x119c, 0x11b1, 0x11c3, 0x11d3, 0x11e1, 0x11ee, 0x11fa, 0x1105, 0x1111, 0x111d, 0x112a, 0x1139, 0x1149, 0x115d, 0x1175, + 0x1d85, 0x1d9c, 0x1db1, 0x1dc3, 0x1dd3, 0x1de1, 0x1dee, 0x1dfa, 0x1d05, 0x1d11, 0x1d1d, 0x1d2a, 0x1d39, 0x1d49, 0x1d5d, 0x1d75, + 0x2a85, 0x2a9c, 0x2ab1, 0x2ac3, 0x2ad3, 0x2ae1, 0x2aee, 0x2afa, 0x2a05, 0x2a11, 0x2a1d, 0x2a2a, 0x2a39, 0x2a49, 0x2a5d, 0x2a75, + 0x3985, 0x399c, 0x39b1, 0x39c3, 0x39d3, 0x39e1, 0x39ee, 0x39fa, 0x3905, 0x3911, 0x391d, 0x392a, 0x3939, 0x3949, 0x395d, 0x3975, + 0x4985, 0x499c, 0x49b1, 0x49c3, 0x49d3, 0x49e1, 0x49ee, 0x49fa, 0x4905, 0x4911, 0x491d, 0x492a, 0x4939, 0x4949, 0x495d, 0x4975, + 0x5d85, 0x5d9c, 0x5db1, 0x5dc3, 0x5dd3, 0x5de1, 0x5dee, 0x5dfa, 0x5d05, 0x5d11, 0x5d1d, 0x5d2a, 0x5d39, 0x5d49, 0x5d5d, 0x5d75, + 0x7585, 0x759c, 0x75b1, 0x75c3, 0x75d3, 0x75e1, 0x75ee, 0x75fa, 0x7505, 0x7511, 0x751d, 0x752a, 0x7539, 0x7549, 0x755d, 0x7575, +}; + +__device__ __forceinline__ int int_from_table_x(const uint8_t * a8, const uint16_t * values) { + return values[a8[0] | (a8[1] << 4)] | (values[a8[2] | (a8[3] << 4)] << 16); +} + diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cu b/ggml/src/ggml-cuda/iqk_mmvq.cu index 54d03f78..d897063f 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cu +++ b/ggml/src/ggml-cuda/iqk_mmvq.cu @@ -950,21 +950,6 @@ __device__ __forceinline__ void vec_dot_iq2_k_r4_q8_1( #define VDR_IQ3_K_Q8_1_MMVQ 4 #define VDR_IQ3_K_Q8_1_MMQ 4 -static const __device__ uint16_t iq3k_table[128] = { - 0xc1c1, 0xc1d8, 0xc1e9, 0xc1f6, 0xc101, 0xc10d, 0xc11c, 0xc12f, 0xd8c1, 0xd8d8, 0xd8e9, 0xd8f6, 0xd801, 0xd80d, 0xd81c, 0xd82f, - 0xe9c1, 0xe9d8, 0xe9e9, 0xe9f6, 0xe901, 0xe90d, 0xe91c, 0xe92f, 0xf6c1, 0xf6d8, 0xf6e9, 0xf6f6, 0xf601, 0xf60d, 0xf61c, 0xf62f, - 0x01c1, 0x01d8, 0x01e9, 0x01f6, 0x0101, 0x010d, 0x011c, 0x012f, 0x0dc1, 0x0dd8, 0x0de9, 0x0df6, 0x0d01, 0x0d0d, 0x0d1c, 0x0d2f, - 0x1cc1, 0x1cd8, 0x1ce9, 0x1cf6, 0x1c01, 0x1c0d, 0x1c1c, 0x1c2f, 0x2fc1, 0x2fd8, 0x2fe9, 0x2ff6, 0x2f01, 0x2f0d, 0x2f1c, 0x2f2f, - 0xc5c5, 0xc5dc, 0xc5ed, 0xc5fa, 0xc505, 0xc511, 0xc520, 0xc533, 0xdcc5, 0xdcdc, 0xdced, 0xdcfa, 0xdc05, 0xdc11, 0xdc20, 0xdc33, - 0xedc5, 0xeddc, 0xeded, 0xedfa, 0xed05, 0xed11, 0xed20, 0xed33, 0xfac5, 0xfadc, 0xfaed, 0xfafa, 0xfa05, 0xfa11, 0xfa20, 0xfa33, - 0x05c5, 0x05dc, 0x05ed, 0x05fa, 0x0505, 0x0511, 0x0520, 0x0533, 0x11c5, 0x11dc, 0x11ed, 0x11fa, 0x1105, 0x1111, 0x1120, 0x1133, - 0x20c5, 0x20dc, 0x20ed, 0x20fa, 0x2005, 0x2011, 0x2020, 0x2033, 0x33c5, 0x33dc, 0x33ed, 0x33fa, 0x3305, 0x3311, 0x3320, 0x3333, -}; - -__device__ __forceinline__ int int_from_table_2(const uint8_t * a8, const uint16_t * values) { - return values[a8[0] | (a8[1] << 3)] | (values[a8[2] | (a8[3] << 3)] << 16); -} - __device__ __forceinline__ void vec_dot_iq3_k_q8_1( const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iiqs, float * result) { const block_iq3_k * bq3 = (const block_iq3_k *) vbq + kbx; diff --git a/ggml/src/ggml-cuda/mmq.cuh b/ggml/src/ggml-cuda/mmq.cuh index 8a87e3e8..ee34452a 100644 --- a/ggml/src/ggml-cuda/mmq.cuh +++ b/ggml/src/ggml-cuda/mmq.cuh @@ -2436,6 +2436,9 @@ template static __device__ __forceinlin const int kbx = 0; // threadIdx.x / QI4_XS const int kqsx = threadIdx.x; // threadIdx.x % QI4_XS + uint32_t aux32[2]; + auto a8 = (const uint8_t *)aux32; + #pragma unroll for (int i0 = 0; i0 < mmq_y; i0 += nwarps) { int i = i0 + threadIdx.y; @@ -2446,15 +2449,16 @@ template static __device__ __forceinlin const block_iq4_xs * bxi = (const block_iq4_xs *)(x + i*stride) + kbx0 + kbx; - const int aux_q4 = get_int_b4(bxi->qs, kqsx); - const int2 v = get_int_from_table_16(aux_q4); + const int q4 = get_int_b4(bxi->qs, kqsx); + aux32[0] = (q4 >> 0) & 0x0f0f0f0f; + aux32[1] = (q4 >> 4) & 0x0f0f0f0f; const int k0 = 8 * (threadIdx.x / 4) + threadIdx.x % 4; #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 0] = v.x; - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 4] = v.y; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 0] = int_from_table_x(a8+0, iq4k_table); + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 4] = int_from_table_x(a8+4, iq4k_table); #else - x_qs[i*(2*WARP_SIZE + 1) + k0 + 0] = v.x; - x_qs[i*(2*WARP_SIZE + 1) + k0 + 4] = v.y; + x_qs[i*(2*WARP_SIZE + 1) + k0 + 0] = int_from_table_x(a8+0, iq4k_table); + x_qs[i*(2*WARP_SIZE + 1) + k0 + 4] = int_from_table_x(a8+4, iq4k_table); #endif // INT8_MMA_AVAILABLE } @@ -2623,8 +2627,6 @@ template static __device__ __forceinlin constexpr int qstep = 8; const int kqsx = threadIdx.x % qstep; - auto values = iq3nl_values; - uint32_t aux32[4]; const uint8_t * aux8 = (const uint8_t *)aux32; #pragma unroll @@ -2646,57 +2648,43 @@ template static __device__ __forceinlin for (int l = 0; l < qstep/4; ++l) { const int ql = get_int_b2(bxi->qs, kqsx + qstep*l); - aux32[0] = ((ql >> 0) & 0x03030303) | ((qh << 2) & 0x04040404) | (((extra << 3) & 8) * 0x01010101); - aux32[1] = ((ql >> 2) & 0x03030303) | ((qh << 1) & 0x04040404) | (((extra << 1) & 8) * 0x01010101); - aux32[2] = ((ql >> 4) & 0x03030303) | ((qh >> 0) & 0x04040404) | (((extra >> 1) & 8) * 0x01010101); - aux32[3] = ((ql >> 6) & 0x03030303) | ((qh >> 1) & 0x04040404) | (((extra >> 3) & 8) * 0x01010101); + aux32[0] = ((ql >> 0) & 0x03030303) | ((qh << 2) & 0x04040404); + aux32[1] = ((ql >> 2) & 0x03030303) | ((qh << 1) & 0x04040404); + aux32[2] = ((ql >> 4) & 0x03030303) | ((qh >> 0) & 0x04040404); + aux32[3] = ((ql >> 6) & 0x03030303) | ((qh >> 1) & 0x04040404); + + const int val0 = int_from_table_2(aux8+ 0, iq3k_table + ((extra << 6) & 0x40)); + const int val1 = int_from_table_2(aux8+ 4, iq3k_table + ((extra << 4) & 0x40)); + const int val2 = int_from_table_2(aux8+ 8, iq3k_table + ((extra << 2) & 0x40)); + const int val3 = int_from_table_2(aux8+12, iq3k_table + ((extra << 0) & 0x40)); + extra >>= 8; qh >>= 4; - const char4 val0 = make_char4(values[aux8[ 0]], values[aux8[ 1]], values[aux8[ 2]], values[aux8[ 3]]); - const char4 val1 = make_char4(values[aux8[ 4]], values[aux8[ 5]], values[aux8[ 6]], values[aux8[ 7]]); - const char4 val2 = make_char4(values[aux8[ 8]], values[aux8[ 9]], values[aux8[10]], values[aux8[11]]); - const char4 val3 = make_char4(values[aux8[12]], values[aux8[13]], values[aux8[14]], values[aux8[15]]); - #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 0] = *(const int *)&val0; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 8] = *(const int *)&val1; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 16] = *(const int *)&val2; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 24] = *(const int *)&val3; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 0] = val0; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 8] = val1; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 16] = val2; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + kqsx + 32*l + 24] = val3; #else - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 0] = *(const int *)&val0; - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 8] = *(const int *)&val1; - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 16] = *(const int *)&val2; - x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 24] = *(const int *)&val3; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 0] = val0; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 8] = val1; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 16] = val2; + x_qs[i*(2*WARP_SIZE + 1) + kqsx + 32*l + 24] = val3; #endif // INT8_MMA_AVAILABLE } uint16_t sh = bxi->scales_h >> 2*kqsx; #ifdef INT8_MMA_AVAILABLE - x_df[i*MMQ_MMA_TILE_X_K_Q3_K + 2*kqsx+0] = d * ((2*((bxi->scales_l[kqsx] >> 0) & 0xf) + 1) * (sh & 1 ? -1 : 1)); - x_df[i*MMQ_MMA_TILE_X_K_Q3_K + 2*kqsx+1] = d * ((2*((bxi->scales_l[kqsx] >> 4) & 0xf) + 1) * (sh & 2 ? -1 : 1)); + x_df[i*MMQ_MMA_TILE_X_K_Q3_K + 2*kqsx+0] = d * ((2*(bxi->scales_l[kqsx] & 0xf) + 1) * (sh & 1 ? -1 : 1)); + x_df[i*MMQ_MMA_TILE_X_K_Q3_K + 2*kqsx+1] = d * ((2*(bxi->scales_l[kqsx] >> 4) + 1) * (sh & 2 ? -1 : 1)); #else - x_df[i*(2*WARP_SIZE*2/QI8_0) + i/(QI8_0/4) + 2*kqsx+0] = d * ((2*((bxi->scales_l[kqsx] >> 0) & 0xf) + 1) * (sh & 1 ? -1 : 1)); - x_df[i*(2*WARP_SIZE*2/QI8_0) + i/(QI8_0/4) + 2*kqsx+1] = d * ((2*((bxi->scales_l[kqsx] >> 4) & 0xf) + 1) * (sh & 2 ? -1 : 1)); + x_df[i*(2*WARP_SIZE*2/QI8_0) + i/(QI8_0/4) + 2*kqsx+0] = d * ((2*(bxi->scales_l[kqsx] & 0xf) + 1) * (sh & 1 ? -1 : 1)); + x_df[i*(2*WARP_SIZE*2/QI8_0) + i/(QI8_0/4) + 2*kqsx+1] = d * ((2*(bxi->scales_l[kqsx] >> 4) + 1) * (sh & 2 ? -1 : 1)); #endif // INT8_MMA_AVAILABLE } } -static const __device__ uint16_t iq3k_table[128] = { - 0xc1c1, 0xc1d8, 0xc1e9, 0xc1f6, 0xc101, 0xc10d, 0xc11c, 0xc12f, 0xd8c1, 0xd8d8, 0xd8e9, 0xd8f6, 0xd801, 0xd80d, 0xd81c, 0xd82f, - 0xe9c1, 0xe9d8, 0xe9e9, 0xe9f6, 0xe901, 0xe90d, 0xe91c, 0xe92f, 0xf6c1, 0xf6d8, 0xf6e9, 0xf6f6, 0xf601, 0xf60d, 0xf61c, 0xf62f, - 0x01c1, 0x01d8, 0x01e9, 0x01f6, 0x0101, 0x010d, 0x011c, 0x012f, 0x0dc1, 0x0dd8, 0x0de9, 0x0df6, 0x0d01, 0x0d0d, 0x0d1c, 0x0d2f, - 0x1cc1, 0x1cd8, 0x1ce9, 0x1cf6, 0x1c01, 0x1c0d, 0x1c1c, 0x1c2f, 0x2fc1, 0x2fd8, 0x2fe9, 0x2ff6, 0x2f01, 0x2f0d, 0x2f1c, 0x2f2f, - 0xc5c5, 0xc5dc, 0xc5ed, 0xc5fa, 0xc505, 0xc511, 0xc520, 0xc533, 0xdcc5, 0xdcdc, 0xdced, 0xdcfa, 0xdc05, 0xdc11, 0xdc20, 0xdc33, - 0xedc5, 0xeddc, 0xeded, 0xedfa, 0xed05, 0xed11, 0xed20, 0xed33, 0xfac5, 0xfadc, 0xfaed, 0xfafa, 0xfa05, 0xfa11, 0xfa20, 0xfa33, - 0x05c5, 0x05dc, 0x05ed, 0x05fa, 0x0505, 0x0511, 0x0520, 0x0533, 0x11c5, 0x11dc, 0x11ed, 0x11fa, 0x1105, 0x1111, 0x1120, 0x1133, - 0x20c5, 0x20dc, 0x20ed, 0x20fa, 0x2005, 0x2011, 0x2020, 0x2033, 0x33c5, 0x33dc, 0x33ed, 0x33fa, 0x3305, 0x3311, 0x3320, 0x3333, -}; - -__device__ __forceinline__ int int_from_table_2(const uint8_t * a8, const uint16_t * values) { - return values[a8[0] | (a8[1] << 3)] | (values[a8[2] | (a8[3] << 3)] << 16); -} - template static __device__ __forceinline__ void load_tiles_iq3_ks( const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { @@ -2781,6 +2769,9 @@ template static __device__ __forceinlin const int kqsx = threadIdx.x / 4; + uint32_t aux32[2]; + auto a8 = (const uint8_t *)aux32; + #pragma unroll for (int i0 = 0; i0 < mmq_y; i0 += 4*nwarps) { int i = i0 + 4*threadIdx.y + threadIdx.x%4; @@ -2792,18 +2783,20 @@ template static __device__ __forceinlin const float * dptr = (const float *)(x + i*stride); const block_iq4_ks * bxi = (const block_iq4_ks *)(dptr + 1) + kbx0; const int ls = (bxi->scales[kqsx] & 254) - 127; - auto values = iq4k_values + ((bxi->scales[kqsx] & 1) << 4); + + auto values = iq4k_table + ((bxi->scales[kqsx] & 1) << 8); #pragma unroll for (int j = 0; j < 4; ++j) { - const int aux_q4 = get_int_b4(bxi->qs, 4*kqsx+j); - const int2 v = get_int_from_table_16(aux_q4, values); + const int q4 = get_int_b4(bxi->qs, 4*kqsx+j); + aux32[0] = (q4 >> 0) & 0x0f0f0f0f; + aux32[1] = (q4 >> 4) & 0x0f0f0f0f; #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*kqsx + j + 0] = v.x; - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*kqsx + j + 4] = v.y; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*kqsx + j + 0] = int_from_table_x(a8+0, values); + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*kqsx + j + 4] = int_from_table_x(a8+4, values); #else - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + j + 0] = v.x; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + j + 4] = v.y; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + j + 0] = int_from_table_x(a8+0, values); + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + j + 4] = int_from_table_x(a8+4, values); #endif // INT8_MMA_AVAILABLE } #ifdef INT8_MMA_AVAILABLE @@ -2830,6 +2823,9 @@ template static __device__ __forceinlin const int kqsx = threadIdx.x/4; + uint32_t aux32[2]; + const uint8_t * a8 = (const uint8_t *)aux32; + #pragma unroll for (int i0 = 0; i0 < mmq_y; i0 += 4*nwarps) { int i = i0 + 4*threadIdx.y + threadIdx.x%4; @@ -2844,18 +2840,19 @@ template static __device__ __forceinlin const block_iq4_ks_r4 * bxi = (const block_iq4_ks_r4 *)(dptr + 4) + kbx0; const int ls = (bxi->scales[4*kqsx + ir] & 254) - 127; - auto values = iq4k_values + ((bxi->scales[4*kqsx+ir] & 1) << 4); + auto values = iq4k_table + ((bxi->scales[4*kqsx+ir] & 1) << 8); #pragma unroll for (int j = 0; j < 4; ++j) { const int q4 = get_int_b4(bxi->qs, 16*kqsx+4*j+ir); - const int2 v = get_int_from_table_16(q4, values); + aux32[0] = (q4 >> 0) & 0x0f0f0f0f; + aux32[1] = (q4 >> 4) & 0x0f0f0f0f; const int k0 = 8*kqsx + 4*(j%2) + j/2; #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 0] = v.x; - x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 2] = v.y; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 0] = int_from_table_x(a8+0, values); + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + k0 + 2] = int_from_table_x(a8+4, values); #else - x_qs[i*(2*WARP_SIZE + 1) + k0 + 0] = v.x; - x_qs[i*(2*WARP_SIZE + 1) + k0 + 2] = v.y; + x_qs[i*(2*WARP_SIZE + 1) + k0 + 0] = int_from_table_x(a8+0, values); + x_qs[i*(2*WARP_SIZE + 1) + k0 + 2] = int_from_table_x(a8+4, values); #endif // INT8_MMA_AVAILABLE } #ifdef INT8_MMA_AVAILABLE @@ -3177,25 +3174,26 @@ template static __device__ __forceinlin const block_iq4_k * bxi = (const block_iq4_k *)(x + i*stride) + kbx0; const uint16_t extra = bxi->extra >> 2*kqsx; - auto values_l = iq4k_values + ((extra & 1) << 4); - auto values_h = iq4k_values + ((extra & 2) << 3); + auto values_l = iq4k_table + ((extra & 1) << 8); + auto values_h = iq4k_table + ((extra & 2) << 7); #pragma unroll for (int l = 0; l < qstep/2; ++l) { const int q4 = get_int_b4(bxi->qs, (qstep/2)*kqsx + l); + aux32[0] = (q4 >> 0) & 0x0f0f0f0f; aux32[1] = (q4 >> 4) & 0x0f0f0f0f; - const char4 val0 = make_char4(values_l[aux8[0]], values_l[aux8[1]], values_l[aux8[2]], values_l[aux8[3]]); - const char4 val1 = make_char4(values_h[aux8[4]], values_h[aux8[5]], values_h[aux8[6]], values_h[aux8[7]]); + int val0 = int_from_table_x(aux8+0, values_l); + int val1 = int_from_table_x(aux8+4, values_h); #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + l + 0] = *(const int *)&val0; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + l + 4] = *(const int *)&val1; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + l + 0] = val0; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + l + 4] = val1; #else - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + l + 0] = *(const int *)&val0; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + l + 4] = *(const int *)&val1; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + l + 0] = val0; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + l + 4] = val1; #endif // INT8_MMA_AVAILABLE } diff --git a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_k_r4.cu b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_k_r4.cu index 7b6096a3..a588969f 100644 --- a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_k_r4.cu +++ b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_k_r4.cu @@ -37,7 +37,7 @@ template static __device__ __forceinlin #pragma unroll for (int l = 0; l < 2; ++l) { - auto values_l = iq3nl_values + (((bxi->extra[ir+4*l] >> kqsx) & 1) << 3); + auto values_l = iq3k_table + (((bxi->extra[ir+4*l] >> kqsx) & 1) << 6); const int ql = get_int_b4(bxi->qs, 8*kqsx + ir + 4*l); aux32[0] = ((ql >> 0) & 0x03030303) | ((qh << 2) & 0x04040404); @@ -45,21 +45,21 @@ template static __device__ __forceinlin aux32[2] = ((ql >> 4) & 0x03030303) | ((qh >> 0) & 0x04040404); aux32[3] = ((ql >> 6) & 0x03030303) | ((qh >> 1) & 0x04040404); - const char4 val0 = make_char4(values_l[aux8[ 0]], values_l[aux8[ 1]], values_l[aux8[ 2]], values_l[aux8[ 3]]); - const char4 val1 = make_char4(values_l[aux8[ 4]], values_l[aux8[ 5]], values_l[aux8[ 6]], values_l[aux8[ 7]]); - const char4 val2 = make_char4(values_l[aux8[ 8]], values_l[aux8[ 9]], values_l[aux8[10]], values_l[aux8[11]]); - const char4 val3 = make_char4(values_l[aux8[12]], values_l[aux8[13]], values_l[aux8[14]], values_l[aux8[15]]); + int val0 = int_from_table_2(aux8+ 0, values_l); + int val1 = int_from_table_2(aux8+ 4, values_l); + int val2 = int_from_table_2(aux8+ 8, values_l); + int val3 = int_from_table_2(aux8+12, values_l); #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 0] = *(const int *)&val0; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 1] = *(const int *)&val1; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 2] = *(const int *)&val2; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 3] = *(const int *)&val3; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 0] = val0; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 1] = val1; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 2] = val2; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 3] = val3; #else - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 0] = *(const int *)&val0; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 1] = *(const int *)&val1; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 2] = *(const int *)&val2; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 3] = *(const int *)&val3; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 0] = val0; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 1] = val1; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 2] = val2; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 3] = val3; #endif // INT8_MMA_AVAILABLE qh >>= 4; diff --git a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_k_r4.cu b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_k_r4.cu index 2fc314e3..a9dd85d4 100644 --- a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_k_r4.cu +++ b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_k_r4.cu @@ -35,7 +35,7 @@ template static __device__ __forceinlin #pragma unroll for (int l = 0; l < 2; ++l) { - auto values_l = iq4k_values + (((bxi->extra[ir+4*l] >> kqsx) & 1) << 4); + auto values_l = iq4k_table + ((bxi->extra[ir+4*l] << (8 - kqsx)) & 0x100); const int ql1 = get_int_b4(bxi->qs, 16*kqsx + ir + 4*l + 0); const int ql2 = get_int_b4(bxi->qs, 16*kqsx + ir + 4*l + 8); @@ -44,21 +44,16 @@ template static __device__ __forceinlin aux32[2] = (ql2 >> 0) & 0x0f0f0f0f; aux32[3] = (ql2 >> 4) & 0x0f0f0f0f; - const char4 val0 = make_char4(values_l[aux8[ 0]], values_l[aux8[ 1]], values_l[aux8[ 2]], values_l[aux8[ 3]]); - const char4 val1 = make_char4(values_l[aux8[ 4]], values_l[aux8[ 5]], values_l[aux8[ 6]], values_l[aux8[ 7]]); - const char4 val2 = make_char4(values_l[aux8[ 8]], values_l[aux8[ 9]], values_l[aux8[10]], values_l[aux8[11]]); - const char4 val3 = make_char4(values_l[aux8[12]], values_l[aux8[13]], values_l[aux8[14]], values_l[aux8[15]]); - #ifdef INT8_MMA_AVAILABLE - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 0] = *(const int *)&val0; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 2] = *(const int *)&val1; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 1] = *(const int *)&val2; - x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 3] = *(const int *)&val3; + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 0] = int_from_table_x(aux8+ 0, values_l); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 2] = int_from_table_x(aux8+ 4, values_l); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 1] = int_from_table_x(aux8+ 8, values_l); + x_qs[i*MMQ_MMA_TILE_X_K_Q3_K + 8*kqsx + 4*l + 3] = int_from_table_x(aux8+12, values_l); #else - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 0] = *(const int *)&val0; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 2] = *(const int *)&val1; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 1] = *(const int *)&val2; - x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 3] = *(const int *)&val3; + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 0] = int_from_table_x(aux8+ 0, values_l); + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 2] = int_from_table_x(aux8+ 4, values_l); + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 1] = int_from_table_x(aux8+ 8, values_l); + x_qs[i*(2*WARP_SIZE + 1) + 8*kqsx + 4*l + 3] = int_from_table_x(aux8+12, values_l); #endif // INT8_MMA_AVAILABLE } From c53cb65251168006b29da91fea7e5e42d815af15 Mon Sep 17 00:00:00 2001 From: saood06 Date: Thu, 10 Jul 2025 02:37:36 -0500 Subject: [PATCH 23/63] Support for dots.llm1 models (#573) * Add llama.cpp changes for dots1 support * Add python changes for dots1 support * Fix to make it convert * Remove V reshaping, remove BOS by default for dots1 and fix warmup to handle models without BOS * Minor fix * Remove commented lines --- convert_hf_to_gguf.py | 28 ++++ gguf-py/gguf/constants.py | 26 ++++ gguf-py/gguf/tensor_mapping.py | 2 +- src/llama.cpp | 273 ++++++++++++++++++++++++++++++++- 4 files changed, 326 insertions(+), 3 deletions(-) diff --git a/convert_hf_to_gguf.py b/convert_hf_to_gguf.py index 33be63fa..b0a82c80 100644 --- a/convert_hf_to_gguf.py +++ b/convert_hf_to_gguf.py @@ -3864,6 +3864,34 @@ class JaisModel(Model): self.gguf_writer.add_max_alibi_bias(self.max_alibi_bias) +@Model.register("Dots1ForCausalLM") +class Dots1Model(Qwen2MoeModel): + model_arch = gguf.MODEL_ARCH.DOTS1 + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.hparams["num_experts"] = self.hparams["n_routed_experts"] + + def set_gguf_parameters(self): + super().set_gguf_parameters() + self.gguf_writer.add_leading_dense_block_count(self.hparams["first_k_dense_replace"]) + self.gguf_writer.add_expert_shared_count(self.hparams["n_shared_experts"]) + self.gguf_writer.add_expert_weights_scale(self.hparams["routed_scaling_factor"]) + self.gguf_writer.add_expert_weights_norm(self.hparams["norm_topk_prob"]) + + if self.hparams["scoring_func"] == "sigmoid": + self.gguf_writer.add_expert_gating_func(gguf.ExpertGatingFuncType.SIGMOID) + else: + raise ValueError(f"Unsupported scoring_func value: {self.hparams['scoring_func']}") + + def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None): + if name.endswith("e_score_correction_bias"): + name = name.replace("e_score_correction_bias", "e_score_correction.bias") + if "shared_experts" in name: + return [(self.map_tensor_name(name), data_torch)] + return super().modify_tensors(data_torch, name, bid) + + @Model.register("ChatGLMModel", "ChatGLMForConditionalGeneration") class ChatGLMModel(Model): model_arch = gguf.MODEL_ARCH.CHATGLM diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py index 489714c4..b3b2bc50 100644 --- a/gguf-py/gguf/constants.py +++ b/gguf-py/gguf/constants.py @@ -226,6 +226,7 @@ class MODEL_ARCH(IntEnum): T5 = auto() T5ENCODER = auto() JAIS = auto() + DOTS1 = auto() class MODEL_TENSOR(IntEnum): @@ -362,6 +363,7 @@ MODEL_ARCH_NAMES: dict[MODEL_ARCH, str] = { MODEL_ARCH.T5: "t5", MODEL_ARCH.T5ENCODER: "t5encoder", MODEL_ARCH.JAIS: "jais", + MODEL_ARCH.DOTS1: "dots1", } TENSOR_NAMES: dict[MODEL_TENSOR, str] = { @@ -1164,6 +1166,30 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = { MODEL_TENSOR.FFN_GATE, MODEL_TENSOR.FFN_UP, ], + MODEL_ARCH.DOTS1: [ + MODEL_TENSOR.TOKEN_EMBD, + MODEL_TENSOR.OUTPUT_NORM, + MODEL_TENSOR.OUTPUT, + MODEL_TENSOR.ATTN_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_EXP_PROBS_B, + MODEL_TENSOR.FFN_NORM, + MODEL_TENSOR.FFN_GATE, + MODEL_TENSOR.FFN_GATE_EXP, + MODEL_TENSOR.FFN_GATE_INP, + MODEL_TENSOR.FFN_GATE_SHEXP, + MODEL_TENSOR.FFN_DOWN, + MODEL_TENSOR.FFN_DOWN_EXP, + MODEL_TENSOR.FFN_DOWN_SHEXP, + MODEL_TENSOR.FFN_UP, + MODEL_TENSOR.FFN_UP_EXP, + MODEL_TENSOR.FFN_UP_SHEXP, + ], # TODO } diff --git a/gguf-py/gguf/tensor_mapping.py b/gguf-py/gguf/tensor_mapping.py index 9688b02c..d507725c 100644 --- a/gguf-py/gguf/tensor_mapping.py +++ b/gguf-py/gguf/tensor_mapping.py @@ -257,7 +257,7 @@ class TensorNameMap: ), MODEL_TENSOR.FFN_EXP_PROBS_B: ( - "model.layers.{bid}.mlp.gate.e_score_correction", # deepseek-v3 + "model.layers.{bid}.mlp.gate.e_score_correction", # deepseek-v3 dots1 ), # Feed-forward up diff --git a/src/llama.cpp b/src/llama.cpp index 92403f6a..8e6c66d3 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -235,6 +235,7 @@ enum llm_arch { LLM_ARCH_GRANITE, LLM_ARCH_GRANITE_MOE, LLM_ARCH_COHERE2, + LLM_ARCH_DOTS1, LLM_ARCH_HUNYUAN_MOE, LLM_ARCH_UNKNOWN, }; @@ -292,6 +293,7 @@ static const std::map LLM_ARCH_NAMES = { { LLM_ARCH_GRANITE, "granite" }, { LLM_ARCH_GRANITE_MOE, "granitemoe" }, { LLM_ARCH_COHERE2, "cohere2" }, + { LLM_ARCH_DOTS1, "dots1" }, { LLM_ARCH_HUNYUAN_MOE, "hunyuan-moe" }, { LLM_ARCH_UNKNOWN, "(unknown)" }, }; @@ -1597,6 +1599,34 @@ static const std::map> LLM_TENSOR_NA { LLM_TENSOR_FFN_UP, "blk.%d.ffn_up" }, }, }, + { + LLM_ARCH_DOTS1, + { + { LLM_TENSOR_TOKEN_EMBD, "token_embd" }, + { LLM_TENSOR_OUTPUT_NORM, "output_norm" }, + { LLM_TENSOR_OUTPUT, "output" }, + { 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_FFN_NORM, "blk.%d.ffn_norm" }, + { LLM_TENSOR_FFN_GATE, "blk.%d.ffn_gate" }, + { LLM_TENSOR_FFN_UP, "blk.%d.ffn_up" }, + { LLM_TENSOR_FFN_DOWN, "blk.%d.ffn_down" }, + { LLM_TENSOR_FFN_GATE_INP, "blk.%d.ffn_gate_inp" }, + { LLM_TENSOR_FFN_GATE_EXPS, "blk.%d.ffn_gate_exps" }, + { LLM_TENSOR_FFN_DOWN_EXPS, "blk.%d.ffn_down_exps" }, + { LLM_TENSOR_FFN_UP_EXPS, "blk.%d.ffn_up_exps" }, + { LLM_TENSOR_FFN_GATE_INP_SHEXP, "blk.%d.ffn_gate_inp_shexp" }, + { LLM_TENSOR_FFN_GATE_SHEXP, "blk.%d.ffn_gate_shexp" }, + { LLM_TENSOR_FFN_DOWN_SHEXP, "blk.%d.ffn_down_shexp" }, + { LLM_TENSOR_FFN_UP_SHEXP, "blk.%d.ffn_up_shexp" }, + { LLM_TENSOR_FFN_EXP_PROBS_B, "blk.%d.exp_probs_b" }, + } + }, { LLM_ARCH_HUNYUAN_MOE, { @@ -1663,6 +1693,7 @@ enum llm_chat_template { LLM_CHAT_TEMPLATE_MEGREZ, LLM_CHAT_TEMPLATE_LLAMA4, LLM_CHAT_TEMPLATE_BITNET, + LLM_CHAT_TEMPLATE_DOTS1, LLM_CHAT_TEMPLATE_HUNYUAN_MOE, LLM_CHAT_TEMPLATE_UNKNOWN, }; @@ -2580,6 +2611,7 @@ enum e_model { MODEL_40B, MODEL_65B, MODEL_70B, + MODEL_142B, MODEL_236B, MODEL_314B, MODEL_405B, @@ -5214,6 +5246,7 @@ static const char * llama_model_type_name(e_model type) { case MODEL_40B: return "40B"; case MODEL_65B: return "65B"; case MODEL_70B: return "70B"; + case MODEL_142B: return "142B"; case MODEL_236B: return "236B"; case MODEL_314B: return "314B"; case MODEL_405B: return "405B"; @@ -6066,6 +6099,20 @@ static void llm_load_hparams( default: model.type = e_model::MODEL_UNKNOWN; } } break; + case LLM_ARCH_DOTS1: + { + ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps); + ml.get_key(LLM_KV_LEADING_DENSE_BLOCK_COUNT, hparams.n_layer_dense_lead); + ml.get_key(LLM_KV_EXPERT_FEED_FORWARD_LENGTH, hparams.n_ff_exp); + ml.get_key(LLM_KV_EXPERT_SHARED_COUNT, hparams.n_expert_shared); + ml.get_key(LLM_KV_EXPERT_WEIGHTS_SCALE, hparams.expert_weights_scale); + ml.get_key(LLM_KV_EXPERT_WEIGHTS_NORM, hparams.expert_weights_norm, false); + ml.get_key(LLM_KV_EXPERT_GATING_FUNC, hparams.expert_gating_func, false); + switch (hparams.n_layer) { + case 62: model.type = e_model::MODEL_142B; break; + default: model.type = e_model::MODEL_UNKNOWN; + } + } break; case LLM_ARCH_HUNYUAN_MOE: { ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps); @@ -6170,7 +6217,12 @@ static void llm_load_vocab( } // default special tokens - vocab.special_bos_id = 11; + if(model.arch == LLM_ARCH_DOTS1) { + vocab.special_bos_id = -1; + } + else { + vocab.special_bos_id = 11; + } vocab.special_eos_id = 11; vocab.special_unk_id = -1; vocab.special_sep_id = -1; @@ -9208,6 +9260,54 @@ static bool llm_load_tensors( layer.ffn_post_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_FFN_POST_NORM, "weight", i), {n_embd}, 0); } } break; + case LLM_ARCH_DOTS1: + { + const int64_t n_ff_exp = hparams.n_ff_exp; + const int64_t n_expert_shared = hparams.n_expert_shared; + + model.tok_embd = create_tensor(ctx_input, tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0); + + model.output_norm = create_tensor(ctx_output, tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0); + model.output = create_tensor(ctx_output_split, tn(LLM_TENSOR_OUTPUT, "weight"), {n_embd, n_vocab}, 0); + for (int i = 0; i < n_layer; ++i) { + auto & layer = model.layers[i]; + ggml_context * ctx_layer = ctx_for_layer(i); + ggml_context * ctx_split = ctx_for_layer_split(i); + + layer.attn_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0); + + layer.wq = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_Q, "weight", i), {n_embd, n_embd_head_k * n_head}, 0); + layer.wk = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_K, "weight", i), {n_embd, n_embd_head_k * n_head}, 0); + layer.wv = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_V, "weight", i), {n_embd, n_embd_head_k * n_head}, 0); + layer.wo = create_tensor(ctx_split, tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head_k * n_head, n_embd}, 0); + + layer.attn_k_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_ATTN_K_NORM, "weight", i), {n_embd_head_k}, 0); + layer.attn_q_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_ATTN_Q_NORM, "weight", i), {n_embd_head_k}, 0); + layer.ffn_norm = create_tensor(ctx_layer, tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0); + if (i < (int) hparams.n_layer_dense_lead) { + layer.ffn_gate = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_GATE, "weight", i), {n_embd, n_ff}, 0); + layer.ffn_down = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_DOWN, "weight", i), { n_ff, n_embd}, 0); + layer.ffn_up = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_UP, "weight", i), {n_embd, n_ff}, 0); + } else { + layer.ffn_gate_inp = create_tensor(ctx_layer, tn(LLM_TENSOR_FFN_GATE_INP, "weight", i), {n_embd, n_expert}, 0); + layer.ffn_exp_probs_b = create_tensor(ctx_layer, tn(LLM_TENSOR_FFN_EXP_PROBS_B, "bias", i), {n_expert}, llama_model_loader::TENSOR_NOT_REQUIRED); + if (n_expert == 0) { + throw std::runtime_error("n_expert must be > 0"); + } + if (n_expert_used == 0) { + throw std::runtime_error("n_expert_used must be > 0"); + } + // MoE branch + layer.ffn_gate_exps = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_GATE_EXPS, "weight", i), { n_embd, n_ff_exp, n_expert}, 0); + layer.ffn_down_exps = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_DOWN_EXPS, "weight", i), {n_ff_exp, n_embd, n_expert}, 0); + layer.ffn_up_exps = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_UP_EXPS, "weight", i), { n_embd, n_ff_exp, n_expert}, 0); + // Shared expert branch + layer.ffn_gate_shexp = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_GATE_SHEXP, "weight", i), {n_embd, n_ff_exp * n_expert_shared}, 0); + layer.ffn_down_shexp = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_DOWN_SHEXP, "weight", i), { n_ff_exp * n_expert_shared, n_embd}, 0); + layer.ffn_up_shexp = create_tensor(ctx_split, tn(LLM_TENSOR_FFN_UP_SHEXP, "weight", i), {n_embd, n_ff_exp * n_expert_shared}, 0); + } + } + } break; case LLM_ARCH_HUNYUAN_MOE: { model.tok_embd = create_tensor(ctx_input, tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0); @@ -16948,6 +17048,153 @@ struct llm_build_context { return gf; } + struct ggml_cgraph * build_dots1() { + struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, llama_model_max_nodes(model), 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); + + ggml_tensor * cur; + ggml_tensor * inpL; + + inpL = llm_build_inp_embd(ctx0, lctx, hparams, batch, model.tok_embd, cb); + + // inp_pos - contains the positions + ggml_tensor * inp_pos = build_inp_pos(); + + struct ggml_tensor * KQ_mask = build_inp_KQ_mask(); + + for (int il = 0; il < n_layer; ++il) { + 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 + ggml_tensor * Qcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wq, cur); + cb(Qcur, "Qcur", il); + + ggml_tensor * Kcur = llm_build_lora_mm(lctx, ctx0, model.layers[il].wk, cur); + cb(Kcur, "Kcur", il); + + 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, n_head, n_tokens); + Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, 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, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + + 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, freq_scale, + ext_factor, attn_factor, beta_fast, beta_slow + ); + + cb(Qcur, "Qcur", il); + 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 + 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 = 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 { + 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 llm_expert_gating_func_type) hparams.expert_gating_func, + cb, il); + cb(moe_out, "ffn_moe_out", il); + + { + 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_hunyuan_moe() { struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, llama_model_max_nodes(model), false); @@ -17198,7 +17445,7 @@ static struct ggml_cgraph * llama_build_graph( const llama_vocab * vocab = llama_get_vocab(&lctx); llama_token bos = llama_token_bos_impl(*vocab); llama_token eos = llama_token_eos_impl(*vocab); - bool is_warming_up = (batch.n_tokens == 1 && batch.token[0] == bos); + bool is_warming_up = (batch.n_tokens == 1 && (batch.token[0] == ((bos != -1) ? bos : eos))); struct llm_build_context llm(lctx, batch, cb, worst_case, is_warming_up); llm.init(); @@ -17394,6 +17641,10 @@ static struct ggml_cgraph * llama_build_graph( { result = llm.build_jais(); } break; + case LLM_ARCH_DOTS1: + { + result = llm.build_dots1(); + } break; case LLM_ARCH_HUNYUAN_MOE: { result = llm.build_hunyuan_moe(); @@ -21170,6 +21421,7 @@ enum llama_rope_type llama_rope_type(const struct llama_model * model) { case LLM_ARCH_OPENELM: case LLM_ARCH_GPTNEOX: case LLM_ARCH_CODESHELL: + case LLM_ARCH_DOTS1: case LLM_ARCH_HUNYUAN_MOE: return LLAMA_ROPE_TYPE_NEOX; @@ -22984,6 +23236,8 @@ static llm_chat_template llama_chat_detect_template(const std::string & tmpl) { return LLM_CHAT_TEMPLATE_MEGREZ; } else if (tmpl_contains("<|header_start|>") && tmpl_contains("<|header_end|>")) { return LLM_CHAT_TEMPLATE_LLAMA4; + } else if (tmpl_contains("<|endofuserprompt|>")) { + return LLM_CHAT_TEMPLATE_DOTS1; } else if (tmpl_contains("<|startoftext|>") && tmpl_contains("<|extra_4|>")) { return LLM_CHAT_TEMPLATE_HUNYUAN_MOE; } @@ -23404,6 +23658,21 @@ static int32_t llama_chat_apply_template_internal( ss << message->content; } } + } else if (tmpl == LLM_CHAT_TEMPLATE_DOTS1) { + // dots.llm1.inst (DOTS1) + for (auto message : chat) { + std::string role(message->role); + if (role == "system") { + ss << "<|system|>" << message->content << "<|endofsystem|>"; + } else if (role == "user") { + ss << "<|userprompt|>" << message->content << "<|endofuserprompt|>"; + } else { + ss << "<|response|>" << message->content << "<|endofresponse|>"; + } + } + if (add_ass) { + ss << "<|response|>"; + } } else if (tmpl == LLM_CHAT_TEMPLATE_HUNYUAN_MOE) { // tencent/Hunyuan-A13B-Instruct for (auto message : chat) { From b5ddec9516c837a40f97e3bb5e96ccebdd30d4f5 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Sun, 13 Jul 2025 07:43:15 +0200 Subject: [PATCH 24/63] Check if MMQ should be used before using it (#603) Co-authored-by: Iwan Kawrakow --- ggml/src/ggml-cuda.cu | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/ggml/src/ggml-cuda.cu b/ggml/src/ggml-cuda.cu index 7fb67738..7defb227 100644 --- a/ggml/src/ggml-cuda.cu +++ b/ggml/src/ggml-cuda.cu @@ -2679,13 +2679,18 @@ static bool ggml_cuda_up_gate_unary(ggml_backend_cuda_context & ctx, ggml_tensor bool use_quantized_src1 = false; int64_t src1_padded_num_cols = 0, src1_padded_row_size = 0, src1_quantized_size = 0; if (ggml_is_quantized(src0_1->type) && src0_1->type == src0_2->type && src1->ne[1] == 1 && src1->ne[3] == 1) { - src1_padded_num_cols = GGML_PAD(src1->ne[0], MATRIX_ROW_PADDING); - src1_padded_row_size = src1_padded_num_cols/ggml_blck_size(GGML_TYPE_Q8_1)*ggml_type_size(GGML_TYPE_Q8_1); - src1_quantized_size = src1_padded_row_size*src1->ne[2] + get_mmq_x_max_host(ggml_cuda_info().devices[ctx.device].cc)*sizeof(block_q8_1_mmq); - src1_quantized.alloc(src1_quantized_size); - use_quantized_src1 = true; + if (ggml_cuda_should_use_mmq(src0_1->type, ggml_cuda_info().devices[ctx.device].cc, src1->ne[2])) { + src1_padded_num_cols = GGML_PAD(src1->ne[0], MATRIX_ROW_PADDING); + src1_padded_row_size = src1_padded_num_cols/ggml_blck_size(GGML_TYPE_Q8_1)*ggml_type_size(GGML_TYPE_Q8_1); + src1_quantized_size = src1_padded_row_size*src1->ne[2] + get_mmq_x_max_host(ggml_cuda_info().devices[ctx.device].cc)*sizeof(block_q8_1_mmq); + src1_quantized.alloc(src1_quantized_size); + use_quantized_src1 = true; + } + } + ggml_cuda_pool_alloc src1_contiguous(ctx.pool()); + if (!use_quantized_src1) { + src1_contiguous.alloc(sizeof(float)*ggml_nelements(src1)); } - ggml_cuda_pool_alloc src1_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(src1)); ggml_cuda_pool_alloc dst_up_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(dst)); ggml_cuda_pool_alloc dst_gate_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(dst)); ggml_cuda_pool_alloc final_dst_contiguous(ctx.pool()); @@ -2728,6 +2733,7 @@ static bool ggml_cuda_up_gate_unary(ggml_backend_cuda_context & ctx, ggml_tensor k_copy_src_to_contiguous<<>>( src1_original, src1_contiguous.get(), dev_row_mapping.get() + mapping_offset, ne10, ne11, nb11, nb12); CUDA_CHECK(cudaGetLastError()); + src1_row.data = src1_contiguous.get(); } src0_1_row.data = src0_1_original + i02*nb02; From e2b1a5e1fcb3ad55eae03c58c986a21e842ff7a4 Mon Sep 17 00:00:00 2001 From: Nexes the Elder <124105151+Nexesenex@users.noreply.github.com> Date: Sun, 13 Jul 2025 11:28:18 +0200 Subject: [PATCH 25/63] Fix attn_v conditionality (#604) To retain compatibility with : https://github.com/ikawrakow/ik_llama.cpp/pull/91 We need "else if" and not "if", otherwise the MOE and 70b condition takes precedence over the specified quant in the CLI. --- src/llama.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/llama.cpp b/src/llama.cpp index 8e6c66d3..5777689e 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -19447,6 +19447,18 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n } } else if (name.find("attn_v.weight") != std::string::npos) { if (qs.params->attn_v_type < GGML_TYPE_COUNT) new_type = qs.params->attn_v_type; + else if (qs.model.hparams.n_expert >= 4) { + // for the 4-8-expert model, bumping this to Q8_0 trades just ~128MB + // TODO: explore better strategies + new_type = GGML_TYPE_Q8_0; + } + else if (qs.model.type == MODEL_70B) { + // In the 70B model we have 8 heads sharing the same attn_v weights. As a result, the attn_v.weight tensor is + // 8x smaller compared to attn_q.weight. Hence, we can get a nice boost in quantization accuracy with + // nearly negligible increase in model size by quantizing this tensor with more bits: + if (new_type == GGML_TYPE_Q3_K || new_type == GGML_TYPE_Q4_K) new_type = GGML_TYPE_Q5_K; + if (new_type == GGML_TYPE_IQ3_K) new_type = GGML_TYPE_IQ5_K; + } else if (ftype == LLAMA_FTYPE_MOSTLY_Q2_K) { new_type = qs.model.hparams.n_gqa() >= 4 ? GGML_TYPE_Q4_K : GGML_TYPE_Q3_K; } @@ -19531,18 +19543,6 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n if (qs.model.hparams.n_vocab >= 127999 && (qs.model.type == MODEL_8B || qs.model.type == MODEL_70B)) new_type = GGML_TYPE_IQ6_K; } - if (qs.model.type == MODEL_70B) { - // In the 70B model we have 8 heads sharing the same attn_v weights. As a result, the attn_v.weight tensor is - // 8x smaller compared to attn_q.weight. Hence, we can get a nice boost in quantization accuracy with - // nearly negligible increase in model size by quantizing this tensor with more bits: - if (new_type == GGML_TYPE_Q3_K || new_type == GGML_TYPE_Q4_K) new_type = GGML_TYPE_Q5_K; - if (new_type == GGML_TYPE_IQ3_K) new_type = GGML_TYPE_IQ5_K; - } - if (qs.model.hparams.n_expert >= 4) { - // for the 4-8-expert model, bumping this to Q8_0 trades just ~128MB - // TODO: explore better strategies - new_type = GGML_TYPE_Q8_0; - } else if (qs.model.hparams.n_gqa() >= 4) { if (new_type == GGML_TYPE_Q2_K || new_type == GGML_TYPE_IQ3_XXS) new_type = GGML_TYPE_IQ3_S; else if (new_type == GGML_TYPE_Q2_K_R4 || new_type == GGML_TYPE_IQ3_XXS_R4) new_type = GGML_TYPE_IQ3_K_R4; From 255c22046bcaef41850125be924f3e42e2a65571 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Sun, 13 Jul 2025 19:14:26 +0200 Subject: [PATCH 26/63] Add iq3_ks to constants.py (#606) Co-authored-by: Iwan Kawrakow --- gguf-py/gguf/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py index b3b2bc50..0fe3ed35 100644 --- a/gguf-py/gguf/constants.py +++ b/gguf-py/gguf/constants.py @@ -1320,6 +1320,7 @@ class GGMLQuantizationType(IntEnum): IQ2_KT = 153 IQ3_KT = 154 IQ4_KT = 155 + IQ3_KS = 156 Q4_0_R8 = 202 Q5_0_R4 = 206 Q8_0_R8 = 208 @@ -1535,6 +1536,7 @@ GGML_QUANT_SIZES: dict[GGMLQuantizationType, tuple[int, int]] = { GGMLQuantizationType.IQ2_KT : ( 256, 68), GGMLQuantizationType.IQ3_KT : ( 256, 100), GGMLQuantizationType.IQ4_KT : ( 256, 128), + GGMLQuantizationType.IQ3_KS : ( 256, 102), GGMLQuantizationType.Q4_0_R8 : ( 32, 18), GGMLQuantizationType.Q5_0_R4 : ( 32, 22), GGMLQuantizationType.Q8_0_R8 : ( 32, 34), From f5353047ef461e6fc9d527e09a06c9802c699929 Mon Sep 17 00:00:00 2001 From: Aleksey Nikiforov Date: Mon, 14 Jul 2025 12:43:52 -0400 Subject: [PATCH 27/63] Ported kimi-k2 support from llama.cpp (#609) Original patch by @gabriellarson: https://github.com/ggml-org/llama.cpp/pull/14654 Co-authored-by: anikifoss --- include/llama.h | 1 + src/llama-vocab.cpp | 7 ++ src/llama.cpp | 6 +- src/unicode.cpp | 208 ++++++++++++++++++++++++++++++++++++++++++++ src/unicode.h | 2 + 5 files changed, 223 insertions(+), 1 deletion(-) diff --git a/include/llama.h b/include/llama.h index 96895afa..eaa5d69d 100644 --- a/include/llama.h +++ b/include/llama.h @@ -112,6 +112,7 @@ extern "C" { LLAMA_VOCAB_PRE_TYPE_FALCON_E = 35, LLAMA_VOCAB_PRE_TYPE_SEED_CODER = 36, //llama.cpp lists this as 35 LLAMA_VOCAB_PRE_TYPE_HUNYUAN = 37, //llama.cpp lists this as 36 + LLAMA_VOCAB_PRE_TYPE_KIMI_K2 = 38, //llama.cpp lists this as 37 }; // note: these values should be synchronized with ggml_rope diff --git a/src/llama-vocab.cpp b/src/llama-vocab.cpp index 7bae4fec..109a6659 100644 --- a/src/llama-vocab.cpp +++ b/src/llama-vocab.cpp @@ -464,6 +464,13 @@ struct llm_tokenizer_bpe { "[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}])([^a-z]))*((?=[\\p{L}])([^A-Z]))+(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}])([^a-z]))+((?=[\\p{L}])([^A-Z]))*(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n/]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+", }; break; + case LLAMA_VOCAB_PRE_TYPE_KIMI_K2: + regex_exprs = { + // K2 trigger pattern - this will activate the custom K2 handler in unicode.cpp + // The custom handler implements all K2 patterns with proper Han character exclusion + "\\p{Han}+", + }; + break; case LLAMA_VOCAB_PRE_TYPE_SUPERBPE: regex_exprs = { "\\p{N}+", diff --git a/src/llama.cpp b/src/llama.cpp index 5777689e..ac02abf6 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -116,7 +116,7 @@ // bump if necessary #define LLAMA_MAX_LAYERS 512 -#define LLAMA_MAX_EXPERTS 256 // DeepSeekV2 +#define LLAMA_MAX_EXPERTS 384 // Kimi-K2 // // helpers @@ -6402,6 +6402,10 @@ static void llm_load_vocab( tokenizer_pre == "hunyuan") { vocab.type_pre = LLAMA_VOCAB_PRE_TYPE_HUNYUAN; vocab.tokenizer_clean_spaces = false; + } else if ( + tokenizer_pre == "kimi-k2") { + vocab.type_pre = LLAMA_VOCAB_PRE_TYPE_KIMI_K2; + vocab.tokenizer_clean_spaces = false; } else { throw std::runtime_error(format("unknown pre-tokenizer type: '%s'", tokenizer_pre.c_str())); } diff --git a/src/unicode.cpp b/src/unicode.cpp index a57456ea..c911fd26 100644 --- a/src/unicode.cpp +++ b/src/unicode.cpp @@ -374,6 +374,178 @@ static std::vector unicode_regex_split_custom_gpt2(const std::string& te return bpe_offsets; } +// K2 system regex patterns (from tokenization_kimi.py): +// [\p{Han}]+|[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]*[\p{Ll}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]+(?i:'s|'t|'re|'ve|'m|'ll|'d)?|[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]+[\p{Ll}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]*(?i:'s|'t|'re|'ve|'m|'ll|'d)?|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+ +static std::vector unicode_regex_split_custom_kimi_k2(const std::string & text, const std::vector & offsets) { + std::vector bpe_offsets; + bpe_offsets.reserve(offsets.size()); + + const auto cpts = unicode_cpts_from_utf8(text); + + size_t start = 0; + for (auto offset : offsets) { + const size_t offset_ini = start; + const size_t offset_end = start + offset; + assert(offset_end <= cpts.size()); + start = offset_end; + + static const uint32_t OUT_OF_RANGE = 0xFFFFFFFF; + auto _get_cpt = [&] (const size_t pos) -> uint32_t { + return (offset_ini <= pos && pos < offset_end) ? cpts[pos] : OUT_OF_RANGE; + }; + + auto _get_flags = [&] (const size_t pos) -> codepoint_flags { + return (offset_ini <= pos && pos < offset_end) ? unicode_cpt_flags(cpts[pos]) : codepoint_flags{}; + }; + + size_t _prev_end = offset_ini; + auto _add_token = [&] (const size_t end) -> size_t { + assert(_prev_end <= end && end <= offset_end); + size_t len = end - _prev_end; + if (len > 0) { + bpe_offsets.push_back(len); + } + _prev_end = end; + return len; + }; + + for (size_t pos = offset_ini; pos < offset_end; /*pos++*/ ) { + const uint32_t cpt = _get_cpt(pos); + const auto flags = _get_flags(pos); + + // Pattern 1: [\p{Han}]+ (Chinese characters) + if (unicode_cpt_is_han(cpt)) { + while (unicode_cpt_is_han(_get_cpt(pos))) { + pos++; + } + _add_token(pos); + continue; + } + + // Pattern 2 & 3: Letter words excluding Han characters with optional contractions + // [^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]*[\p{Ll}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]+(?:'s|'t|'re|'ve|'m|'ll|'d)? + // [^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]+[\p{Ll}\p{Lm}\p{Lo}\p{M}&&[^\p{Han}]]*(?:'s|'t|'re|'ve|'m|'ll|'d)? + // Check if current char is a letter OR if current char could be a leading char and next char is a letter + bool is_letter_pattern = (flags.is_letter && !unicode_cpt_is_han(cpt)) || + (!(cpt == '\r' || cpt == '\n' || flags.is_letter || flags.is_number) && + _get_flags(pos + 1).is_letter && !unicode_cpt_is_han(_get_cpt(pos + 1))); + + if (is_letter_pattern) { + // Handle optional leading non-letter/non-number character + bool has_leading_char = false; + if (!(cpt == '\r' || cpt == '\n' || flags.is_letter || flags.is_number)) { + has_leading_char = true; + pos++; + } + + // Match letter sequence (excluding Han characters) + bool has_letters = false; + while (_get_flags(pos).is_letter && !unicode_cpt_is_han(_get_cpt(pos))) { + has_letters = true; + pos++; + } + + // Only proceed if we found letters (after potentially skipping leading char) + if (has_letters || (!has_leading_char && _get_flags(pos).is_letter && !unicode_cpt_is_han(_get_cpt(pos)))) { + if (!has_letters) pos++; // consume the first letter if we didn't already + + // Continue consuming letters + while (_get_flags(pos).is_letter && !unicode_cpt_is_han(_get_cpt(pos))) { + pos++; + } + + // Check for optional contractions (?:'s|'t|'re|'ve|'m|'ll|'d) + if (_get_cpt(pos) == '\'' && pos + 1 < offset_end) { + uint32_t cpt_next = unicode_tolower(_get_cpt(pos + 1)); + if (cpt_next == 's' || cpt_next == 't' || cpt_next == 'm' || cpt_next == 'd') { + pos += 2; + } else if (pos + 2 < offset_end) { + uint32_t cpt_next_next = unicode_tolower(_get_cpt(pos + 2)); + if ((cpt_next == 'r' && cpt_next_next == 'e') || + (cpt_next == 'v' && cpt_next_next == 'e') || + (cpt_next == 'l' && cpt_next_next == 'l')) { + pos += 3; + } + } + } + + _add_token(pos); + continue; + } else if (has_leading_char) { + // We consumed a leading char but found no letters, backtrack + pos--; + } + } + + // Pattern 4: \p{N}{1,3} (numbers 1-3 digits) + if (flags.is_number) { + size_t ini = pos; + while (_get_flags(pos).is_number) { + if (++pos - ini >= 3) { + _add_token(pos); + ini = pos; + } + } + _add_token(pos); + continue; + } + + // Pattern 5: ?[^\s\p{L}\p{N}]+[\r\n]* (optional space + non-word chars + optional newlines) + auto flags2 = (cpt == ' ' ? _get_flags(pos + 1) : flags); + if (!(flags2.is_whitespace || flags2.is_letter || flags2.is_number) && flags2.as_uint()) { + pos += (cpt == ' '); + while (!(flags2.is_whitespace || flags2.is_letter || flags2.is_number) && flags2.as_uint()) { + flags2 = _get_flags(++pos); + } + // Match optional [\r\n]* + uint32_t cpt2 = _get_cpt(pos); + while (cpt2 == '\r' || cpt2 == '\n') { + cpt2 = _get_cpt(++pos); + } + _add_token(pos); + continue; + } + + // Count whitespace characters + size_t num_whitespaces = 0; + size_t last_end_r_or_n = 0; + while (_get_flags(pos + num_whitespaces).is_whitespace) { + uint32_t cpt2 = _get_cpt(pos + num_whitespaces); + if (cpt2 == '\r' || cpt2 == '\n') { + last_end_r_or_n = pos + num_whitespaces + 1; + } + num_whitespaces++; + } + + // Pattern 6: \s*[\r\n]+ (whitespace with newlines) + if (last_end_r_or_n > 0) { + pos = last_end_r_or_n; + _add_token(pos); + continue; + } + + // Pattern 7: \s+(?!\S) (trailing whitespace) + if (num_whitespaces > 1 && _get_cpt(pos + num_whitespaces) != OUT_OF_RANGE) { + pos += num_whitespaces - 1; + _add_token(pos); + continue; + } + + // Pattern 8: \s+ (general whitespace) + if (num_whitespaces > 0) { + pos += num_whitespaces; + _add_token(pos); + continue; + } + + // No matches - consume single character + _add_token(++pos); + } + } + + return bpe_offsets; +} + // LLAMA3 system regex: "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+" static std::vector unicode_regex_split_custom_llama3(const std::string& text, const std::vector& offsets) { std::vector bpe_offsets; // store the offset of each word @@ -587,6 +759,10 @@ static std::vector unicode_regex_split_custom(const std::string& text, c bpe_offsets = unicode_regex_split_custom_llama3(text, offsets); } + else if (regex_expr == "\\p{Han}+") { + // K2's first pattern - handle all K2 patterns together + bpe_offsets = unicode_regex_split_custom_kimi_k2(text, offsets); + } return bpe_offsets; } @@ -662,6 +838,38 @@ codepoint_flags unicode_cpt_flags(const std::string& utf8) { return unicode_cpt_flags(unicode_cpt_from_utf8(utf8, offset)); } +bool unicode_cpt_is_han(uint32_t cpt) { + // Han character ranges (Chinese/CJK characters) + // CJK Unified Ideographs (most common) + if (cpt >= 0x4E00 && cpt <= 0x9FFF) return true; + + // CJK Extension A + if (cpt >= 0x3400 && cpt <= 0x4DBF) return true; + + // CJK Extension B + if (cpt >= 0x20000 && cpt <= 0x2A6DF) return true; + + // CJK Extension C + if (cpt >= 0x2A700 && cpt <= 0x2B73F) return true; + + // CJK Extension D + if (cpt >= 0x2B740 && cpt <= 0x2B81F) return true; + + // CJK Extension E + if (cpt >= 0x2B820 && cpt <= 0x2CEAF) return true; + + // CJK Extension F + if (cpt >= 0x2CEB0 && cpt <= 0x2EBEF) return true; + + // CJK Compatibility Ideographs + if (cpt >= 0xF900 && cpt <= 0xFAFF) return true; + + // CJK Compatibility Ideographs Supplement + if (cpt >= 0x2F800 && cpt <= 0x2FA1F) return true; + + return false; +} + std::string unicode_byte_to_utf8(uint8_t byte) { static std::unordered_map map = unicode_byte_to_utf8_map(); return map.at(byte); diff --git a/src/unicode.h b/src/unicode.h index 008532a2..48940239 100644 --- a/src/unicode.h +++ b/src/unicode.h @@ -64,4 +64,6 @@ uint8_t unicode_utf8_to_byte(const std::string & utf8); uint32_t unicode_tolower(uint32_t cp); +bool unicode_cpt_is_han(uint32_t cpt); + std::vector unicode_regex_split(const std::string & text, const std::vector & regex_exprs); From 45fae1a14444622478774f9a417e1d417af1ca46 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Mon, 14 Jul 2025 18:55:08 +0200 Subject: [PATCH 28/63] Adding IQ2_KL (#602) * Experiments for 2.6875 bpw quants At least according to rmse, this is significantly better than q2_K, while using only 1/16 more bits per weight. * iq2_kl: basics * iq2_kl: CUDA dequantize * iq2_kl: small improvement in PPL Also check the two neighbouring values for the block scale and use the one that minimizes RMSE. * iq2_kl: MMQ Quite good: PP-512(L3-8B) = 8472 t/s. * iq2_kl: MMVQ We get PP-128(L3-8B) = 162 t/s. Which means that this is not quite as good as it should be as (almost) same bpq q2_K is at 170 t/s. * iq2_kl: Zen4 GEMM/GEMV Not particularly fast. I may need to think about rearranging the bits. * iq2_kl: better Zen4 * iq2_kl: convert/repack to q8_k_r8 (AVX2) * iq2_kl: AVX2 GEMM/GEMV * iq2_kl: WIP NEON The compiler started crashing!!! * iq2_kl: NEON Had to work around a compiler crash when using vzip2q_u8 using vqtbl2q_u8. * iq2_kl: convert/repack to q8_k_r8 (NEON) * iq2_kl: Metal dequantize * iq2_kl: Metal GEMV - pretty slow * iq2_kl: Metal GEMV - slightly better (40 t/s -> 44.5 t/s) * iq2_kl: Metal GEMV - slightly better (44.5 t/s -> 46.5 t/s) * iq2_kl: Metal GEMV - slightly better (46.5 t/s -> 47.2 t/s) * iq2_kl: slightly better Metal dequantize PP-512 goes to 476 t/s up from 466 t/s. * iq2_kl: slightly better Metal dequantize PP-512 goes to 492 t/s up from 476 t/s. * Add iq2_kl to constants.py --------- Co-authored-by: Iwan Kawrakow --- examples/quantize-stats/quantize-stats.cpp | 529 ++++++++++++++++++ examples/quantize/quantize.cpp | 1 + ggml/include/ggml.h | 2 + ggml/src/ggml-common.h | 14 + ggml/src/ggml-cuda.cu | 1 + ggml/src/ggml-cuda/common.cuh | 7 + ggml/src/ggml-cuda/convert.cu | 56 ++ ggml/src/ggml-cuda/iqk_mmvq.cu | 54 ++ ggml/src/ggml-cuda/iqk_mmvq.cuh | 5 + ggml/src/ggml-cuda/mmq.cu | 4 + ggml/src/ggml-cuda/mmq.cuh | 4 + ggml/src/ggml-cuda/mmvq.cu | 4 + .../template-instances/mmq-instance-iq2_kl.cu | 70 +++ ggml/src/ggml-metal.m | 40 +- ggml/src/ggml-metal.metal | 183 ++++++ ggml/src/ggml-quants.c | 1 + ggml/src/ggml.c | 22 + ggml/src/iqk/iqk_gemm_iqk_quants.cpp | 481 ++++++++++++++++ ggml/src/iqk/iqk_mul_mat.cpp | 15 +- ggml/src/iqk/iqk_quantize.cpp | 314 ++++++++++- ggml/src/iqk/iqk_quantize.h | 6 + gguf-py/gguf/constants.py | 2 + include/llama.h | 1 + src/llama.cpp | 15 +- 24 files changed, 1819 insertions(+), 12 deletions(-) create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_kl.cu diff --git a/examples/quantize-stats/quantize-stats.cpp b/examples/quantize-stats/quantize-stats.cpp index d1598aec..02cfb25d 100644 --- a/examples/quantize-stats/quantize-stats.cpp +++ b/examples/quantize-stats/quantize-stats.cpp @@ -831,6 +831,477 @@ static void analyze_x(const char * name, int nrows, int n_per_row, const float * sqrt(mse_q/(n_per_row*nrows)), sqrt(tot_mse_q/tot_elements)); } +static const int8_t iq3nl_index[111] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, + 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 11, 11, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 12, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; +static inline int best_index_iq3nl(const int8_t * values, float x) { + int ix = (int)x - values[0]; + if (ix < 0 || ix >= 111) return ix < 0 ? 0 : 7; + ix = iq3nl_index[ix]; + return ix < 8 ? ix : x - values[ix-8] < values[ix-7] - x ? ix-8 : ix-7; +} + +static void analyze_iq2kl(const char * name, int nrows, int n_per_row, const float * x_values, const float * imatrix, float& tot_mse, float& tot_elements) { + constexpr int kBlockSize = 32; + constexpr int ntry = 5; + static const int k_index[64] = {-1, 0, -2, 1, -3, -4, 2, -5, -6, -7, -8, 3, -9, 4, -10, -11, 5, 6, 7, -12, 8, 9, 10, 11, -13, -14, -15, -16, 12, 13, + -17, -18, -19, -20, 14, 15, 16, 17, 18, -21, 19, 20, 21, 22, 23, 24, -22, 25, -23, -24, 26, -25, 27, -26, 28, -27, -28, 29, -29, 30, -30, -31, 31, -32,}; + static const std::vector> k_neighbours = { + { 0, 5, 6, 1, 7, 3, 8, 14, }, + { 1, 0, 3, 7, 4, 6, 8, 2, }, + { 1, 3, 4, 2, 8, 0, 9, 7, }, + { 2, 1, 4, 3, 9, 8, 10, 11, }, + { 2, 11, 4, 10, 9, 1, 8, 3, }, + { 5, 6, 0, 7, 3, 19, 14, 1, }, + { 6, 0, 7, 5, 3, 1, 8, 14, }, + { 3, 7, 6, 1, 0, 8, 4, 12, }, + { 3, 4, 8, 9, 1, 7, 12, 10, }, + { 4, 10, 9, 2, 11, 8, 13, 3, }, + { 11, 10, 2, 4, 9, 18, 13, 8, }, + { 8, 7, 3, 12, 9, 15, 16, 13, }, + { 5, 19, 6, 20, 14, 7, 21, 15, }, + { 6, 14, 7, 20, 5, 21, 15, 19, }, + { 14, 7, 15, 6, 21, 12, 16, 22, }, + { 12, 15, 16, 8, 14, 7, 13, 22, }, + { 18, 10, 13, 17, 9, 11, 12, 24, }, + { 11, 18, 25, 10, 13, 17, 9, 24, }, + { 19, 5, 20, 6, 14, 21, 7, 26, }, + { 20, 14, 21, 6, 19, 7, 15, 26, }, + { 25, 18, 11, 10, 28, 17, 13, 24, }, + { 18, 24, 28, 25, 17, 23, 13, 16, }, + { 19, 20, 29, 26, 21, 14, 5, 22, }, + { 20, 26, 29, 21, 19, 14, 22, 30, }, + { 27, 26, 22, 23, 30, 21, 15, 24, }, + { 27, 24, 28, 23, 31, 17, 22, 16, }, + { 25, 28, 31, 18, 24, 17, 27, 23, }, + { 29, 19, 20, 26, 21, 30, 14, 22, }, + { 30, 29, 26, 27, 21, 22, 20, 23, }, + { 30, 27, 31, 26, 28, 23, 22, 24, }, + { 31, 27, 30, 28, 24, 23, 26, 22, }, + { 31, 28, 25, 24, 18, 27, 30, 17, }, + }; + //static const int k_index[64] = {-1, -2, -3, 0, -4, -5, -6, -7, -8, 1, -9, -10, -11, 2, 3, -12, -13, -14, 4, 5, 6, 7, 8, -15, 9, -16, 10, 11, 12, 13, 14, + // -17, -18, -19, 15, 16, 17, 18, 19, -20, -21, 20, 21, 22, 23, 24, 25, -22, -23, 26, 27, 28, 29, 30, 31, -24, -25, -26, -27, -28, -29, -30, -31, -32,}; + //static const std::vector> k_neighbours = { + // { 1, 4, }, + // { 1, 0, 4, 5, }, + // { 0, 1, 4, 5, 6, }, + // { 0, 2, 6, 3, 5, 7, 4, 8, }, + // { 2, 3, 0, 7, 6, 8, 5, }, + // { 3, 2, 8, 7, 6, }, + // { 3, 2, 8, 7, }, + // { 1, 9, 4, 10, }, + // { 1, 4, 0, 5, 10, 6, 11, 9, }, + // { 0, 5, 4, 6, 1, 2, 11, 7, }, + // { 2, 6, 0, 5, 7, 3, 12, 4, }, + // { 3, 8, 2, 7, 14, 13, }, + // { 9, 1, 4, 10, 15, }, + // { 1, 4, 9, 10, 5, 11, 15, 0, }, + // { 8, 3, 14, 7, 2, 13, 19, 18, }, + // { 9, 10, 4, 15, 1, 11, 20, 5, }, + // { 14, 8, 19, 13, 3, 7, 18, 25, }, + // { 9, 20, 15, 10, 21, 26, 4, 27, }, + // { 15, 20, 9, 10, 21, 16, 26, 4, }, + // { 19, 14, 25, 18, 8, 13, 24, 31, }, + // { 20, 26, 9, 21, 15, 27, 10, }, + // { 25, 19, 31, 24, 14, 18, 30, 13, }, + // { 26, 20, 27, 21, 15, }, + // { 31, 25, 30, 19, 24, 18, }, + // { 26, 20, 27, 21, }, + // { 26, 27, 20, 21, 28, 22, }, + // { 27, 26, 28, 21, 20, 22, 29, 23, }, + // { 28, 27, 29, 22, 21, 23, 26, 30, }, + // { 29, 28, 30, 23, 22, 24, 27, 31, }, + // { 30, 29, 31, 24, 23, 25, 28, 22, }, + // { 31, 30, 25, 24, 29, 23, }, + // { 31, 25, 30, 24, }, + //}; + auto values = iq3nl_values; + std::vector> grid(32); + for (int j = 0; j < 64; ++j) { + if (int i = k_index[j]; i >= 0) { + int i1 = j/8, i2 = j%8; + grid[i] = {values[i1], values[i2]}; + } + } + auto index = [&grid, values] (float id, float x1, float x2, float w1, float w2) { + float sx1 = id*x1; + float sx2 = id*x2; + int l1 = best_index_iq3nl(values, sx1); + int l2 = best_index_iq3nl(values, sx2); + int i = k_index[8*l1 + l2]; + if (i >= 0) return i; + auto& neigh = k_neighbours[-i-1]; + // d*q - x1 = d*(q - x1/d) + float best = std::numeric_limits::max(); + int ibest = -1; + //printf("sx1 = %g, sx2 = %g, l1 = %d, l2 = %d, %d neighbours\n", sx1, sx2, l1, l2, int(neigh.size())); + for (auto& n : neigh) { + //printf(" neigh %d,%d: %d %d\n", grid[n].first, grid[n].second, values[grid[n].first ], values[grid[n].second]); + float diff1 = grid[n].first - sx1; + float diff2 = grid[n].second - sx2; + float score = w1*diff1*diff1 + w2*diff2*diff2; + if (score < best) { + best = score; ibest = n; + } + } + GGML_ASSERT(ibest >= 0); + return ibest; + }; + auto compute_1row = [&] (const float * xr) { + float weight[kBlockSize]; + int nblock = n_per_row/kBlockSize; + int last_ibl = -1; + float sigma2 = 0; + float mse = 0, sum_x2 = 0; + for (int ib = 0; ib < nblock; ++ib) { + auto xb = xr + ib*kBlockSize; + int ibl = ib/8; + if (ibl != last_ibl) { + int n = std::min(256, n_per_row - ib*kBlockSize); + float sumx2 = 0; + for (int j = 0; j < n; ++j) sumx2 += xb[j]*xb[j]; + sigma2 = 2*sumx2/n; + last_ibl = ibl; + } + if (imatrix) { + auto qw = imatrix + ib*kBlockSize; + for (int j = 0; j < kBlockSize; ++j) weight[j] = qw[j]*sqrt(sigma2 + xb[j]*xb[j]); + } else { + for (int j = 0; j < kBlockSize; ++j) weight[j] = std::abs(xb[j]); //xb[j]*xb[j]; + } + float amax = 0, max = 0; + for (int j = 0; j < kBlockSize; ++j) { + float ax = std::abs(xb[j]); + if (ax > amax) { + amax = ax; max = xb[j]; + } + } + if (!amax) { + continue; + } + float d = ntry > 0 ? -max/values[0] : max/values[0]; + float id = 1/d; + float sumqx_p = 0, sumq2_p = 0; + float sumqx_m = 0, sumq2_m = 0; + for (int j = 0; j < kBlockSize; j += 2) { + float w1 = weight[j+0]; + float w2 = weight[j+1]; + int idx = index(id, xb[j+0], xb[j+1], w1, w2); + float q1 = grid[idx].first ; + float q2 = grid[idx].second; + sumqx_p += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_p += w1*q1*q1 + w2*q2*q2; + idx = index(-id, xb[j+0], xb[j+1], w1, w2); + q1 = grid[idx].first ; + q2 = grid[idx].second; + sumqx_m += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_m += w1*q1*q1 + w2*q2*q2; + } + d = sumqx_p/sumq2_p; + float best = d*sumqx_p; + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d*sumqx_m; + } + for (int itry = -ntry; itry <= ntry; ++itry) { + id = (itry + values[0])/max; + sumqx_p = sumq2_p = 0; + sumqx_m = sumq2_m = 0; + for (int j = 0; j < kBlockSize; j += 2) { + float w1 = weight[j+0]; + float w2 = weight[j+1]; + int idx = index(id, xb[j+0], xb[j+1], w1, w2); + float q1 = grid[idx].first ; + float q2 = grid[idx].second; + sumqx_p += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_p += w1*q1*q1 + w2*q2*q2; + idx = index(-id, xb[j+0], xb[j+1], w1, w2); + q1 = grid[idx].first ; + q2 = grid[idx].second; + sumqx_m += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_m += w1*q1*q1 + w2*q2*q2; + } + if (sumq2_p > 0 && sumqx_p*sumqx_p > best*sumq2_p) { + d = sumqx_p/sumq2_p; best = d * sumqx_p; + } + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d * sumqx_m; + } + } + id = 1/d; + float block_mse = 0; + for (int j = 0; j < kBlockSize; j += 2) { + int idx = index(id, xb[j+0], xb[j+1], weight[j], weight[j+1]); + float q1 = grid[idx].first ; + float q2 = grid[idx].second; + float diff1 = d*q1 - xb[j+0]; + float diff2 = d*q2 - xb[j+1]; + block_mse += diff1*diff1 + diff2*diff2; + sum_x2 += xb[j+0]*xb[j+0] + xb[j+1]*xb[j+1]; + } + mse += block_mse; + } + return std::make_pair(mse, sum_x2); + }; + std::mutex mutex; + int counter = 0; + float mse = 0, sum_x2 = 0; + auto compute = [&mutex, &counter, &compute_1row, &mse, &sum_x2, x_values, nrows, n_per_row] () { + float local_mse = 0, local_x2 = 0; + while (true) { + std::unique_lock lock(mutex); + int row = counter++; + if (row >= nrows) { + mse += local_mse; sum_x2 += local_x2; + return; + } + lock.unlock(); + auto [row_mse, row_x2] = compute_1row(x_values + row*n_per_row); + local_mse += row_mse; + local_x2 += row_x2; + } + }; + int nthread = std::thread::hardware_concurrency()/2; + std::vector workers(nthread-1); + for (auto& w : workers) w = std::thread(compute); + compute(); + for (auto& w : workers) w.join(); + //float weight[kBlockSize]; + //int nblock = n_per_row/kBlockSize; + //int last_ibl = -1; + //float sigma2 = 0; + //auto shifted_values = values + 8; + //float mse = 0, sum_x2 = 0; + //for (int row = 0; row < nrows; ++row) { + // auto xr = x_values + row*n_per_row; + // for (int ib = 0; ib < nblock; ++ib) { + // auto xb = xr + ib*kBlockSize; + // int ibl = ib/8; + // if (ibl != last_ibl) { + // int n = std::min(256, n_per_row - ib*kBlockSize); + // float sumx2 = 0; + // for (int j = 0; j < n; ++j) sumx2 += xb[j]*xb[j]; + // sigma2 = 2*sumx2/n; + // last_ibl = ibl; + // } + // if (imatrix) { + // auto qw = imatrix + ib*kBlockSize; + // for (int j = 0; j < kBlockSize; ++j) weight[j] = qw[j]*sqrt(sigma2 + xb[j]*xb[j]); + // } else { + // for (int j = 0; j < kBlockSize; ++j) weight[j] = xb[j]*xb[j]; + // } + // float amax = 0, max = 0; + // for (int j = 0; j < kBlockSize; ++j) { + // float ax = std::abs(xb[j]); + // if (ax > amax) { + // amax = ax; max = xb[j]; + // } + // } + // if (!amax) { + // continue; + // } + // float d = ntry > 0 ? -max/values[0] : max/values[0]; + // float id = 1/d; + // float sumqx_p = 0, sumq2_p = 0; + // float sumqx_m = 0, sumq2_m = 0; + // for (int j = 0; j < kBlockSize; j += 2) { + // float w1 = weight[j+0]; + // float w2 = weight[j+1]; + // int idx = index(id, xb[j+0], xb[j+1], w1, w2); + // float q1 = grid[idx].first ; + // float q2 = grid[idx].second; + // sumqx_p += w1*q1*xb[j] + w2*q2*xb[j+1]; + // sumq2_p += w1*q1*q1 + w2*q2*q2; + // idx = index(-id, xb[j+0], xb[j+1], w1, w2); + // q1 = grid[idx].first ; + // q2 = grid[idx].second; + // sumqx_m += w1*q1*xb[j] + w2*q2*xb[j+1]; + // sumq2_m += w1*q1*q1 + w2*q2*q2; + // } + // d = sumqx_p/sumq2_p; + // float best = d*sumqx_p; + // if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + // d = sumqx_m/sumq2_m; best = d*sumqx_m; + // } + // for (int itry = -ntry; itry <= ntry; ++itry) { + // id = (itry + values[0])/max; + // sumqx_p = sumq2_p = 0; + // sumqx_m = sumq2_m = 0; + // for (int j = 0; j < kBlockSize; j += 2) { + // float w1 = weight[j+0]; + // float w2 = weight[j+1]; + // int idx = index(id, xb[j+0], xb[j+1], w1, w2); + // float q1 = grid[idx].first ; + // float q2 = grid[idx].second; + // sumqx_p += w1*q1*xb[j] + w2*q2*xb[j+1]; + // sumq2_p += w1*q1*q1 + w2*q2*q2; + // idx = index(-id, xb[j+0], xb[j+1], w1, w2); + // q1 = grid[idx].first ; + // q2 = grid[idx].second; + // sumqx_m += w1*q1*xb[j] + w2*q2*xb[j+1]; + // sumq2_m += w1*q1*q1 + w2*q2*q2; + // } + // if (sumq2_p > 0 && sumqx_p*sumqx_p > best*sumq2_p) { + // d = sumqx_p/sumq2_p; best = d * sumqx_p; + // } + // if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + // d = sumqx_m/sumq2_m; best = d * sumqx_m; + // } + // } + // id = 1/d; + // float block_mse = 0; + // for (int j = 0; j < kBlockSize; j += 2) { + // int idx = index(id, xb[j+0], xb[j+1], weight[j], weight[j+1]); + // float q1 = grid[idx].first ; + // float q2 = grid[idx].second; + // float diff1 = d*q1 - xb[j+0]; + // float diff2 = d*q2 - xb[j+1]; + // block_mse += diff1*diff1 + diff2*diff2; + // sum_x2 += xb[j+0]*xb[j+0] + xb[j+1]*xb[j+1]; + // } + // mse += block_mse; + // } + //} + tot_mse += mse; + tot_elements += sum_x2; + printf("%s: %g, %g %g\n", name, sqrt(mse/(nrows*n_per_row)), sqrt(mse/sum_x2), sqrt(tot_mse/tot_elements)); +} + + +static void analyze_iq3ks(const char * name, int nrows, int n_per_row, const float * x_values, const float * imatrix, float& tot_mse, float& tot_elements, + std::vector& Htot) { + constexpr int kBlockSize = 32; + constexpr int ntry = 5; + float weight[kBlockSize]; + int nblock = n_per_row/kBlockSize; + int last_ibl = -1; + float sigma2 = 0; + auto values = iq3nl_values; + auto shifted_values = values + 8; + std::vector H(64, 0); + float mse = 0; + for (int row = 0; row < nrows; ++row) { + auto xr = x_values + row*n_per_row; + for (int ib = 0; ib < nblock; ++ib) { + auto xb = xr + ib*kBlockSize; + int ibl = ib/8; + if (ibl != last_ibl) { + int n = std::min(256, n_per_row - ib*kBlockSize); + float sumx2 = 0; + for (int j = 0; j < n; ++j) sumx2 += xb[j]*xb[j]; + sigma2 = 2*sumx2/n; + last_ibl = ibl; + } + if (imatrix) { + auto qw = imatrix + ib*kBlockSize; + for (int j = 0; j < kBlockSize; ++j) weight[j] = qw[j]*sqrt(sigma2 + xb[j]*xb[j]); + } else { + for (int j = 0; j < kBlockSize; ++j) weight[j] = xb[j]*xb[j]; + } + float amax = 0, max = 0; + for (int j = 0; j < kBlockSize; ++j) { + float ax = std::abs(xb[j]); + if (ax > amax) { + amax = ax; max = xb[j]; + } + } + if (!amax) { + continue; + } + float d = ntry > 0 ? -max/values[0] : max/values[0]; + float id = 1/d; + float sumqx_p = 0, sumq2_p = 0; + float sumqx_m = 0, sumq2_m = 0; + for (int j = 0; j < kBlockSize; ++j) { + float w = weight[j]; + float al = id*xb[j]; + int l = best_index_iq3nl(values, al); + float q = values[l]; + sumqx_p += w*q*xb[j]; + sumq2_p += w*q*q; + l = best_index_iq3nl(values, -al); + q = values[l]; + sumqx_m += w*q*xb[j]; + sumq2_m += w*q*q; + } + d = sumqx_p/sumq2_p; + bool is_shifted = false; + float best = d*sumqx_p; + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d*sumqx_m; + } + for (int itry = -ntry; itry <= ntry; ++itry) { + id = (itry + values[0])/max; + sumqx_p = sumq2_p = 0; + sumqx_m = sumq2_m = 0; + for (int j = 0; j < kBlockSize; ++j) { + float w = weight[j]; + float al = id*xb[j]; + int l = best_index_iq3nl(values, al); + float q = values[l]; + sumqx_p += w*q*xb[j]; + sumq2_p += w*q*q; + l = best_index_iq3nl(values, -al); + q = values[l]; + sumqx_m += w*q*xb[j]; + sumq2_m += w*q*q; + } + if (sumq2_p > 0 && sumqx_p*sumqx_p > best*sumq2_p) { + d = sumqx_p/sumq2_p; best = d * sumqx_p; is_shifted = false; + } + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d * sumqx_m; is_shifted = false; + } + //id = (itry + shifted_values[0])/max; + //sumqx_p = sumq2_p = 0; + //sumqx_m = sumq2_m = 0; + //for (int j = 0; j < kBlockSize; ++j) { + // float w = weight[j]; + // float al = id*xb[j]; + // int l = best_index_iq3nl(shifted_values, al); + // float q = shifted_values[l]; + // sumqx_p += w*q*xb[j]; + // sumq2_p += w*q*q; + // l = best_index_iq3nl(shifted_values, -al); + // q = shifted_values[l]; + // sumqx_m += w*q*xb[j]; + // sumq2_m += w*q*q; + //} + //if (sumq2_p > 0 && sumqx_p*sumqx_p > best*sumq2_p) { + // d = sumqx_p/sumq2_p; best = d * sumqx_p; is_shifted = true; + //} + //if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + // d = sumqx_m/sumq2_m; best = d * sumqx_m; is_shifted = true; + //} + } + auto block_values = is_shifted ? shifted_values : values; + id = 1/d; + float block_mse = 0; + for (int j = 0; j < kBlockSize; j += 2) { + int l1 = best_index_iq3nl(block_values, id*xb[j+0]); + int l2 = best_index_iq3nl(block_values, id*xb[j+1]); + float diff1 = d*block_values[l1] - xb[j+0]; + float diff2 = d*block_values[l2] - xb[j+1]; + block_mse += diff1*diff1 + diff2*diff2; + ++H[8*l1+l2]; + } + mse += block_mse; + } + } + tot_mse += mse; + tot_elements += nrows*n_per_row; + printf("%s: %g %f\n", name, sqrt(mse/(nrows*n_per_row)), sqrt(tot_mse/tot_elements)); + + if (Htot.empty()) Htot = std::move(H); + else { + if (Htot.size() != H.size()) printf("Oops: inconsistent H sizes %zu vs %zu\n", H.size(), Htot.size()); + else for (int j = 0; j < (int)H.size(); ++j) Htot[j] += H[j]; + } +} + static void analyze_iq4ks(const char * name, int nrows, int n_per_row, const float * values, float& tot_mse, float& tot_elements) { int row_size = ggml_row_size(GGML_TYPE_IQ4_KS, n_per_row); int nblock = n_per_row/QK_K; @@ -929,6 +1400,40 @@ static void analyze_iq4ks(const ggml_tensor * t, float& tot_mse, float& tot_mse_ } } +static void analyze_iq2kl(const ggml_tensor * t, float& tot_mse, float& tot_elements) { + if (!ggml_is_contiguous(t) || (t->type != GGML_TYPE_F32 && t->type != GGML_TYPE_F16 && t->type != GGML_TYPE_BF16)) { + return; + } + if (t->type == GGML_TYPE_F32) { + analyze_iq2kl(t->name, t->ne[1], t->ne[0], (const float *)t->data, nullptr, tot_mse, tot_elements); + } else { + std::vector aux(t->ne[0]*t->ne[1]); + if (t->type == GGML_TYPE_F16) { + ggml_fp16_to_fp32_row((const ggml_fp16_t *)t->data, aux.data(), aux.size()); + } else { + ggml_bf16_to_fp32_row((const ggml_bf16_t *)t->data, aux.data(), aux.size()); + } + analyze_iq2kl(t->name, t->ne[1], t->ne[0], aux.data(), nullptr, tot_mse, tot_elements); + } +} + +static void analyze_iq3ks(const ggml_tensor * t, float& tot_mse, float& tot_elements, std::vector& Htot) { + if (!ggml_is_contiguous(t) || (t->type != GGML_TYPE_F32 && t->type != GGML_TYPE_F16 && t->type != GGML_TYPE_BF16)) { + return; + } + if (t->type == GGML_TYPE_F32) { + analyze_iq3ks(t->name, t->ne[1], t->ne[0], (const float *)t->data, nullptr, tot_mse, tot_elements, Htot); + } else { + std::vector aux(t->ne[0]*t->ne[1]); + if (t->type == GGML_TYPE_F16) { + ggml_fp16_to_fp32_row((const ggml_fp16_t *)t->data, aux.data(), aux.size()); + } else { + ggml_bf16_to_fp32_row((const ggml_bf16_t *)t->data, aux.data(), aux.size()); + } + analyze_iq3ks(t->name, t->ne[1], t->ne[0], aux.data(), nullptr, tot_mse, tot_elements, Htot); + } +} + static void print_fp_stats(const char * msg, const uint64_t * counts) { printf("===== %s\n", msg); uint64_t tot = 0; for (int i = 0; i < 32; ++i) tot += counts[i]; @@ -1108,6 +1613,30 @@ int main(int argc, char ** argv) { std::vector quantized_scratch; std::vector output_scratch; + if (analyze) { + float tot_mse = 0, tot_elements = 0; + //std::vector Htot; + for (const auto& kv_tensor : tensors) { + if (!layer_included(params, kv_tensor.first)) { + continue; + } + if (kv_tensor.second->ne[0] == 1 || kv_tensor.second->ne[1] == 1) { + // we never quantize those + continue; + } + //analyze_iq3ks(kv_tensor.second, tot_mse, tot_elements, Htot); + analyze_iq2kl(kv_tensor.second, tot_mse, tot_elements); + } + //if (!Htot.empty()) { + // printf("=============================== pair histogram\n"); + // for (int i = 0; i < (int)Htot.size(); ++i) { + // int i1 = i/8, i2 = i%8; + // printf("%d %d %d %g\n", i, i1, i2, 1.*Htot[i]); + // } + //} + return 0; + } + if (analyze) { float tot_mse = 0, tot_mse_q = 0, tot_elements = 0; for (const auto& kv_tensor : tensors) { diff --git a/examples/quantize/quantize.cpp b/examples/quantize/quantize.cpp index fd657373..7dd02313 100644 --- a/examples/quantize/quantize.cpp +++ b/examples/quantize/quantize.cpp @@ -76,6 +76,7 @@ static const std::vector QUANT_OPTIONS = { { "IQ2_K_R4", LLAMA_FTYPE_MOSTLY_IQ2_K_R4, "IQ2_K repacked",}, { "IQ2_KS", LLAMA_FTYPE_MOSTLY_IQ2_KS, " 2.1875 bpw non-linear quantization",}, { "IQ2_KT", LLAMA_FTYPE_MOSTLY_IQ2_KT, " 2.125 bpw trellis quantization", }, + { "IQ2_KL", LLAMA_FTYPE_MOSTLY_IQ2_KL, " 2.69 bpw non-linear quantization", }, { "IQ3_KS", LLAMA_FTYPE_MOSTLY_IQ3_KS, " 3.19 bpw non-linear quantization", }, { "IQ3_K", LLAMA_FTYPE_MOSTLY_IQ3_K, " 3.44 bpw non-linear quantization", }, { "IQ3_K_R4", LLAMA_FTYPE_MOSTLY_IQ3_K_R4, "IQ3_K repacked", }, diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index 655170a6..ecce1959 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -430,6 +430,7 @@ extern "C" { GGML_TYPE_IQ3_KT = 154, GGML_TYPE_IQ4_KT = 155, GGML_TYPE_IQ3_KS = 156, + GGML_TYPE_IQ2_KL = 157, GGML_TYPE_Q4_0_R8 = 202, GGML_TYPE_Q5_0_R4 = 206, @@ -523,6 +524,7 @@ extern "C" { GGML_FTYPE_MOSTLY_IQ3_KT = 143, // except 1d tensors GGML_FTYPE_MOSTLY_IQ4_KT = 144, // except 1d tensors GGML_FTYPE_MOSTLY_IQ3_KS = 145, // except 1d tensors + GGML_FTYPE_MOSTLY_IQ2_KL = 146, // except 1d tensors // GGML_FTYPE_MOSTLY_Q4_0_R8 = 202, // except 1d tensors GGML_FTYPE_MOSTLY_Q8_0_R8 = 207, // except 1d tensors diff --git a/ggml/src/ggml-common.h b/ggml/src/ggml-common.h index a1f97911..6dc439b8 100644 --- a/ggml/src/ggml-common.h +++ b/ggml/src/ggml-common.h @@ -606,6 +606,14 @@ typedef struct { } block_iq2_k; static_assert(sizeof(block_iq2_k) == sizeof(ggml_half) + sizeof(uint16_t) + QK_K/32 + QK_K/4, "wrong iq2_k block size/padding"); +typedef struct { + uint16_t scales_h; + uint8_t scales_l[QK_K/64]; + uint8_t qs[QK_K/4]; + uint8_t qh[QK_K/16]; +} block_iq2_kl; +static_assert(sizeof(block_iq2_kl) == sizeof(uint16_t) + QK_K/64 + QK_K/4 + QK_K/16, "wrong iq2_kl block size/padding"); + typedef struct { ggml_half d[4]; uint8_t extra[8]; @@ -2164,6 +2172,12 @@ GGML_TABLE_BEGIN(int8_t, iq2nl_values, 8) -31, -13, 1, 17, -26, -8, 6, 22 GGML_TABLE_END() +GGML_TABLE_BEGIN(uint16_t, iq2kl_values, 32) + 0xe9c1, 0x0dc1, 0xc1d8, 0xf6d8, 0x0dd8, 0x2fd8, 0xd8e9, 0xe9e9, 0x01e9, 0x0de9, 0x1ce9, 0xc1f6, 0x01f6, 0x0df6, 0x2ff6, 0xe901, + 0xf601, 0x0101, 0x0d01, 0x1c01, 0xd80d, 0xe90d, 0xf60d, 0x010d, 0x0d0d, 0xc11c, 0xe91c, 0x011c, 0x1c1c, 0x2f1c, 0xe92f, 0x0d2f, +GGML_TABLE_END() + + GGML_TABLE_BEGIN(int8_t, iq3nl_values, 16) -63, -40, -23, -10, 1, 13, 28, 47, -59, -36, -19, -6, 5, 17, 32, 51, diff --git a/ggml/src/ggml-cuda.cu b/ggml/src/ggml-cuda.cu index 7defb227..b33c952b 100644 --- a/ggml/src/ggml-cuda.cu +++ b/ggml/src/ggml-cuda.cu @@ -3499,6 +3499,7 @@ GGML_CALL static bool ggml_backend_cuda_supports_op(ggml_backend_t backend, cons case GGML_TYPE_IQ3_XXS: case GGML_TYPE_IQ4_NL: case GGML_TYPE_IQ4_XS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ4_KSS: diff --git a/ggml/src/ggml-cuda/common.cuh b/ggml/src/ggml-cuda/common.cuh index 973af2b8..38b52fd0 100644 --- a/ggml/src/ggml-cuda/common.cuh +++ b/ggml/src/ggml-cuda/common.cuh @@ -599,6 +599,13 @@ struct ggml_cuda_type_traits { static constexpr int qi = QI4_XS; }; +template<> +struct ggml_cuda_type_traits { + static constexpr int qk = QK_K; + static constexpr int qr = QR4_XS; + static constexpr int qi = QI4_XS; +}; + template<> struct ggml_cuda_type_traits { static constexpr int qk = QK_K; diff --git a/ggml/src/ggml-cuda/convert.cu b/ggml/src/ggml-cuda/convert.cu index 61c09481..c8e02a83 100644 --- a/ggml/src/ggml-cuda/convert.cu +++ b/ggml/src/ggml-cuda/convert.cu @@ -1333,6 +1333,48 @@ static __global__ void dequantize_block_iq3_k(const void * __restrict__ vx, dst_ } } +template +static __global__ void dequantize_block_iq2_kl(const void * __restrict__ vx, dst_t * __restrict__ yy, int64_t n_per_row, int64_t row_size) { + + int64_t ii = blockIdx.x; + int64_t row = (QK_K * ii) / n_per_row; + const char * cx = (const char *)vx + row * row_size; + float scale = (float)*(const ggml_half *)cx; + const block_iq2_kl * x = (const block_iq2_kl *)(cx + sizeof(ggml_half)); + const int64_t i = ii - (row*n_per_row)/QK_K; + + const int64_t tid = threadIdx.x; + const int64_t ib64 = tid/8; + const int64_t il = tid%8; + dst_t * y = yy + ii*QK_K + 64*ib64 + 4*il; + const uint8_t * qs = x[i].qs + 16*ib64 + 2*il; + const uint8_t * qh = x[i].qh + 2*il; + auto sh = x[i].scales_h >> 4*ib64; + const float d1 = scale * (int(((x[i].scales_l[(2*ib64+0)%4] >> 4*(ib64/2)) & 0xf) | ((sh << 4) & 0x30)) - 32); + const float d2 = scale * (int(((x[i].scales_l[(2*ib64+1)%4] >> 4*(ib64/2)) & 0xf) | ((sh << 2) & 0x30)) - 32); + if constexpr (std::is_same_v) { + for (int j = 0; j < 2; ++j) { + uint8_t h = qh[j] >> 2*ib64; + auto val1 = (const int8_t *)(iq2kl_values + ((qs[j] & 0xf) | ((h & 1) << 4))); + auto val2 = (const int8_t *)(iq2kl_values + ((qs[j] >> 4) | ((h & 2) << 3))); + y[2*j+ 0] = __float2bfloat16(d1 * val1[0]); + y[2*j+ 1] = __float2bfloat16(d1 * val1[1]); + y[2*j+32] = __float2bfloat16(d2 * val2[0]); + y[2*j+33] = __float2bfloat16(d2 * val2[1]); + } + } else { + for (int j = 0; j < 2; ++j) { + uint8_t h = qh[j] >> 2*ib64; + auto val1 = (const int8_t *)(iq2kl_values + ((qs[j] & 0xf) | ((h & 1) << 4))); + auto val2 = (const int8_t *)(iq2kl_values + ((qs[j] >> 4) | ((h & 2) << 3))); + y[2*j+ 0] = d1 * val1[0]; + y[2*j+ 1] = d1 * val1[1]; + y[2*j+32] = d2 * val2[0]; + y[2*j+33] = d2 * val2[1]; + } + } +} + template static __global__ void dequantize_block_iq3_ks(const void * __restrict__ vx, dst_t * __restrict__ yy, int64_t n_per_row, int64_t row_size) { @@ -1618,6 +1660,14 @@ static void dequantize_row_iq3_k_cuda(const void * vx, dst_t * y, const int64_t dequantize_block_iq3_k<<>>(vx, y); } +template +static void dequantize_row_iq2_kl_cuda(const void * vx, dst_t * y, const int64_t nrows, const int64_t n_per_row, cudaStream_t stream) { + const int64_t k = nrows * n_per_row; + const int64_t row_size = ggml_row_size(GGML_TYPE_IQ2_KL, n_per_row); + const int nb = (k + QK_K - 1) / QK_K; + dequantize_block_iq2_kl<<>>(vx, y, n_per_row, row_size); +} + template static void dequantize_row_iq3_ks_cuda(const void * vx, dst_t * y, const int64_t nrows, const int64_t n_per_row, cudaStream_t stream) { const int64_t k = nrows * n_per_row; @@ -1772,6 +1822,8 @@ to_bf16_cuda_t ggml_get_to_bf16_cuda(ggml_type type) { return dequantize_row_iq2_k_cuda; case GGML_TYPE_IQ3_K: return dequantize_row_iq3_k_cuda; + case GGML_TYPE_IQ2_KL: + return dequantize_row_iq2_kl_cuda; case GGML_TYPE_IQ3_KS: return dequantize_row_iq3_ks_cuda; case GGML_TYPE_IQ4_KSS: @@ -1876,6 +1928,8 @@ to_fp16_cuda_t ggml_get_to_fp16_cuda(ggml_type type) { return dequantize_row_iq2_k_cuda; case GGML_TYPE_IQ3_K: return dequantize_row_iq3_k_cuda; + case GGML_TYPE_IQ2_KL: + return dequantize_row_iq2_kl_cuda; case GGML_TYPE_IQ3_KS: return dequantize_row_iq3_ks_cuda; case GGML_TYPE_IQ4_K: @@ -1973,6 +2027,8 @@ to_fp32_cuda_t ggml_get_to_fp32_cuda(ggml_type type) { return dequantize_row_iq2_k_cuda; case GGML_TYPE_IQ3_K: return dequantize_row_iq3_k_cuda; + case GGML_TYPE_IQ2_KL: + return dequantize_row_iq2_kl_cuda; case GGML_TYPE_IQ3_KS: return dequantize_row_iq3_ks_cuda; case GGML_TYPE_IQ4_K: diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cu b/ggml/src/ggml-cuda/iqk_mmvq.cu index d897063f..a669390d 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cu +++ b/ggml/src/ggml-cuda/iqk_mmvq.cu @@ -1016,6 +1016,52 @@ __device__ __forceinline__ void vec_dot_iq3_k_q8_1( } +// TODO +__device__ __forceinline__ void vec_dot_iq2_kl_q8_1( + const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iiqs, float * result) { + + float d = __half2float(*(const half *)vbq); + const block_iq2_kl * bq2 = (const block_iq2_kl *)((const char *)vbq + sizeof(half)) + kbx; + + int iqs = iiqs/4; + const int ib64 = iqs/2; // 0...3. 0 works on quants 0...63, 1 on quants 64...127, etc. + // Each thread processes 16 quants in each of the 2 32-blocks + const int il16 = iqs%2; // 0...3. 0 works on quants 0...7, 1 on quants 8...15, 2 on 16...23, 3 on 24...31 + + const uint16_t * ql = (const uint16_t *)bq2->qs + 8*ib64 + 4*il16; + const uint16_t * qh = (const uint16_t *)bq2->qh + 4*il16; + + int32_t aux32; + const uint8_t * aux8 = (const uint8_t *)&aux32; + + const int * q8l = (const int *)bq8_1[2*ib64+0].qs + 4*il16; + const int * q8h = (const int *)bq8_1[2*ib64+1].qs + 4*il16; + + int sumi1 = 0, sumi2 = 0; + int v1, v2; + for (int i = 0; i < 2; ++i) { + uint32_t vl = ql[2*i+0] | (ql[2*i+1] << 16); + uint32_t vh = (qh[2*i+0] | (qh[2*i+1] << 16)) >> 2*ib64; + + aux32 = (vl & 0x0f0f0f0f) | ((vh << 4) & 0x10101010); + v1 = iq2kl_values[aux8[0]] | (iq2kl_values[aux8[1]] << 16); + v2 = iq2kl_values[aux8[2]] | (iq2kl_values[aux8[3]] << 16); + sumi1 = ggml_cuda_dp4a(v1, q8l[2*i+0], ggml_cuda_dp4a(v2, q8l[2*i+1], sumi1)); + + aux32 = ((vl >> 4) & 0x0f0f0f0f) | ((vh << 3) & 0x10101010); + v1 = iq2kl_values[aux8[0]] | (iq2kl_values[aux8[1]] << 16); + v2 = iq2kl_values[aux8[2]] | (iq2kl_values[aux8[3]] << 16); + sumi2 = ggml_cuda_dp4a(v1, q8h[2*i+0], ggml_cuda_dp4a(v2, q8h[2*i+1], sumi2)); + } + + auto sh = bq2->scales_h >> 4*ib64; + int ls1 = int(((bq2->scales_l[(2*ib64+0)%4] >> 4*(ib64/2)) & 0xf) | ((sh << 4) & 0x30)) - 32; + int ls2 = int(((bq2->scales_l[(2*ib64+1)%4] >> 4*(ib64/2)) & 0xf) | ((sh << 2) & 0x30)) - 32; + + *result += d * (__low2float(bq8_1[2*ib64+0].ds) * ls1 * sumi1 + __low2float(bq8_1[2*ib64+1].ds) * ls2 * sumi2); + +} + __device__ __forceinline__ void vec_dot_iq3_ks_q8_1( const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iiqs, float * result) { @@ -1280,6 +1326,14 @@ void mul_mat_vec_iq4_ks_q8_1_cuda( iqk_mul_mat_vec_q_cuda(vx, vy, dst, ids_data, ncols_x, nrows_x, nrows_y, ncols_y, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); } +void mul_mat_vec_iq2_kl_q8_1_cuda( + const void * vx, const void * vy, float * dst, const char * ids_data, + const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, + const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, int64_t ids_nb0, cudaStream_t stream) { + + iqk_mul_mat_vec_q_cuda(vx, vy, dst, ids_data, ncols_x, nrows_x, nrows_y, ncols_y, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); +} + void mul_mat_vec_iq3_ks_q8_1_cuda( const void * vx, const void * vy, float * dst, const char * ids_data, const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cuh b/ggml/src/ggml-cuda/iqk_mmvq.cuh index c2416b1e..d14c3541 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cuh +++ b/ggml/src/ggml-cuda/iqk_mmvq.cuh @@ -16,6 +16,11 @@ void mul_mat_vec_iq3_k_q8_1_cuda( const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, const int64_t ids_nb0, cudaStream_t stream); +void mul_mat_vec_iq2_kl_q8_1_cuda( + const void * vx, const void * vy, float * dst, const char * ids_data, + const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, + const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, const int64_t ids_nb0, cudaStream_t stream); + void mul_mat_vec_iq3_ks_q8_1_cuda( const void * vx, const void * vy, float * dst, const char * ids_data, const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, diff --git a/ggml/src/ggml-cuda/mmq.cu b/ggml/src/ggml-cuda/mmq.cu index 231c4a41..cde5d044 100644 --- a/ggml/src/ggml-cuda/mmq.cu +++ b/ggml/src/ggml-cuda/mmq.cu @@ -94,6 +94,9 @@ void ggml_cuda_op_mul_mat_q( case GGML_TYPE_IQ4_NL: mul_mat_q_case(ctx, args, stream); break; + case GGML_TYPE_IQ2_KL: + mul_mat_q_case(ctx, args, stream); + break; case GGML_TYPE_IQ3_KS: mul_mat_q_case(ctx, args, stream); break; @@ -201,6 +204,7 @@ bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11) { case GGML_TYPE_IQ1_S_R4: case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ4_NL: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ4_KS_R4: diff --git a/ggml/src/ggml-cuda/mmq.cuh b/ggml/src/ggml-cuda/mmq.cuh index ee34452a..21b50082 100644 --- a/ggml/src/ggml-cuda/mmq.cuh +++ b/ggml/src/ggml-cuda/mmq.cuh @@ -88,6 +88,7 @@ static mmq_q8_1_ds_layout mmq_get_q8_1_ds_layout(const ggml_type type_x) { case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_KS: @@ -201,6 +202,7 @@ static constexpr __host__ __device__ tile_x_sizes mmq_get_dp4a_tile_x_sizes(ggml case GGML_TYPE_IQ1_S_R4: return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_XS : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_NL : return MMQ_DP4A_TXS_Q8_0; + case GGML_TYPE_IQ2_KL : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ3_KS : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_KS : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_KS_R4 : return MMQ_DP4A_TXS_Q8_0; @@ -257,6 +259,7 @@ static constexpr __host__ __device__ int mmq_get_mma_tile_x_k(ggml_type type) { case GGML_TYPE_IQ1_S_R4: return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_XS : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_NL : return MMQ_MMA_TILE_X_K_Q8_0; + case GGML_TYPE_IQ2_KL : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ3_KS : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_KS : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_KS_R4 : return MMQ_MMA_TILE_X_K_Q8_0; @@ -4156,6 +4159,7 @@ extern DECL_MMQ_CASE(GGML_TYPE_IQ3_S); extern DECL_MMQ_CASE(GGML_TYPE_IQ1_S); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_NL); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_XS); +extern DECL_MMQ_CASE(GGML_TYPE_IQ2_KL); extern DECL_MMQ_CASE(GGML_TYPE_IQ3_KS); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_KS); extern DECL_MMQ_CASE(GGML_TYPE_IQ4_KS_R4); diff --git a/ggml/src/ggml-cuda/mmvq.cu b/ggml/src/ggml-cuda/mmvq.cu index 2b619f67..d0746031 100644 --- a/ggml/src/ggml-cuda/mmvq.cu +++ b/ggml/src/ggml-cuda/mmvq.cu @@ -518,6 +518,9 @@ static void ggml_cuda_op_mul_mat_vec_q_impl(ggml_backend_cuda_context & ctx, ggm case GGML_TYPE_IQ3_K: mul_mat_vec_iq3_k_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); break; + case GGML_TYPE_IQ2_KL: + mul_mat_vec_iq2_kl_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); + break; case GGML_TYPE_IQ3_KS: mul_mat_vec_iq3_ks_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); break; @@ -682,6 +685,7 @@ bool ggml_cuda_mmvq_type_supported(ggml_type src0_type) { case GGML_TYPE_IQ4_NL: case GGML_TYPE_IQ4_XS: case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ4_K: diff --git a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_kl.cu b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_kl.cu new file mode 100644 index 00000000..a5c22879 --- /dev/null +++ b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_kl.cu @@ -0,0 +1,70 @@ +#include "../mmq.cuh" + +template static __device__ __forceinline__ void load_tiles_iq2_kl( + const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { + +#ifdef INT8_MMA_AVAILABLE + int * x_qs = (int *) x_tile; + float * x_df = (float *) (x_qs + WARP_SIZE*2); +#else + constexpr tile_x_sizes txs = mmq_get_dp4a_tile_x_sizes(GGML_TYPE_IQ4_XS, mmq_y); + int * x_qs = (int *) x_tile; + float * x_df = (float *) (x_qs + txs.qs); +#endif // INT8_MMA_AVAILABLE + + const int kqsx = threadIdx.x/4; + + uint32_t aux32[2]; + const uint8_t * a8 = (const uint8_t *)aux32; + +#pragma unroll + for (int i0 = 0; i0 < mmq_y; i0 += 4*nwarps) { + int i = i0 + 4*threadIdx.y + threadIdx.x%4; + + if (need_check) { + i = min(i, i_max); + } + + const half * dptr = (const half *)(x + i*stride); + const float d = *dptr; + const block_iq2_kl * bxi = (const block_iq2_kl *)(dptr + 1) + kbx0; + + #pragma unroll + for (int j = 0; j < 2; ++j) { + auto ql = get_int_b2(bxi->qs, 4*(kqsx/2) + 2*(kqsx%2) + j); + auto qh = get_int_b2(bxi->qh, 2*(kqsx%2) + j) >> 2*(kqsx/2); + aux32[0] = ((ql >> 0) & 0x0f0f0f0f) | ((qh << 4) & 0x10101010); + aux32[1] = ((ql >> 4) & 0x0f0f0f0f) | ((qh << 3) & 0x10101010); + #pragma unroll + for (int l = 0; l < 2; ++l) { + int val1 = iq2kl_values[a8[2*l+0]] | (iq2kl_values[a8[2*l+1]] << 16); + int val2 = iq2kl_values[a8[2*l+4]] | (iq2kl_values[a8[2*l+5]] << 16); +#ifdef INT8_MMA_AVAILABLE + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 16*(kqsx/2) + 4*(kqsx%2) + 2*j + l + 0] = val1; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 16*(kqsx/2) + 4*(kqsx%2) + 2*j + l + 8] = val2; +#else + x_qs[i*(2*WARP_SIZE + 1) + 16*(kqsx/2) + 4*(kqsx%2) + 2*j + l + 0] = val1; + x_qs[i*(2*WARP_SIZE + 1) + 16*(kqsx/2) + 4*(kqsx%2) + 2*j + l + 8] = val2; +#endif + } + } + + int ls = int(((bxi->scales_l[kqsx%4] >> 4*(kqsx/4)) & 0xf) | (((bxi->scales_h >> 2*kqsx) & 3) << 4)) - 32; + +#ifdef INT8_MMA_AVAILABLE + x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + kqsx] = d * ls; +#else + x_df[i*(WARP_SIZE/4) + i/4 + kqsx] = d * ls; +#endif + } + +} + +template +struct mmq_type_traits { + static constexpr load_tiles_mmq_t load_tiles = load_tiles_iq2_kl; + static constexpr vec_dot_mmq_t vec_dot_mma = vec_dot_q8_0_q8_1_mma; + static constexpr vec_dot_mmq_t vec_dot_dp4a = vec_dot_q8_0_q8_1_dp4a; +}; + +DECL_MMQ_CASE(GGML_TYPE_IQ2_KL); diff --git a/ggml/src/ggml-metal.m b/ggml/src/ggml-metal.m index e1e49fcb..a86c66b6 100644 --- a/ggml/src/ggml-metal.m +++ b/ggml/src/ggml-metal.m @@ -112,6 +112,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_KSS, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_K, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_KS, + GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_KL, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ3_K, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_K, GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_K, @@ -159,6 +160,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MV_IQ5_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_KS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_KL_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ3_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_IQ5_K_F32, @@ -200,6 +202,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ5_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_KS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_KL_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ3_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ5_K_F32, @@ -238,6 +241,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KL_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_K_F32, @@ -276,6 +280,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_K_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KS_F16, + GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KL_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_K_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_K_F16, GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_K_F16, @@ -314,6 +319,7 @@ enum ggml_metal_kernel_type { GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_KS_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_KS_F32, + GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_KL_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ3_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_K_F32, GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_K_F32, @@ -768,6 +774,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_KS, get_rows_iq5_ks, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_K, get_rows_iq2_k, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_KS, get_rows_iq2_ks, true); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_KL, get_rows_iq2_kl, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ3_K, get_rows_iq3_k, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_K, get_rows_iq4_k, true); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_K, get_rows_iq5_k, true); @@ -815,6 +822,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ5_KS_F32, mul_mv_iq5_ks_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_K_F32, mul_mv_iq2_k_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_KS_F32, mul_mv_iq2_ks_f32, ctx->support_simdgroup_reduction); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_KL_F32, mul_mv_iq2_kl_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ3_K_F32, mul_mv_iq3_k_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ4_K_F32, mul_mv_iq4_k_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_IQ5_K_F32, mul_mv_iq5_k_f32, ctx->support_simdgroup_reduction); @@ -856,6 +864,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ5_KS_F32, mul_mv_id_iq5_ks_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_K_F32, mul_mv_id_iq2_k_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_KS_F32, mul_mv_id_iq2_ks_f32, ctx->support_simdgroup_reduction); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_KL_F32, mul_mv_id_iq2_kl_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ3_K_F32, mul_mv_id_iq3_k_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ4_K_F32, mul_mv_id_iq4_k_f32, ctx->support_simdgroup_reduction); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ5_K_F32, mul_mv_id_iq5_k_f32, ctx->support_simdgroup_reduction); @@ -894,6 +903,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F32, mul_mm_iq5_ks_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_K_F32, mul_mm_iq2_k_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KS_F32, mul_mm_iq2_ks_f32, ctx->support_simdgroup_mm); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KL_F32, mul_mm_iq2_kl_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_K_F32, mul_mm_iq3_k_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_K_F32, mul_mm_iq4_k_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_K_F32, mul_mm_iq5_k_f32, ctx->support_simdgroup_mm); @@ -932,6 +942,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F16, mul_mm_iq5_ks_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_K_F16, mul_mm_iq2_k_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KS_F16, mul_mm_iq2_ks_f16, ctx->support_simdgroup_mm); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KL_F16, mul_mm_iq2_kl_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_K_F16, mul_mm_iq3_k_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_K_F16, mul_mm_iq4_k_f16, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_K_F16, mul_mm_iq5_k_f16, ctx->support_simdgroup_mm); @@ -970,6 +981,7 @@ static struct ggml_backend_metal_context * ggml_metal_init(int n_cb) { GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_KS_F32, mul_mm_id_iq5_ks_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_K_F32, mul_mm_id_iq2_k_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_KS_F32, mul_mm_id_iq2_ks_f32, ctx->support_simdgroup_mm); + GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_KL_F32, mul_mm_id_iq2_kl_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ3_K_F32, mul_mm_id_iq3_k_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_K_F32, mul_mm_id_iq4_k_f32, ctx->support_simdgroup_mm); GGML_METAL_ADD_KERNEL(GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_K_F32, mul_mm_id_iq5_k_f32, ctx->support_simdgroup_mm); @@ -2187,6 +2199,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F32 ].pipeline; break; case GGML_TYPE_IQ2_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_K_F32 ].pipeline; break; case GGML_TYPE_IQ2_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KS_F32 ].pipeline; break; + case GGML_TYPE_IQ2_KL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KL_F32 ].pipeline; break; case GGML_TYPE_IQ3_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_K_F32 ].pipeline; break; case GGML_TYPE_IQ4_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_K_F32 ].pipeline; break; case GGML_TYPE_IQ5_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_K_F32 ].pipeline; break; @@ -2230,6 +2243,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_KS_F16 ].pipeline; break; case GGML_TYPE_IQ2_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_K_F16 ].pipeline; break; case GGML_TYPE_IQ2_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KS_F16 ].pipeline; break; + case GGML_TYPE_IQ2_KL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ2_KL_F16 ].pipeline; break; case GGML_TYPE_IQ3_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ3_K_F16 ].pipeline; break; case GGML_TYPE_IQ4_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ4_K_F16 ].pipeline; break; case GGML_TYPE_IQ5_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_IQ5_K_F16 ].pipeline; break; @@ -2478,6 +2492,12 @@ static void ggml_metal_encode_node( nth1 = 16; pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_KS_F32].pipeline; } break; + case GGML_TYPE_IQ2_KL: + { + nth0 = 4; + nth1 = 16; + pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_IQ2_KL_F32].pipeline; + } break; case GGML_TYPE_IQ3_K: { nth0 = 4; @@ -2555,8 +2575,10 @@ static void ggml_metal_encode_node( src0t == GGML_TYPE_IQ2_KT|| src0t == GGML_TYPE_IQ3_KT) { //|| src0t == GGML_TYPE_IQ4_KT) { [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, ne11, ne12*ne13) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; } - else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS) { - const int mem_size = src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) + else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS || + src0t == GGML_TYPE_IQ2_KL) { + const int mem_size = src0t == GGML_TYPE_IQ2_KL ? 128*sizeof(float) + : src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) : src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS ? 32*sizeof(float) : 16*sizeof(float); [encoder setThreadgroupMemoryLength:mem_size atIndex:0]; [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, ne11, ne12*ne13) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; @@ -2675,6 +2697,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_KS_F32 ].pipeline; break; case GGML_TYPE_IQ2_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_K_F32 ].pipeline; break; case GGML_TYPE_IQ2_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_KS_F32 ].pipeline; break; + case GGML_TYPE_IQ2_KL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ2_KL_F32 ].pipeline; break; case GGML_TYPE_IQ3_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ3_K_F32 ].pipeline; break; case GGML_TYPE_IQ4_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ4_K_F32 ].pipeline; break; case GGML_TYPE_IQ5_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MM_ID_IQ5_K_F32 ].pipeline; break; @@ -2907,6 +2930,12 @@ static void ggml_metal_encode_node( nth1 = 16; pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_KS_F32].pipeline; } break; + case GGML_TYPE_IQ2_KL: + { + nth0 = 4; + nth1 = 16; + pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_MUL_MV_ID_IQ2_KL_F32].pipeline; + } break; case GGML_TYPE_IQ3_K: { nth0 = 4; @@ -2995,8 +3024,10 @@ static void ggml_metal_encode_node( src0t == GGML_TYPE_IQ2_KT|| src0t == GGML_TYPE_IQ3_KT) { //|| src0t == GGML_TYPE_IQ4_KT) { [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, _ne1, tgz) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; } - else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS) { - const int mem_size = src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) + else if (src0t == GGML_TYPE_IQ2_KS || src0t == GGML_TYPE_IQ2_K || src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS || + src0t == GGML_TYPE_IQ2_KL) { + const int mem_size = src0t == GGML_TYPE_IQ2_KL ? 128*sizeof(float) + : src0t == GGML_TYPE_IQ2_KS ? 64*sizeof(float) : src0t == GGML_TYPE_IQ3_K || src0t == GGML_TYPE_IQ3_KS ? 32*sizeof(float) : 16*sizeof(float); [encoder setThreadgroupMemoryLength:mem_size atIndex:0]; [encoder dispatchThreadgroups:MTLSizeMake((ne01 + 7)/8, _ne1, tgz) threadsPerThreadgroup:MTLSizeMake(nth0, nth1, 1)]; @@ -3071,6 +3102,7 @@ static void ggml_metal_encode_node( case GGML_TYPE_IQ5_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_KS ].pipeline; break; case GGML_TYPE_IQ2_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_K ].pipeline; break; case GGML_TYPE_IQ2_KS: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_KS ].pipeline; break; + case GGML_TYPE_IQ2_KL: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ2_KL ].pipeline; break; case GGML_TYPE_IQ3_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ3_K ].pipeline; break; case GGML_TYPE_IQ4_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ4_K ].pipeline; break; case GGML_TYPE_IQ5_K: pipeline = ctx->kernels[GGML_METAL_KERNEL_TYPE_GET_ROWS_IQ5_K ].pipeline; break; diff --git a/ggml/src/ggml-metal.metal b/ggml/src/ggml-metal.metal index baaac407..53de59dd 100644 --- a/ggml/src/ggml-metal.metal +++ b/ggml/src/ggml-metal.metal @@ -4002,6 +4002,13 @@ constexpr constant static half kvalues_iq2k_h[8] = { -31.h, -13.h, 1.h, 17.h, - constexpr constant static float kvalues_iq3k_f[16] = { -63.f, -40.f, -23.f, -10.f, 1.f, 13.f, 28.f, 47.f, -59.f, -36.f, -19.f, -6.f, 5.f, 17.f, 32.f, 51.f }; constexpr constant static half kvalues_iq3k_h[16] = { -63.h, -40.h, -23.h, -10.h, 1.h, 13.h, 28.h, 47.h, -59.h, -36.h, -19.h, -6.h, 5.h, 17.h, 32.h, 51.h }; +constexpr constant static half2 kvalues_iq2kl_h[32] = { + {-63.h, -23.h}, {-63.h, 13.h}, {-40.h, -63.h}, {-40.h, -10.h}, {-40.h, 13.h}, {-40.h, 47.h}, {-23.h, -40.h}, {-23.h, -23.h}, + {-23.h, 1.h}, {-23.h, 13.h}, {-23.h, 28.h}, {-10.h, -63.h}, {-10.h, 1.h}, {-10.h, 13.h}, {-10.h, 47.h}, {1.h, -23.h}, {1.h, -10.h}, + {1.h, 1.h}, {1.h, 13.h}, {1.h, 28.h}, {13.h, -40.h}, {13.h, -23.h}, {13.h, -10.h}, {13.h, 1.h}, {13.h, 13.h}, {28.h, -63.h}, + {28.h, -23.h}, {28.h, 1.h}, {28.h, 28.h}, {28.h, 47.h}, {47.h, -23.h}, {47.h, 13.h}, +}; + kernel void kernel_cpy_f32_iq4_nl( device const float * src0, device void * dst, @@ -7231,6 +7238,152 @@ kernel void kernel_mul_mv_iq2_ks_f32( kernel_mul_mv_iq2_ks_f32_impl(src0, src1, dst, ne00, ne01, ne02, ne10, ne12, ne0, ne1, r2, r3, shared_values, tgpig, tiisg, sgitg); } +void kernel_mul_mv_iq2_kl_f32_impl( + device const void * src0, + device const float * src1, + device float * dst, + int64_t ne00, + int64_t ne01, + int64_t ne02, + int64_t ne10, + int64_t ne12, + int64_t ne0, + int64_t ne1, + uint r2, + uint r3, + threadgroup int8_t * shared_values, + uint3 tgpig, + uint tiisg, + uint sgitg) { + + const int nb = ne00/QK_K; + const int r0 = tgpig.x; + const int r1 = tgpig.y; + const int im = tgpig.z; + + const int first_row = (r0 * N_SIMDGROUP + sgitg) * N_DST; + const uint row_size = 2 + nb*sizeof(block_iq2_kl); + + const uint i12 = im%ne12; + const uint i13 = im/ne12; + + const uint offset0 = (i12/r2)*(ne01) + (i13/r3)*(ne01*ne02); + + device const char * cx0 = (device const char *) src0 + (first_row + offset0)*row_size; + device const float * y = (device const float *) src1 + r1*ne10 + im*ne00*ne1; + + float2 yl[16]; + float sumf[N_DST]={0.f}; + float drow[N_DST]; + + const int ix = tiisg/8; // 0...3 + const int it = tiisg%8; // 0...7 + const int iq = it/2; // 0...3 + const int ir = it%2; // 0 or 1 + + device const float * y4 = y + ix * QK_K + 64 * iq + 16 * ir; + + uint16_t aux16[2]; + thread const uint8_t * aux8 = (thread const uint8_t *)&aux16; + + device const char * cx = cx0; + for (int row = 0; row < N_DST; row++) { + device const half * dptr = (device const half *)cx; + drow[row] = dptr[0]; + cx += row_size; + } + + threadgroup float2 * all_values = (threadgroup float2 *)shared_values + 32*sgitg; + { + constant const int8_t * val = (constant const int8_t *)iq2kl_values; + all_values[tiisg][0] = val[2*tiisg + 0]; + all_values[tiisg][1] = val[2*tiisg + 1]; + simdgroup_barrier(mem_flags::mem_none); + } + + cx0 += sizeof(half); + + for (int ib = ix; ib < nb; ib += 4) { + + device const float2 * y2 = (device const float2 *)y4; + for (int i = 0; i < 8; ++i) { + yl[i+0] = y2[i+ 0]; + yl[i+8] = y2[i+16]; + } + + device const char * cx = cx0; + + for (int row = 0; row < N_DST; row++) { + + device const block_iq2_kl * x = (device const block_iq2_kl *)cx + ib; + + uint16_t h = x->scales_h >> 4*iq; + int8_t ls1 = int8_t(((x->scales_l[(2*iq+0)%4] >> 4*((2*iq+0)/4)) & 0xf) | ((h & 0x03) << 4)) - 32; + int8_t ls2 = int8_t(((x->scales_l[(2*iq+1)%4] >> 4*((2*iq+1)/4)) & 0xf) | ((h & 0x0c) << 2)) - 32; + + device const uint16_t * ql = (device const uint16_t *)x->qs + 8*iq + 4*ir; + device const uint16_t * qh = (device const uint16_t *)x->qh + 4*ir; + + float2 acc[2] = {0.f}; + for (int l = 0; l < 4; ++l) { + uint16_t h = qh[l] >> 2*iq; + aux16[0] = ((ql[l] >> 0) & 0x0f0f) | ((h & 0x0101) << 4); + aux16[1] = ((ql[l] >> 4) & 0x0f0f) | ((h & 0x0202) << 3); + for (int j = 0; j < 2; ++j) { + threadgroup const float2 & val1 = all_values[aux8[j+0]]; + threadgroup const float2 & val2 = all_values[aux8[j+2]]; + acc[0] += yl[2*l+j+0] * val1; + acc[1] += yl[2*l+j+8] * val2; + } + + } + sumf[row] += drow[row] * ((acc[0][0] + acc[0][1]) * ls1 + (acc[1][0] + acc[1][1]) * ls2); + + cx += row_size; + + } + + y4 += 4 * QK_K; + } + + for (int row = 0; row < N_DST; row += 2) { + float2 tmp = {sumf[row], sumf[row+1]}; + tmp = simd_sum(tmp); + if (tiisg < 2) { + dst[r1*ne0 + im*ne0*ne1 + first_row + row + tiisg] = tmp[tiisg]; + } + } +} + +[[host_name("kernel_mul_mv_iq2_kl_f32")]] +kernel void kernel_mul_mv_iq2_kl_f32( + device const void * src0, + device const float * 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 int64_t & ne12, + constant uint64_t & nb10, + constant uint64_t & nb11, + constant uint64_t & nb12, + constant int64_t & ne0, + constant int64_t & ne1, + constant uint & r2, + constant uint & r3, + threadgroup int8_t * shared_values [[threadgroup(0)]], + uint3 tgpig[[threadgroup_position_in_grid]], + uint tiisg[[thread_index_in_simdgroup]], + uint sgitg[[simdgroup_index_in_threadgroup]]) { + + kernel_mul_mv_iq2_kl_f32_impl(src0, src1, dst, ne00, ne01, ne02, ne10, ne12, ne0, ne1, r2, r3, shared_values, tgpig, tiisg, sgitg); +} + void kernel_mul_mv_iq3_k_f32_impl( device const void * src0, device const float * src1, @@ -8820,6 +8973,31 @@ void dequantize_iq2_ks(device const block_iq2_ks * xb, short il, thread type4x4 } } +template +void dequantize_iq2_kl(device const block_iq2_kl * xb, short il, thread type4x4 & reg) { + // il is 0...15 for QK_K = 256 + const short ib32 = il/2; + device const uint16_t * ql = (device const uint16_t * )xb->qs + 8*(ib32/2) + 4*(il%2); + device const uint16_t * qh = (device const uint16_t * )xb->qh + 4*(il%2); + + half d = (int16_t(((xb->scales_l[ib32%4] >> 4*(ib32/4)) & 0xf) | (((xb->scales_h >> 2*ib32) & 0x3) << 4)) - 32); + + uint32_t aux32[2]; + thread const uint8_t * aux8 = (thread const uint8_t *)aux32; + + aux32[0] = (((ql[0] | (ql[1] << 16)) >> 4*(ib32%2)) & 0x0f0f0f0f) | ((((qh[0] | (qh[1] << 16)) >> ib32) & 0x01010101) << 4); + aux32[1] = (((ql[2] | (ql[3] << 16)) >> 4*(ib32%2)) & 0x0f0f0f0f) | ((((qh[2] | (qh[3] << 16)) >> ib32) & 0x01010101) << 4); + + for (int i = 0; i < 4; ++i) { + constant const half2 & val1 = *(constant const half2 *)(kvalues_iq2kl_h + aux8[2*i+0]); + constant const half2 & val2 = *(constant const half2 *)(kvalues_iq2kl_h + aux8[2*i+1]); + reg[i][0] = d * val1[0]; + reg[i][1] = d * val1[1]; + reg[i][2] = d * val2[0]; + reg[i][3] = d * val2[1]; + } +} + template void dequantize_iq3_k(device const block_iq3_k * xb, short il, thread type4x4 & reg) { // il is 0...15 for QK_K = 256 @@ -9596,6 +9774,7 @@ template [[host_name("kernel_get_rows_iq4_ks")]] kernel get_rows_q_t kernel_get template [[host_name("kernel_get_rows_iq5_ks")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq4_kss")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq2_ks")]] kernel get_rows_q_t kernel_get_rows_q2>; +template [[host_name("kernel_get_rows_iq2_kl")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq2_kt")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq3_kt")]] kernel get_rows_q_t kernel_get_rows_q2>; template [[host_name("kernel_get_rows_iq4_kt")]] kernel get_rows_q_t kernel_get_rows_q2>; @@ -9644,6 +9823,7 @@ template [[host_name("kernel_mul_mm_iq4_ks_f32")]] kernel mat_mm_t kernel_mul_m template [[host_name("kernel_mul_mm_iq5_ks_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq4_kss_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq2_ks_f32")]] kernel mat_mm_t kernel_mul_mm, float>; +template [[host_name("kernel_mul_mm_iq2_kl_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq2_kt_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq3_kt_f32")]] kernel mat_mm_t kernel_mul_mm, float>; template [[host_name("kernel_mul_mm_iq4_kt_f32")]] kernel mat_mm_t kernel_mul_mm, float>; @@ -9683,6 +9863,7 @@ template [[host_name("kernel_mul_mm_iq4_ks_f16")]] kernel mat_mm_t kernel_mul_m template [[host_name("kernel_mul_mm_iq5_ks_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq4_kss_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq2_ks_f16")]] kernel mat_mm_t kernel_mul_mm, half>; +template [[host_name("kernel_mul_mm_iq2_kl_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq2_kt_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq3_kt_f16")]] kernel mat_mm_t kernel_mul_mm, half>; template [[host_name("kernel_mul_mm_iq4_kt_f16")]] kernel mat_mm_t kernel_mul_mm, half>; @@ -9729,6 +9910,7 @@ template [[host_name("kernel_mul_mm_id_iq4_ks_f32")]] kernel mat_mm_id_t kernel template [[host_name("kernel_mul_mm_id_iq5_ks_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq4_kss_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq2_ks_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; +template [[host_name("kernel_mul_mm_id_iq2_kl_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq2_kt_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq3_kt_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; template [[host_name("kernel_mul_mm_id_iq4_kt_f32")]] kernel mat_mm_id_t kernel_mul_mm_id>; @@ -9951,6 +10133,7 @@ template [[host_name("kernel_mul_mv_id_iq5_ks_f32")]] kernel kernel_mul_mv_id_t template [[host_name("kernel_mul_mv_id_iq4_kss_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq2_k_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq2_ks_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; +template [[host_name("kernel_mul_mv_id_iq2_kl_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq2_kt_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq3_kt_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; template [[host_name("kernel_mul_mv_id_iq4_kt_f32")]] kernel kernel_mul_mv_id_t kernel_mul_mv_id>; diff --git a/ggml/src/ggml-quants.c b/ggml/src/ggml-quants.c index 96242727..e18cee73 100644 --- a/ggml/src/ggml-quants.c +++ b/ggml/src/ggml-quants.c @@ -15426,6 +15426,7 @@ bool ggml_validate_row_data(enum ggml_type type, const void * data, size_t nbyte case GGML_TYPE_IQ4_KT: break; case GGML_TYPE_IQ3_K: break; case GGML_TYPE_IQ3_KS: break; + case GGML_TYPE_IQ2_KL: break; case GGML_TYPE_IQ4_K: break; case GGML_TYPE_IQ5_K: break; case GGML_TYPE_IQ6_K: break; diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index 2e6983df..dbb080f8 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -1669,6 +1669,19 @@ static const ggml_type_traits_t type_traits[GGML_TYPE_COUNT] = { .nrows = 1, .row_meta_size = 2, }, + [GGML_TYPE_IQ2_KL] = { + .type_name = "iq2_kl", + .blck_size = QK_K, + .type_size = sizeof(block_iq2_kl), + .is_quantized = true, + .to_float = (ggml_to_float_t) dequantize_row_iq2_kl, + .from_float = quantize_row_iq2_kl, + .from_float_ref = (ggml_from_float_t)quantize_row_iq2_kl_ref, + .vec_dot = vec_dot_iq2_kl_q8_k, + .vec_dot_type = GGML_TYPE_Q8_K, + .nrows = 1, + .row_meta_size = 2, + }, [GGML_TYPE_IQ4_K] = { .type_name = "iq4_k", .blck_size = QK_K, @@ -4592,6 +4605,7 @@ enum ggml_type ggml_ftype_to_ggml_type(enum ggml_ftype ftype) { case GGML_FTYPE_MOSTLY_IQ4_KT: wtype = GGML_TYPE_IQ4_KT; break; case GGML_FTYPE_MOSTLY_IQ3_K: wtype = GGML_TYPE_IQ3_K; break; case GGML_FTYPE_MOSTLY_IQ3_KS: wtype = GGML_TYPE_IQ3_KS; break; + case GGML_FTYPE_MOSTLY_IQ2_KL: wtype = GGML_TYPE_IQ2_KL; break; case GGML_FTYPE_MOSTLY_IQ4_K: wtype = GGML_TYPE_IQ4_K; break; case GGML_FTYPE_MOSTLY_IQ3_K_R4: wtype = GGML_TYPE_IQ3_K_R4; break; case GGML_FTYPE_MOSTLY_IQ4_K_R4: wtype = GGML_TYPE_IQ4_K_R4; break; @@ -11362,6 +11376,7 @@ static void ggml_compute_forward_add( case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_KS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -11840,6 +11855,7 @@ static void ggml_compute_forward_add1( case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_KS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -12015,6 +12031,7 @@ static void ggml_compute_forward_acc( case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_KS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -15517,6 +15534,7 @@ static void ggml_compute_forward_out_prod( case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_KS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -15932,6 +15950,7 @@ static void ggml_compute_forward_set( case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_KS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -16253,6 +16272,7 @@ static void ggml_compute_forward_get_rows( case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_KS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -16891,6 +16911,7 @@ static void ggml_compute_forward_clamp( case GGML_TYPE_IQ4_KT: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_KS: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ4_K: case GGML_TYPE_IQ3_K_R4: case GGML_TYPE_IQ4_K_R4: @@ -23965,6 +23986,7 @@ size_t ggml_quantize_chunk( case GGML_TYPE_IQ4_KT: result = quantize_iq4_kt (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ3_K: result = quantize_iq3_k (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ3_KS: result = quantize_iq3_ks (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; + case GGML_TYPE_IQ2_KL: result = quantize_iq2_kl (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ4_K: result = quantize_iq4_k (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ3_K_R4:result = quantize_iq3_k_r4(src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ4_K_R4:result = quantize_iq4_k_r4(src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; diff --git a/ggml/src/iqk/iqk_gemm_iqk_quants.cpp b/ggml/src/iqk/iqk_gemm_iqk_quants.cpp index 57038d0c..ba2fa235 100644 --- a/ggml/src/iqk/iqk_gemm_iqk_quants.cpp +++ b/ggml/src/iqk/iqk_gemm_iqk_quants.cpp @@ -337,6 +337,97 @@ struct DequantizerIQ4KSS final : public BaseDequantizer { }; }; +struct DequantizerIQ2KL final : public BaseDequantizer { + DequantizerIQ2KL(const void * vx, size_t bx) : BaseDequantizer(vx, bx) { load_values(); } + inline __m128i make_scales(int i) const { + uint32_t aux32; std::memcpy(&aux32, x[i].scales_l, 4); + auto scl = _mm_cvtepu8_epi16(_mm_and_si128(_mm_srlv_epi32(_mm_set1_epi32(aux32), _mm_set_epi32(0, 0, 4, 0)), _mm_set1_epi8(0xf))); + auto sch = _mm_srlv_epi16(_mm_sllv_epi64(_mm_set1_epi16(x[i].scales_h), _mm_set_epi64x(0, 8)), _mm_set1_epi64x(0x000a000800060004)); + auto scales128 = _mm_sub_epi16(_mm_or_si128(scl, _mm_and_si128(sch, _mm_set1_epi16(0x30))), _mm_set1_epi16(32)); + return scales128; + } + template + inline void compute_block(int i, const Q8& q8, __m512 * acc) { + auto scales128 = make_scales(i); + auto mins128 = _mm_mullo_epi16(scales128, _mm_set1_epi16(-64)); + auto mins = MM256_SET_M128I(_mm_shuffle_epi8(mins128, s8k.shuffles[1]), _mm_shuffle_epi8(mins128, s8k.shuffles[0])); + auto scales256 = MM256_SET_M128I(scales128, scales128); + auto all_scales = _mm512_inserti32x8(_mm512_castsi256_si512(scales256), scales256, 1); + __m512i scales[4]; + for (int k = 0; k < 4; ++k) scales[k] = _mm512_shuffle_epi8(all_scales, shuffles[k]); + prepare(i); + for (int iy = 0; iy < Q8::nrc_y; ++iy) { + auto q8s = q8.load_bsums(iy, i); + auto prod = _mm256_madd_epi16(mins, q8s); + auto sumi = _mm512_inserti32x8(_mm512_setzero_si512(), prod, 0); + for (int k = 0; k < 4; ++k) { + auto p = _mm512_maddubs_epi16(bits.values[k], q8.load_quants64(iy, i, k)); + sumi = _mm512_dpwssd_epi32(sumi, p, scales[k]); + } + acc[iy] = _mm512_fmadd_ps(_mm512_set1_ps(d*q8.scale(iy, i)), _mm512_cvtepi32_ps(sumi), acc[iy]); + } + } + inline void prepare(int i) { + __m512i ql[2], qs[4]; + __mmask64 mask[2]; + auto lbits = _mm512_loadu_si512((const __m512i *)x[i].qs); + ql[0] = _mm512_and_si512(lbits, m4); + ql[1] = _mm512_and_si512(_mm512_srli_epi16(lbits, 4), m4); + auto tmp = _mm512_permutex2var_epi64(ql[0], permute1, ql[1]); + ql[1] = _mm512_permutex2var_epi64(ql[0], permute2, ql[1]); + ql[0] = tmp; + auto h128 = _mm_loadu_si128((const __m128i *)x[i].qh); + auto h256 = MM256_SET_M128I(_mm_srli_epi16(h128, 1), h128); + auto h512 = _mm512_inserti32x8(_mm512_castsi256_si512(h256), _mm256_srli_epi16(h256, 2), 1); + mask[0] = _mm512_cmpeq_epi8_mask(_mm512_and_si512(h512, m01), m01); + mask[1] = _mm512_cmpeq_epi8_mask(_mm512_and_si512(h512, m10), m10); + + for (int k = 0; k < 2; ++k) { + // qs[0]: even quants when hbits is not set (so pair index is in 0...15) + // qs[1]: even quants when hbits is set (so pair index is in 16...31) + // qs[2]: odd quants when hbits is not set (so pair index is in 0...15) + // qs[3]: odd quants when hbits is set (so pair index is in 16...31) + // if we blend qs[0] and qs[1] with the hbit mask, we get the correct even quants -> q1 + // if we blend qs[2] and qs[3] with the hbit mask, we get the correct odd quants -> q2 + // If we convert q1 and q2 to int16_t, shift q2 left by 8 bits, and or them, we get the quants in the correct order + for (int l = 0; l < 4; ++l) qs[l] = _mm512_shuffle_epi8(values[l], ql[k]); + auto q1 = _mm512_mask_blend_epi8(mask[k], qs[0], qs[1]); + auto q2 = _mm512_mask_blend_epi8(mask[k], qs[2], qs[3]); + auto t1 = _mm512_unpacklo_epi8(q1, q2); // 0...15, 32...47, 64...79, 96...111 + auto t2 = _mm512_unpackhi_epi8(q1, q2); // 16...31, 48...63, 80...95, 112...127 + bits.values[2*k+0] = _mm512_permutex2var_epi64(t1, permute1, t2); + bits.values[2*k+1] = _mm512_permutex2var_epi64(t1, permute2, t2); + } + } + void load_values() { + static const uint8_t k_values[64] = { + 1, 1, 24, 24, 24, 24, 41, 41, 41, 41, 41, 54, 54, 54, 54, 65, 65, 65, 65, 65, 77, 77, 77, 77, 77, 92, 92, 92, 92, 92, 111, 111, + 41, 77, 1, 54, 77, 111, 24, 41, 65, 77, 92, 1, 65, 77, 111, 41, 54, 65, 77, 92, 24, 41, 54, 65, 77, 1, 41, 65, 92, 111, 41, 77, + }; + for (int k = 0; k < 4; ++k) { + auto v128 = _mm_loadu_si128((const __m128i *)k_values + k); + auto v256 = MM256_SET_M128I(v128, v128); + values[k] = _mm512_inserti32x8(_mm512_castsi256_si512(v256), v256, 1); + } + } + + struct { __m512i values[4]; } bits; + Scales8KBase s8k; + const __m512i m01 = _mm512_set1_epi8(0x01); + const __m512i m10 = _mm512_set1_epi8(0x10); + const __m512i m4 = _mm512_set1_epi8(0xf); + const __m512i permute1 = _mm512_set_epi64(11, 10, 3, 2, 9, 8, 1, 0); + const __m512i permute2 = _mm512_set_epi64(15, 14, 7, 6, 13, 12, 5, 4); + __m512i values[4]; + const __m512i shuffles[4] = { + _mm512_inserti32x8(_mm512_set1_epi16(0x0100), _mm256_set1_epi16(0x0302), 1), + _mm512_inserti32x8(_mm512_set1_epi16(0x0504), _mm256_set1_epi16(0x0706), 1), + _mm512_inserti32x8(_mm512_set1_epi16(0x0908), _mm256_set1_epi16(0x0b0a), 1), + _mm512_inserti32x8(_mm512_set1_epi16(0x0d0c), _mm256_set1_epi16(0x0f0e), 1), + }; +}; + + struct DequantizerIQ4KS final : public BaseDequantizer { DequantizerIQ4KS(const void * vx, size_t bx) : BaseDequantizer(vx, bx), values(load_iq4nl_values_512()) {} template @@ -908,6 +999,68 @@ struct DequantizerIQ2KS final : public BaseDequantizer const __m128i shift = _mm_set_epi32(0, 0, 4, 0); }; +struct DequantizerIQ2KL final : public BaseDequantizer { + DequantizerIQ2KL(const void * vx, size_t bx) : BaseDequantizer(vx, bx) { load_values(); } + template + inline __m256i new_block(int i, const Q8& q8, __m256 * accm) { + auto hbits128 = _mm_loadu_si128((const __m128i *)x[i].qh); + hbits = MM256_SET_M128I(_mm_srli_epi16(hbits128, 1), hbits128); + auto scales128 = make_scales(i); + auto scales_s = _mm_mullo_epi16(scales128, _mm_set1_epi16(-64)); + s8k.accum_mins(scales_s, q8, i, d, accm); + return MM256_SET_M128I(scales128, scales128); + } + inline void prepare(int i, int j) { + __m256i ql[2], mask[2]; + auto b1 = _mm_loadu_si128((const __m128i *)x[i].qs+2*j+0); + auto b2 = _mm_loadu_si128((const __m128i *)x[i].qs+2*j+1); + ql[0] = _mm256_and_si256(_mm256_set1_epi8(0xf), MM256_SET_M128I(_mm_srli_epi16(b1, 4), b1)); + ql[1] = _mm256_and_si256(_mm256_set1_epi8(0xf), MM256_SET_M128I(_mm_srli_epi16(b2, 4), b2)); + mask[0] = _mm256_cmpeq_epi8(_mm256_and_si256(hbits, _mm256_set1_epi8(0x1)), _mm256_set1_epi8(0x1)); + mask[1] = _mm256_cmpeq_epi8(_mm256_and_si256(hbits, _mm256_set1_epi8(0x4)), _mm256_set1_epi8(0x4)); + for (int k = 0; k < 2; ++k) { + auto v0 = _mm256_shuffle_epi8(values[0], ql[k]); + auto v1 = _mm256_shuffle_epi8(values[1], ql[k]); + auto v2 = _mm256_shuffle_epi8(values[2], ql[k]); + auto v3 = _mm256_shuffle_epi8(values[3], ql[k]); + auto q1 = _mm256_or_si256(_mm256_and_si256(mask[k], v1), _mm256_andnot_si256(mask[k], v0)); + auto q2 = _mm256_or_si256(_mm256_and_si256(mask[k], v3), _mm256_andnot_si256(mask[k], v2)); + auto q1l = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(q1)); + auto q1h = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(q1, 1)); + auto q2l = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(q2)); + auto q2h = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(q2, 1)); + bits.values[2*k+0] = _mm256_or_si256(q1l, _mm256_slli_epi16(q2l, 8)); + bits.values[2*k+1] = _mm256_or_si256(q1h, _mm256_slli_epi16(q2h, 8)); + } + hbits = _mm256_srli_epi16(hbits, 4); + } + inline __m128i make_scales(int i) const { + uint32_t aux32; std::memcpy(&aux32, x[i].scales_l, 4); + auto scl = _mm_cvtepu8_epi16(_mm_and_si128(_mm_srlv_epi32(_mm_set1_epi32(aux32), shift), _mm_set1_epi8(0xf))); + auto sch = _mm_srlv_epi32(_mm_set1_epi16(x[i].scales_h), _mm_set_epi32(12, 8, 4, 0)); + sch = _mm_and_si128(sch, _mm_set1_epi32(0x000c0003)); + sch = _mm_mullo_epi16(sch, _mm_set1_epi32(0x00040010)); + auto scales128 = _mm_sub_epi16(_mm_or_si128(scl, sch), _mm_set1_epi16(32)); + return scales128; + } + void load_values() { + static const uint8_t k_values[64] = { + 1, 1, 24, 24, 24, 24, 41, 41, 41, 41, 41, 54, 54, 54, 54, 65, 65, 65, 65, 65, 77, 77, 77, 77, 77, 92, 92, 92, 92, 92, 111, 111, + 41, 77, 1, 54, 77, 111, 24, 41, 65, 77, 92, 1, 65, 77, 111, 41, 54, 65, 77, 92, 24, 41, 54, 65, 77, 1, 41, 65, 92, 111, 41, 77, + }; + for (int k = 0; k < 4; ++k) { + auto v128 = _mm_loadu_si128((const __m128i *)k_values + k); + values[k] = MM256_SET_M128I(v128, v128); + } + } + struct { __m256i values[4]; } bits; + Scales8KBase s8k; + + __m256i values[4]; + __m256i hbits; + const __m128i shift = _mm_set_epi32(0, 0, 4, 0); +}; + struct DequantizerIQ2K final : public BaseDequantizer { DequantizerIQ2K(const void * vx, size_t bx) : BaseDequantizer(vx, bx), iqxk(5, -32), values(load_values()) {} template @@ -2127,6 +2280,7 @@ static void mul_mat_iq5_ks_r4_q8_k(int n, const void * vx, size_t bx, const Data template void set_functions(std::array& funcs) { #ifdef HAVE_FANCY_SIMD if constexpr (std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) { @@ -2267,6 +2421,94 @@ void iqk_convert_iq2_ks_q8_k_r8(int n, const void * vx, size_t bx, void * vy, in } } +void iqk_convert_iq2_kl_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { + GGML_ASSERT(n%QK_K == 0); + GGML_ASSERT(nrc_x%8 == 0); + + int nb = n/QK_K; + + const block_iq2_kl * x8[8]; + + block_q8_k_r8 * y = (block_q8_k_r8 *)vy; + + __m256i values[4]; + { + static const int8_t k_values[64] = { + -63, -63, -40, -40, -40, -40, -23, -23, -23, -23, -23, -10, -10, -10, -10, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 28, 28, 28, 28, 28, 47, 47, + -23, 13, -63, -10, 13, 47, -40, -23, 1, 13, 28, -63, 1, 13, 47, -23, -10, 1, 13, 28, -40, -23, -10, 1, 13, -63, -23, 1, 28, 47, -23, 13, + }; + for (int k = 0; k < 4; ++k) { + auto v = _mm_loadu_si128((const __m128i *)k_values + k); + values[k] = MM256_SET_M128I(v, v); + } + } + + ggml_half dh[8]; + float dnew[8]; + uint32_t block[8]; + int16_t ls[16]; + + __m256i xv[8]; + __m256i ql[2]; + __m256i mask[2]; + + uint32_t sl32; + const auto sl8 = (const int8_t *)&sl32; + + for (int ix = 0; ix < nrc_x; ix += 8) { + for (int k = 0; k < 8; ++k) { + const ggml_half * dptr = (const ggml_half *)((const char *)vx + (ix+k)*bx); + dh[k] = dptr[0]; + x8[k] = (const block_iq2_kl *)(dptr + 1); + } + for (int i = 0; i < nb; ++i) { + for (int k = 0; k < 8; ++k) { + uint32_t aux32; + std::memcpy(&aux32, x8[k][i].scales_l, 4); + auto sh = x8[k][i].scales_h; + auto hbits128 = _mm_loadu_si128((const __m128i *)x8[k][i].qh); + auto hbits = MM256_SET_M128I(_mm_srli_epi16(hbits128, 1), hbits128); + //auto sl = _mm_and_si128(_mm_cvtepu8_epi16(_mm_srlv_epi32(_mm_set1_epi32(aux32), _mm_set_epi32(0, 0, 4, 0))), _mm_set1_epi16(0xf)); + for (int i128 = 0; i128 < 2; ++i128) { + sl32 = aux32 & 0x0f0f0f0f; + ls[8*i128+0] = ls[8*i128+1] = (sl8[0] | ((sh << 4) & 0x30)) - 32; + ls[8*i128+2] = ls[8*i128+3] = (sl8[1] | ((sh << 2) & 0x30)) - 32; + ls[8*i128+4] = ls[8*i128+5] = (sl8[2] | ((sh >> 0) & 0x30)) - 32; + ls[8*i128+6] = ls[8*i128+7] = (sl8[3] | ((sh >> 2) & 0x30)) - 32; + aux32 >>= 4; sh >>= 8; + { + auto b1 = _mm_loadu_si128((const __m128i *)x8[k][i].qs+2*i128+0); + auto b2 = _mm_loadu_si128((const __m128i *)x8[k][i].qs+2*i128+1); + ql[0] = _mm256_and_si256(_mm256_set1_epi8(0xf), MM256_SET_M128I(_mm_srli_epi16(b1, 4), b1)); + ql[1] = _mm256_and_si256(_mm256_set1_epi8(0xf), MM256_SET_M128I(_mm_srli_epi16(b2, 4), b2)); + } + mask[0] = _mm256_cmpeq_epi8(_mm256_and_si256(hbits, _mm256_set1_epi8(0x1)), _mm256_set1_epi8(0x1)); + mask[1] = _mm256_cmpeq_epi8(_mm256_and_si256(hbits, _mm256_set1_epi8(0x4)), _mm256_set1_epi8(0x4)); + for (int k = 0; k < 2; ++k) { + auto v0 = _mm256_shuffle_epi8(values[0], ql[k]); + auto v1 = _mm256_shuffle_epi8(values[1], ql[k]); + auto v2 = _mm256_shuffle_epi8(values[2], ql[k]); + auto v3 = _mm256_shuffle_epi8(values[3], ql[k]); + auto q1 = _mm256_or_si256(_mm256_and_si256(mask[k], v1), _mm256_andnot_si256(mask[k], v0)); + auto q2 = _mm256_or_si256(_mm256_and_si256(mask[k], v3), _mm256_andnot_si256(mask[k], v2)); + auto q1l = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(q1)); + auto q1h = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(q1, 1)); + auto q2l = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(q2)); + auto q2h = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(q2, 1)); + xv[4*i128+2*k+0] = _mm256_or_si256(q1l, _mm256_slli_epi16(q2l, 8)); + xv[4*i128+2*k+1] = _mm256_or_si256(q1h, _mm256_slli_epi16(q2h, 8)); + } + hbits = _mm256_srli_epi16(hbits, 4); + } + dnew[k] = convert_to_q8_k_r8(k, 1.f/125, xv, ls, block, y[i].qs); + } + auto vd = _mm256_mul_ps(_mm256_loadu_ps(dnew), _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)dh))); + _mm_storeu_si128((__m128i *)y[i].d, _mm256_cvtps_ph(vd, _MM_ROUND_NEAREST)); + } + y += nb; + } +} + void iqk_convert_iq2_k_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { GGML_ASSERT(n%QK_K == 0); GGML_ASSERT(nrc_x%8 == 0); @@ -2887,6 +3129,7 @@ bool iqk_convert_iqk_quants_q80_r8(int type, int n, const void * vx, size_t bx, switch (ggml_type(type)) { case GGML_TYPE_IQ2_KS : iqk_convert_iq2_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ2_K : iqk_convert_iq2_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; + case GGML_TYPE_IQ2_KL : iqk_convert_iq2_kl_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ3_KS : iqk_convert_iq3_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ3_K : iqk_convert_iq3_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ4_KS : iqk_convert_iq4_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; @@ -2916,6 +3159,12 @@ bool iqk_set_kernels_iqk_quants(int ne00, int typeA, int typeB, std::array(kernels); break; + case GGML_TYPE_IQ2_KL: + set_functions(kernels); +#ifdef HAVE_FANCY_SIMD + func16 = mul_mat_iqX_k_q8_K_AVX512_new; +#endif + break; case GGML_TYPE_IQ3_KS: set_functions(kernels); break; @@ -3469,6 +3718,98 @@ struct DequantizerIQ2KS final : public BaseDequantizer }; +struct DequantizerIQ2KL final : public BaseDequantizer { + DequantizerIQ2KL(const void * vx, size_t bx, int nrc) : BaseDequantizer(vx, bx, nrc), shuff(load_shuffle()), shifts(load_shift()) { load_values(values); } + + constexpr static int num_blocks() { return 8; } + constexpr static bool should_scale_quants() { return false; } + + template + inline int32x4x2_t new_block(int i, [[maybe_unused]] const Q8& q8, [[maybe_unused]] float32x4_t * acc) { + uint32_t aux32; std::memcpy(&aux32, x[i].scales_l, 4); + auto scl = vand_u8(vdup_n_u8(0xf), vreinterpret_u8_u32(uint32x2_t{aux32, aux32 >> 4})); + auto sch = vandq_u16(vshlq_u16(vdupq_n_u16(x[i].scales_h), shifts), vdupq_n_u16(0x30)); + auto scales16 = vsubq_s16(vreinterpretq_s16_u16(vorrq_u16(sch, vmovl_u8(scl))), vdupq_n_s16(32)); + int32x4x2_t scales = {vmovl_s16(vget_low_s16(scales16)), vmovl_s16(vget_high_s16(scales16))}; + return scales; + } + inline void process_pair(uint8x16_t x, uint8x16_t * val) const { + uint8x16x2_t aux{ vqtbl2q_s8(values[0], x), vqtbl2q_s8(values[1], x) }; + val[0] = vqtbl2q_u8(aux, shuff.val[0]); + val[1] = vqtbl2q_u8(aux, shuff.val[1]); + } + inline void prepare(int i, int j) { + hbits = j == 0 ? vld1q_u8(x[i].qh) : vshrq_n_u8(hbits, 4); + auto lbits = vld1q_u8_x2(x[i].qs+32*j); + + uint8x16x4_t aux; + aux.val[0] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 4)), vandq_u8(lbits.val[0], vdupq_n_u8(0xf))); + aux.val[1] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 3)), vshrq_n_u8(lbits.val[0], 4)); + aux.val[2] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 2)), vandq_u8(lbits.val[1], vdupq_n_u8(0xf))); + aux.val[3] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 1)), vshrq_n_u8(lbits.val[1], 4)); + + process_pair(aux.val[0], bits.b1.val+0); + process_pair(aux.val[1], bits.b1.val+2); + process_pair(aux.val[2], bits.b2.val+0); + process_pair(aux.val[3], bits.b2.val+2); + + // The compiler crashes the moment I try to use vzip2q_u8!!! + //bits.b1.val[0] = vandq_u8(lbits.val[0], vdupq_n_u8(0xf)); + //bits.b1.val[2] = vshrq_n_u8(lbits.val[0], 4); + //bits.b2.val[0] = vandq_u8(lbits.val[1], vdupq_n_u8(0xf)); + //bits.b2.val[2] = vshrq_n_u8(lbits.val[1], 4); + //bits.b1.val[0] = vorrq_u8(bits.b1.val[0], vandq_u8(m10, vshlq_n_u8(hbits, 4))); + //bits.b1.val[2] = vorrq_u8(bits.b1.val[2], vandq_u8(m10, vshlq_n_u8(hbits, 3))); + //bits.b2.val[0] = vorrq_u8(bits.b2.val[0], vandq_u8(m10, vshlq_n_u8(hbits, 2))); + //bits.b2.val[2] = vorrq_u8(bits.b2.val[2], vandq_u8(m10, vshlq_n_u8(hbits, 1))); + + //auto t1 = vqtbl2q_s8(values[0], bits.b1.val[0]); + //auto t2 = vqtbl2q_s8(values[1], bits.b1.val[0]); + //bits.b1.val[0] = vzip1q_s8(t1, t2); + ////bits.b1.val[1] = vzip2q_u8(t1, t2); + //t1 = vqtbl2q_s8(values[0], bits.b1.val[2]); + //t2 = vqtbl2q_s8(values[1], bits.b1.val[2]); + //bits.b1.val[2] = vzip1q_s8(t1, t2); + ////bits.b1.val[3] = vzip2q_s8(t1, t2); + + //t1 = vqtbl2q_s8(values[0], bits.b2.val[0]); + //t2 = vqtbl2q_s8(values[1], bits.b2.val[0]); + //bits.b2.val[0] = vzip1q_s8(t1, t2); + ////bits.b2.val[1] = vzip2q_s8(t1, t2); + //t1 = vqtbl2q_s8(values[0], bits.b2.val[2]); + //t2 = vqtbl2q_s8(values[1], bits.b2.val[2]); + //bits.b2.val[2] = vzip1q_s8(t1, t2); + ////bits.b2.val[3] = vzip2q_s8(t1, t2); + } + static inline int16x8_t load_shift() { + static const int16_t k_shift[8] = {4, 2, 0, -2, -4, -6, -8, -10}; + return vld1q_s16(k_shift); + } + static inline void load_values(int8x16x2_t * values) { + static const int8_t k_values[64] = { + -63, -63, -40, -40, -40, -40, -23, -23, -23, -23, -23, -10, -10, -10, -10, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 28, 28, 28, 28, 28, 47, 47, + -23, 13, -63, -10, 13, 47, -40, -23, 1, 13, 28, -63, 1, 13, 47, -23, -10, 1, 13, 28, -40, -23, -10, 1, 13, -63, -23, 1, 28, 47, -23, 13, + }; + values[0] = vld1q_s8_x2(k_values+ 0); + values[1] = vld1q_s8_x2(k_values+32); + } + static uint8x16x2_t load_shuffle() { + static const uint8_t k_shuff[32] = { + 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23, + 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 + }; + return vld1q_u8_x2(k_shuff); + } + + struct { uint8x16x4_t b1, b2; } bits; + uint8x16_t hbits; + const uint8x16x2_t shuff; + const int16x8_t shifts; + const uint8x16_t m10 = vdupq_n_u8(0x10); + int8x16x2_t values[2]; + +}; + template void mul_mat_iq4_ks_r4_q8_k(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { GGML_ASSERT(nrc_x%4 == 0); @@ -4241,6 +4582,142 @@ void iqk_convert_iq2_ks_q8_k_r8(int n, const void * vx, size_t bx, void * vy, in } } +//struct DequantizerIQ2KL final : public BaseDequantizer { +// DequantizerIQ2KL(const void * vx, size_t bx, int nrc) : BaseDequantizer(vx, bx, nrc), shuff(load_shuffle()), shifts(load_shift()) { load_values(values); } +// +// constexpr static int num_blocks() { return 8; } +// constexpr static bool should_scale_quants() { return false; } +// +// template +// inline int32x4x2_t new_block(int i, [[maybe_unused]] const Q8& q8, [[maybe_unused]] float32x4_t * acc) { +// uint32_t aux32; std::memcpy(&aux32, x[i].scales_l, 4); +// auto scl = vand_u8(vdup_n_u8(0xf), vreinterpret_u8_u32(uint32x2_t{aux32, aux32 >> 4})); +// auto sch = vandq_u16(vshlq_u16(vdupq_n_u16(x[i].scales_h), shifts), vdupq_n_u16(0x30)); +// auto scales16 = vsubq_s16(vreinterpretq_s16_u16(vorrq_u16(sch, vmovl_u8(scl))), vdupq_n_s16(32)); +// int32x4x2_t scales = {vmovl_s16(vget_low_s16(scales16)), vmovl_s16(vget_high_s16(scales16))}; +// return scales; +// } +// inline void prepare(int i, int j) { +// hbits = j == 0 ? vld1q_u8(x[i].qh) : vshrq_n_u8(hbits, 4); +// auto lbits = vld1q_u8_x2(x[i].qs+32*j); +// +// uint8x16x4_t aux; +// aux.val[0] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 4)), vandq_u8(lbits.val[0], vdupq_n_u8(0xf))); +// aux.val[1] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 3)), vshrq_n_u8(lbits.val[0], 4)); +// aux.val[2] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 2)), vandq_u8(lbits.val[1], vdupq_n_u8(0xf))); +// aux.val[3] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 1)), vshrq_n_u8(lbits.val[1], 4)); +// +// process_pair(aux.val[0], bits.b1.val+0); +// process_pair(aux.val[1], bits.b1.val+2); +// process_pair(aux.val[2], bits.b2.val+0); +// process_pair(aux.val[3], bits.b2.val+2); +// +// } +// static inline int16x8_t load_shift() { +// } +// static inline void load_values(int8x16x2_t * values) { +// } +// static uint8x16x2_t load_shuffle() { +// return vld1q_u8_x2(k_shuff); +// } +// +// struct { uint8x16x4_t b1, b2; } bits; +// uint8x16_t hbits; +// const uint8x16x2_t shuff; +// const int16x8_t shifts; +// const uint8x16_t m10 = vdupq_n_u8(0x10); +// int8x16x2_t values[2]; +// +//}; + +void iqk_convert_iq2_kl_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { + GGML_ASSERT(n%QK_K == 0); + GGML_ASSERT(nrc_x%8 == 0); + + int nb = n/QK_K; + + const block_iq2_kl * x8[8]; + + block_q8_k_r8 * y = (block_q8_k_r8 *)vy; + + ggml_half dh[8]; + float dnew[8]; + uint32_t block[8]; + int8_t ls[16]; + + int8x16x2_t xv[8]; + + const uint8x16_t m10 = vdupq_n_u8(0x10); + static const uint8_t k_shuff[32] = { + 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23, + 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 + }; + auto shuff = vld1q_u8_x2(k_shuff); + + int8x16x2_t values[2]; + static const int8_t k_values[64] = { + -63, -63, -40, -40, -40, -40, -23, -23, -23, -23, -23, -10, -10, -10, -10, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 28, 28, 28, 28, 28, 47, 47, + -23, 13, -63, -10, 13, 47, -40, -23, 1, 13, 28, -63, 1, 13, 47, -23, -10, 1, 13, 28, -40, -23, -10, 1, 13, -63, -23, 1, 28, 47, -23, 13, + }; + values[0] = vld1q_s8_x2(k_values+ 0); + values[1] = vld1q_s8_x2(k_values+32); + + auto process_pair = [&values, &shuff] (uint8x16_t x, int8x16_t * val) { + int8x16x2_t aux{ vqtbl2q_s8(values[0], x), vqtbl2q_s8(values[1], x) }; + val[0] = vqtbl2q_s8(aux, shuff.val[0]); + val[1] = vqtbl2q_s8(aux, shuff.val[1]); + }; + + uint32_t sl32; + auto s8 = (const int8_t *)&sl32; + + for (int ix = 0; ix < nrc_x; ix += 8) { + for (int k = 0; k < 8; ++k) { + const ggml_half * dptr = (const ggml_half *)((const char *)vx + (ix+k)*bx); + dh[k] = dptr[0]; + x8[k] = (const block_iq2_kl *)(dptr + 1); + } + float32x4x2_t vd{vcvt_f32_f16(vld1_f16((const float16_t *)dh+0)), vcvt_f32_f16(vld1_f16((const float16_t *)dh+4))}; + for (int i = 0; i < nb; ++i) { + for (int k = 0; k < 8; ++k) { + uint32_t aux32; std::memcpy(&aux32, x8[k][i].scales_l, 4); + auto sh = x8[k][i].scales_h; + auto hbits = vld1q_u8(x8[k][i].qh); + for (int i128 = 0; i128 < 2; ++i128) { + + sl32 = aux32 & 0x0f0f0f0f; + ls[8*i128+0] = ls[8*i128+1] = (s8[0] | ((sh << 4) & 0x30)) - 32; + ls[8*i128+2] = ls[8*i128+3] = (s8[1] | ((sh << 2) & 0x30)) - 32; + ls[8*i128+4] = ls[8*i128+5] = (s8[2] | ((sh >> 0) & 0x30)) - 32; + ls[8*i128+6] = ls[8*i128+7] = (s8[3] | ((sh >> 2) & 0x30)) - 32; + sh >>= 8; aux32 >>= 4; + + auto lbits = vld1q_u8_x2(x8[k][i].qs+32*i128); + + uint8x16x4_t aux; + aux.val[0] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 4)), vandq_u8(lbits.val[0], vdupq_n_u8(0xf))); + aux.val[1] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 3)), vshrq_n_u8(lbits.val[0], 4)); + aux.val[2] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 2)), vandq_u8(lbits.val[1], vdupq_n_u8(0xf))); + aux.val[3] = vorrq_u8(vandq_u8(m10, vshlq_n_u8(hbits, 1)), vshrq_n_u8(lbits.val[1], 4)); + hbits = vshrq_n_u8(hbits, 4); + + process_pair(aux.val[0], xv[4*i128+0].val); + process_pair(aux.val[1], xv[4*i128+1].val); + process_pair(aux.val[2], xv[4*i128+2].val); + process_pair(aux.val[3], xv[4*i128+3].val); + } + dnew[k] = convert_to_q8_k_r8(1.f/125, xv, ls, block, (uint32_t *)y[i].qs + k); + } + auto d = vld1q_f32_x2(dnew); + d.val[0] = vmulq_f32(d.val[0], vd.val[0]); + d.val[1] = vmulq_f32(d.val[1], vd.val[1]); + vst1_f16((float16_t *)y[i].d + 0,vcvt_f16_f32(d.val[0])); + vst1_f16((float16_t *)y[i].d + 4,vcvt_f16_f32(d.val[1])); + } + y += nb; + } +} + void iqk_convert_iq4_ks_q8_k_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { GGML_ASSERT(n%QK_K == 0); GGML_ASSERT(nrc_x%8 == 0); @@ -4683,6 +5160,7 @@ bool iqk_convert_iqk_quants_q80_r8(int type, int n, const void * vx, size_t bx, switch (ggml_type(type)) { case GGML_TYPE_IQ2_KS : iqk_convert_iq2_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ2_K : iqk_convert_iq2_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; + case GGML_TYPE_IQ2_KL : iqk_convert_iq2_kl_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ3_KS : iqk_convert_iq3_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ3_K : iqk_convert_iq3_k_q8_k_r8 (n, vx, bx, vy, nrc_x); break; case GGML_TYPE_IQ4_KS : iqk_convert_iq4_ks_q8_k_r8(n, vx, bx, vy, nrc_x); break; @@ -4710,6 +5188,9 @@ bool iqk_set_kernels_iqk_quants(int ne00, int typeA, int typeB, std::array= 64 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ2_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ2_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; + case GGML_TYPE_IQ2_KL : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ3_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ3_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ4_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; @@ -296,6 +297,7 @@ struct MulMat { case GGML_TYPE_IQ3_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ4_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ2_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; + case GGML_TYPE_IQ2_KL : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ3_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ4_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ5_KS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; @@ -424,6 +426,7 @@ bool iqk_convert_repack(int typeA, int n, const void * vx, size_t bx, void * vy, return iqk_convert_iquants_q80_r8(typeA, n, vx, bx, vy, nrc_x); case GGML_TYPE_IQ2_KS: case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ4_KSS: @@ -827,14 +830,15 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& mm, int Ny) { case GGML_TYPE_IQ3_XXS_R4: case GGML_TYPE_IQ3_S_R4: return iqk_set_kernels_iquants(ne00, typeA, typeB, mm.funcs, mm.func16); - case GGML_TYPE_IQ3_KS: - case GGML_TYPE_IQ4_KS: - case GGML_TYPE_IQ5_KS: - case GGML_TYPE_IQ4_KSS: - case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ2_KL: + case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: + case GGML_TYPE_IQ4_KSS: + case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ4_K: + case GGML_TYPE_IQ5_KS: case GGML_TYPE_IQ5_K: case GGML_TYPE_IQ6_K: case GGML_TYPE_IQ2_K_R4: @@ -909,6 +913,7 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& m, int /*Ny*/) { return iqk_set_kernels_kquants(ne00, typeA, typeB, m.funcs, m.func16); case GGML_TYPE_IQ2_KS: case GGML_TYPE_IQ2_K: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ4_KSS: diff --git a/ggml/src/iqk/iqk_quantize.cpp b/ggml/src/iqk/iqk_quantize.cpp index 9095cda4..b38cc51f 100644 --- a/ggml/src/iqk/iqk_quantize.cpp +++ b/ggml/src/iqk/iqk_quantize.cpp @@ -1515,9 +1515,10 @@ void vec_dot_iq2_ks_q8_k(int n, float * s, size_t bs, const void * vx, size_t bx } // -// ============================================== iq3_k +// ======================================== iq2_kl // namespace { + const int8_t iq3nl_index[111] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 11, 11, 4, 4, 4, 4, @@ -1531,6 +1532,317 @@ inline int best_index_iq3nl(const int8_t * values, float x) { return ix < 8 ? ix : x - values[ix-8] < values[ix-7] - x ? ix-8 : ix-7; } +void quantize_row_iq2_kl_impl(const float * x, void * vy, int n_per_row, const float * quant_weights, float * all_scales) { + constexpr int kBlockSize = 32; + constexpr float kSigmaFactor = 2.25f; + constexpr int ntry = 5; + static const int k_index[64] = {-1, -2, 0, -3, -4, 1, -5, -6, 2, -7, -8, 3, -9, 4, -10, 5, -11, 6, 7, -12, 8, 9, 10, -13, 11, -14, -15, -16, 12, 13, -17, + 14, -18, -19, 15, 16, 17, 18, 19, -20, -21, 20, 21, 22, 23, 24, -22, -23, 25, -24, 26, -25, 27, -26, 28, 29, -27, -28, 30, -29, -30, 31, -31, -32}; + static const std::vector> k_neighbours = { + { 2, 0, 6, 11, 7, 3, 8, 15, }, + { 0, 2, 3, 6, 7, 1, 8, 4, }, + { 0, 1, 3, 4, 8, 7, 9, 6, }, + { 1, 0, 3, 4, 8, 9, 7, 10, }, + { 1, 4, 5, 10, 9, 3, 8, 0, }, + { 5, 1, 4, 10, 9, 14, 8, 3, }, + { 6, 2, 7, 0, 3, 11, 8, 15, }, + { 3, 7, 0, 6, 8, 4, 12, 9, }, + { 3, 4, 8, 9, 1, 7, 12, 10, }, + { 4, 10, 5, 9, 1, 8, 13, 14, }, + { 11, 2, 6, 7, 20, 15, 25, 21, }, + { 8, 7, 3, 12, 9, 16, 17, 13, }, + { 14, 5, 10, 19, 9, 13, 4, 18, }, + { 6, 15, 7, 11, 20, 21, 16, 2, }, + { 15, 7, 16, 6, 21, 12, 17, 22, }, + { 12, 16, 17, 8, 15, 7, 13, 22, }, + { 19, 10, 13, 18, 14, 9, 12, 24, }, + { 11, 20, 25, 6, 15, 2, 21, 7, }, + { 20, 15, 21, 6, 11, 7, 16, 26, }, + { 14, 19, 29, 10, 28, 18, 13, 24, }, + { 25, 11, 20, 21, 15, 6, 26, 30, }, + { 19, 24, 28, 18, 29, 23, 13, 17, }, + { 29, 19, 14, 28, 24, 18, 10, 13, }, + { 20, 26, 21, 25, 30, 15, 22, 16, }, + { 27, 26, 22, 23, 21, 30, 16, 24, }, + { 27, 24, 28, 31, 23, 18, 22, 17, }, + { 25, 30, 20, 26, 21, 11, 15, 22, }, + { 30, 26, 25, 20, 21, 27, 22, 15, }, + { 30, 27, 31, 26, 22, 23, 21, 24, }, + { 31, 27, 30, 26, 28, 23, 22, 24, }, + { 31, 28, 29, 27, 24, 23, 19, 18, }, + { 29, 28, 31, 24, 19, 27, 14, 18, }, + }; + auto values = iq3nl_values; + std::pair grid[32]; + for (int j = 0; j < 64; ++j) { + if (int i = k_index[j]; i >= 0) { + int i1 = j/8, i2 = j%8; + grid[i] = {values[i1], values[i2]}; + } + } + + ggml_half * dptr = (ggml_half *)vy; + auto y = (block_iq2_kl *)(dptr + 1); + + float weight[kBlockSize]; + + auto index = [&grid, values] (float id, float x1, float x2, float w1, float w2) { + float sx1 = id*x1; + float sx2 = id*x2; + int l1 = best_index_iq3nl(values, sx1); + int l2 = best_index_iq3nl(values, sx2); + int i = k_index[8*l1 + l2]; + if (i >= 0) return i; + auto& neigh = k_neighbours[-i-1]; + float best = std::numeric_limits::max(); + int ibest = -1; + for (auto& n : neigh) { + float diff1 = grid[n].first - sx1; + float diff2 = grid[n].second - sx2; + float score = w1*diff1*diff1 + w2*diff2*diff2; + if (score < best) { + best = score; ibest = n; + } + } + GGML_ASSERT(ibest >= 0); + return ibest; + }; + + float max_scale = 0, max_abs_scale = 0; + + for (int ibl = 0; ibl < n_per_row/QK_K; ++ibl) { + std::memset(&y[ibl], 0, sizeof(block_iq2_kl)); + auto scales = all_scales + ibl*(QK_K/kBlockSize); + auto xbl = x + ibl*QK_K; + float sigma2 = 0; + for (int j = 0; j < QK_K; ++j) sigma2 += xbl[j]*xbl[j]; + sigma2 *= kSigmaFactor/QK_K; + for (int ib = 0; ib < QK_K/kBlockSize; ++ib) { + auto xb = xbl + ib*kBlockSize; + if (quant_weights) { + auto qw = quant_weights + ibl*QK_K + ib*kBlockSize; + for (int j = 0; j < kBlockSize; ++j) weight[j] = qw[j]*sqrt(sigma2 + xb[j]*xb[j]); + } else { + for (int j = 0; j < kBlockSize; ++j) weight[j] = std::abs(xb[j]); //xb[j]*xb[j]; + } + float amax = 0, max = 0; + for (int j = 0; j < kBlockSize; ++j) { + float ax = std::abs(xb[j]); + if (ax > amax) { + amax = ax; max = xb[j]; + } + } + if (!amax) { + scales[ib] = 0; + continue; + } + float d = ntry > 0 ? -max/values[0] : max/values[0]; + float id = 1/d; + float sumqx_p = 0, sumq2_p = 0; + float sumqx_m = 0, sumq2_m = 0; + for (int j = 0; j < kBlockSize; j += 2) { + float w1 = weight[j+0]; + float w2 = weight[j+1]; + int idx = index(id, xb[j+0], xb[j+1], w1, w2); + float q1 = grid[idx].first ; + float q2 = grid[idx].second; + sumqx_p += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_p += w1*q1*q1 + w2*q2*q2; + idx = index(-id, xb[j+0], xb[j+1], w1, w2); + q1 = grid[idx].first ; + q2 = grid[idx].second; + sumqx_m += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_m += w1*q1*q1 + w2*q2*q2; + } + d = sumqx_p/sumq2_p; + float best = d*sumqx_p; + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d*sumqx_m; + } + for (int itry = -ntry; itry <= ntry; ++itry) { + id = (itry + values[0])/max; + sumqx_p = sumq2_p = 0; + sumqx_m = sumq2_m = 0; + for (int j = 0; j < kBlockSize; j += 2) { + float w1 = weight[j+0]; + float w2 = weight[j+1]; + int idx = index(id, xb[j+0], xb[j+1], w1, w2); + float q1 = grid[idx].first ; + float q2 = grid[idx].second; + sumqx_p += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_p += w1*q1*q1 + w2*q2*q2; + idx = index(-id, xb[j+0], xb[j+1], w1, w2); + q1 = grid[idx].first ; + q2 = grid[idx].second; + sumqx_m += w1*q1*xb[j] + w2*q2*xb[j+1]; + sumq2_m += w1*q1*q1 + w2*q2*q2; + } + if (sumq2_p > 0 && sumqx_p*sumqx_p > best*sumq2_p) { + d = sumqx_p/sumq2_p; best = d * sumqx_p; + } + if (sumq2_m > 0 && sumqx_m*sumqx_m > best*sumq2_m) { + d = sumqx_m/sumq2_m; best = d * sumqx_m; + } + } + scales[ib] = d; + float ad = std::abs(d); + if (ad > max_abs_scale) { + max_abs_scale = ad; max_scale = d; + } + } + } + + if (!max_abs_scale) { + dptr[0] = GGML_FP32_TO_FP16(0.f); + return; + } + + float d = -max_scale/32; + float id = 1/d; + + float sumqx = 0, sumq2 = 0; + for (int ibl = 0; ibl < n_per_row/QK_K; ++ibl) { + auto scales = all_scales + ibl*(QK_K/kBlockSize); + auto xbl = x + ibl*QK_K; + float sigma2 = 0; + for (int j = 0; j < QK_K; ++j) sigma2 += xbl[j]*xbl[j]; + sigma2 *= kSigmaFactor/QK_K; + for (int ib = 0; ib < QK_K/kBlockSize; ++ib) { + auto xb = xbl + ib*kBlockSize; + if (quant_weights) { + auto qw = quant_weights + ibl*QK_K + ib*kBlockSize; + for (int j = 0; j < kBlockSize; ++j) weight[j] = qw[j]*sqrt(sigma2 + xb[j]*xb[j]); + } else { + for (int j = 0; j < kBlockSize; ++j) weight[j] = std::abs(xb[j]); //xb[j]*xb[j]; + } + int ls = nearest_int(id*scales[ib]); + ls = std::max(-32, std::min(31, ls)); + int lsmin = std::max(-32, ls-1); + int lsmax = std::min( 31, ls+1); + float best_score = std::numeric_limits::max(); + int best_ls = ls; + for (int ils = lsmin; ils <= lsmax; ++ils) { + float dl = d*ils; + float idl = dl ? 1/dl : 0.f; + float score = 0; + for (int j = 0; j < kBlockSize/2; ++j) { + float w1 = weight[2*j+0]; + float w2 = weight[2*j+1]; + int idx = index(idl, xb[2*j+0], xb[2*j+1], w1, w2); + float diff1 = dl*grid[idx].first - xb[2*j+0]; + float diff2 = dl*grid[idx].second - xb[2*j+1]; + score += w1*diff1*diff1 + w2*diff2*diff2; + } + if (score < best_score) { + best_score = score; + best_ls = ils; + } + } + ls = best_ls; + int uls = ls + 32; + y[ibl].scales_l[ib%4] |= ((uls & 0xf) << 4*(ib/4)); + y[ibl].scales_h |= ((uls >> 4) << 2*ib); + if (ls == 0) continue; + float dl = d*ls; + float idl = 1/dl; + for (int j = 0; j < kBlockSize/2; ++j) { + float w1 = weight[2*j+0]; + float w2 = weight[2*j+1]; + int idx = index(idl, xb[2*j+0], xb[2*j+1], w1, w2); + y[ibl].qs[16*(ib/2) + j] |= ((idx & 0xf) << 4*(ib%2)); + y[ibl].qh[j] |= ((idx >> 4) << ib); + float q1 = ls*grid[idx].first ; + float q2 = ls*grid[idx].second; + sumqx += w1*q1*xb[2*j] + w2*q2*xb[2*j+1]; + sumq2 += w1*q1*q1 + w2*q2*q2; + } + } + } + if (sumq2 > 0) d = sumqx/sumq2; + + dptr[0] = GGML_FP32_TO_FP16(1.025f * d); + +} +} + +void quantize_row_iq2_kl_ref(const float * x, block_iq2_kl * y, int64_t k) { + assert(k % QK_K == 0); + quantize_iq2_kl(x, (void *)y, 1, k, nullptr); +} + +void quantize_row_iq2_kl(const float * x, void * vy, int64_t k) { + assert(k % QK_K == 0); + block_iq2_kl * y = (block_iq2_kl *)vy; + quantize_row_iq2_kl_ref(x, y, k); +} + +size_t quantize_iq2_kl(const float * src, void * dst, int64_t nrows, int64_t n_per_row, const float * imatrix) { + constexpr int kBlockSize = 32; + GGML_ASSERT(n_per_row%QK_K == 0); + auto row_size = ggml_row_size(GGML_TYPE_IQ2_KL, n_per_row); + int nblock = n_per_row/QK_K; + std::vector all_scales(nblock*(QK_K/kBlockSize)); + char * qrow = (char *)dst; + for (int64_t row = 0; row < nrows; ++row) { + quantize_row_iq2_kl_impl(src, (void *)qrow, n_per_row, imatrix, all_scales.data()); + src += n_per_row; + qrow += row_size; + } + return nrows * row_size; +} + +void dequantize_row_iq2_kl(const block_iq2_kl * x, float * y, int64_t k) { + assert(k % QK_K == 0); + const int nb = k / QK_K; + + const ggml_half * dptr = (const ggml_half *)x; + const float d = GGML_FP16_TO_FP32(*dptr); + x = (const block_iq2_kl *)(dptr + 1); + + for (int i = 0; i < nb; i++) { + + auto qs = x[i].qs; + auto qh = x[i].qh; + auto scales_h = x[i].scales_h; + + for (int ib64 = 0; ib64 < QK_K/64; ++ib64) { + float dl1 = d * (int(((x[i].scales_l[(2*ib64+0)%4] >> 4*(ib64/2)) & 0xf) | (((scales_h >> (4*ib64+0)) & 3) << 4)) - 32); + float dl2 = d * (int(((x[i].scales_l[(2*ib64+1)%4] >> 4*(ib64/2)) & 0xf) | (((scales_h >> (4*ib64+2)) & 3) << 4)) - 32); + for (int j = 0; j < 16; ++j) { + const int8_t * val1 = (const int8_t *)(iq2kl_values + ((qs[j] & 0xf) | (((qh[j] >> (2*ib64+0)) & 1) << 4))); + const int8_t * val2 = (const int8_t *)(iq2kl_values + ((qs[j] >> 4) | (((qh[j] >> (2*ib64+1)) & 1) << 4))); + y[2*j+ 0] = dl1 * val1[0]; + y[2*j+ 1] = dl1 * val1[1]; + y[2*j+32] = dl2 * val2[0]; + y[2*j+33] = dl2 * val2[1]; + } + y += 64; + qs += 16; + } + + } +} + +void vec_dot_iq2_kl_q8_k(int n, float * s, size_t bs, const void * vx, size_t bx, const void * vy, size_t by, int nrc) { + assert(n % QK_K == 0); + assert(nrc == 1); + GGML_UNUSED(nrc); + GGML_UNUSED(bx); + GGML_UNUSED(by); + GGML_UNUSED(bs); + +#if GGML_USE_IQK_MULMAT + if (iqk_mul_mat(1, 1, n, GGML_TYPE_IQ2_KL, vx, 0, GGML_TYPE_Q8_K, vy, 0, s, 0, 0, 1)) { + return; + } +#endif +} + +// +// ============================================== iq3_k +// +namespace { + static void quantize_row_iq3_k_impl(const float * x, void * vy, int n_per_row, const float * quant_weights) { constexpr int ntry = 3; diff --git a/ggml/src/iqk/iqk_quantize.h b/ggml/src/iqk/iqk_quantize.h index 3fc02a5e..75fa9b4e 100644 --- a/ggml/src/iqk/iqk_quantize.h +++ b/ggml/src/iqk/iqk_quantize.h @@ -73,6 +73,12 @@ size_t quantize_iq2_ks(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst void dequantize_row_iq2_ks(const block_iq2_ks * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k); void vec_dot_iq2_ks_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); +void quantize_row_iq2_kl_ref(const float * GGML_RESTRICT x, block_iq2_kl * GGML_RESTRICT y, int64_t k); +void quantize_row_iq2_kl(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k); +size_t quantize_iq2_kl(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix); +void dequantize_row_iq2_kl(const block_iq2_kl * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k); +void vec_dot_iq2_kl_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); + void quantize_row_iq2_kt_ref(const float * GGML_RESTRICT x, block_iq2_kt * GGML_RESTRICT y, int64_t k); void quantize_row_iq2_kt(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k); size_t quantize_iq2_kt(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix); diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py index 0fe3ed35..767637c5 100644 --- a/gguf-py/gguf/constants.py +++ b/gguf-py/gguf/constants.py @@ -1321,6 +1321,7 @@ class GGMLQuantizationType(IntEnum): IQ3_KT = 154 IQ4_KT = 155 IQ3_KS = 156 + IQ2_KL = 157 Q4_0_R8 = 202 Q5_0_R4 = 206 Q8_0_R8 = 208 @@ -1537,6 +1538,7 @@ GGML_QUANT_SIZES: dict[GGMLQuantizationType, tuple[int, int]] = { GGMLQuantizationType.IQ3_KT : ( 256, 100), GGMLQuantizationType.IQ4_KT : ( 256, 128), GGMLQuantizationType.IQ3_KS : ( 256, 102), + GGMLQuantizationType.IQ2_KL : ( 256, 86), GGMLQuantizationType.Q4_0_R8 : ( 32, 18), GGMLQuantizationType.Q5_0_R4 : ( 32, 22), GGMLQuantizationType.Q8_0_R8 : ( 32, 34), diff --git a/include/llama.h b/include/llama.h index eaa5d69d..bcd81f4f 100644 --- a/include/llama.h +++ b/include/llama.h @@ -205,6 +205,7 @@ extern "C" { LLAMA_FTYPE_MOSTLY_IQ3_KT = 152, // except 1d tensors LLAMA_FTYPE_MOSTLY_IQ4_KT = 153, // except 1d tensors LLAMA_FTYPE_MOSTLY_IQ3_KS = 154, // except 1d tensors + LLAMA_FTYPE_MOSTLY_IQ2_KL = 155, // except 1d tensors // LLAMA_FTYPE_MOSTLY_Q4_0_R8 = 202, // except 1d tensors LLAMA_FTYPE_MOSTLY_Q8_0_R8 = 207, // except 1d tensors diff --git a/src/llama.cpp b/src/llama.cpp index ac02abf6..c11affb6 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -4435,6 +4435,7 @@ struct llama_model_loader { case GGML_TYPE_IQ2_K: ftype = LLAMA_FTYPE_MOSTLY_IQ2_K; break; case GGML_TYPE_IQ2_K_R4:ftype = LLAMA_FTYPE_MOSTLY_IQ2_K_R4;break; case GGML_TYPE_IQ3_KS: ftype = LLAMA_FTYPE_MOSTLY_IQ3_KS; break; + case GGML_TYPE_IQ2_KL: ftype = LLAMA_FTYPE_MOSTLY_IQ2_KL; break; case GGML_TYPE_IQ3_K: ftype = LLAMA_FTYPE_MOSTLY_IQ3_K; break; case GGML_TYPE_IQ3_K_R4:ftype = LLAMA_FTYPE_MOSTLY_IQ3_K_R4;break; case GGML_TYPE_IQ4_K: ftype = LLAMA_FTYPE_MOSTLY_IQ4_K; break; @@ -5177,6 +5178,7 @@ static std::string llama_model_ftype_name(llama_ftype ftype) { case LLAMA_FTYPE_MOSTLY_IQ2_K: return "IQ2_K - 2.375 bpw"; case LLAMA_FTYPE_MOSTLY_IQ2_K_R4: return "IQ2_K_R4 - 2.375 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_KS: return "IQ3_KS - 3.1875 bpw"; + case LLAMA_FTYPE_MOSTLY_IQ2_KL: return "IQ2_KL - 2.6875 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_K: return "IQ3_K - 3.4325 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_K_R4: return "IQ3_K_R4 - 3.4325 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_KL: return "IQ3_KL - 4 bpw"; @@ -19133,7 +19135,7 @@ static ggml_type change_type_if_necessary(ggml_type new_type, int nx, int ny) { new_type == GGML_TYPE_IQ3_XXS_R4 || new_type == GGML_TYPE_IQ2_XXS_R4 || new_type == GGML_TYPE_IQ2_XS_R4 || new_type == GGML_TYPE_IQ2_S_R4|| new_type == GGML_TYPE_IQ3_S_R4|| new_type == GGML_TYPE_IQ3_KS || new_type == GGML_TYPE_IQ2_KT || new_type == GGML_TYPE_IQ3_KT || new_type == GGML_TYPE_IQ4_KT || - new_type == GGML_TYPE_IQ5_KS || new_type == GGML_TYPE_IQ5_KS_R4) { + new_type == GGML_TYPE_IQ5_KS || new_type == GGML_TYPE_IQ5_KS_R4|| new_type == GGML_TYPE_IQ2_KL) { if (nx % QK_K != 0) { LLAMA_LOG_WARN("\n\n%s : tensor cols %d x %d are not divisible by %d, required for %s", __func__, nx, ny, QK_K, ggml_type_name(new_type)); convert_incompatible_tensor = true; @@ -19165,6 +19167,7 @@ static ggml_type change_type_if_necessary(ggml_type new_type, int nx, int ny) { case GGML_TYPE_Q3_K_R4: case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: + case GGML_TYPE_IQ2_KL: case GGML_TYPE_IQ3_KS: case GGML_TYPE_IQ3_K: case GGML_TYPE_IQ3_K_R4: @@ -19301,7 +19304,7 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n ftype == LLAMA_FTYPE_MOSTLY_IQ1_S || ftype == LLAMA_FTYPE_MOSTLY_IQ2_S || ftype == LLAMA_FTYPE_MOSTLY_IQ2_M || ftype == LLAMA_FTYPE_MOSTLY_IQ1_M || ftype == LLAMA_FTYPE_MOSTLY_IQ2_K || ftype == LLAMA_FTYPE_MOSTLY_IQ3_K || ftype == LLAMA_FTYPE_MOSTLY_IQ2_KS || ftype == LLAMA_FTYPE_MOSTLY_IQ3_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KS || - ftype == LLAMA_FTYPE_MOSTLY_IQ2_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || + ftype == LLAMA_FTYPE_MOSTLY_IQ2_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_KL || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_M_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ1_S_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ1_M_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_KT || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KT) { @@ -19508,6 +19511,9 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n else if (ftype == LLAMA_FTYPE_MOSTLY_IQ3_KS && qs.model.hparams.n_gqa() >= 2) { new_type = GGML_TYPE_IQ4_KS; } + else if (ftype == LLAMA_FTYPE_MOSTLY_IQ2_KL && qs.model.hparams.n_gqa() >= 2) { + new_type = GGML_TYPE_IQ4_KS; + } else if (ftype == LLAMA_FTYPE_MOSTLY_IQ3_K_R4 && qs.model.hparams.n_gqa() >= 2) { new_type = GGML_TYPE_IQ4_K_R4; } @@ -19553,6 +19559,7 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n else if (new_type == GGML_TYPE_Q3_K || new_type == GGML_TYPE_IQ3_S) new_type = GGML_TYPE_Q4_K; else if (new_type == GGML_TYPE_IQ3_K) new_type = GGML_TYPE_IQ4_K; else if (new_type == GGML_TYPE_IQ3_KS) new_type = GGML_TYPE_IQ4_KS; + else if (new_type == GGML_TYPE_IQ2_KL) new_type = GGML_TYPE_IQ4_KS; else if (new_type == GGML_TYPE_IQ3_S_R4) new_type = GGML_TYPE_Q4_K_R4; else if (new_type == GGML_TYPE_Q3_K_R4) new_type = GGML_TYPE_Q4_K_R4; else if (new_type == GGML_TYPE_Q4_K || new_type == GGML_TYPE_IQ4_XS) new_type = GGML_TYPE_Q5_K; @@ -19685,6 +19692,9 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n new_type = GGML_TYPE_Q5_K; // should the IQ_K quants be applied here as the new type for the IQ_K ftypes ? // also, this condition could be reproduced on attn_q, eventually with Q4_K instead of Q5_K. } + else if (ftype == LLAMA_FTYPE_MOSTLY_IQ2_KL) { + new_type = GGML_TYPE_IQ4_KS; + } } else { if (ftype == LLAMA_FTYPE_MOSTLY_Q2_K ) new_type = GGML_TYPE_Q3_K; // This list could be generalized and streamlined else if (ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS) new_type = GGML_TYPE_IQ3_S; @@ -19922,6 +19932,7 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s case LLAMA_FTYPE_MOSTLY_IQ2_K: default_type = GGML_TYPE_IQ2_K; break; case LLAMA_FTYPE_MOSTLY_IQ2_K_R4:default_type = GGML_TYPE_IQ2_K_R4;break; case LLAMA_FTYPE_MOSTLY_IQ3_KS: default_type = GGML_TYPE_IQ3_KS; break; + case LLAMA_FTYPE_MOSTLY_IQ2_KL: default_type = GGML_TYPE_IQ2_KL; break; case LLAMA_FTYPE_MOSTLY_IQ3_K: default_type = GGML_TYPE_IQ3_K; break; case LLAMA_FTYPE_MOSTLY_IQ3_K_R4:default_type = GGML_TYPE_IQ3_K_R4;break; case LLAMA_FTYPE_MOSTLY_IQ3_KL: default_type = GGML_TYPE_IQ3_K; break; From 2081b3fccb9923699bf4d5e926d8719fc1d12c39 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Tue, 15 Jul 2025 08:03:13 +0200 Subject: [PATCH 29/63] Vulkan: a fresh start (#608) * It compiles * Seems to be working with coopmat * Vulkan needs f32 precision for flash attention * Vulkan: fix u_batch > 4096/n_active_experts for coopmat1. Without this fix we get an assert. We get the same assert in mainline too. --------- Co-authored-by: Iwan Kawrakow --- ggml/include/ggml-vulkan.h | 2 +- ggml/include/ggml.h | 9 + ggml/src/ggml-impl.h | 10 + ggml/src/ggml-vulkan.cpp | 1807 +++++++++++++---- ggml/src/ggml.c | 28 +- ggml/src/vulkan-shaders/CMakeLists.txt | 2 +- ggml/src/vulkan-shaders/conv2d_dw.comp | 105 + ggml/src/vulkan-shaders/copy_to_quant.comp | 69 +- ggml/src/vulkan-shaders/flash_attn.comp | 8 +- ggml/src/vulkan-shaders/flash_attn_base.comp | 15 +- ggml/src/vulkan-shaders/flash_attn_cm1.comp | 8 +- ggml/src/vulkan-shaders/flash_attn_cm2.comp | 9 +- .../flash_attn_split_k_reduce.comp | 56 +- ggml/src/vulkan-shaders/geglu.comp | 13 + ggml/src/vulkan-shaders/geglu_erf.comp | 27 + ggml/src/vulkan-shaders/geglu_quick.comp | 11 + ggml/src/vulkan-shaders/gelu_erf.comp | 39 + ggml/src/vulkan-shaders/glu_head.comp | 15 + ggml/src/vulkan-shaders/glu_main.comp | 29 + ggml/src/vulkan-shaders/l2_norm.comp | 41 + ggml/src/vulkan-shaders/mul_mm.comp | 192 +- ggml/src/vulkan-shaders/mul_mm_cm2.comp | 47 +- ggml/src/vulkan-shaders/reglu.comp | 9 + ggml/src/vulkan-shaders/rms_norm.comp | 15 +- ggml/src/vulkan-shaders/roll.comp | 46 + ggml/src/vulkan-shaders/rope_multi.comp | 16 +- ggml/src/vulkan-shaders/rope_neox.comp | 16 +- ggml/src/vulkan-shaders/rope_norm.comp | 16 +- ggml/src/vulkan-shaders/scale.comp | 2 +- ggml/src/vulkan-shaders/soft_max.comp | 24 +- ggml/src/vulkan-shaders/swiglu.comp | 9 + ggml/src/vulkan-shaders/upscale.comp | 74 +- .../src/vulkan-shaders/vulkan-shaders-gen.cpp | 57 +- ggml/src/vulkan-shaders/wkv7.comp | 91 + src/llama.cpp | 21 +- 35 files changed, 2342 insertions(+), 596 deletions(-) create mode 100644 ggml/src/vulkan-shaders/conv2d_dw.comp create mode 100644 ggml/src/vulkan-shaders/geglu.comp create mode 100644 ggml/src/vulkan-shaders/geglu_erf.comp create mode 100644 ggml/src/vulkan-shaders/geglu_quick.comp create mode 100644 ggml/src/vulkan-shaders/gelu_erf.comp create mode 100644 ggml/src/vulkan-shaders/glu_head.comp create mode 100644 ggml/src/vulkan-shaders/glu_main.comp create mode 100644 ggml/src/vulkan-shaders/l2_norm.comp create mode 100644 ggml/src/vulkan-shaders/reglu.comp create mode 100644 ggml/src/vulkan-shaders/roll.comp create mode 100644 ggml/src/vulkan-shaders/swiglu.comp create mode 100644 ggml/src/vulkan-shaders/wkv7.comp diff --git a/ggml/include/ggml-vulkan.h b/ggml/include/ggml-vulkan.h index e3e62864..7a482d6f 100644 --- a/ggml/include/ggml-vulkan.h +++ b/ggml/include/ggml-vulkan.h @@ -10,7 +10,7 @@ extern "C" { #define GGML_VK_NAME "Vulkan" #define GGML_VK_MAX_DEVICES 16 -GGML_API GGML_CALL void ggml_vk_instance_init(void); +//GGML_API GGML_CALL void ggml_vk_instance_init(void); // backend API GGML_API GGML_CALL ggml_backend_t ggml_backend_vk_init(size_t dev_num); diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index ecce1959..a85f52b2 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -884,6 +884,15 @@ extern "C" { GGML_API GGML_CALL bool ggml_is_contiguous_1(const struct ggml_tensor * tensor); // contiguous for dims >= 1 GGML_API GGML_CALL bool ggml_is_contiguous_2(const struct ggml_tensor * tensor); // contiguous for dims >= 2 + // returns whether the tensor elements are allocated as one contiguous block of memory (no gaps, but permutation ok) + GGML_API bool ggml_is_contiguously_allocated(const struct ggml_tensor * tensor); + + // true for tensor that is stored in memory as CxWxHxN and has been permuted to WxHxCxN + GGML_API bool ggml_is_contiguous_channels(const struct ggml_tensor * tensor); + + // true if the elements in dimension 0 are contiguous, or there is just 1 block of elements + GGML_API bool ggml_is_contiguous_rows(const struct ggml_tensor * tensor); + GGML_API bool ggml_are_same_shape (const struct ggml_tensor * t0, const struct ggml_tensor * t1); GGML_API bool ggml_are_same_stride(const struct ggml_tensor * t0, const struct ggml_tensor * t1); diff --git a/ggml/src/ggml-impl.h b/ggml/src/ggml-impl.h index 190af081..e4e36860 100644 --- a/ggml/src/ggml-impl.h +++ b/ggml/src/ggml-impl.h @@ -748,6 +748,16 @@ static size_t ggml_hash_find_or_insert(struct ggml_hash_set * hash_set, struct g GGML_ABORT("fatal error"); } +static int32_t ggml_get_op_params_i32(const struct ggml_tensor * tensor, uint32_t i) { + assert(i < GGML_MAX_OP_PARAMS / sizeof(int32_t)); + return ((const int32_t *)(tensor->op_params))[i]; +} + +static float ggml_get_op_params_f32(const struct ggml_tensor * tensor, uint32_t i) { + assert(i < GGML_MAX_OP_PARAMS / sizeof(float)); + return ((const float *)(tensor->op_params))[i]; +} + #ifdef __cplusplus } #endif diff --git a/ggml/src/ggml-vulkan.cpp b/ggml/src/ggml-vulkan.cpp index 4091c89f..778033d9 100644 --- a/ggml/src/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan.cpp @@ -99,6 +99,7 @@ static bool is_pow2(uint32_t x) { return x > 1 && (x & (x-1)) == 0; } #else #define VK_LOG_DEBUG(msg) ((void) 0) #endif // GGML_VULKAN_DEBUG + #define GGML_DEBUG 0 #if (GGML_DEBUG >= 1) #define GGML_LOG_DEBUG(...) printf(__VA_ARGS__) @@ -433,36 +434,41 @@ struct vk_device_struct { vk_pipeline pipeline_div_norepeat[2][2][2]; vk_pipeline pipeline_concat_f32, pipeline_concat_f16, pipeline_concat_i32; - vk_pipeline pipeline_upscale_f32; + vk_pipeline pipeline_upscale_nearest_f32, pipeline_upscale_bilinear_f32, pipeline_upscale_bilinear_ac_f32; vk_pipeline pipeline_scale_f32; vk_pipeline pipeline_sqr_f32; + vk_pipeline pipeline_sin_f32; + vk_pipeline pipeline_cos_f32; vk_pipeline pipeline_clamp_f32; vk_pipeline pipeline_pad_f32; + vk_pipeline pipeline_roll_f32; vk_pipeline pipeline_repeat_f32, pipeline_repeat_back_f32; vk_pipeline pipeline_cpy_f32_f32, pipeline_cpy_f32_f16, pipeline_cpy_f16_f16, pipeline_cpy_f16_f32, pipeline_cpy_f32_bf16; vk_pipeline pipeline_contig_cpy_f32_f32, pipeline_contig_cpy_f32_f16, pipeline_contig_cpy_f16_f16, pipeline_contig_cpy_f16_f32, pipeline_contig_cpy_f32_bf16; vk_pipeline pipeline_cpy_f32_quant[GGML_TYPE_COUNT]; vk_pipeline pipeline_cpy_quant_f32[GGML_TYPE_COUNT]; + vk_pipeline pipeline_set_rows[GGML_TYPE_COUNT]; vk_pipeline pipeline_norm_f32; vk_pipeline pipeline_group_norm_f32; vk_pipeline pipeline_rms_norm_f32; - vk_pipeline pipeline_fused_rms_norm_f32; + vk_pipeline pipeline_rms_norm_mul_f32; vk_pipeline pipeline_rms_norm_back_f32; + vk_pipeline pipeline_l2_norm_f32; // [src/dst 0=fp32,1=fp16] vk_pipeline pipeline_gelu[2]; + vk_pipeline pipeline_gelu_erf[2]; vk_pipeline pipeline_gelu_quick[2]; vk_pipeline pipeline_silu[2]; vk_pipeline pipeline_relu[2]; vk_pipeline pipeline_tanh[2]; vk_pipeline pipeline_sigmoid[2]; - // [src/dst 0=fp32,1=fp16] - vk_pipeline pipeline_fused_mul_gelu[2]; - vk_pipeline pipeline_fused_mul_silu[2]; - vk_pipeline pipeline_fused_mul_relu[2]; - - vk_pipeline pipeline_multi_add_f32; + vk_pipeline pipeline_geglu[2]; + vk_pipeline pipeline_reglu[2]; + vk_pipeline pipeline_swiglu[2]; + vk_pipeline pipeline_geglu_erf[2]; + vk_pipeline pipeline_geglu_quick[2]; vk_pipeline pipeline_leaky_relu_f32; vk_pipeline pipeline_silu_back_f32; @@ -483,7 +489,10 @@ struct vk_device_struct { vk_pipeline pipeline_conv_transpose_1d_f32; vk_pipeline pipeline_pool2d_f32; vk_pipeline pipeline_rwkv_wkv6_f32; + vk_pipeline pipeline_rwkv_wkv7_f32; vk_pipeline pipeline_opt_step_adamw_f32; + vk_pipeline pipeline_conv2d_dw_whcn_f32; + vk_pipeline pipeline_conv2d_dw_cwhn_f32; // [2][2][2] is for {f16acc,f32acc}x{large,small_rows}x{unaligned, aligned} vk_pipeline pipeline_flash_attn_f32_f16_cm2[GGML_TYPE_COUNT][FA_HEAD_SIZE_COUNT][2][2][2]; @@ -494,6 +503,17 @@ struct vk_device_struct { vk_pipeline pipeline_flash_attn_split_k_reduce; + // ============================== ik_llama.cpp pipelines begin ======================================== + + vk_pipeline pipeline_fused_rms_norm_f32; + vk_pipeline pipeline_fused_mul_gelu[2]; + vk_pipeline pipeline_fused_mul_silu[2]; + vk_pipeline pipeline_fused_mul_relu[2]; + vk_pipeline pipeline_multi_add_f32; + + // ============================== ik_llama.cpp pipelines end ======================================== + + std::unordered_map pipelines; std::vector> pinned_memory; @@ -503,6 +523,8 @@ struct vk_device_struct { ggml_backend_buffer_type buffer_type; + bool disable_fusion; + #ifdef GGML_VULKAN_MEMORY_DEBUG std::unique_ptr memory_logger; #endif @@ -637,6 +659,8 @@ struct vk_flash_attn_push_constants { uint32_t nev2; uint32_t nev3; uint32_t nem1; + uint32_t nem2; + uint32_t nem3; uint32_t nb01; uint32_t nb02; @@ -647,14 +671,12 @@ struct vk_flash_attn_push_constants { uint32_t nb21; uint32_t nb22; uint32_t nb23; - uint32_t nb31; float scale; float max_bias; float logit_softcap; - uint32_t mask; - uint32_t n_head_log2; + uint32_t mask_n_head_log2; float m0; float m1; @@ -662,6 +684,7 @@ struct vk_flash_attn_push_constants { uint32_t split_kv; uint32_t k_num; }; +static_assert(sizeof(vk_flash_attn_push_constants) <= 128, "sizeof(vk_flash_attn_push_constants) must be <= 128"); struct vk_op_push_constants { uint32_t KX; @@ -670,6 +693,20 @@ struct vk_op_push_constants { float param2; }; +struct vk_op_glu_push_constants { + uint32_t N; + uint32_t ne00; + uint32_t ne20; + uint32_t mode; // 0: default, 1: swapped, 2: split +}; + +struct vk_op_multiadd_push_constants { + uint32_t ne; + uint32_t ne0, ne1; + uint32_t nb0, nb01; + uint32_t nadd; +}; + struct vk_op_unary_push_constants { uint32_t ne; uint32_t ne00; uint32_t ne01; uint32_t ne02; uint32_t ne03; uint32_t nb00; uint32_t nb01; uint32_t nb02; uint32_t nb03; @@ -685,12 +722,36 @@ struct vk_op_unary_push_constants { }; static_assert(sizeof(vk_op_unary_push_constants) <= 128, "sizeof(vk_op_unary_push_constants) must be <= 128"); -struct vk_op_multiadd_push_constants { - uint32_t ne; - uint32_t ne0, ne1; - uint32_t nb0, nb01; - uint32_t nadd; -}; +static vk_op_unary_push_constants vk_op_unary_push_constants_init(const ggml_tensor * src0, const ggml_tensor * dst, int64_t ne = 0) { + GGML_ASSERT(ne != 0 || (ggml_nelements(src0) == ggml_nelements(dst))); + ne = ne != 0 ? ne : ggml_nelements(dst); + GGML_ASSERT(ne <= (int64_t)std::numeric_limits::max()); + + vk_op_unary_push_constants p{}; + p.ne = (uint32_t)ne; + + size_t src0_tsize = ggml_type_size(src0->type); + p.ne00 = (uint32_t)src0->ne[0]; + p.ne01 = (uint32_t)src0->ne[1]; + p.ne02 = (uint32_t)src0->ne[2]; + p.ne03 = (uint32_t)src0->ne[3]; + p.nb00 = (uint32_t)(src0->nb[0] / src0_tsize); + p.nb01 = (uint32_t)(src0->nb[1] / src0_tsize); + p.nb02 = (uint32_t)(src0->nb[2] / src0_tsize); + p.nb03 = (uint32_t)(src0->nb[3] / src0_tsize); + + size_t dst_tsize = ggml_type_size(dst->type); + p.ne10 = (uint32_t)dst->ne[0]; + p.ne11 = (uint32_t)dst->ne[1]; + p.ne12 = (uint32_t)dst->ne[2]; + p.ne13 = (uint32_t)dst->ne[3]; + p.nb10 = (uint32_t)(dst->nb[0] / dst_tsize); + p.nb11 = (uint32_t)(dst->nb[1] / dst_tsize); + p.nb12 = (uint32_t)(dst->nb[2] / dst_tsize); + p.nb13 = (uint32_t)(dst->nb[3] / dst_tsize); + + return p; // fastdiv values and offsets are initialized later in ggml_vk_op +} // See https://gmplib.org/~tege/divcnst-pldi94.pdf figure 4.1. // Precompute mp (m' in the paper) and L such that division @@ -760,6 +821,14 @@ struct vk_op_rope_push_constants { struct vk_op_soft_max_push_constants { uint32_t KX; uint32_t KY; + uint32_t ne00; + uint32_t ne01; + uint32_t ne02; + uint32_t ne12; + uint32_t ne13; + uint32_t nb11; + uint32_t nb12; + uint32_t nb13; float scale; float max_bias; float m0; @@ -826,6 +895,12 @@ struct vk_op_rwkv_wkv6_push_constants { uint32_t H; }; +struct vk_op_rwkv_wkv7_push_constants { + uint32_t B; + uint32_t T; + uint32_t C; + uint32_t H; +}; struct vk_op_conv2d_dw_push_constants { uint32_t ne; @@ -845,9 +920,9 @@ struct vk_op_conv2d_dw_push_constants { int32_t dilation_y; }; - struct vk_op_upscale_push_constants { uint32_t ne; uint32_t a_offset; uint32_t d_offset; + uint32_t ne00; uint32_t ne01; uint32_t nb00; uint32_t nb01; uint32_t nb02; uint32_t nb03; uint32_t ne10; uint32_t ne11; uint32_t ne12; uint32_t ne13; float sf0; float sf1; float sf2; float sf3; @@ -990,6 +1065,10 @@ struct ggml_backend_vk_context { vk_command_pool compute_cmd_pool; vk_command_pool transfer_cmd_pool; + + // number of additional consecutive nodes that are being fused with the + // node currently being processed + int num_additional_fused_ops {}; }; static void * const vk_ptr_base = (void *)(uintptr_t) 0x1000; // NOLINT @@ -1075,13 +1154,13 @@ static size_t vk_skip_checks; static size_t vk_output_tensor; static void ggml_vk_print_tensor(const ggml_tensor * tensor, const char * name); -static void ggml_vk_check_results_0(ggml_tensor * tensor); -static void ggml_vk_check_results_1(ggml_tensor * tensor); +static void ggml_vk_check_results_0(ggml_backend_vk_context * ctx, ggml_cgraph * cgraph, int tensor_idx); +static void ggml_vk_check_results_1(ggml_backend_vk_context * ctx, ggml_cgraph * cgraph, int tensor_idx); #endif typedef void (*ggml_vk_func_t)(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst); -GGML_CALL static void ggml_backend_vk_free(ggml_backend_t backend); +static void ggml_backend_vk_free(ggml_backend_t backend); // Wait for ctx->fence to be signaled. static void ggml_vk_wait_for_fence(ggml_backend_vk_context * ctx) { @@ -1717,7 +1796,14 @@ static FaHeadSizes fa_get_head_sizes(uint32_t hsk, uint32_t hsv) { // number of rows/cols for flash attention shader static constexpr uint32_t flash_attention_num_small_rows = 32; static constexpr uint32_t scalar_flash_attention_num_small_rows = 1; -static constexpr uint32_t scalar_flash_attention_num_large_rows = 8; + +static uint32_t get_fa_scalar_num_large_rows(uint32_t hsv) { + if (hsv >= 512) { + return 2; + } else { + return 8; + } +} // The FA coopmat1 shader assumes 16x16x16 matrix multiply support. // 128 threads split into four subgroups, each subgroup does 1/4 @@ -1742,7 +1828,7 @@ static std::array fa_rows_cols(FaCodePath path, uint32_t hsk, uint3 if (small_rows) { return {scalar_flash_attention_num_small_rows, 64}; } else { - return {scalar_flash_attention_num_large_rows, 32}; + return {get_fa_scalar_num_large_rows(hsv), 32}; } } @@ -1761,7 +1847,11 @@ static std::array fa_rows_cols(FaCodePath path, uint32_t hsk, uint3 // small cols to reduce register count if (ggml_is_quantized(type) || hsk >= 256) { - return {64, 32}; + if (hsk >= 512) { + return {32, 32}; + } else { + return {64, 32}; + } } return {64, 64}; } @@ -1803,7 +1893,7 @@ static bool ggml_vk_matmul_shmem_support(const vk_device& device, const std::vec const uint32_t warps = warptile[0] / warptile[10]; const uint32_t load_bufs = (warptile[1] + warptile[2]) * (warptile[3] + bank_conflict_offset) * type_size; - const uint32_t mmid_row_ids = mul_mat_id ? 4096 * sizeof(uint32_t) : 0; + const uint32_t mmid_row_ids = mul_mat_id ? (4096 * sizeof(uint32_t) + 4/*_ne1*/) : 0; const uint32_t coopmat_stage = device->coopmat_support ? warptile[7] * warptile[8] / warps * sizeof(float) : 0; const uint32_t total_size = load_bufs + mmid_row_ids + coopmat_stage + lut_size; @@ -1928,10 +2018,10 @@ static void ggml_vk_load_shaders(vk_device& device) { s_mmq_wg_denoms_k = { 32, 32, 1 }; // spec constants and tile sizes for quant matmul_id - l_warptile_mmqid = { 256, 128, 64, 16, 0 }; + l_warptile_mmqid = { 256, 128, 128, 16, 0 }; m_warptile_mmqid = { 256, 128, 64, 16, 0 }; s_warptile_mmqid = { 256, 128, 64, 16, 0 }; - l_mmqid_wg_denoms = { 128, 64, 1 }; + l_mmqid_wg_denoms = { 128, 128, 1 }; m_mmqid_wg_denoms = { 128, 64, 1 }; s_mmqid_wg_denoms = { 128, 64, 1 }; @@ -2688,7 +2778,7 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ4_NL], "get_rows_iq4_nl_f32", get_rows_iq4_nl_f32_len, get_rows_iq4_nl_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_matmul_split_k_reduce, "split_k_reduce", split_k_reduce_len, split_k_reduce_data, "main", 2, 2 * sizeof(uint32_t), {256 * 4, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_flash_attn_split_k_reduce, "fa_split_k_reduce", fa_split_k_reduce_len, fa_split_k_reduce_data, "main", 2, 3 * sizeof(uint32_t), {1, 1, 1}, {}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_flash_attn_split_k_reduce, "fa_split_k_reduce", fa_split_k_reduce_len, fa_split_k_reduce_data, "main", 2, 4 * sizeof(uint32_t), {1, device->subgroup_size, 1}, {device->subgroup_size}, 1, true); ggml_vk_create_pipeline(device, device->pipeline_quantize_q8_1, "quantize_q8_1", quantize_q8_1_len, quantize_q8_1_data, "main", 2, 1 * sizeof(uint32_t), {32 * device->subgroup_size / 8, 1, 1}, { device->subgroup_size }, 1); for (uint32_t i = 0; i < p021_max_gqa_ratio; ++i) { @@ -2702,9 +2792,10 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_norm_f32, "norm_f32", norm_f32_len, norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_group_norm_f32, "group_norm_f32", group_norm_f32_len, group_norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_rms_norm_f32, "rms_norm_f32", rms_norm_f32_len, rms_norm_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_fused_rms_norm_f32, "fused_rms_norm_f32", fused_rms_norm_f32_len, fused_rms_norm_f32_data, "main", 3, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rms_norm_f32, "rms_norm_f32", rms_norm_f32_len, rms_norm_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {0, 0}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rms_norm_mul_f32, "rms_norm_mul_f32", rms_norm_f32_len, rms_norm_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {0, 1}, 1); ggml_vk_create_pipeline(device, device->pipeline_rms_norm_back_f32, "rms_norm_back_f32", rms_norm_back_f32_len, rms_norm_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_l2_norm_f32, "l2_norm_f32", l2_norm_f32_len, l2_norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_f32, "cpy_f32_f32", cpy_f32_f32_len, cpy_f32_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_f16, "cpy_f32_f16", cpy_f32_f16_len, cpy_f32_f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); @@ -2719,19 +2810,41 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_f32_bf16,"contig_cpy_f32_bf16",contig_cpy_f32_bf16_len,contig_cpy_f32_bf16_data,"main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); if (device->float_controls_rte_fp16) { - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_0], "cpy_f32_q4_0", cpy_f32_q4_0_rte_len, cpy_f32_q4_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_0), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_1], "cpy_f32_q4_1", cpy_f32_q4_1_rte_len, cpy_f32_q4_1_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_1), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_0], "cpy_f32_q5_0", cpy_f32_q5_0_rte_len, cpy_f32_q5_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_0), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_1], "cpy_f32_q5_1", cpy_f32_q5_1_rte_len, cpy_f32_q5_1_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_1), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_rte_len, cpy_f32_q8_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q8_0), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_rte_len, cpy_f32_iq4_nl_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_IQ4_NL), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_0], "cpy_f32_q4_0", cpy_f32_q4_0_rte_len, cpy_f32_q4_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_1], "cpy_f32_q4_1", cpy_f32_q4_1_rte_len, cpy_f32_q4_1_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_0], "cpy_f32_q5_0", cpy_f32_q5_0_rte_len, cpy_f32_q5_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_1], "cpy_f32_q5_1", cpy_f32_q5_1_rte_len, cpy_f32_q5_1_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_rte_len, cpy_f32_q8_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_rte_len, cpy_f32_iq4_nl_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); } else { - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_0], "cpy_f32_q4_0", cpy_f32_q4_0_len, cpy_f32_q4_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_0), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_1], "cpy_f32_q4_1", cpy_f32_q4_1_len, cpy_f32_q4_1_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_1), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_0], "cpy_f32_q5_0", cpy_f32_q5_0_len, cpy_f32_q5_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_0), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_1], "cpy_f32_q5_1", cpy_f32_q5_1_len, cpy_f32_q5_1_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_1), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_len, cpy_f32_q8_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q8_0), 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_len, cpy_f32_iq4_nl_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_IQ4_NL), 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_0], "cpy_f32_q4_0", cpy_f32_q4_0_len, cpy_f32_q4_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_1], "cpy_f32_q4_1", cpy_f32_q4_1_len, cpy_f32_q4_1_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_0], "cpy_f32_q5_0", cpy_f32_q5_0_len, cpy_f32_q5_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q5_1], "cpy_f32_q5_1", cpy_f32_q5_1_len, cpy_f32_q5_1_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_len, cpy_f32_q8_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_len, cpy_f32_iq4_nl_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1); + } + + if (device->float_controls_rte_fp16) { + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_F32], "set_rows_f32", set_rows_f32_rte_len, set_rows_f32_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_F16], "set_rows_f16", set_rows_f16_rte_len, set_rows_f16_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_BF16], "set_rows_bf16", set_rows_bf16_rte_len, set_rows_bf16_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q4_0], "set_rows_q4_0", set_rows_q4_0_rte_len, set_rows_q4_0_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q4_1], "set_rows_q4_1", set_rows_q4_1_rte_len, set_rows_q4_1_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q5_0], "set_rows_q5_0", set_rows_q5_0_rte_len, set_rows_q5_0_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q5_1], "set_rows_q5_1", set_rows_q5_1_rte_len, set_rows_q5_1_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q8_0], "set_rows_q8_0", set_rows_q8_0_rte_len, set_rows_q8_0_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_IQ4_NL], "set_rows_iq4_nl", set_rows_iq4_nl_rte_len, set_rows_iq4_nl_rte_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + } else { + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_F32], "set_rows_f32", set_rows_f32_len, set_rows_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_F16], "set_rows_f16", set_rows_f16_len, set_rows_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_BF16], "set_rows_bf16", set_rows_bf16_len, set_rows_bf16_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q4_0], "set_rows_q4_0", set_rows_q4_0_len, set_rows_q4_0_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q4_1], "set_rows_q4_1", set_rows_q4_1_len, set_rows_q4_1_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q5_0], "set_rows_q5_0", set_rows_q5_0_len, set_rows_q5_0_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q5_1], "set_rows_q5_1", set_rows_q5_1_len, set_rows_q5_1_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_Q8_0], "set_rows_q8_0", set_rows_q8_0_len, set_rows_q8_0_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); + ggml_vk_create_pipeline(device, device->pipeline_set_rows[GGML_TYPE_IQ4_NL], "set_rows_iq4_nl", set_rows_iq4_nl_len, set_rows_iq4_nl_data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); } ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q4_0], "cpy_q4_0_f32", cpy_q4_0_f32_len, cpy_q4_0_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_0), 1, 1}, {}, 1); @@ -2771,16 +2884,18 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_concat_f16, "concat_f16", concat_f16_len, concat_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_concat_i32, "concat_i32", concat_i32_len, concat_i32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_upscale_f32, "upscale_f32", upscale_f32_len, upscale_f32_data, "main", 2, sizeof(vk_op_upscale_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_scale_f32, "scale_f32", scale_f32_len, scale_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_sqr_f32, "sqr_f32", sqr_f32_len, sqr_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_sin_f32, "sin_f32", sin_f32_len, sin_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_cos_f32, "cos_f32", cos_f32_len, cos_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_clamp_f32, "clamp_f32", clamp_f32_len, clamp_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_pad_f32, "pad_f32", pad_f32_len, pad_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_roll_f32, "roll_f32", roll_f32_len, roll_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_repeat_f32, "repeat_f32", repeat_f32_len, repeat_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_repeat_back_f32, "repeat_back_f32", repeat_back_f32_len, repeat_back_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); @@ -2789,6 +2904,7 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_ ## name [1], #name "_f16", name ## _f16_len, name ## _f16_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); CREATE_UNARY(gelu) + CREATE_UNARY(gelu_erf) CREATE_UNARY(gelu_quick) CREATE_UNARY(silu) CREATE_UNARY(relu) @@ -2796,14 +2912,16 @@ static void ggml_vk_load_shaders(vk_device& device) { CREATE_UNARY(sigmoid) #undef CREATE_UNARY - ggml_vk_create_pipeline(device, device->pipeline_fused_mul_silu[0], "fused_mul_silu_f32", fused_mul_silu_f32_len, fused_mul_silu_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_fused_mul_silu[1], "fused_mul_silu_f16", fused_mul_silu_f16_len, fused_mul_silu_f16_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_fused_mul_gelu[0], "fused_mul_gelu_f32", fused_mul_gelu_f32_len, fused_mul_gelu_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_fused_mul_gelu[1], "fused_mul_gelu_f16", fused_mul_gelu_f16_len, fused_mul_gelu_f16_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[0], "fused_mul_relu_f32", fused_mul_relu_f32_len, fused_mul_relu_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); - ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[1], "fused_mul_relu_f16", fused_mul_relu_f16_len, fused_mul_relu_f16_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); +#define CREATE_GLU(name) \ + ggml_vk_create_pipeline(device, device->pipeline_ ## name [0], #name "_f32", name ## _f32_len, name ## _f32_data, "main", 3, sizeof(vk_op_glu_push_constants), {512, 1, 1}, {}, 1, true); \ + ggml_vk_create_pipeline(device, device->pipeline_ ## name [1], #name "_f16", name ## _f16_len, name ## _f16_data, "main", 3, sizeof(vk_op_glu_push_constants), {512, 1, 1}, {}, 1, true); - ggml_vk_create_pipeline(device, device->pipeline_multi_add_f32, "multi_add_f32", multi_add_f32_len, multi_add_f32_data, "main", 2, sizeof(vk_op_multiadd_push_constants), {512, 1, 1}, {}, 1); + CREATE_GLU(geglu) + CREATE_GLU(reglu) + CREATE_GLU(swiglu) + CREATE_GLU(geglu_erf) + CREATE_GLU(geglu_quick) +#undef CREATE_GLU ggml_vk_create_pipeline(device, device->pipeline_leaky_relu_f32, "leaky_relu_f32", leaky_relu_f32_len, leaky_relu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); ggml_vk_create_pipeline(device, device->pipeline_silu_back_f32, "silu_back_f32", silu_back_f32_len, silu_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); @@ -2856,8 +2974,37 @@ static void ggml_vk_load_shaders(vk_device& device) { ggml_vk_create_pipeline(device, device->pipeline_rwkv_wkv6_f32, "rwkv_wkv6_f32", rwkv_wkv6_f32_len, rwkv_wkv6_f32_data, "main", 7, sizeof(vk_op_rwkv_wkv6_push_constants), {1, 1, 1}, {device->subgroup_size}, 1); + ggml_vk_create_pipeline(device, device->pipeline_rwkv_wkv7_f32, "rwkv_wkv7_f32", rwkv_wkv7_f32_len, rwkv_wkv7_f32_data, "main", 8, sizeof(vk_op_rwkv_wkv7_push_constants), {1, 1, 1}, {device->subgroup_size}, 1); + ggml_vk_create_pipeline(device, device->pipeline_opt_step_adamw_f32, "opt_step_adamw_f32", opt_step_adamw_f32_len, opt_step_adamw_f32_data, "main", 5, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_conv2d_dw_whcn_f32, "conv2d_dw_whcn_f32", conv2d_dw_whcn_f32_len, conv2d_dw_whcn_f32_data, "main", 3, sizeof(vk_op_conv2d_dw_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_conv2d_dw_cwhn_f32, "conv2d_dw_cwhn_f32", conv2d_dw_cwhn_f32_len, conv2d_dw_cwhn_f32_data, "main", 3, sizeof(vk_op_conv2d_dw_push_constants), {512, 1, 1}, {}, 1); + + // ================================ ik_llama.cpp pipelines begin ========================================= + // + ggml_vk_create_pipeline(device, device->pipeline_fused_rms_norm_f32, "fused_rms_norm_f32", fused_rms_norm_f32_len, fused_rms_norm_f32_data, + "main", 3, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1); + + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_silu[0], "fused_mul_silu_f32", fused_mul_silu_f32_len, fused_mul_silu_f32_data, + "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_silu[1], "fused_mul_silu_f16", fused_mul_silu_f16_len, fused_mul_silu_f16_data, + "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_gelu[0], "fused_mul_gelu_f32", fused_mul_gelu_f32_len, fused_mul_gelu_f32_data, + "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_gelu[1], "fused_mul_gelu_f16", fused_mul_gelu_f16_len, fused_mul_gelu_f16_data, + "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[0], "fused_mul_relu_f32", fused_mul_relu_f32_len, fused_mul_relu_f32_data, + "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + ggml_vk_create_pipeline(device, device->pipeline_fused_mul_relu[1], "fused_mul_relu_f16", fused_mul_relu_f16_len, fused_mul_relu_f16_data, + "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); + + ggml_vk_create_pipeline(device, device->pipeline_multi_add_f32, "multi_add_f32", multi_add_f32_len, multi_add_f32_data, + "main", 2, sizeof(vk_op_multiadd_push_constants), {512, 1, 1}, {}, 1); + // + // ================================ ik_llama.cpp pipelines end ========================================= + + for (auto &c : compiles) { c.wait(); } @@ -3479,6 +3626,8 @@ static vk_device ggml_vk_get_device(size_t idx) { device->idx = idx; + device->disable_fusion = getenv("GGML_VK_DISABLE_FUSION") != nullptr; + return device; } @@ -3597,8 +3746,8 @@ static void ggml_vk_print_gpu_info(size_t idx) { fp16 = fp16 && vk12_features.shaderFloat16; uint32_t default_subgroup_size = get_subgroup_size("", device_architecture); - const size_t subgroup_size = (default_subgroup_size != 0) ? default_subgroup_size : subgroup_props.subgroupSize; - const bool uma = props2.properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu; + [[maybe_unused]] const size_t subgroup_size = (default_subgroup_size != 0) ? default_subgroup_size : subgroup_props.subgroupSize; + [[maybe_unused]] const bool uma = props2.properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu; integer_dot_product = integer_dot_product && shader_integer_dot_product_props.integerDotProduct4x8BitPackedSignedAccelerated @@ -3618,7 +3767,7 @@ static void ggml_vk_print_gpu_info(size_t idx) { props2.properties.limits.maxComputeSharedMemorySize, integer_dot_product, matrix_cores.c_str()); if (props2.properties.deviceType == vk::PhysicalDeviceType::eCpu) { - GGML_LOG_INFO("ggml_vulkan: Warning: Device type is CPU. This is probably not the device you want.\n"); + GGML_LOG_WARN("ggml_vulkan: Warning: Device type is CPU. This is probably not the device you want.\n"); } } @@ -3627,14 +3776,12 @@ static bool ggml_vk_instance_portability_enumeration_ext_available(const std::ve static bool ggml_vk_instance_debug_utils_ext_available(const std::vector & instance_extensions); -GGML_CALL void ggml_vk_instance_init() { +static void ggml_vk_instance_init() { if (vk_instance_initialized) { return; } VK_LOG_DEBUG("ggml_vk_instance_init()"); - vk_instance_initialized = true; - uint32_t api_version = vk::enumerateInstanceVersion(); if (api_version < VK_API_VERSION_1_2) { @@ -3688,6 +3835,7 @@ GGML_CALL void ggml_vk_instance_init() { GGML_LOG_DEBUG("ggml_vulkan: Validation layers enabled\n"); } vk_instance.instance = vk::createInstance(instance_create_info); + vk_instance_initialized = true; if (debug_utils_ext) { vk_instance.debug_utils_support = true; @@ -3725,7 +3873,7 @@ GGML_CALL void ggml_vk_instance_init() { // If no vulkan devices are found, return early if (devices.empty()) { GGML_LOG_INFO("ggml_vulkan: No devices found.\n"); - GGML_ABORT("fatal error"); + return; } // Default to using all dedicated GPUs @@ -4028,6 +4176,11 @@ static vk_matmul_pipeline ggml_vk_get_mul_mat_mat_id_pipeline(ggml_backend_vk_co } } + if (!(src1_type == GGML_TYPE_F32 || (ctx->device->coopmat2 && src1_type == GGML_TYPE_F16))) { + // Better we return a nullptr than assert below + return nullptr; + } + GGML_ASSERT(src1_type == GGML_TYPE_F32 || (ctx->device->coopmat2 && src1_type == GGML_TYPE_F16)); switch (src0_type) { @@ -4233,7 +4386,33 @@ static vk_submission ggml_vk_begin_submission(vk_device& device, vk_command_pool return s; } -static void ggml_vk_dispatch_pipeline(ggml_backend_vk_context* ctx, vk_context& subctx, vk_pipeline& pipeline, std::initializer_list const& descriptor_buffer_infos, size_t push_constant_size, const void* push_constants, std::array elements) { +template size_t push_constant_size(const T &t) { + static_assert(std::is_class::value, "T must be a struct/class"); + GGML_UNUSED(t); + return sizeof(T); +} +template size_t push_constant_size(const std::vector &t) { + GGML_UNUSED(t); + return sizeof(T) * t.size(); +} +template size_t push_constant_size(const std::array &t) { + GGML_UNUSED(t); + return sizeof(T) * N; +} + +template const T *push_constant_data(const T &t) { + static_assert(std::is_class::value, "T must be a struct/class"); + return &t; +} +template const T *push_constant_data(const std::vector &t) { + return t.data(); +} +template const T *push_constant_data(const std::array &t) { + return t.data(); +} + +template +static void ggml_vk_dispatch_pipeline(ggml_backend_vk_context* ctx, vk_context& subctx, vk_pipeline& pipeline, std::initializer_list const& descriptor_buffer_infos, const T &push_constants, std::array elements) { const uint32_t wg0 = CEIL_DIV(elements[0], pipeline->wg_denoms[0]); const uint32_t wg1 = CEIL_DIV(elements[1], pipeline->wg_denoms[1]); const uint32_t wg2 = CEIL_DIV(elements[2], pipeline->wg_denoms[2]); @@ -4249,7 +4428,7 @@ static void ggml_vk_dispatch_pipeline(ggml_backend_vk_context* ctx, vk_context& vk::WriteDescriptorSet write_descriptor_set{ descriptor_set, 0, 0, pipeline->parameter_count, vk::DescriptorType::eStorageBuffer, nullptr, descriptor_buffer_infos.begin() }; ctx->device->device.updateDescriptorSets({ write_descriptor_set }, {}); - subctx->s->buffer.pushConstants(pipeline->layout, vk::ShaderStageFlagBits::eCompute, 0, push_constant_size, push_constants); + subctx->s->buffer.pushConstants(pipeline->layout, vk::ShaderStageFlagBits::eCompute, 0, push_constant_size(push_constants), push_constant_data(push_constants)); subctx->s->buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->pipeline); subctx->s->buffer.bindDescriptorSets(vk::PipelineBindPoint::eCompute, pipeline->layout, @@ -4722,7 +4901,7 @@ static void ggml_vk_matmul( ggml_vk_sync_buffers(subctx); if (split_k == 1) { const vk_mat_mat_push_constants pc = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, k, ne02, ne12, broadcast2, broadcast3, padded_n }; - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, d }, sizeof(vk_mat_mat_push_constants), &pc, { m, n, batch }); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, d }, pc, { m, n, batch }); return; } @@ -4730,10 +4909,10 @@ static void ggml_vk_matmul( const vk_mat_mat_push_constants pc1 = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, CEIL_DIV(k, split_k), ne02, ne12, broadcast2, broadcast3, padded_n }; // Make sure enough workgroups get assigned for split k to work - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, split_k_buffer }, sizeof(vk_mat_mat_push_constants), &pc1, { (CEIL_DIV(m, pipeline->wg_denoms[0]) * pipeline->wg_denoms[0]) * split_k, n, batch }); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, split_k_buffer }, pc1, { (CEIL_DIV(m, pipeline->wg_denoms[0]) * pipeline->wg_denoms[0]) * split_k, n, batch }); ggml_vk_sync_buffers(subctx); const std::array pc2 = { (uint32_t)(m * n * batch), split_k }; - ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_matmul_split_k_reduce, { split_k_buffer, d }, pc2.size() * sizeof(uint32_t), pc2.data(), { m * n * batch, 1, 1 }); + ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_matmul_split_k_reduce, { split_k_buffer, d }, pc2, { m * n * batch, 1, 1 }); } static vk_pipeline ggml_vk_guess_matmul_id_pipeline(ggml_backend_vk_context * ctx, vk_matmul_pipeline& mmp, uint32_t m, uint32_t n, bool aligned, ggml_type src0_type) { @@ -4781,7 +4960,7 @@ static void ggml_vk_matmul_id( ggml_vk_sync_buffers(subctx); const vk_mat_mat_id_push_constants pc = { m, n, k, stride_a, stride_b, stride_d, batch_stride_a, batch_stride_b, batch_stride_d, nei0, nei1, nbi1, ne11, padded_n }; - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, d, ids }, sizeof(vk_mat_mat_id_push_constants), &pc, { m, nei1, n_as }); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { a, b, d, ids }, pc, { m, nei1, n_as }); } static bool ggml_vk_dim01_contiguous(const ggml_tensor * tensor) { @@ -4910,7 +5089,7 @@ static void ggml_vk_cpy_to_contiguous(ggml_backend_vk_context * ctx, vk_context& }; init_pushconst_fastdiv(pc); ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, sizeof(vk_op_unary_push_constants), &pc, elements); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, pc, elements); } static vk_pipeline ggml_vk_get_quantize_pipeline(ggml_backend_vk_context * ctx, ggml_type type) { @@ -4929,7 +5108,7 @@ static void ggml_vk_quantize_q8_1(ggml_backend_vk_context * ctx, vk_context& sub vk_pipeline pipeline = ggml_vk_get_quantize_pipeline(ctx, GGML_TYPE_Q8_1); ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, sizeof(uint32_t), &ne, { ne, 1, 1 }); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, std::array{ne}, { ne, 1, 1 }); } static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { @@ -5129,7 +5308,7 @@ static void ggml_vk_mul_mat_q_f16(ggml_backend_vk_context * ctx, vk_context& sub } else if (qx_needs_dequant) { const std::vector pc = { (uint32_t)ne01, (uint32_t)ne10, (uint32_t)ne10, (uint32_t)ne10, (uint32_t)(ggml_nelements(src0)) }; ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, to_fp16_vk_0, { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz * ne02 * ne03 }, vk_subbuffer{ d_X, 0, x_sz * ne02 * ne03 } }, pc.size() * sizeof(uint32_t), pc.data(), { (uint32_t)(x_ne * ne02 * ne03), 1, 1}); + ggml_vk_dispatch_pipeline(ctx, subctx, to_fp16_vk_0, { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz * ne02 * ne03 }, vk_subbuffer{ d_X, 0, x_sz * ne02 * ne03 } }, pc, { (uint32_t)(x_ne * ne02 * ne03), 1, 1}); } if (y_non_contig) { ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_1, src1, { d_Qy, qy_buf_offset, VK_WHOLE_SIZE }, { d_Y, 0, VK_WHOLE_SIZE }); @@ -5345,7 +5524,7 @@ static void ggml_vk_mul_mat_vec_q_f16(ggml_backend_vk_context * ctx, vk_context& ggml_vk_sync_buffers(subctx); ggml_vk_dispatch_pipeline(ctx, subctx, dmmv, { vk_subbuffer{ d_X, x_buf_offset, x_sz * ne02 * ne03 }, vk_subbuffer{ d_Y, y_buf_offset, y_sz * ne12 * ne13 }, vk_subbuffer{ d_D, d_buf_offset, d_sz * ne22 * ne23} }, - sizeof(vk_mat_vec_push_constants), &pc, { groups_x, (uint32_t)(ne12 * ne13), groups_z }); + pc, { groups_x, (uint32_t)(ne12 * ne13), groups_z }); } static void ggml_vk_mul_mat_vec_p021_f16_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { @@ -5433,7 +5612,7 @@ static void ggml_vk_mul_mat_vec_p021_f16_f32(ggml_backend_vk_context * ctx, vk_c } ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_mul_mat_vec_p021_f16_f32[gqa_ratio - 1], { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz }, vk_subbuffer{ d_Qy, qy_buffer_offset, qy_sz + qy_shader_offset }, vk_subbuffer{ d_D, d_buffer_offset, d_sz + d_shader_offset } }, 6 * sizeof(uint32_t), &pc, { 1, (uint32_t)ne01, workgroups_z }); + ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_mul_mat_vec_p021_f16_f32[gqa_ratio - 1], { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz }, vk_subbuffer{ d_Qy, qy_buffer_offset, qy_sz + qy_shader_offset }, vk_subbuffer{ d_D, d_buffer_offset, d_sz + d_shader_offset } }, pc, { 1, (uint32_t)ne01, workgroups_z }); } static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { @@ -5516,7 +5695,7 @@ static void ggml_vk_mul_mat_vec_nc_f16_f32(ggml_backend_vk_context * ctx, vk_con const std::array pc = { (uint32_t)ne00, (uint32_t)ne01, row_stride_x, channel_stride_x, channel_stride_y, (uint32_t)(ne12 / ne02), (uint32_t)ne12, (uint32_t)(qy_shader_offset / ggml_type_size(src1->type)), (uint32_t)(d_shader_offset / ggml_type_size(dst->type)) }; ggml_vk_sync_buffers(subctx); ggml_vk_dispatch_pipeline(ctx, subctx, ctx->device->pipeline_mul_mat_vec_nc_f16_f32, - { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz }, vk_subbuffer{ d_Qy, qy_buffer_offset, qy_sz + qy_shader_offset }, vk_subbuffer{ d_D, d_buffer_offset, d_sz + d_shader_offset } }, 7 * sizeof(uint32_t), &pc, { 1, (uint32_t)ne01, (uint32_t)ne12 }); + { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz }, vk_subbuffer{ d_Qy, qy_buffer_offset, qy_sz + qy_shader_offset }, vk_subbuffer{ d_D, d_buffer_offset, d_sz + d_shader_offset } }, pc, { 1, (uint32_t)ne01, (uint32_t)ne12 }); } static void ggml_vk_mul_mat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { @@ -5565,9 +5744,6 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& const uint64_t nei0 = ids->ne[0]; const uint64_t nei1 = ids->ne[1]; - if (nei0*nei1 > 4096) { - fprintf(stderr, "%s: nei0 = %d, nei1 = %d\n", __func__, (int)nei0, (int)nei1); - } GGML_ASSERT(nei0 * nei1 <= 4096); const uint32_t nbi1 = ids->nb[1]; @@ -5735,7 +5911,7 @@ static void ggml_vk_mul_mat_id_q_f16(ggml_backend_vk_context * ctx, vk_context& const std::vector pc = { (uint32_t)ne01, (uint32_t)ne10, (uint32_t)ne10, (uint32_t)ne10, (uint32_t)(ggml_nelements(src0)) }; ggml_vk_sync_buffers(subctx); ggml_vk_dispatch_pipeline(ctx, subctx, to_fp16_vk_0, - { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz * ne02 * ne03 }, vk_subbuffer{ d_X, 0, x_sz * ne02 * ne03 } }, pc.size() * sizeof(uint32_t), pc.data(), { (uint32_t)(x_ne * ne02 * ne03), 1, 1}); + { vk_subbuffer{ d_Qx, qx_buf_offset, qx_sz * ne02 * ne03 }, vk_subbuffer{ d_X, 0, x_sz * ne02 * ne03 } }, pc, { (uint32_t)(x_ne * ne02 * ne03), 1, 1}); } if (y_non_contig) { ggml_vk_cpy_to_contiguous(ctx, subctx, to_fp16_vk_1, src1, { d_Qy, qy_buf_offset, VK_WHOLE_SIZE }, { d_Y, 0, VK_WHOLE_SIZE }); @@ -5955,7 +6131,7 @@ static void ggml_vk_mul_mat_vec_id_q_f16(ggml_backend_vk_context * ctx, vk_conte ggml_vk_dispatch_pipeline(ctx, subctx, dmmv, { vk_subbuffer{ d_X, x_buf_offset, x_sz * ne02 * ne03 }, vk_subbuffer{ d_Y, y_buf_offset, y_sz * ne12 * ne13 }, vk_subbuffer{ d_D, d_buf_offset, d_sz * ne22 * ne23}, vk_subbuffer{ d_ids, ids_buf_offset, ids_sz } }, - sizeof(vk_mat_vec_id_push_constants), &pc, { groups_x, (uint32_t)nei0, groups_z }); + pc, { groups_x, (uint32_t)nei0, groups_z }); } static void ggml_vk_mul_mat_id(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst, bool dryrun = false) { @@ -5981,9 +6157,15 @@ static void ggml_vk_mul_mat_id(ggml_backend_vk_context * ctx, vk_context& subctx src2_copy.view_offs = src2->view_offs + token_start * src2_copy.nb[1]; dst_copy.view_offs = dst->view_offs + token_start * dst_copy.nb[2]; + // Note: we do need to update the nb members, else the copies are interpreted as being non-contiguous, + // triggers an assert src1_copy.ne[2] = n_tokens; + src1_copy.nb[3] = src1_copy.nb[2] * src1_copy.ne[2]; src2_copy.ne[1] = n_tokens; + src2_copy.nb[2] = src2_copy.nb[1] * src2_copy.ne[1]; + src2_copy.nb[3] = src2_copy.nb[2] * src2_copy.ne[2]; dst_copy.ne[2] = n_tokens; + dst_copy.nb[3] = dst_copy.nb[2] * dst_copy.ne[2]; ggml_vk_mul_mat_id_q_f16(ctx, subctx, src0, &src1_copy, &src2_copy, &dst_copy, dryrun); } @@ -5994,7 +6176,7 @@ static bool ggml_vk_flash_attn_scalar_shmem_support(const vk_device& device, con // Needs to be kept up to date on shader changes GGML_UNUSED(hsv); const uint32_t wg_size = scalar_flash_attention_workgroup_size; - const uint32_t Br = scalar_flash_attention_num_large_rows; + const uint32_t Br = get_fa_scalar_num_large_rows(hsv); const uint32_t Bc = scalar_flash_attention_Bc; const uint32_t tmpsh = wg_size * sizeof(float); @@ -6060,7 +6242,8 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx GGML_TENSOR_LOCALS(size_t, nb, dst, nb) const uint32_t nem1 = mask ? mask->ne[1] : 0; - const uint32_t nbm1 = mask ? mask->nb[1] : 0; + const uint32_t nem2 = mask ? mask->ne[2] : 0; + const uint32_t nem3 = mask ? mask->ne[3] : 0; const uint32_t HSK = nek0; const uint32_t HSV = nev0; @@ -6118,7 +6301,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx case FA_SCALAR: case FA_COOPMAT1: // We may switch from coopmat1 to scalar, so use the scalar limit for both - max_gqa = scalar_flash_attention_num_large_rows; + max_gqa = get_fa_scalar_num_large_rows(HSV); break; case FA_COOPMAT2: max_gqa = get_fa_num_small_rows(FA_COOPMAT2); @@ -6128,7 +6311,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx } if (N == 1 && qk_ratio > 1 && qk_ratio <= max_gqa && - qk_ratio * nek2 == neq2 && nek2 == nev2 && neq3 == 1 && nek3 == 1 && nev3 == 1) { + qk_ratio * nek2 == neq2 && nek2 == nev2 && nem2 <= 1) { // grouped query attention - make the N dimension equal to gqa_ratio, reduce // workgroups proportionally in y dimension. The shader will detect gqa_ratio > 1 // and change addressing calculations to index Q's dimension 2. @@ -6197,13 +6380,13 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx const uint32_t shader_core_count = ctx->device->shader_core_count ? ctx->device->shader_core_count : 16; // Try to use split_k when KV is large enough to be worth the overhead - if (workgroups_x == 1 && shader_core_count > 0 && KV >= 512) { + if (workgroups_x == 1 && shader_core_count > 0) { // Try to run two workgroups per SM. split_k = shader_core_count * 2 / (workgroups_y * workgroups_z); if (split_k > 1) { // Try to evenly split KV into split_k chunks, but it needs to be a multiple // of "align", so recompute split_k based on that. - split_kv = ROUNDUP_POW2(KV / split_k, pipelines[1]->align); + split_kv = ROUNDUP_POW2(std::max(1u, KV / split_k), pipelines[1]->align); split_k = CEIL_DIV(KV, split_kv); workgroups_x = split_k; } @@ -6298,18 +6481,19 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx } } + uint32_t mask_n_head_log2 = ((mask != nullptr) << 16) | n_head_log2; + const vk_flash_attn_push_constants pc = { N, KV, (uint32_t)ne1, (uint32_t)ne2, (uint32_t)ne3, (uint32_t)neq2, (uint32_t)neq3, (uint32_t)nek2, (uint32_t)nek3, (uint32_t)nev2, (uint32_t)nev3, - nem1, + nem1, nem2, nem3, q_stride, (uint32_t)nbq2, (uint32_t)nbq3, k_stride, (uint32_t)nbk2, (uint32_t)nbk3, v_stride, (uint32_t)nbv2, (uint32_t)nbv3, - nbm1, scale, max_bias, logit_softcap, - mask != nullptr, n_head_log2, m0, m1, + mask_n_head_log2, m0, m1, gqa_ratio, split_kv, split_k }; ggml_vk_sync_buffers(subctx); @@ -6327,7 +6511,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx // there's no more than one tile of rows (i.e. workgroups_x would have been // one). We reuse workgroups_x to mean the number of splits, so we need to // cancel out the divide by wg_denoms[0]. - sizeof(vk_flash_attn_push_constants), &pc, { workgroups_x * pipeline->wg_denoms[0], workgroups_y, workgroups_z }); + pc, { workgroups_x * pipeline->wg_denoms[0], workgroups_y, workgroups_z }); ggml_vk_sync_buffers(subctx); const std::array pc2 = { HSV, (uint32_t)ne1, (uint32_t)ne3, split_k }; @@ -6336,7 +6520,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx vk_subbuffer{ctx->prealloc_split_k, 0, VK_WHOLE_SIZE}, vk_subbuffer{d_D, d_buf_offset, VK_WHOLE_SIZE}, }, - pc2.size() * uint32_t{sizeof(uint32_t)}, pc2.data(), { (uint32_t)ne1, 1, 1 }); + pc2, { (uint32_t)ne1, HSV, (uint32_t)ne3 }); } else { ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { @@ -6346,10 +6530,14 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx vk_subbuffer{d_M, m_buf_offset, VK_WHOLE_SIZE}, vk_subbuffer{d_D, d_buf_offset, VK_WHOLE_SIZE}, }, - sizeof(vk_flash_attn_push_constants), &pc, { workgroups_x, workgroups_y, workgroups_z }); + pc, { workgroups_x, workgroups_y, workgroups_z }); } } +#define GGML_ROPE_TYPE_NEOX 2 +#define GGML_ROPE_TYPE_MROPE 8 +#define GGML_ROPE_TYPE_VISION 24 + static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, ggml_tensor * dst, ggml_op op) { switch (op) { case GGML_OP_GET_ROWS: @@ -6361,6 +6549,11 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_get_rows_f32[src0->type]; } return nullptr; + case GGML_OP_ACC: + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_acc_f32; + } + return nullptr; case GGML_OP_ADD: case GGML_OP_SUB: case GGML_OP_MUL: @@ -6406,11 +6599,6 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_concat_i32; } return nullptr; - case GGML_OP_UPSCALE: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_upscale_f32; - } - return nullptr; case GGML_OP_SCALE: if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_scale_f32; @@ -6421,6 +6609,16 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_sqr_f32; } return nullptr; + //case GGML_OP_SIN: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // return ctx->device->pipeline_sin_f32; + // } + // return nullptr; + //case GGML_OP_COS: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // return ctx->device->pipeline_cos_f32; + // } + // return nullptr; case GGML_OP_CLAMP: if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_clamp_f32; @@ -6431,6 +6629,11 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_pad_f32; } return nullptr; + //case GGML_OP_ROLL: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // return ctx->device->pipeline_roll_f32; + // } + // return nullptr; case GGML_OP_REPEAT: if (ggml_type_size(src0->type) == sizeof(float) && ggml_type_size(dst->type) == sizeof(float)) { return ctx->device->pipeline_repeat_f32; @@ -6445,6 +6648,8 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const case GGML_OP_CONT: case GGML_OP_DUP: return ggml_vk_get_cpy_pipeline(ctx, src0, dst, dst->type); + //case GGML_OP_SET_ROWS: + // return ctx->device->pipeline_set_rows[dst->type]; case GGML_OP_SILU_BACK: if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { return ctx->device->pipeline_silu_back_f32; @@ -6462,12 +6667,7 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return nullptr; case GGML_OP_RMS_NORM: if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_rms_norm_f32; - } - return nullptr; - case GGML_OP_FUSED_RMS_NORM: - if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_fused_rms_norm_f32; + return ctx->num_additional_fused_ops > 0 ? ctx->device->pipeline_rms_norm_mul_f32 : ctx->device->pipeline_rms_norm_f32; } return nullptr; case GGML_OP_RMS_NORM_BACK: @@ -6475,6 +6675,196 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_rms_norm_back_f32; } return nullptr; + //case GGML_OP_L2_NORM: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // return ctx->device->pipeline_l2_norm_f32; + // } + // return nullptr; + case GGML_OP_UNARY: + if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || + (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16) || + (src0->type != dst->type)) { + return nullptr; + } + + switch (ggml_get_unary_op(dst)) { + case GGML_UNARY_OP_SILU: + return ctx->device->pipeline_silu[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_GELU: + return ctx->device->pipeline_gelu[dst->type == GGML_TYPE_F16]; + //case GGML_UNARY_OP_GELU_ERF: + // return ctx->device->pipeline_gelu_erf[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_GELU_QUICK: + return ctx->device->pipeline_gelu_quick[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_RELU: + return ctx->device->pipeline_relu[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_TANH: + return ctx->device->pipeline_tanh[dst->type == GGML_TYPE_F16]; + case GGML_UNARY_OP_SIGMOID: + return ctx->device->pipeline_sigmoid[dst->type == GGML_TYPE_F16]; + default: + break; + } + return nullptr; + //case GGML_OP_GLU: + // if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || + // (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16) || + // (src0->type != dst->type)) { + // return nullptr; + // } + + // switch (ggml_get_glu_op(dst)) { + // case GGML_GLU_OP_GEGLU: + // return ctx->device->pipeline_geglu[dst->type == GGML_TYPE_F16]; + // case GGML_GLU_OP_REGLU: + // return ctx->device->pipeline_reglu[dst->type == GGML_TYPE_F16]; + // case GGML_GLU_OP_SWIGLU: + // return ctx->device->pipeline_swiglu[dst->type == GGML_TYPE_F16]; + // case GGML_GLU_OP_GEGLU_ERF: + // return ctx->device->pipeline_geglu_erf[dst->type == GGML_TYPE_F16]; + // case GGML_GLU_OP_GEGLU_QUICK: + // return ctx->device->pipeline_geglu_quick[dst->type == GGML_TYPE_F16]; + // default: + // break; + // } + // return nullptr; + case GGML_OP_DIAG_MASK_INF: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_diag_mask_inf_f32; + } + return nullptr; + case GGML_OP_SOFT_MAX: + GGML_ASSERT(!src1 || src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16); + + if (src0->type == GGML_TYPE_F32 && (src1 == nullptr || src1->type == GGML_TYPE_F32) && dst->type == GGML_TYPE_F32) { + return src0->ne[0] > 1024 ? ctx->device->pipeline_soft_max_f32_wg512 : ctx->device->pipeline_soft_max_f32; + } + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F32) { + return src0->ne[0] > 1024 ? ctx->device->pipeline_soft_max_f32_f16_wg512 : ctx->device->pipeline_soft_max_f32_f16; + } + return nullptr; + case GGML_OP_SOFT_MAX_BACK: + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_soft_max_back_f32; + } + return nullptr; + case GGML_OP_ROPE: + case GGML_OP_ROPE_BACK: + { + const int mode = ((const int32_t *) dst->op_params)[2]; + const bool is_neox = mode & GGML_ROPE_TYPE_NEOX; + const bool is_mrope = mode & GGML_ROPE_TYPE_MROPE; + const bool is_vision = mode == GGML_ROPE_TYPE_VISION; + + if (is_neox) { + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_rope_neox_f32; + } + if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { + return ctx->device->pipeline_rope_neox_f16; + } + } else if (is_mrope && !is_vision) { + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_rope_multi_f32; + } + if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { + return ctx->device->pipeline_rope_multi_f16; + } + } else if (is_vision) { + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_rope_vision_f32; + } + if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { + return ctx->device->pipeline_rope_vision_f16; + } + } else { + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_rope_norm_f32; + } + if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { + return ctx->device->pipeline_rope_norm_f16; + } + } + return nullptr; + } + case GGML_OP_ARGSORT: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_I32) { + return ctx->device->pipeline_argsort_f32; + } + return nullptr; + case GGML_OP_SUM: + case GGML_OP_SUM_ROWS: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_sum_rows_f32; + } + return nullptr; + case GGML_OP_ARGMAX: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_I32) { + return ctx->device->pipeline_argmax_f32; + } + return nullptr; + //case GGML_OP_COUNT_EQUAL: + // if (src0->type == GGML_TYPE_I32 && src1->type == GGML_TYPE_I32 && dst->type == GGML_TYPE_I64) { + // return ctx->device->pipeline_count_equal_i32; + // } + // return nullptr; + case GGML_OP_IM2COL: + if (src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_im2col_f32; + } + if (src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F16) { + return ctx->device->pipeline_im2col_f32_f16; + } + return nullptr; + case GGML_OP_TIMESTEP_EMBEDDING: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_timestep_embedding_f32; + } + return nullptr; + case GGML_OP_CONV_TRANSPOSE_1D: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_conv_transpose_1d_f32; + } + return nullptr; + case GGML_OP_POOL_2D: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_pool2d_f32; + } + return nullptr; + //case GGML_OP_RWKV_WKV6: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // return ctx->device->pipeline_rwkv_wkv6_f32; + // } + // return nullptr; + //case GGML_OP_RWKV_WKV7: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // return ctx->device->pipeline_rwkv_wkv7_f32; + // } + // return nullptr; + //case GGML_OP_OPT_STEP_ADAMW: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // return ctx->device->pipeline_opt_step_adamw_f32; + // } + // return nullptr; + case GGML_OP_LEAKY_RELU: + if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_leaky_relu_f32; + } + return nullptr; + //case GGML_OP_CONV_2D_DW: + // if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + // if (ggml_is_contiguous(src1)) { + // return ctx->device->pipeline_conv2d_dw_whcn_f32; + // } else if (ggml_is_contiguous_channels(src1)) { + // return ctx->device->pipeline_conv2d_dw_cwhn_f32; + // } + // } + // return nullptr; + case GGML_OP_FUSED_RMS_NORM: + if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { + return ctx->device->pipeline_fused_rms_norm_f32; + } + return nullptr; case GGML_OP_FUSED_MUL_UNARY: if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || (src1->type != GGML_TYPE_F32 && src1->type != GGML_TYPE_F16) || @@ -6501,117 +6891,7 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const return ctx->device->pipeline_multi_add_f32; } return nullptr; - case GGML_OP_UNARY: - if ((src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) || - (dst->type != GGML_TYPE_F32 && dst->type != GGML_TYPE_F16) || - (src0->type != dst->type)) { - return nullptr; - } - switch (ggml_get_unary_op(dst)) { - case GGML_UNARY_OP_SILU: - return ctx->device->pipeline_silu[dst->type == GGML_TYPE_F16]; - case GGML_UNARY_OP_GELU: - return ctx->device->pipeline_gelu[dst->type == GGML_TYPE_F16]; - case GGML_UNARY_OP_GELU_QUICK: - return ctx->device->pipeline_gelu_quick[dst->type == GGML_TYPE_F16]; - case GGML_UNARY_OP_RELU: - return ctx->device->pipeline_relu[dst->type == GGML_TYPE_F16]; - case GGML_UNARY_OP_TANH: - return ctx->device->pipeline_tanh[dst->type == GGML_TYPE_F16]; - case GGML_UNARY_OP_SIGMOID: - return ctx->device->pipeline_sigmoid[dst->type == GGML_TYPE_F16]; - default: - break; - } - return nullptr; - case GGML_OP_DIAG_MASK_INF: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_diag_mask_inf_f32; - } - return nullptr; - case GGML_OP_SOFT_MAX: - GGML_ASSERT(!src1 || src1->type == GGML_TYPE_F32 || src1->type == GGML_TYPE_F16); - - if (src0->type == GGML_TYPE_F32 && (src1 == nullptr || src1->type == GGML_TYPE_F32) && dst->type == GGML_TYPE_F32) { - return src0->ne[0] > 1024 ? ctx->device->pipeline_soft_max_f32_wg512 : ctx->device->pipeline_soft_max_f32; - } - if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F32) { - return src0->ne[0] > 1024 ? ctx->device->pipeline_soft_max_f32_f16_wg512 : ctx->device->pipeline_soft_max_f32_f16; - } - return nullptr; - case GGML_OP_SOFT_MAX_BACK: - if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_soft_max_back_f32; - } - return nullptr; - case GGML_OP_ROPE: - case GGML_OP_ROPE_BACK: - { - const int mode = ((const int32_t *) dst->op_params)[2]; - const bool is_neox = mode & 2; - - if (is_neox) { - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_rope_neox_f32; - } - if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { - return ctx->device->pipeline_rope_neox_f16; - } - } else { - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_rope_norm_f32; - } - if (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) { - return ctx->device->pipeline_rope_norm_f16; - } - } - return nullptr; - } - case GGML_OP_ARGSORT: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_I32) { - return ctx->device->pipeline_argsort_f32; - } - return nullptr; - case GGML_OP_SUM: - case GGML_OP_SUM_ROWS: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_sum_rows_f32; - } - return nullptr; - case GGML_OP_ARGMAX: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_I32) { - return ctx->device->pipeline_argmax_f32; - } - return nullptr; - case GGML_OP_IM2COL: - if (src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_im2col_f32; - } - if (src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F16) { - return ctx->device->pipeline_im2col_f32_f16; - } - return nullptr; - case GGML_OP_TIMESTEP_EMBEDDING: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_timestep_embedding_f32; - } - return nullptr; - case GGML_OP_CONV_TRANSPOSE_1D: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_conv_transpose_1d_f32; - } - return nullptr; - case GGML_OP_POOL_2D: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_pool2d_f32; - } - return nullptr; - case GGML_OP_LEAKY_RELU: - if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) { - return ctx->device->pipeline_leaky_relu_f32; - } - return nullptr; default: return nullptr; } @@ -6630,14 +6910,18 @@ static bool ggml_vk_op_supports_incontiguous(ggml_op op) { case GGML_OP_CONCAT: case GGML_OP_UPSCALE: case GGML_OP_SQR: + //case GGML_OP_SIN: + //case GGML_OP_COS: case GGML_OP_CLAMP: case GGML_OP_PAD: case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: case GGML_OP_ROPE: case GGML_OP_RMS_NORM: - case GGML_OP_FUSED_RMS_NORM: + //case GGML_OP_CONV_2D_DW: case GGML_OP_IM2COL: + //case GGML_OP_SET_ROWS: + case GGML_OP_FUSED_RMS_NORM: case GGML_OP_MULTI_ADD: return true; default: @@ -6850,6 +7134,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co switch (op) { case GGML_OP_NORM: case GGML_OP_RMS_NORM_BACK: + //case GGML_OP_L2_NORM: case GGML_OP_SOFT_MAX: case GGML_OP_SOFT_MAX_BACK: case GGML_OP_SUM_ROWS: @@ -6868,10 +7153,6 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co elements = { (uint32_t)ne01, (uint32_t)ne02, (uint32_t)ne03 }; break; - case GGML_OP_FUSED_RMS_NORM: - elements = { (uint32_t)ne01, (uint32_t)ne02, (uint32_t)ne03 }; - break; - case GGML_OP_SUM: // We use GGML_OP_SUM_ROWS with 1 row. elements = { 1, 1, 1 }; @@ -6926,22 +7207,31 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co const uint32_t OW = dst->ne[0]; elements = { N * OC * OH * OW, 1, 1}; } break; + case GGML_OP_FUSED_RMS_NORM: + elements = { (uint32_t)ne01, (uint32_t)ne02, (uint32_t)ne03 }; + break; + case GGML_OP_ADD: case GGML_OP_SUB: case GGML_OP_DIV: case GGML_OP_MUL: case GGML_OP_SCALE: case GGML_OP_SQR: + //case GGML_OP_SIN: + //case GGML_OP_COS: case GGML_OP_CLAMP: case GGML_OP_PAD: + //case GGML_OP_ROLL: case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: case GGML_OP_CPY: case GGML_OP_CONCAT: case GGML_OP_UPSCALE: + case GGML_OP_UNARY: case GGML_OP_FUSED_MUL_UNARY: case GGML_OP_MULTI_ADD: - case GGML_OP_UNARY: + //case GGML_OP_GLU: + //case GGML_OP_CONV_2D_DW: { uint32_t ne = ggml_nelements(dst); if (op == GGML_OP_CPY && ggml_is_quantized(src0->type) && ggml_is_quantized(dst->type)) { @@ -6953,6 +7243,12 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co ne *= ggml_type_size(src0->type) / 2; } } + // copy_to_quant has block size of 32, and each thread does QUANT_K elements. + // Splitting into 512x512xZ wouldn't work well since each workgroup does 1024 elements. + // So divide by block size here before splitting into 512x512 groups. + if (op == GGML_OP_CPY && !ggml_is_quantized(src0->type) && ggml_is_quantized(dst->type)) { + ne = CEIL_DIV(ne, ggml_blck_size(dst->type)); + } if (ne > 262144) { elements = { 512, 512, CEIL_DIV(ne, 262144) }; } else if (ne > 512) { @@ -6961,6 +7257,25 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co elements = { ne, 1, 1 }; } } break; + //case GGML_OP_SET_ROWS: + // { + // uint32_t ne = ggml_nelements(src0); + // if (ggml_is_quantized(dst->type)) { + // // quants run 32 threads each doing QUANT_K elements + // ne = CEIL_DIV(ne, 32 * ggml_blck_size(dst->type)); + // } else { + // // scalar types do one element per thread, running 512 threads + // ne = CEIL_DIV(ne, 512); + // } + // if (ne > 262144) { + // elements = { 512, 512, CEIL_DIV(ne, 262144) }; + // } else if (ne > 512) { + // elements = { 512, CEIL_DIV(ne, 512), 1 }; + // } else { + // elements = { ne, 1, 1 }; + // } + // } + // break; default: elements = { (uint32_t)ggml_nelements(src0), 1, 1 }; break; @@ -6981,7 +7296,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co } } - if (op == GGML_OP_SOFT_MAX) { + if (op == GGML_OP_SOFT_MAX) { // || op == GGML_OP_GLU) { // Empty src1 is possible in soft_max, but the shader needs a buffer vk_subbuffer subbuf_y; if (use_src1) { @@ -6991,7 +7306,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co } ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, subbuf_y, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, subbuf_y, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, pc, elements); } else if (op == GGML_OP_ROPE || op == GGML_OP_ROPE_BACK) { // Empty src2 is possible in rope, but the shader needs a buffer vk_subbuffer subbuf_z; @@ -7002,20 +7317,26 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co } ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, subbuf_z, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, subbuf_z, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, pc, elements); } else if (op == GGML_OP_IM2COL) { // im2col uses only src1 and dst buffers ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, pc, elements); + //} else if (op == GGML_OP_COUNT_EQUAL) { + // ggml_vk_sync_buffers(subctx); + // // count_equal assumes that destination buffer is initialized with zeroes + // ggml_vk_buffer_memset_async(subctx, d_D, d_buf_offset, 0, d_sz); + // ggml_vk_sync_buffers(subctx); + // ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, pc, elements); } else if (use_src2) { ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_Z, z_buf_offset, z_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_Z, z_buf_offset, z_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, pc, elements); } else if (use_src1) { ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_Y, y_buf_offset, y_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, pc, elements); } else { ggml_vk_sync_buffers(subctx); - ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, sizeof(PC), &pc, elements); + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { vk_subbuffer{ d_X, x_buf_offset, x_sz }, vk_subbuffer{ d_D, d_buf_offset, d_sz } }, pc, elements); } } @@ -7114,6 +7435,238 @@ static void ggml_vk_div(ggml_backend_vk_context * ctx, vk_context& subctx, const }, dryrun); } +static void ggml_vk_op_f32_wkv(ggml_backend_vk_context * ctx, vk_context& subctx, ggml_tensor * dst, const vk_op_rwkv_wkv6_push_constants&& pc, int version, bool dryrun = false) { + GGML_ASSERT(version == 6 || version == 7); + int num_srcs = version == 6 ? 6 : 7; + + for (int i = 0; i < num_srcs; i++) { + GGML_ASSERT(!ggml_is_quantized(dst->src[i]->type)); + } + + GGML_ASSERT(dst->buffer != nullptr); + + vk_pipeline pipeline = ggml_vk_op_get_pipeline(ctx, dst->src[0], dst->src[1], dst->src[2], dst, dst->op); + GGML_ASSERT(pipeline != nullptr); + + if (dryrun) { + ggml_pipeline_request_descriptor_sets(ctx, pipeline, 1); + return; + } + + ggml_backend_vk_buffer_context * dst_buf_ctx = (ggml_backend_vk_buffer_context *)dst->buffer->context; + ggml_backend_vk_buffer_context * src_buf_ctxs[7] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + for (int i = 0; i < num_srcs; i++) { + src_buf_ctxs[i] = (ggml_backend_vk_buffer_context *)dst->src[i]->buffer->context; + } + + ggml_vk_sync_buffers(subctx); + + vk_buffer d_D = nullptr, d_srcs[7] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + size_t dst_offset = 0, src_offsets[7] = { 0, 0, 0, 0, 0, 0, 0 }; + bool dst_uma = false, srcs_uma[7] = { false, false, false, false, false, false, false }; + + if (ctx->device->uma) { + for (int i = 0; i < num_srcs; i++) { + ggml_vk_host_get(ctx->device, dst->src[i]->data, d_srcs[i], src_offsets[i]); + srcs_uma[i] = d_srcs[i] != nullptr; + } + + ggml_vk_host_get(ctx->device, dst->data, d_D, dst_offset); + dst_uma = d_D != nullptr; + } + + uint64_t src_sizes[7] = { 0, 0, 0, 0, 0, 0, 0 }; + for (int i = 0; i < num_srcs; i++) { + src_sizes[i] = ggml_nbytes(dst->src[i]); + if (!srcs_uma[i]) { + d_srcs[i] = src_buf_ctxs[i]->dev_buffer; + src_offsets[i] = vk_tensor_offset(dst->src[i]) + dst->src[i]->view_offs; + } + } + + const uint64_t dst_size = ggml_nbytes(dst); + if (!dst_uma) { + d_D = dst_buf_ctx->dev_buffer; + dst_offset = vk_tensor_offset(dst) + dst->view_offs; + } + + std::array elements = { + (uint32_t)(pc.B * pc.H), + 1, + 1 + }; + + if (version == 6) { + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { + vk_subbuffer{ d_srcs[0], src_offsets[0], src_sizes[0] }, + vk_subbuffer{ d_srcs[1], src_offsets[1], src_sizes[1] }, + vk_subbuffer{ d_srcs[2], src_offsets[2], src_sizes[2] }, + vk_subbuffer{ d_srcs[3], src_offsets[3], src_sizes[3] }, + vk_subbuffer{ d_srcs[4], src_offsets[4], src_sizes[4] }, + vk_subbuffer{ d_srcs[5], src_offsets[5], src_sizes[5] }, + vk_subbuffer{ d_D, dst_offset, dst_size } + }, pc, elements); + } else if (version == 7) { + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { + vk_subbuffer{ d_srcs[0], src_offsets[0], src_sizes[0] }, + vk_subbuffer{ d_srcs[1], src_offsets[1], src_sizes[1] }, + vk_subbuffer{ d_srcs[2], src_offsets[2], src_sizes[2] }, + vk_subbuffer{ d_srcs[3], src_offsets[3], src_sizes[3] }, + vk_subbuffer{ d_srcs[4], src_offsets[4], src_sizes[4] }, + vk_subbuffer{ d_srcs[5], src_offsets[5], src_sizes[5] }, + vk_subbuffer{ d_srcs[6], src_offsets[6], src_sizes[6] }, + vk_subbuffer{ d_D, dst_offset, dst_size } + }, pc, elements); + } else { + // shouldn't happen + GGML_ASSERT(false); + } +} + +#if 0 +static void ggml_vk_rwkv_wkv6(ggml_backend_vk_context * ctx, vk_context& subctx, ggml_tensor * dst, bool dryrun = false) { + const size_t seq_length = dst->src[0]->ne[2]; + const size_t n_embed = dst->ne[0]; + const size_t n_heads = dst->src[0]->ne[1]; + const size_t n_seqs = dst->src[5]->ne[1]; + + ggml_vk_op_f32_wkv( + ctx, subctx, dst, + { + (uint32_t)n_seqs, + (uint32_t)seq_length, + (uint32_t)n_embed, + (uint32_t)n_heads, + }, + 6, + dryrun + ); +} + +static void ggml_vk_rwkv_wkv7(ggml_backend_vk_context * ctx, vk_context& subctx, ggml_tensor * dst, bool dryrun = false) { + const size_t seq_length = dst->src[0]->ne[2]; + const size_t n_embed = dst->ne[0]; + const size_t n_heads = dst->src[0]->ne[1]; + const size_t n_seqs = dst->src[6]->ne[1]; + + ggml_vk_op_f32_wkv( + ctx, subctx, dst, + { + (uint32_t)n_seqs, + (uint32_t)seq_length, + (uint32_t)n_embed, + (uint32_t)n_heads, + }, + 7, + dryrun + ); +} + +static void ggml_vk_op_f32_opt_step_adamw(ggml_backend_vk_context * ctx, vk_context& subctx, ggml_tensor * dst, const vk_op_push_constants&& pc, bool dryrun = false) { + const ggml_tensor * x = dst->src[0]; + const ggml_tensor * g = dst->src[1]; + const ggml_tensor * gm = dst->src[2]; + const ggml_tensor * gv = dst->src[3]; + const ggml_tensor * p = dst->src[4]; + + GGML_ASSERT(x->type == GGML_TYPE_F32); + GGML_ASSERT(g->type == GGML_TYPE_F32); + GGML_ASSERT(gm->type == GGML_TYPE_F32); + GGML_ASSERT(gv->type == GGML_TYPE_F32); + GGML_ASSERT(p->type == GGML_TYPE_F32); + GGML_ASSERT(dst->buffer != nullptr); + GGML_ASSERT(ggml_is_contiguous(x)); + GGML_ASSERT(ggml_is_contiguous(g)); + GGML_ASSERT(ggml_is_contiguous(gm)); + GGML_ASSERT(ggml_is_contiguous(gv)); + GGML_ASSERT(ggml_is_contiguous(p)); + GGML_ASSERT(ggml_are_same_shape(x, g)); + GGML_ASSERT(ggml_are_same_shape(x, gm)); + GGML_ASSERT(ggml_are_same_shape(x, gv)); + GGML_ASSERT(ggml_nelements(p) == 7); + + vk_pipeline pipeline = ggml_vk_op_get_pipeline(ctx, g, gm, gv, dst, GGML_OP_OPT_STEP_ADAMW); + GGML_ASSERT(pipeline != nullptr); + + if (dryrun) { + ggml_pipeline_request_descriptor_sets(ctx, pipeline, 1); + return; + } + + ggml_backend_vk_buffer_context * x_buf_ctx = (ggml_backend_vk_buffer_context *)x->buffer->context; + ggml_backend_vk_buffer_context * g_buf_ctx = (ggml_backend_vk_buffer_context *)g->buffer->context; + ggml_backend_vk_buffer_context * gm_buf_ctx = (ggml_backend_vk_buffer_context *)gm->buffer->context; + ggml_backend_vk_buffer_context * gv_buf_ctx = (ggml_backend_vk_buffer_context *)gv->buffer->context; + ggml_backend_vk_buffer_context * p_buf_ctx = (ggml_backend_vk_buffer_context *)p->buffer->context; + + ggml_vk_sync_buffers(subctx); + + vk_buffer d_X = nullptr, d_G = nullptr, d_GM = nullptr, d_GV = nullptr, d_P = nullptr; + size_t x_offset = 0, g_offset = 0, gm_offset = 0, gv_offset = 0, p_offset = 0; + bool X_uma = false, G_uma = false, GM_uma = false, GV_uma = false, P_uma = false; + + if (ctx->device->uma) { + ggml_vk_host_get(ctx->device, x->data, d_X, x_offset); + ggml_vk_host_get(ctx->device, g->data, d_G, g_offset); + ggml_vk_host_get(ctx->device, gm->data, d_GM, gm_offset); + ggml_vk_host_get(ctx->device, gv->data, d_GV, gv_offset); + ggml_vk_host_get(ctx->device, p->data, d_P, p_offset); + + X_uma = d_X != nullptr; + G_uma = d_G != nullptr; + GM_uma = d_GM != nullptr; + GV_uma = d_GV != nullptr; + P_uma = d_P != nullptr; + } + + if (!X_uma) { + d_X = x_buf_ctx->dev_buffer; + x_offset = vk_tensor_offset(x) + x->view_offs; + } + if (!G_uma) { + d_G = g_buf_ctx->dev_buffer; + g_offset = vk_tensor_offset(g) + g->view_offs; + } + if (!GM_uma) { + d_GM = gm_buf_ctx->dev_buffer; + gm_offset = vk_tensor_offset(gm) + gm->view_offs; + } + if (!GV_uma) { + d_GV = gv_buf_ctx->dev_buffer; + gv_offset = vk_tensor_offset(gv) + gv->view_offs; + } + if (!P_uma) { + d_P = p_buf_ctx->dev_buffer; + p_offset = vk_tensor_offset(p) + p->view_offs; + } + + const uint64_t x_size = ggml_nbytes(x); + const uint64_t g_size = ggml_nbytes(g); + const uint64_t gm_size = ggml_nbytes(gm); + const uint64_t gv_size = ggml_nbytes(gv); + const uint64_t p_size = ggml_nbytes(p); + + std::array elements = { (uint32_t)ggml_nelements(x), 1, 1 }; + + ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { + vk_subbuffer{ d_X, x_offset, x_size }, + vk_subbuffer{ d_G, g_offset, g_size }, + vk_subbuffer{ d_GM, gm_offset, gm_size }, + vk_subbuffer{ d_GV, gv_offset, gv_size }, + vk_subbuffer{ d_P, p_offset, p_size }, + }, pc, elements); +} + +static void ggml_vk_opt_step_adamw(ggml_backend_vk_context * ctx, vk_context& subctx, ggml_tensor * dst, bool dryrun = false) { + const size_t n = ggml_nelements(dst->src[0]); + + ggml_vk_op_f32_opt_step_adamw( + ctx, subctx, dst, + { (uint32_t)n, 0, 0.0f, 0.0f }, + dryrun + ); +} +#endif static void ggml_vk_concat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { int * op_params = (int *)dst->op_params; @@ -7132,113 +7685,94 @@ static void ggml_vk_concat(ggml_backend_vk_context * ctx, vk_context& subctx, co }, dryrun); } +#if 0 static void ggml_vk_upscale(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t mode = (uint32_t)ggml_get_op_params_i32(dst, 0); - const float sf0 = (float)dst->ne[0] / src0->ne[0]; - const float sf1 = (float)dst->ne[1] / src0->ne[1]; - const float sf2 = (float)dst->ne[2] / src0->ne[2]; - const float sf3 = (float)dst->ne[3] / src0->ne[3]; + float sf0 = (float)dst->ne[0] / src0->ne[0]; + float sf1 = (float)dst->ne[1] / src0->ne[1]; + float sf2 = (float)dst->ne[2] / src0->ne[2]; + float sf3 = (float)dst->ne[3] / src0->ne[3]; + + if (mode & GGML_SCALE_FLAG_ALIGN_CORNERS) { + sf0 = (float)(dst->ne[0] - 1) / (src0->ne[0] - 1); + sf1 = (float)(dst->ne[1] - 1) / (src0->ne[1] - 1); + } ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_UPSCALE, { (uint32_t)ggml_nelements(dst), 0, 0, + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, (uint32_t)dst->ne[0], (uint32_t)dst->ne[1], (uint32_t)dst->ne[2],(uint32_t)dst->ne[3], sf0, sf1, sf2, sf3, }, dryrun); } +#endif static void ggml_vk_scale(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - float * op_params = (float *)dst->op_params; - const uint32_t src0_type_size = ggml_type_size(src0->type); - const uint32_t dst_type_size = ggml_type_size(dst->type); + vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst); + p.param1 = ggml_get_op_params_f32(dst, 0); + p.param2 = ggml_get_op_params_f32(dst, 1); - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SCALE, { - (uint32_t)ggml_nelements(src0), - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, - 0, - op_params[0], 0.0f, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, dryrun); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SCALE, std::move(p), dryrun); } static void ggml_vk_sqr(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - const uint32_t src0_type_size = ggml_type_size(src0->type); - const uint32_t dst_type_size = ggml_type_size(dst->type); - - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SQR, { - (uint32_t)ggml_nelements(src0), - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, - 0, - 0.0f, 0.0f, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, dryrun); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SQR, vk_op_unary_push_constants_init(src0, dst), dryrun); } +#if 0 +static void ggml_vk_sin(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_SIN, vk_op_unary_push_constants_init(src0, dst), dryrun); +} + +static void ggml_vk_cos(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_COS, vk_op_unary_push_constants_init(src0, dst), dryrun); +} +#endif static void ggml_vk_clamp(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - float * op_params = (float *)dst->op_params; - const uint32_t src0_type_size = ggml_type_size(src0->type); - const uint32_t dst_type_size = ggml_type_size(dst->type); + vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst); + p.param1 = ggml_get_op_params_f32(dst, 0); + p.param2 = ggml_get_op_params_f32(dst, 1); - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_CLAMP, { - (uint32_t)ggml_nelements(src0), - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, - 0, - op_params[0], op_params[1], - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, dryrun); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_CLAMP, std::move(p), dryrun); } static void ggml_vk_pad(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - const uint32_t src0_type_size = ggml_type_size(src0->type); - const uint32_t dst_type_size = ggml_type_size(dst->type); - - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_PAD, { - (uint32_t)ggml_nelements(dst), - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, - 0, - 0.0f, 0.0f, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, dryrun); + vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst, ggml_nelements(dst)); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_PAD, std::move(p), dryrun); } -static void ggml_vk_repeat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - const uint32_t src0_type_size = ggml_type_size(src0->type); - const uint32_t dst_type_size = ggml_type_size(dst->type); +#if 0 +static void ggml_vk_roll(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + const int32_t s0 = ggml_get_op_params_i32(dst, 0); + const int32_t s1 = ggml_get_op_params_i32(dst, 1); + const int32_t s2 = ggml_get_op_params_i32(dst, 2); + const int32_t s3 = ggml_get_op_params_i32(dst, 3); + const uint32_t s01_packed = ((s0 + 0x8000) << 16) | (s1 + 0x8000); + const uint32_t s23_packed = ((s2 + 0x8000) << 16) | (s3 + 0x8000); - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_REPEAT, { - (uint32_t)ggml_nelements(dst), - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, - 0, - 0.0f, 0.0f, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, dryrun); + vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst); + memcpy(&p.param1, &s01_packed, sizeof(float)); + memcpy(&p.param2, &s23_packed, sizeof(float)); + + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_ROLL, std::move(p), dryrun); +} +#endif + +static void ggml_vk_repeat(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst, ggml_nelements(dst)); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_REPEAT, std::move(p), dryrun); } static void ggml_vk_repeat_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - const uint32_t src0_type_size = ggml_type_size(src0->type); - const uint32_t dst_type_size = ggml_type_size(dst->type); - - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_REPEAT_BACK, { - (uint32_t)ggml_nelements(dst), - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, - 0, - 0.0f, 0.0f, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, dryrun); + vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst, ggml_nelements(dst)); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_REPEAT_BACK, std::move(p), dryrun); } static void ggml_vk_cpy(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - const uint32_t src0_type_size = ggml_type_size(src0->type); - const uint32_t dst_type_size = ggml_type_size(dst->type); - uint32_t ne = (uint32_t)ggml_nelements(src0); if (ggml_is_quantized(src0->type) && ggml_is_quantized(dst->type)) { // Convert from number of logical elements to 2- or 4-byte units. @@ -7250,15 +7784,26 @@ static void ggml_vk_cpy(ggml_backend_vk_context * ctx, vk_context& subctx, const } } - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_CPY, { - ne, - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, + vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst, ne); + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_CPY, std::move(p), dryrun); +} + +#if 0 +static void ggml_vk_set_rows(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t src1_type_size = ggml_type_size(src1->type); + const uint32_t dst_type_size = ggml_type_size(dst->type); + + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_SET_ROWS, { + (uint32_t)ggml_nelements(src0), + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2],(uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t)src1->ne[0], (uint32_t)src1->ne[1], (uint32_t)src1->ne[2],(uint32_t)src1->ne[3], (uint32_t)src1->nb[0] / src1_type_size, (uint32_t)src1->nb[1] / src1_type_size, (uint32_t)src1->nb[2] / src1_type_size, (uint32_t)src1->nb[3] / src1_type_size, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, - 0.0f, 0.0f, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.0f, 0.0f, 0, }, dryrun); } +#endif static void ggml_vk_silu_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_SILU_BACK, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); @@ -7281,21 +7826,26 @@ static void ggml_vk_group_norm(ggml_backend_vk_context * ctx, vk_context& subctx ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_GROUP_NORM, { group_size, 0, eps, 0.0f }, dryrun); } -static void ggml_vk_rms_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - float * op_params = (float *)dst->op_params; +static void ggml_vk_rms_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, float * op_params, bool dryrun = false) { const uint32_t src0_type_size = ggml_type_size(src0->type); + const uint32_t src1_type_size = ggml_type_size(src1->type); const uint32_t dst_type_size = ggml_type_size(dst->type); - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_RMS_NORM, { + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_RMS_NORM, { (uint32_t)ggml_nelements(src0), - (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, - (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2],(uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size, + (uint32_t)src1->ne[0], (uint32_t)src1->ne[1], (uint32_t)src1->ne[2],(uint32_t)src1->ne[3], (uint32_t)src1->nb[0] / src1_type_size, (uint32_t)src1->nb[1] / src1_type_size, (uint32_t)src1->nb[2] / src1_type_size, (uint32_t)src1->nb[3] / src1_type_size, + (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2],(uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size, 0, - op_params[0], 0.0f, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + op_params[0], 0.0f, 0, }, dryrun); } +static void ggml_vk_rms_norm_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + float * op_params = (float *)dst->op_params; + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_RMS_NORM_BACK, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }, dryrun); +} + static void ggml_vk_fused_rms_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { float * op_params = (float *)dst->op_params; const uint32_t src0_type_size = ggml_type_size(src0->type); @@ -7314,15 +7864,6 @@ static void ggml_vk_fused_rms_norm(ggml_backend_vk_context * ctx, vk_context& su }, dryrun); } -static void ggml_vk_rms_norm_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { - float * op_params = (float *)dst->op_params; - ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_RMS_NORM_BACK, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }, dryrun); -} - -static void ggml_vk_unary(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { - ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); -} - static void ggml_vk_fused_mul_unary(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { GGML_ASSERT(ggml_is_contiguous(src0)); GGML_ASSERT(ggml_are_same_shape(src0, src1)); @@ -7336,6 +7877,38 @@ static void ggml_vk_multi_add(ggml_backend_vk_context * ctx, vk_context& subctx, { (uint32_t)ggml_nelements(dst), (uint32_t)dst->ne[0], (uint32_t)dst->ne[1], (uint32_t)(dst->nb[1]/sizeof(float)), (uint32_t)(src0->nb[1]/sizeof(float)), nadd }, dryrun); } +#if 0 +static void ggml_vk_l2_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + float * op_params = (float *)dst->op_params; + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_L2_NORM, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f }, dryrun); +} +#endif + +static void ggml_vk_unary(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); +} + +#if 0 +static void ggml_vk_glu(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + const bool swapped = (bool)dst->op_params[1]; + const bool split = src1 != nullptr; + + GGML_ASSERT(ggml_is_contiguous(src0)); + + if (!split) { + GGML_ASSERT(src0->ne[0] / 2 == dst->ne[0]); + } else { + GGML_ASSERT(src0->ne[0] == src1->ne[0]); + GGML_ASSERT(src0->ne[0] == dst->ne[0]); + GGML_ASSERT(src0->type == src1->type); + } + + const uint32_t mode = split ? 2 : (swapped ? 1 : 0); + + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_GLU, { (uint32_t)ggml_nelements(dst), (uint32_t)src0->ne[0], (uint32_t)dst->ne[0], mode }, dryrun); +} +#endif + static void ggml_vk_diag_mask_inf(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { int32_t * op_params = (int32_t *)dst->op_params; ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_DIAG_MASK_INF, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0] }, dryrun); @@ -7351,7 +7924,13 @@ static void ggml_vk_soft_max(ggml_backend_vk_context * ctx, vk_context& subctx, const uint32_t nrows_x = (uint32_t)ggml_nrows(src0); const uint32_t nrows_y = (uint32_t)src0->ne[1]; - const uint32_t n_head_kv = nrows_x/nrows_y; + const uint32_t ne12 = src1 ? (uint32_t)(src1->ne[2]) : 0u; + const uint32_t ne13 = src1 ? (uint32_t)(src1->ne[3]) : 0u; + const uint32_t nb11 = src1 ? (uint32_t)(src1->nb[1] / src1->nb[0]) : 0u; + const uint32_t nb12 = src1 ? (uint32_t)(src1->nb[2] / src1->nb[0]) : 0u; + const uint32_t nb13 = src1 ? (uint32_t)(src1->nb[3] / src1->nb[0]) : 0u; + + const uint32_t n_head_kv = src0->ne[2]; const uint32_t n_head_log2 = 1u << (uint32_t) floorf(log2f((float) n_head_kv)); const float m0 = powf(2.0f, -(max_bias ) / n_head_log2); @@ -7360,6 +7939,9 @@ static void ggml_vk_soft_max(ggml_backend_vk_context * ctx, vk_context& subctx, ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_SOFT_MAX, { ncols, src1 != nullptr ? nrows_y : (uint32_t)0, + (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], + ne12, ne13, + nb11, nb12, nb13, scale, max_bias, m0, m1, n_head_log2, @@ -7384,7 +7966,7 @@ static void ggml_vk_rope(ggml_backend_vk_context * ctx, vk_context& subctx, cons const float beta_fast = ((float *) dst->op_params)[9]; const float beta_slow = ((float *) dst->op_params)[10]; int sections[4] {}; - if (mode & 8) { + if (mode & GGML_ROPE_TYPE_MROPE) { memcpy(sections, (int32_t *) dst->op_params + 11, sizeof(int)*4); } @@ -7435,6 +8017,12 @@ static void ggml_vk_argmax(ggml_backend_vk_context * ctx, vk_context& subctx, co ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, dst, GGML_OP_ARGMAX, { (uint32_t)src0->ne[0], 0, 0.0f, 0.0f }, dryrun); } +#if 0 +static void ggml_vk_count_equal(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_COUNT_EQUAL, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f }, dryrun); +} +#endif + static void ggml_vk_im2col(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { const int32_t s0 = dst->op_params[0]; const int32_t s1 = dst->op_params[1]; @@ -7538,6 +8126,31 @@ static void ggml_vk_pool_2d(ggml_backend_vk_context * ctx, vk_context& subctx, c }, dryrun); } +#if 0 +static void ggml_vk_conv_2d_dw(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, bool dryrun = false) { + vk_op_conv2d_dw_push_constants p{}; + p.ne = ggml_nelements(dst); + p.channels = dst->ne[2]; + p.batches = dst->ne[3]; + p.dst_w = dst->ne[0]; + p.dst_h = dst->ne[1]; + p.src_w = src1->ne[0]; + p.src_h = src1->ne[1]; + p.knl_w = src0->ne[0]; + p.knl_h = src0->ne[1]; + p.stride_x = dst->op_params[0]; + p.stride_y = dst->op_params[1]; + p.pad_x = dst->op_params[2]; + p.pad_y = dst->op_params[3]; + p.dilation_x = dst->op_params[4]; + p.dilation_y = dst->op_params[5]; + + GGML_ASSERT(src0->ne[3] == p.channels); + GGML_ASSERT(src1->ne[3] == p.batches); + + ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, dst, GGML_OP_CONV_2D_DW, std::move(p), dryrun); +} +#endif static void ggml_vk_leaky_relu(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst, bool dryrun = false) { const float * op_params = (const float *)dst->op_params; @@ -7920,9 +8533,9 @@ static void ggml_vk_dequantize_data(const void * from, float * to, size_t ne, gg return; } - ggml_type_traits_t tt = ggml_internal_get_type_traits(quant); + const auto * tt = ggml_get_type_traits(quant); - ggml_to_float_t dequant_fn = tt.to_float; + ggml_to_float_t dequant_fn = tt->to_float; dequant_fn(from, to, ne); } @@ -7961,7 +8574,7 @@ static void ggml_vk_test_dequant(ggml_backend_vk_context * ctx, size_t ne, ggml_ vk_context subctx = ggml_vk_create_context(ctx, ctx->compute_cmd_pool); ggml_vk_ctx_begin(ctx->device, subctx); const std::vector pc = { 1, (uint32_t)ne, (uint32_t)ne, (uint32_t)ne, (uint32_t)ne }; - ggml_vk_dispatch_pipeline(ctx, subctx, p, { vk_subbuffer{ qx_buf, 0, qx_sz }, vk_subbuffer{ x_buf, 0, x_sz_f16 } }, pc.size() * sizeof(int), pc.data(), { (uint32_t)ne, 1, 1}); + ggml_vk_dispatch_pipeline(ctx, subctx, p, { vk_subbuffer{ qx_buf, 0, qx_sz }, vk_subbuffer{ x_buf, 0, x_sz_f16 } }, pc, { (uint32_t)ne, 1, 1}); ggml_vk_ctx_end(subctx); auto begin = std::chrono::high_resolution_clock::now(); @@ -8482,11 +9095,12 @@ static void ggml_vk_preallocate_buffers(ggml_backend_vk_context * ctx) { } } -static bool ggml_vk_compute_forward(ggml_backend_vk_context* ctx, ggml_tensor* tensor, int tensor_idx, bool use_fence, bool almost_ready); +static bool ggml_vk_compute_forward(ggml_backend_vk_context* ctx, ggml_cgraph * cgraph, ggml_tensor* tensor, int tensor_idx, bool use_fence, bool almost_ready); // Returns true if node has enqueued work into the queue, false otherwise // If submit is true the current all operations queued so far are being submitted to Vulkan to overlap cmdlist creation and GPU execution. -static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * node, int node_idx, ggml_tensor *node_begin, int node_idx_begin, bool dryrun, bool last_node, bool almost_ready, bool submit){ +static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_cgraph * cgraph, int node_idx, ggml_tensor *node_begin, int node_idx_begin, bool dryrun, bool last_node, bool almost_ready, bool submit){ + ggml_tensor * node = cgraph->nodes[node_idx]; if (ggml_is_empty(node) || !node->buffer) { return false; } @@ -8511,6 +9125,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod switch (ggml_get_unary_op(node)) { case GGML_UNARY_OP_SILU: case GGML_UNARY_OP_GELU: + //case GGML_UNARY_OP_GELU_ERF: case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: @@ -8520,12 +9135,23 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod return false; } break; - case GGML_OP_FUSED_MUL_UNARY: - case GGML_OP_MULTI_ADD: + //case GGML_OP_GLU: + // switch (ggml_get_glu_op(node)) { + // case GGML_GLU_OP_GEGLU: + // case GGML_GLU_OP_REGLU: + // case GGML_GLU_OP_SWIGLU: + // case GGML_GLU_OP_GEGLU_ERF: + // case GGML_GLU_OP_GEGLU_QUICK: + // break; + // default: + // return false; + // } + // break; case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: case GGML_OP_GET_ROWS: case GGML_OP_ADD: + case GGML_OP_ACC: case GGML_OP_SUB: case GGML_OP_MUL: case GGML_OP_DIV: @@ -8533,17 +9159,24 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_UPSCALE: case GGML_OP_SCALE: case GGML_OP_SQR: + //case GGML_OP_SIN: + //case GGML_OP_COS: case GGML_OP_CLAMP: case GGML_OP_PAD: + //case GGML_OP_ROLL: case GGML_OP_CPY: + //case GGML_OP_SET_ROWS: case GGML_OP_CONT: case GGML_OP_DUP: case GGML_OP_SILU_BACK: case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: - case GGML_OP_FUSED_RMS_NORM: case GGML_OP_RMS_NORM_BACK: + case GGML_OP_FUSED_RMS_NORM: + case GGML_OP_FUSED_MUL_UNARY: + case GGML_OP_MULTI_ADD: + //case GGML_OP_L2_NORM: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: case GGML_OP_SOFT_MAX_BACK: @@ -8555,12 +9188,17 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_SUM: case GGML_OP_SUM_ROWS: case GGML_OP_ARGMAX: + //case GGML_OP_COUNT_EQUAL: case GGML_OP_IM2COL: case GGML_OP_TIMESTEP_EMBEDDING: case GGML_OP_CONV_TRANSPOSE_1D: case GGML_OP_POOL_2D: + //case GGML_OP_CONV_2D_DW: + //case GGML_OP_RWKV_WKV6: + //case GGML_OP_RWKV_WKV7: case GGML_OP_LEAKY_RELU: case GGML_OP_FLASH_ATTN_EXT: + //case GGML_OP_OPT_STEP_ADAMW: break; default: std::cerr << "ggml_vulkan: Error: Missing op: " << ggml_op_name(node->op) << std::endl; @@ -8592,20 +9230,25 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_UPSCALE: case GGML_OP_SCALE: case GGML_OP_SQR: + //case GGML_OP_SIN: + //case GGML_OP_COS: case GGML_OP_CLAMP: case GGML_OP_PAD: case GGML_OP_CPY: + //case GGML_OP_SET_ROWS: case GGML_OP_CONT: case GGML_OP_DUP: case GGML_OP_SILU_BACK: case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: - case GGML_OP_FUSED_RMS_NORM: case GGML_OP_RMS_NORM_BACK: - case GGML_OP_UNARY: + case GGML_OP_FUSED_RMS_NORM: case GGML_OP_FUSED_MUL_UNARY: case GGML_OP_MULTI_ADD: + //case GGML_OP_L2_NORM: + case GGML_OP_UNARY: + //case GGML_OP_GLU: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: case GGML_OP_SOFT_MAX_BACK: @@ -8615,10 +9258,12 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_SUM: case GGML_OP_SUM_ROWS: case GGML_OP_ARGMAX: + //case GGML_OP_COUNT_EQUAL: case GGML_OP_IM2COL: case GGML_OP_TIMESTEP_EMBEDDING: case GGML_OP_CONV_TRANSPOSE_1D: case GGML_OP_POOL_2D: + //case GGML_OP_CONV_2D_DW: case GGML_OP_LEAKY_RELU: { // These operations all go through ggml_vk_op_f32, so short-circuit and @@ -8669,10 +9314,10 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod ggml_vk_concat(ctx, compute_ctx, src0, src1, node, dryrun); break; - case GGML_OP_UPSCALE: - ggml_vk_upscale(ctx, compute_ctx, src0, node, dryrun); + //case GGML_OP_UPSCALE: + // ggml_vk_upscale(ctx, compute_ctx, src0, node, dryrun); - break; + // break; case GGML_OP_SCALE: ggml_vk_scale(ctx, compute_ctx, src0, node, dryrun); @@ -8681,6 +9326,14 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod ggml_vk_sqr(ctx, compute_ctx, src0, node, dryrun); break; + //case GGML_OP_SIN: + // ggml_vk_sin(ctx, compute_ctx, src0, node, dryrun); + + // break; + //case GGML_OP_COS: + // ggml_vk_cos(ctx, compute_ctx, src0, node, dryrun); + + // break; case GGML_OP_CLAMP: ggml_vk_clamp(ctx, compute_ctx, src0, node, dryrun); @@ -8689,12 +9342,20 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod ggml_vk_pad(ctx, compute_ctx, src0, node, dryrun); break; + //case GGML_OP_ROLL: + // ggml_vk_roll(ctx, compute_ctx, src0, node, dryrun); + + // break; case GGML_OP_CPY: case GGML_OP_CONT: case GGML_OP_DUP: ggml_vk_cpy(ctx, compute_ctx, src0, node, dryrun); break; + //case GGML_OP_SET_ROWS: + // ggml_vk_set_rows(ctx, compute_ctx, src0, src1, node, dryrun); + + // break; case GGML_OP_SILU_BACK: ggml_vk_silu_back(ctx, compute_ctx, src0, src1, node, dryrun); @@ -8708,16 +9369,21 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod break; case GGML_OP_RMS_NORM: - ggml_vk_rms_norm(ctx, compute_ctx, src0, node, dryrun); - - break; - case GGML_OP_FUSED_RMS_NORM: - ggml_vk_fused_rms_norm(ctx, compute_ctx, src0, src1, node, dryrun); - + if (ctx->num_additional_fused_ops > 0) { + // fused rms_norm + mul + ggml_tensor *mul = cgraph->nodes[node_idx + 1]; + ggml_tensor *other_src = mul->src[0] == node ? mul->src[1] : mul->src[0]; + ggml_vk_rms_norm(ctx, compute_ctx, src0, other_src, mul, (float *)node->op_params, dryrun); + } else { + ggml_vk_rms_norm(ctx, compute_ctx, src0, src0, node, (float *)node->op_params, dryrun); + } break; case GGML_OP_RMS_NORM_BACK: ggml_vk_rms_norm_back(ctx, compute_ctx, src0, src1, node, dryrun); + break; + case GGML_OP_FUSED_RMS_NORM: + ggml_vk_fused_rms_norm(ctx, compute_ctx, src0, src1, node, dryrun); break; case GGML_OP_FUSED_MUL_UNARY: ggml_vk_fused_mul_unary(ctx, compute_ctx, src0, src1, node, dryrun); @@ -8725,10 +9391,15 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod case GGML_OP_MULTI_ADD: ggml_vk_multi_add(ctx, compute_ctx, src0, node, dryrun); break; + //case GGML_OP_L2_NORM: + // ggml_vk_l2_norm(ctx, compute_ctx, src0, node, dryrun); + + // break; case GGML_OP_UNARY: switch (ggml_get_unary_op(node)) { case GGML_UNARY_OP_SILU: case GGML_UNARY_OP_GELU: + //case GGML_UNARY_OP_GELU_ERF: case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: @@ -8739,6 +9410,19 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod return false; } break; + //case GGML_OP_GLU: + // switch (ggml_get_glu_op(node)) { + // case GGML_GLU_OP_GEGLU: + // case GGML_GLU_OP_REGLU: + // case GGML_GLU_OP_SWIGLU: + // case GGML_GLU_OP_GEGLU_ERF: + // case GGML_GLU_OP_GEGLU_QUICK: + // ggml_vk_glu(ctx, compute_ctx, src0, src1, node, dryrun); + // break; + // default: + // return false; + // } + // break; case GGML_OP_DIAG_MASK_INF: ggml_vk_diag_mask_inf(ctx, compute_ctx, src0, node, dryrun); @@ -8775,6 +9459,10 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod ggml_vk_argmax(ctx, compute_ctx, src0, node, dryrun); break; + //case GGML_OP_COUNT_EQUAL: + // ggml_vk_count_equal(ctx, compute_ctx, src0, src1, node, dryrun); + + // break; case GGML_OP_IM2COL: ggml_vk_im2col(ctx, compute_ctx, src0, src1, node, dryrun); @@ -8791,6 +9479,10 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod ggml_vk_pool_2d(ctx, compute_ctx, src0, node, dryrun); break; + //case GGML_OP_CONV_2D_DW: + // ggml_vk_conv_2d_dw(ctx, compute_ctx, src0, src1, node, dryrun); + + // break; case GGML_OP_LEAKY_RELU: ggml_vk_leaky_relu(ctx, compute_ctx, src0, node, dryrun); @@ -8808,6 +9500,21 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod ggml_vk_flash_attn(ctx, compute_ctx, src0, src1, src2, src3, node, dryrun); break; + + //case GGML_OP_RWKV_WKV6: + // ggml_vk_rwkv_wkv6(ctx, compute_ctx, node, dryrun); + + // break; + + //case GGML_OP_RWKV_WKV7: + // ggml_vk_rwkv_wkv7(ctx, compute_ctx, node, dryrun); + + // break; + + //case GGML_OP_OPT_STEP_ADAMW: + // ggml_vk_opt_step_adamw(ctx, compute_ctx, node, dryrun); + + // break; default: return false; } @@ -8837,12 +9544,13 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod ctx->compute_ctx.reset(); - bool ok = ggml_vk_compute_forward(ctx, node_begin, node_idx_begin, false, almost_ready); + bool ok = ggml_vk_compute_forward(ctx, cgraph, node_begin, node_idx_begin, false, almost_ready); if (!ok) { if (node->op == GGML_OP_UNARY) { std::cerr << __func__ << ": error: op not supported UNARY " << node->name << " (" << ggml_unary_op_name(static_cast(node->op_params[0])) << ")" << std::endl; - } - else { + //} else if (node->op == GGML_OP_GLU) { + // std::cerr << __func__ << ": error: op not supported GLU " << node->name << " (" << ggml_glu_op_name(static_cast(node->op_params[0])) << ")" << std::endl; + } else { std::cerr << __func__ << ": error: op not supported " << node->name << " (" << ggml_op_name(node->op) << ")" << std::endl; } } @@ -8851,11 +9559,13 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_tensor * nod return true; } -static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * tensor, int tensor_idx, bool use_fence = true, bool almost_ready = false) { +static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_cgraph * cgraph, ggml_tensor * tensor, int tensor_idx, bool use_fence = true, bool almost_ready = false) { + GGML_UNUSED(cgraph); ggml_backend_buffer * buf = nullptr; switch (tensor->op) { case GGML_OP_ADD: + case GGML_OP_ACC: case GGML_OP_GET_ROWS: case GGML_OP_SUB: case GGML_OP_MUL: @@ -8864,17 +9574,24 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * case GGML_OP_UPSCALE: case GGML_OP_SCALE: case GGML_OP_SQR: + //case GGML_OP_SIN: + //case GGML_OP_COS: case GGML_OP_CLAMP: case GGML_OP_PAD: + //case GGML_OP_ROLL: case GGML_OP_CPY: + //case GGML_OP_SET_ROWS: case GGML_OP_CONT: case GGML_OP_DUP: case GGML_OP_SILU_BACK: case GGML_OP_NORM: case GGML_OP_GROUP_NORM: case GGML_OP_RMS_NORM: - case GGML_OP_FUSED_RMS_NORM: case GGML_OP_RMS_NORM_BACK: + case GGML_OP_FUSED_RMS_NORM: + case GGML_OP_FUSED_MUL_UNARY: + case GGML_OP_MULTI_ADD: + //case GGML_OP_L2_NORM: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: case GGML_OP_SOFT_MAX_BACK: @@ -8889,15 +9606,18 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * case GGML_OP_SUM: case GGML_OP_SUM_ROWS: case GGML_OP_ARGMAX: + //case GGML_OP_COUNT_EQUAL: case GGML_OP_IM2COL: case GGML_OP_TIMESTEP_EMBEDDING: case GGML_OP_CONV_TRANSPOSE_1D: case GGML_OP_POOL_2D: + //case GGML_OP_CONV_2D_DW: + //case GGML_OP_RWKV_WKV6: + //case GGML_OP_RWKV_WKV7: case GGML_OP_LEAKY_RELU: case GGML_OP_REPEAT: case GGML_OP_REPEAT_BACK: - case GGML_OP_FUSED_MUL_UNARY: - case GGML_OP_MULTI_ADD: + //case GGML_OP_OPT_STEP_ADAMW: buf = tensor->buffer; break; @@ -8905,6 +9625,7 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * switch (ggml_get_unary_op(tensor)) { case GGML_UNARY_OP_SILU: case GGML_UNARY_OP_GELU: + //case GGML_UNARY_OP_GELU_ERF: case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_RELU: case GGML_UNARY_OP_TANH: @@ -8915,6 +9636,19 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * return false; } break; + //case GGML_OP_GLU: + // switch (ggml_get_glu_op(tensor)) { + // case GGML_GLU_OP_GEGLU: + // case GGML_GLU_OP_REGLU: + // case GGML_GLU_OP_SWIGLU: + // case GGML_GLU_OP_GEGLU_ERF: + // case GGML_GLU_OP_GEGLU_QUICK: + // buf = tensor->buffer; + // break; + // default: + // return false; + // } + // break; case GGML_OP_MUL_MAT: case GGML_OP_MUL_MAT_ID: case GGML_OP_FLASH_ATTN_EXT: @@ -8941,7 +9675,7 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * // Only run if ctx hasn't been submitted yet if (!subctx->seqs.empty()) { #ifdef GGML_VULKAN_CHECK_RESULTS - ggml_vk_check_results_0(tensor); + ggml_vk_check_results_0(ctx, cgraph, tensor_idx); use_fence = true; #endif @@ -8961,7 +9695,7 @@ static bool ggml_vk_compute_forward(ggml_backend_vk_context * ctx, ggml_tensor * ggml_vk_wait_for_fence(ctx); } #ifdef GGML_VULKAN_CHECK_RESULTS - ggml_vk_check_results_1(tensor); + ggml_vk_check_results_1(ctx, cgraph, tensor_idx); #endif } @@ -9046,13 +9780,13 @@ static void ggml_vk_cleanup(ggml_backend_vk_context * ctx) { ctx->transfer_cmd_pool.destroy(ctx->device->device); } -GGML_CALL static int ggml_vk_get_device_count() { +static int ggml_vk_get_device_count() { ggml_vk_instance_init(); return vk_instance.device_indices.size(); } -GGML_CALL static void ggml_vk_get_device_description(int device, char * description, size_t description_size) { +static void ggml_vk_get_device_description(int device, char * description, size_t description_size) { ggml_vk_instance_init(); std::vector devices = vk_instance.instance.enumeratePhysicalDevices(); @@ -9092,14 +9826,14 @@ GGML_CALL static void * ggml_backend_vk_buffer_get_base(ggml_backend_buffer_t bu } GGML_CALL static void ggml_backend_vk_buffer_init_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor) { - VK_LOG_DEBUG("ggml_backend_vk_buffer_init_tensor(" << buffer << " (" << buffer->context << "), " << tensor << ")"); + VK_LOG_DEBUG("ggml_backend_vk_buffer_init_tensor(" << buffer << " (" << buffer->context << "), " << tensor << ")"); if (tensor->view_src != nullptr) { GGML_ASSERT(tensor->view_src->buffer->buft == buffer->buft); } } static void ggml_backend_vk_buffer_memset_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, uint8_t value, size_t offset, size_t size) { - VK_LOG_DEBUG("ggml_backend_vk_buffer_memset_tensor(" << buffer << ", " << tensor << ", " << value << ", " << offset << ", " << size << ")"); + VK_LOG_DEBUG("ggml_backend_vk_buffer_memset_tensor(" << buffer << ", " << tensor << ", " << value << ", " << offset << ", " << size << ")"); ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)buffer->context; vk_buffer buf = buf_ctx->dev_buffer; @@ -9108,7 +9842,7 @@ static void ggml_backend_vk_buffer_memset_tensor(ggml_backend_buffer_t buffer, g } static void ggml_backend_vk_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, const void * data, size_t offset, size_t size) { - VK_LOG_DEBUG("ggml_backend_vk_buffer_set_tensor(" << buffer << ", " << tensor << ", " << data << ", " << offset << ", " << size << ")"); + VK_LOG_DEBUG("ggml_backend_vk_buffer_set_tensor(" << buffer << ", " << tensor << ", " << data << ", " << offset << ", " << size << ")"); ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)buffer->context; vk_buffer buf = buf_ctx->dev_buffer; @@ -9116,7 +9850,7 @@ static void ggml_backend_vk_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml } GGML_CALL static void ggml_backend_vk_buffer_get_tensor(ggml_backend_buffer_t buffer, const ggml_tensor * tensor, void * data, size_t offset, size_t size) { - VK_LOG_DEBUG("ggml_backend_vk_buffer_get_tensor(" << buffer << ", " << tensor << ", " << data << ", " << offset << ", " << size << ")"); + VK_LOG_DEBUG("ggml_backend_vk_buffer_get_tensor(" << buffer << ", " << tensor << ", " << data << ", " << offset << ", " << size << ")"); ggml_backend_vk_buffer_context * buf_ctx = (ggml_backend_vk_buffer_context *)buffer->context; vk_buffer buf = buf_ctx->dev_buffer; @@ -9161,13 +9895,13 @@ static ggml_backend_buffer_i ggml_backend_vk_buffer_interface = { }; // vk buffer type -GGML_CALL static const char * ggml_backend_vk_buffer_type_name(ggml_backend_buffer_type_t buft) { +static const char * ggml_backend_vk_buffer_type_name(ggml_backend_buffer_type_t buft) { ggml_backend_vk_buffer_type_context * ctx = (ggml_backend_vk_buffer_type_context *)buft->context; return ctx->name.c_str(); } -GGML_CALL static ggml_backend_buffer_t ggml_backend_vk_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) { +static ggml_backend_buffer_t ggml_backend_vk_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) { VK_LOG_MEMORY("ggml_backend_vk_buffer_type_alloc_buffer(" << size << ")"); ggml_backend_vk_buffer_type_context * ctx = (ggml_backend_vk_buffer_type_context *) buft->context; @@ -9183,23 +9917,23 @@ GGML_CALL static ggml_backend_buffer_t ggml_backend_vk_buffer_type_alloc_buffer( return ggml_backend_buffer_init(buft, ggml_backend_vk_buffer_interface, bufctx, size); } -GGML_CALL static size_t ggml_backend_vk_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) { +static size_t ggml_backend_vk_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) { ggml_backend_vk_buffer_type_context * ctx = (ggml_backend_vk_buffer_type_context *) buft->context; return ctx->device->properties.limits.minStorageBufferOffsetAlignment; } -GGML_CALL static size_t ggml_backend_vk_buffer_type_get_max_size(ggml_backend_buffer_type_t buft) { +static size_t ggml_backend_vk_buffer_type_get_max_size(ggml_backend_buffer_type_t buft) { ggml_backend_vk_buffer_type_context * ctx = (ggml_backend_vk_buffer_type_context *) buft->context; return ctx->device->suballocation_block_size; } -GGML_CALL static size_t ggml_backend_vk_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor) { +static size_t ggml_backend_vk_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor) { return ggml_nbytes(tensor); UNUSED(buft); } -GGML_CALL ggml_backend_buffer_type_t ggml_backend_vk_buffer_type(size_t dev_num) { +ggml_backend_buffer_type_t ggml_backend_vk_buffer_type(size_t dev_num) { ggml_vk_instance_init(); VK_LOG_DEBUG("ggml_backend_vk_buffer_type(" << dev_num << ")"); @@ -9211,24 +9945,24 @@ GGML_CALL ggml_backend_buffer_type_t ggml_backend_vk_buffer_type(size_t dev_num) // host buffer type -GGML_CALL static const char * ggml_backend_vk_host_buffer_type_name(ggml_backend_buffer_type_t buft) { +static const char * ggml_backend_vk_host_buffer_type_name(ggml_backend_buffer_type_t buft) { return GGML_VK_NAME "_Host"; UNUSED(buft); } -GGML_CALL static const char * ggml_backend_vk_host_buffer_name(ggml_backend_buffer_t buffer) { +static const char * ggml_backend_vk_host_buffer_name(ggml_backend_buffer_t buffer) { return GGML_VK_NAME "_Host"; UNUSED(buffer); } -GGML_CALL static void ggml_backend_vk_host_buffer_free_buffer(ggml_backend_buffer_t buffer) { +static void ggml_backend_vk_host_buffer_free_buffer(ggml_backend_buffer_t buffer) { VK_LOG_MEMORY("ggml_backend_vk_host_buffer_free_buffer()"); ggml_vk_host_free(vk_instance.devices[0], buffer->context); } -GGML_CALL static ggml_backend_buffer_t ggml_backend_vk_host_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) { +static ggml_backend_buffer_t ggml_backend_vk_host_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) { VK_LOG_MEMORY("ggml_backend_vk_host_buffer_type_alloc_buffer(" << size << ")"); size += 32; // Behave like the CPU buffer type @@ -9243,7 +9977,6 @@ GGML_CALL static ggml_backend_buffer_t ggml_backend_vk_host_buffer_type_alloc_bu ggml_backend_buffer_t buffer = ggml_backend_cpu_buffer_from_ptr(ptr, size); buffer->buft = buft; - buffer->iface.get_name = ggml_backend_vk_host_buffer_name; buffer->iface.free_buffer = ggml_backend_vk_host_buffer_free_buffer; return buffer; @@ -9251,7 +9984,7 @@ GGML_CALL static ggml_backend_buffer_t ggml_backend_vk_host_buffer_type_alloc_bu UNUSED(buft); } -GGML_CALL static size_t ggml_backend_vk_host_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) { +static size_t ggml_backend_vk_host_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) { return vk_instance.devices[0]->properties.limits.minMemoryMapAlignment; UNUSED(buft); @@ -9265,7 +9998,7 @@ static size_t ggml_backend_vk_host_buffer_type_get_max_size(ggml_backend_buffer_ // Should be changed to return device-specific host buffer type // but that probably requires changes in llama.cpp -GGML_CALL ggml_backend_buffer_type_t ggml_backend_vk_host_buffer_type() { +ggml_backend_buffer_type_t ggml_backend_vk_host_buffer_type() { static struct ggml_backend_buffer_type ggml_backend_vk_buffer_type_host = { /* .iface = */ { /* .get_name = */ ggml_backend_vk_host_buffer_type_name, @@ -9288,13 +10021,13 @@ GGML_CALL ggml_backend_buffer_type_t ggml_backend_vk_host_buffer_type() { // backend -GGML_CALL static const char * ggml_backend_vk_name(ggml_backend_t backend) { +static const char * ggml_backend_vk_name(ggml_backend_t backend) { ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; return ctx->name.c_str(); } -GGML_CALL static void ggml_backend_vk_free(ggml_backend_t backend) { +static void ggml_backend_vk_free(ggml_backend_t backend) { ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; VK_LOG_DEBUG("ggml_backend_vk_free(" << ctx->name << ")"); @@ -9304,13 +10037,13 @@ GGML_CALL static void ggml_backend_vk_free(ggml_backend_t backend) { delete backend; } -GGML_CALL static ggml_backend_buffer_type_t ggml_backend_vk_get_default_buffer_type(ggml_backend_t backend) { +static ggml_backend_buffer_type_t ggml_backend_vk_get_default_buffer_type(ggml_backend_t backend) { ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; return &ctx->device->buffer_type; } -GGML_CALL static void ggml_backend_vk_set_tensor_async(ggml_backend_t backend, ggml_tensor * tensor, const void * data, size_t offset, size_t size) { +static void ggml_backend_vk_set_tensor_async(ggml_backend_t backend, ggml_tensor * tensor, const void * data, size_t offset, size_t size) { VK_LOG_DEBUG("ggml_backend_vk_set_tensor_async(" << size << ")"); ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; GGML_ASSERT((tensor->buffer->buft == ggml_backend_vk_get_default_buffer_type(backend) || tensor->buffer->buft == ggml_backend_vk_host_buffer_type()) && "unsupported buffer type"); @@ -9333,7 +10066,7 @@ GGML_CALL static void ggml_backend_vk_set_tensor_async(ggml_backend_t backend, g ggml_vk_buffer_write_async(transfer_ctx, buf, vk_tensor_offset(tensor) + tensor->view_offs + offset, data, size); } -GGML_CALL static void ggml_backend_vk_get_tensor_async(ggml_backend_t backend, const ggml_tensor * tensor, void * data, size_t offset, size_t size) { +static void ggml_backend_vk_get_tensor_async(ggml_backend_t backend, const ggml_tensor * tensor, void * data, size_t offset, size_t size) { VK_LOG_DEBUG("ggml_backend_vk_get_tensor_async(" << size << ")"); ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; GGML_ASSERT((tensor->buffer->buft == ggml_backend_vk_get_default_buffer_type(backend) || tensor->buffer->buft == ggml_backend_vk_host_buffer_type()) && "unsupported buffer type"); @@ -9356,7 +10089,7 @@ GGML_CALL static void ggml_backend_vk_get_tensor_async(ggml_backend_t backend, c ggml_vk_buffer_read_async(transfer_ctx, buf, vk_tensor_offset(tensor) + tensor->view_offs + offset, data, size); } -GGML_CALL static bool ggml_backend_vk_cpy_tensor_async(ggml_backend_t backend, const ggml_tensor * src, ggml_tensor * dst) { +static bool ggml_backend_vk_cpy_tensor_async(ggml_backend_t backend, const ggml_tensor * src, ggml_tensor * dst) { VK_LOG_DEBUG("ggml_backend_vk_cpy_tensor_async()"); ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; if ((dst->buffer->buft == ggml_backend_vk_get_default_buffer_type(backend) || dst->buffer->buft == ggml_backend_vk_host_buffer_type()) && ggml_backend_buffer_is_vk(src->buffer)) { @@ -9384,7 +10117,7 @@ GGML_CALL static bool ggml_backend_vk_cpy_tensor_async(ggml_backend_t backend, c return false; } -GGML_CALL static void ggml_backend_vk_synchronize(ggml_backend_t backend) { +static void ggml_backend_vk_synchronize(ggml_backend_t backend) { VK_LOG_DEBUG("ggml_backend_vk_synchronize()"); ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; if(ctx->transfer_ctx.expired()) { @@ -9413,7 +10146,38 @@ static bool ggml_vk_is_empty(ggml_tensor * node) { return ggml_is_empty(node) || node->op == GGML_OP_NONE || node->op == GGML_OP_RESHAPE || node->op == GGML_OP_TRANSPOSE || node->op == GGML_OP_VIEW || node->op == GGML_OP_PERMUTE; } -GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backend, ggml_cgraph * cgraph) { +static bool ggml_vk_can_fuse(const struct ggml_cgraph * cgraph, int node_idx, std::initializer_list ops) { + //if (!ggml_can_fuse(cgraph, node_idx, ops)) { + return false; + //} + + if (ops.size() == 2 && ops.begin()[0] == GGML_OP_RMS_NORM && ops.begin()[1] == GGML_OP_MUL) { + // additional constraints specific to this fusion + const ggml_tensor *rms_norm = cgraph->nodes[node_idx]; + const ggml_tensor *mul = cgraph->nodes[node_idx + 1]; + + GGML_ASSERT(rms_norm->src[0]->type == GGML_TYPE_F32); + GGML_ASSERT(rms_norm->type == GGML_TYPE_F32); + // rms_norm only supports f32 + if (mul->src[0]->type != GGML_TYPE_F32 || + mul->src[1]->type != GGML_TYPE_F32 || + mul->type != GGML_TYPE_F32) { + return false; + } + // if rms_norm is the B operand, then we don't handle broadcast + if (rms_norm == mul->src[1] && + mul->src[0]->ne[1] != rms_norm->ne[1]) { + return false; + } + // rms_norm shader assumes contiguous rows + if (!ggml_is_contiguous_rows(mul->src[0]) || !ggml_is_contiguous_rows(mul->src[1])) { + return false; + } + } + return true; +} + +static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backend, ggml_cgraph * cgraph) { VK_LOG_DEBUG("ggml_backend_vk_graph_compute(" << cgraph->n_nodes << " nodes)"); ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; @@ -9426,10 +10190,15 @@ GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backen uint64_t total_mat_mul_bytes = 0; for (int i = 0; i < cgraph->n_nodes; i++) { - ggml_vk_build_graph(ctx, cgraph->nodes[i], i, nullptr, 0, true, false, false, false); + if (!ctx->device->disable_fusion && ggml_vk_can_fuse(cgraph, i, { GGML_OP_RMS_NORM, GGML_OP_MUL })) { + ctx->num_additional_fused_ops = 1; + } + ggml_vk_build_graph(ctx, cgraph, i, nullptr, 0, true, false, false, false); if (cgraph->nodes[i]->op == GGML_OP_MUL_MAT || cgraph->nodes[i]->op == GGML_OP_MUL_MAT_ID) { total_mat_mul_bytes += ggml_nbytes(cgraph->nodes[i]->src[0]); } + i += ctx->num_additional_fused_ops; + ctx->num_additional_fused_ops = 0; } if (ctx->device->need_compiles) { ggml_vk_load_shaders(ctx->device); @@ -9491,14 +10260,18 @@ GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backen mul_mat_bytes += ggml_nbytes(cgraph->nodes[i]->src[0]); } + if (!ctx->device->disable_fusion && ggml_vk_can_fuse(cgraph, i, { GGML_OP_RMS_NORM, GGML_OP_MUL })) { + ctx->num_additional_fused_ops = 1; + } + // Signal the almost_ready fence when the graph is mostly complete (< 20% remaining) bool almost_ready = (cgraph->n_nodes - i) < cgraph->n_nodes / 5; bool submit = (submitted_nodes >= nodes_per_submit) || (mul_mat_bytes >= mul_mat_bytes_per_submit) || - (i == last_node) || + (i + ctx->num_additional_fused_ops == last_node) || (almost_ready && !ctx->almost_ready_fence_pending); - bool enqueued = ggml_vk_build_graph(ctx, cgraph->nodes[i], i, cgraph->nodes[submit_node_idx], submit_node_idx, false, i == last_node, almost_ready, submit); + bool enqueued = ggml_vk_build_graph(ctx, cgraph, i, cgraph->nodes[submit_node_idx], submit_node_idx, false, i + ctx->num_additional_fused_ops == last_node, almost_ready, submit); if (vk_perf_logger_enabled) { if (ctx->compute_ctx.expired()) { @@ -9508,7 +10281,10 @@ GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backen } else { compute_ctx = ctx->compute_ctx.lock(); } - compute_ctx->s->buffer.writeTimestamp(vk::PipelineStageFlagBits::eAllCommands, ctx->device->query_pool, i+1); + // If there are fused ops, just write out timestamps for all nodes to keep the accounting simple + for (int j = 0; j < ctx->num_additional_fused_ops + 1; ++j) { + compute_ctx->s->buffer.writeTimestamp(vk::PipelineStageFlagBits::eAllCommands, ctx->device->query_pool, i+j+1); + } } if (enqueued) { @@ -9530,6 +10306,8 @@ GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backen } submit_count++; } + i += ctx->num_additional_fused_ops; + ctx->num_additional_fused_ops = 0; } if (vk_perf_logger_enabled) { @@ -9561,13 +10339,12 @@ GGML_CALL static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backen UNUSED(backend); } -GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const ggml_tensor * op) { - // ggml_backend_vk_context * ctx = (ggml_backend_vk_context *) backend->context; - +static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const ggml_tensor * op) { switch (op->op) { case GGML_OP_UNARY: switch (ggml_get_unary_op(op)) { case GGML_UNARY_OP_GELU: + //case GGML_UNARY_OP_GELU_ERF: case GGML_UNARY_OP_GELU_QUICK: case GGML_UNARY_OP_SILU: case GGML_UNARY_OP_RELU: @@ -9596,11 +10373,26 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const break; case GGML_OP_MULTI_ADD: return op->src[0]->type == GGML_TYPE_F32 && op->type == GGML_TYPE_F32 && op->ne[2] == 1 && op->ne[3] == 1; + //case GGML_OP_GLU: + // switch (ggml_get_glu_op(op)) { + // case GGML_GLU_OP_GEGLU: + // case GGML_GLU_OP_REGLU: + // case GGML_GLU_OP_SWIGLU: + // case GGML_GLU_OP_GEGLU_ERF: + // case GGML_GLU_OP_GEGLU_QUICK: + // return ggml_is_contiguous(op->src[0]) && + // (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) && + // (op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16) && + // (op->src[0]->type == op->type); + // default: + // return false; + // } + // break; case GGML_OP_MUL_MAT: case GGML_OP_MUL_MAT_ID: { ggml_type src0_type = op->src[0]->type; - ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; + const ggml_backend_vk_context * ctx = (const ggml_backend_vk_context *)backend->context; const vk_device& device = ctx->device; if (op->op == GGML_OP_MUL_MAT_ID) { if (!device->mul_mat_id_s[src0_type] && !device->mul_mat_id_m[src0_type] && !device->mul_mat_id_l[src0_type]) { @@ -9665,8 +10457,9 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const } break; case GGML_OP_FLASH_ATTN_EXT: { - ggml_backend_vk_context * ctx = (ggml_backend_vk_context *)backend->context; - bool coopmat2 = ctx->device->coopmat2; + const ggml_backend_vk_context * ctx = (const ggml_backend_vk_context *)backend->context; + auto& device = ctx->device; + bool coopmat2 = device->coopmat2; FaHeadSizes head_sizes = fa_get_head_sizes(op->src[1]->ne[0], op->src[2]->ne[0]); if (head_sizes == FA_HEAD_SIZE_UNSUPPORTED) { return false; @@ -9717,7 +10510,7 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const default: return false; } - if (!coopmat2 && !ctx->device->subgroup_shuffle) { + if (!coopmat2 && !device->subgroup_shuffle) { // scalar FA uses subgroupShuffle return false; } @@ -9748,6 +10541,23 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const return false; } } break; + //case GGML_OP_SET_ROWS: + // { + // switch (op->type) { + // case GGML_TYPE_F32: + // case GGML_TYPE_F16: + // case GGML_TYPE_BF16: + // case GGML_TYPE_Q4_0: + // case GGML_TYPE_Q4_1: + // case GGML_TYPE_Q5_0: + // case GGML_TYPE_Q5_1: + // case GGML_TYPE_Q8_0: + // case GGML_TYPE_IQ4_NL: + // return true; + // default: + // return false; + // } + // } break; case GGML_OP_CONT: case GGML_OP_CPY: case GGML_OP_DUP: @@ -9816,6 +10626,7 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const return true; case GGML_OP_NORM: case GGML_OP_GROUP_NORM: + //case GGML_OP_L2_NORM: return ggml_is_contiguous(op->src[0]); case GGML_OP_ADD: case GGML_OP_SUB: @@ -9827,13 +10638,16 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const case GGML_OP_SILU_BACK: case GGML_OP_RMS_NORM_BACK: 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_UPSCALE: case GGML_OP_ACC: case GGML_OP_CONCAT: - case GGML_OP_UPSCALE: case GGML_OP_SCALE: case GGML_OP_PAD: + //case GGML_OP_ROLL: case GGML_OP_DIAG_MASK_INF: case GGML_OP_SOFT_MAX: case GGML_OP_SOFT_MAX_BACK: @@ -9841,9 +10655,15 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const case GGML_OP_SUM: case GGML_OP_SUM_ROWS: case GGML_OP_ARGMAX: + //case GGML_OP_COUNT_EQUAL: case GGML_OP_IM2COL: case GGML_OP_TIMESTEP_EMBEDDING: + //case GGML_OP_CONV_2D_DW: + case GGML_OP_POOL_2D: + //case GGML_OP_RWKV_WKV6: + //case GGML_OP_RWKV_WKV7: case GGML_OP_LEAKY_RELU: + //case GGML_OP_OPT_STEP_ADAMW: return true; case GGML_OP_CONV_TRANSPOSE_1D: return op->src[0]->type == GGML_TYPE_F32 && op->src[1]->type == GGML_TYPE_F32; @@ -9851,19 +10671,9 @@ GGML_CALL static bool ggml_backend_vk_supports_op(ggml_backend_t backend, const return false; } - UNUSED(backend); } -GGML_CALL static bool ggml_backend_vk_offload_op(ggml_backend_t backend, const ggml_tensor * op) { - const int min_batch_size = 32; - - return (op->ne[1] >= min_batch_size && op->op != GGML_OP_GET_ROWS) || - (op->ne[2] >= min_batch_size && op->op == GGML_OP_MUL_MAT_ID); - - UNUSED(backend); -} - -GGML_CALL static bool ggml_backend_vk_supports_buft(ggml_backend_t backend, ggml_backend_buffer_type_t buft) { +static bool ggml_backend_vk_supports_buft(ggml_backend_t backend, ggml_backend_buffer_type_t buft) { if (buft->iface.get_name != ggml_backend_vk_buffer_type_name) { return false; } @@ -9874,6 +10684,15 @@ GGML_CALL static bool ggml_backend_vk_supports_buft(ggml_backend_t backend, ggml return buft_ctx->device == ctx->device; } +static bool ggml_backend_vk_offload_op(ggml_backend_t backend, const ggml_tensor * op) { + const int min_batch_size = 32; + + return (op->ne[1] >= min_batch_size && op->op != GGML_OP_GET_ROWS) || + (op->ne[2] >= min_batch_size && op->op == GGML_OP_MUL_MAT_ID); + + UNUSED(backend); +} + // TODO: enable async and synchronize static ggml_backend_i ggml_backend_vk_interface = { /* .get_name = */ ggml_backend_vk_name, @@ -9903,7 +10722,7 @@ static ggml_guid_t ggml_backend_vk_guid() { return &guid; } -GGML_CALL ggml_backend_t ggml_backend_vk_init(size_t dev_num) { +ggml_backend_t ggml_backend_vk_init(size_t dev_num) { VK_LOG_DEBUG("ggml_backend_vk_init(" << dev_num << ")"); ggml_backend_vk_context * ctx = new ggml_backend_vk_context; @@ -9918,19 +10737,21 @@ GGML_CALL ggml_backend_t ggml_backend_vk_init(size_t dev_num) { return vk_backend; } -GGML_CALL bool ggml_backend_is_vk(ggml_backend_t backend) { +bool ggml_backend_is_vk(ggml_backend_t backend) { return backend != NULL && ggml_guid_matches(backend->guid, ggml_backend_vk_guid()); } -GGML_CALL int ggml_backend_vk_get_device_count() { +int ggml_backend_vk_get_device_count() { return ggml_vk_get_device_count(); } -GGML_CALL void ggml_backend_vk_get_device_description(int device, char * description, size_t description_size) { - ggml_vk_get_device_description(device, description, description_size); +void ggml_backend_vk_get_device_description(int device, char * description, size_t description_size) { + GGML_ASSERT(device < (int) vk_instance.device_indices.size()); + int dev_idx = vk_instance.device_indices[device]; + ggml_vk_get_device_description(dev_idx, description, description_size); } -GGML_CALL void ggml_backend_vk_get_device_memory(int device, size_t * free, size_t * total) { +void ggml_backend_vk_get_device_memory(int device, size_t * free, size_t * total) { GGML_ASSERT(device < (int) vk_instance.device_indices.size()); vk::PhysicalDevice vkdev = vk_instance.instance.enumeratePhysicalDevices()[vk_instance.device_indices[device]]; @@ -9946,7 +10767,6 @@ GGML_CALL void ggml_backend_vk_get_device_memory(int device, size_t * free, size } } -// backend registry GGML_CALL static ggml_backend_t ggml_backend_reg_vk_init(const char * params, void * user_data) { ggml_backend_t vk_backend = ggml_backend_vk_init((int) (intptr_t) user_data); return vk_backend; @@ -9967,6 +10787,90 @@ GGML_CALL int ggml_backend_vk_reg_devices() { return vk_instance.device_indices.size(); } +////////////////////////// + +#if 0 +static const struct ggml_backend_device_i ggml_backend_vk_device_i = { + /* .get_name = */ ggml_backend_vk_device_get_name, + /* .get_description = */ ggml_backend_vk_device_get_description, + /* .get_memory = */ ggml_backend_vk_device_get_memory, + /* .get_type = */ ggml_backend_vk_device_get_type, + /* .get_props = */ ggml_backend_vk_device_get_props, + /* .init_backend = */ ggml_backend_vk_device_init, + /* .get_buffer_type = */ ggml_backend_vk_device_get_buffer_type, + /* .get_host_buffer_type = */ ggml_backend_vk_device_get_host_buffer_type, + /* .buffer_from_host_ptr = */ NULL, + /* .supports_op = */ ggml_backend_vk_device_supports_op, + /* .supports_buft = */ ggml_backend_vk_device_supports_buft, + /* .offload_op = */ ggml_backend_vk_device_offload_op, + /* .event_new = */ NULL, + /* .event_free = */ NULL, + /* .event_synchronize = */ NULL, +}; + +static const char * ggml_backend_vk_reg_get_name(ggml_backend_reg_t reg) { + UNUSED(reg); + return GGML_VK_NAME; +} + +static size_t ggml_backend_vk_reg_get_device_count(ggml_backend_reg_t reg) { + UNUSED(reg); + return ggml_backend_vk_get_device_count(); +} + +static ggml_backend_dev_t ggml_backend_vk_reg_get_device(ggml_backend_reg_t reg, size_t device) { + static std::vector devices; + + static bool initialized = false; + + { + static std::mutex mutex; + std::lock_guard lock(mutex); + if (!initialized) { + for (int i = 0; i < ggml_backend_vk_get_device_count(); i++) { + ggml_backend_vk_device_context * ctx = new ggml_backend_vk_device_context; + char desc[256]; + ggml_backend_vk_get_device_description(i, desc, sizeof(desc)); + ctx->device = i; + ctx->name = GGML_VK_NAME + std::to_string(i); + ctx->description = desc; + devices.push_back(new ggml_backend_device { + /* .iface = */ ggml_backend_vk_device_i, + /* .reg = */ reg, + /* .context = */ ctx, + }); + } + initialized = true; + } + } + + GGML_ASSERT(device < devices.size()); + return devices[device]; +} + +static const struct ggml_backend_reg_i ggml_backend_vk_reg_i = { + /* .get_name = */ ggml_backend_vk_reg_get_name, + /* .get_device_count = */ ggml_backend_vk_reg_get_device_count, + /* .get_device = */ ggml_backend_vk_reg_get_device, + /* .get_proc_address = */ NULL, +}; + +ggml_backend_reg_t ggml_backend_vk_reg() { + static ggml_backend_reg reg = { + /* .api_version = */ GGML_BACKEND_API_VERSION, + /* .iface = */ ggml_backend_vk_reg_i, + /* .context = */ nullptr, + }; + try { + ggml_vk_instance_init(); + return ® + } catch (const vk::SystemError& e) { + VK_LOG_DEBUG("ggml_backend_vk_reg() -> Error: System error: " << e.what()); + return nullptr; + } +} +#endif + // Extension availability static bool ggml_vk_instance_validation_ext_available(const std::vector& instance_extensions) { #ifdef GGML_VULKAN_VALIDATE @@ -10131,11 +11035,21 @@ void * comp_result; size_t comp_size; size_t comp_nb[GGML_MAX_DIMS]; size_t check_counter = 0; -static void ggml_vk_check_results_0(ggml_tensor * tensor) { +static void ggml_vk_check_results_0(ggml_backend_vk_context * ctx, ggml_cgraph * cgraph, int tensor_idx) { + ggml_tensor * tensor = cgraph->nodes[tensor_idx]; if (tensor->op == GGML_OP_TRANSPOSE) { return; } + bool fused_rms_norm_mul = false; + int rms_norm_idx = -1; + if (ctx->num_additional_fused_ops == 1 && + tensor->op == GGML_OP_RMS_NORM && + cgraph->nodes[tensor_idx + 1]->op == GGML_OP_MUL) { + fused_rms_norm_mul = true; + tensor = cgraph->nodes[tensor_idx + 1]; + } + check_counter++; if (!(vk_output_tensor > 0 && vk_output_tensor == check_counter) && check_counter <= vk_skip_checks) { return; @@ -10163,6 +11077,15 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { for (int i = 0; i < 6; i++) { ggml_tensor * srci = tensor->src[i]; + if (fused_rms_norm_mul) { + rms_norm_idx = tensor->src[0]->op == GGML_OP_RMS_NORM ? 0 : 1; + ggml_tensor *rms_norm = tensor->src[rms_norm_idx]; + switch (i) { + case 0: srci = rms_norm->src[0]; break; + case 1: srci = tensor->src[1 - rms_norm_idx]; break; + default: continue; + } + } if (srci == nullptr) { continue; } @@ -10220,19 +11143,28 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { } else if (tensor->op == GGML_OP_SUB) { tensor_clone = ggml_sub(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_MUL) { - tensor_clone = ggml_mul(ggml_ctx, src_clone[0], src_clone[1]); + if (fused_rms_norm_mul) { + tensor_clone = ggml_rms_norm(ggml_ctx, src_clone[0], *(float *)tensor->src[rms_norm_idx]->op_params); + tensor_clone = ggml_mul(ggml_ctx, tensor_clone, src_clone[1 - rms_norm_idx]); + } else { + tensor_clone = ggml_mul(ggml_ctx, src_clone[0], src_clone[1]); + } } else if (tensor->op == GGML_OP_DIV) { tensor_clone = ggml_div(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_CONCAT) { tensor_clone = ggml_concat(ggml_ctx, src_clone[0], src_clone[1], *(int *)tensor->op_params); } else if (tensor->op == GGML_OP_UPSCALE) { - tensor_clone = ggml_upscale_ext(ggml_ctx, src_clone[0], tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); + tensor_clone = ggml_upscale_ext(ggml_ctx, src_clone[0], tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3], (ggml_scale_mode) tensor->op_params[0]); } else if (tensor->op == GGML_OP_SCALE) { const float * params = (const float *)tensor->op_params; tensor_clone = ggml_scale(ggml_ctx, src_clone[0], params[0]); } else if (tensor->op == GGML_OP_SQR) { tensor_clone = ggml_sqr(ggml_ctx, src_clone[0]); - } else if (tensor->op == GGML_OP_CLAMP) { + } else if (tensor->op == GGML_OP_SIN) { + tensor_clone = ggml_sin(ggml_ctx, src_clone[0]); + } else if (tensor->op == GGML_OP_COS) { + tensor_clone = ggml_cos(ggml_ctx, src_clone[0]); + } else if (tensor->op == GGML_OP_CLAMP) { const float * params = (const float *)tensor->op_params; tensor_clone = ggml_clamp(ggml_ctx, src_clone[0], params[0], params[1]); } else if (tensor->op == GGML_OP_PAD) { @@ -10252,13 +11184,20 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { tensor_clone = ggml_group_norm(ggml_ctx, src_clone[0], tensor->op_params[0], float_params[1]); } else if (tensor->op == GGML_OP_RMS_NORM) { tensor_clone = ggml_rms_norm(ggml_ctx, src_clone[0], *(float *)tensor->op_params); - } else if (tensor->op == GGML_OP_FUSED_RMS_NORM) { - tensor_clone = ggml_fused_rms_norm(ggml_ctx, src_clone[0], src_clone[1], *(float *)tensor->op_params); } else if (tensor->op == GGML_OP_RMS_NORM_BACK) { const float eps = ((float *) tensor->op_params)[0]; tensor_clone = ggml_rms_norm_back(ggml_ctx, src_clone[0], src_clone[1], eps); + } else if (tensor->op == GGML_OP_FUSED_RMS_NORM) { + tensor_clone = ggml_fused_rms_norm(ggml_ctx, src_clone[0], src_clone[1], *(float *)tensor->op_params); + } else if (tensor->op == GGML_OP_FUSED_MUL_UNARY) { + tensor_clone = ggml_fused_mul_unary(ggml_ctx, src_clone[0], src_clone[1], (ggml_unary_op)tensor->op_params[0]); + } else if (tensor->op == GGML_OP_MULTI_ADD) { + tensor_clone = ggml_multi_add(ggml_ctx, src_clone[0], tensor->op_params[0]); } else if (tensor->op == GGML_OP_SILU_BACK) { tensor_clone = ggml_silu_back(ggml_ctx, src_clone[0], src_clone[1]); + } else if (tensor->op == GGML_OP_L2_NORM) { + const float eps = ((float *) tensor->op_params)[0]; + tensor_clone = ggml_l2_norm(ggml_ctx, src_clone[0], eps); } else if (tensor->op == GGML_OP_SOFT_MAX) { if (src1 != nullptr) { const float * params = (const float *)tensor->op_params; @@ -10303,6 +11242,9 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { case GGML_UNARY_OP_GELU: tensor_clone = ggml_gelu(ggml_ctx, src_clone[0]); break; + //case GGML_UNARY_OP_GELU_ERF: + // tensor_clone = ggml_gelu_erf(ggml_ctx, src_clone[0]); + // break; case GGML_UNARY_OP_GELU_QUICK: tensor_clone = ggml_gelu_quick(ggml_ctx, src_clone[0]); break; @@ -10319,10 +11261,12 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { std::cerr << "Missing vk_check_results OP: " << ggml_op_name(tensor->op) << std::endl; GGML_ABORT("fatal error"); } - } else if (tensor->op == GGML_OP_FUSED_MUL_UNARY) { - tensor_clone = ggml_fused_mul_unary(ggml_ctx, src_clone[0], src_clone[1], (ggml_unary_op)tensor->op_params[0]); - } else if (tensor->op == GGML_OP_MULTI_ADD) { - tensor_clone = ggml_multi_add(ggml_ctx, src_clone[0], tensor->op_params[0]); + //} else if (tensor->op == GGML_OP_GLU) { + // if (src_clone[1] == nullptr) { + // tensor_clone = ggml_glu(ggml_ctx, src_clone[0], (ggml_glu_op) tensor->op_params[0], tensor->op_params[1]); + // } else { + // tensor_clone = ggml_glu_split(ggml_ctx, src_clone[0], src_clone[1], (ggml_glu_op) tensor->op_params[0]); + // } } else if (tensor->op == GGML_OP_CPY || tensor->op == GGML_OP_DUP) { if (src1 == nullptr) { tensor_clone = ggml_dup(ggml_ctx, src_clone[0]); @@ -10330,6 +11274,8 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { } else { tensor_clone = ggml_cpy(ggml_ctx, src_clone[0], src_clone[1]); } + //} else if (tensor->op == GGML_OP_SET_ROWS) { + // tensor_clone = ggml_set_rows(ggml_ctx, src_clone[0], src_clone[1]); } else if (tensor->op == GGML_OP_CONT) { tensor_clone = ggml_cont_4d(ggml_ctx, src_clone[0], tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]); } else if (tensor->op == GGML_OP_RESHAPE) { @@ -10351,7 +11297,9 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { tensor_clone = ggml_sum_rows(ggml_ctx, src_clone[0]); } else if (tensor->op == GGML_OP_ARGMAX) { tensor_clone = ggml_argmax(ggml_ctx, src_clone[0]); - } else if (tensor->op == GGML_OP_IM2COL) { + //} else if (tensor->op == GGML_OP_COUNT_EQUAL) { + // tensor_clone = ggml_count_equal(ggml_ctx, src_clone[0], src_clone[1]); + } else if (tensor->op == GGML_OP_IM2COL) { const int32_t s0 = tensor->op_params[0]; const int32_t s1 = tensor->op_params[1]; const int32_t p0 = tensor->op_params[2]; @@ -10383,16 +11331,26 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { } else if (tensor->op == GGML_OP_LEAKY_RELU) { const float * op_params = (const float *)tensor->op_params; tensor_clone = ggml_leaky_relu(ggml_ctx, src_clone[0], op_params[0], false); - } + } else if (tensor->op == GGML_OP_RWKV_WKV6) { + tensor_clone = ggml_rwkv_wkv6(ggml_ctx, src_clone[0], src_clone[1], + src_clone[2], src_clone[3], src_clone[4], src_clone[5]); + } else if (tensor->op == GGML_OP_RWKV_WKV7) { + tensor_clone = ggml_rwkv_wkv7(ggml_ctx, src_clone[0], src_clone[1], src_clone[2], src_clone[3], + src_clone[4], src_clone[5], src_clone[6]); + } else if (tensor->op == GGML_OP_OPT_STEP_ADAMW) { + src_clone[0]->flags = src0->flags; + tensor_clone = ggml_opt_step_adamw(ggml_ctx, src_clone[0], src_clone[1], + src_clone[2], src_clone[3], src_clone[4]); + } else { std::cerr << "Missing vk_check_results OP: " << ggml_op_name(tensor->op) << std::endl; GGML_ABORT("fatal error"); } - ggml_cgraph * cgraph = ggml_new_graph(ggml_ctx); - ggml_build_forward_expand(cgraph, tensor_clone); + ggml_cgraph * cgraph_cpu = ggml_new_graph(ggml_ctx); + ggml_build_forward_expand(cgraph_cpu, tensor_clone); - ggml_graph_compute_with_ctx(ggml_ctx, cgraph, 8); + ggml_graph_compute_with_ctx(ggml_ctx, cgraph_cpu, 8); if (vk_output_tensor > 0 && vk_output_tensor == check_counter) { ggml_vk_print_tensor(tensor_clone, "tensor_clone"); @@ -10415,10 +11373,19 @@ static void ggml_vk_check_results_0(ggml_tensor * tensor) { VK_LOG_DEBUG("END ggml_vk_check_results_0(" << tensor->name << ")"); } -static void ggml_vk_check_results_1(ggml_tensor * tensor) { +static void ggml_vk_check_results_1(ggml_backend_vk_context * ctx, ggml_cgraph * cgraph, int tensor_idx) { + ggml_tensor * tensor = cgraph->nodes[tensor_idx]; if (tensor->op == GGML_OP_TRANSPOSE) { return; } + bool fused_rms_norm_mul = false; + if (ctx->num_additional_fused_ops == 1 && + tensor->op == GGML_OP_RMS_NORM && + cgraph->nodes[tensor_idx + 1]->op == GGML_OP_MUL) { + fused_rms_norm_mul = true; + tensor = cgraph->nodes[tensor_idx + 1]; + } + if (!(vk_output_tensor > 0 && vk_output_tensor == check_counter) && check_counter <= vk_skip_checks) { return; } @@ -10594,3 +11561,5 @@ static void ggml_vk_check_results_1(ggml_tensor * tensor) { VK_LOG_DEBUG("END ggml_vk_check_results_1(" << tensor->name << ")"); } #endif + +//GGML_BACKEND_DL_IMPL(ggml_backend_vk_reg) diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index dbb080f8..b3982538 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -4682,6 +4682,24 @@ GGML_CALL bool ggml_is_permuted(const struct ggml_tensor * tensor) { return tensor->nb[0] > tensor->nb[1] || tensor->nb[1] > tensor->nb[2] || tensor->nb[2] > tensor->nb[3]; } +GGML_CALL bool ggml_is_contiguously_allocated(const struct ggml_tensor * tensor) { + return ggml_nbytes(tensor) == ggml_nelements(tensor) * ggml_type_size(tensor->type)/ggml_blck_size(tensor->type); +} + +GGML_CALL bool ggml_is_contiguous_channels(const struct ggml_tensor * tensor) { + return + tensor->nb[0] > tensor->nb[2] && + tensor->nb[1] > tensor->nb[0] && + tensor->nb[2] == ggml_type_size(tensor->type); +} + +GGML_CALL bool ggml_is_contiguous_rows(const struct ggml_tensor * tensor) { + return + tensor->ne[0] == ggml_blck_size(tensor->type) || + tensor->nb[0] == ggml_type_size(tensor->type); +} + + static inline bool ggml_is_padded_1d(const struct ggml_tensor * tensor) { static_assert(GGML_MAX_DIMS == 4, "GGML_MAX_DIMS is not 4 - update this function"); @@ -5195,16 +5213,6 @@ static void ggml_set_op_params(struct ggml_tensor * tensor, const void * params, memcpy(tensor->op_params, params, params_size); } -static int32_t ggml_get_op_params_i32(const struct ggml_tensor * tensor, uint32_t i) { - assert(i < GGML_MAX_OP_PARAMS / sizeof(int32_t)); - return ((const int32_t *)(tensor->op_params))[i]; -} - -static float ggml_get_op_params_f32(const struct ggml_tensor * tensor, uint32_t i) { - assert(i < GGML_MAX_OP_PARAMS / sizeof(float)); - return ((const float *)(tensor->op_params))[i]; -} - static void ggml_set_op_params_i32(struct ggml_tensor * tensor, uint32_t i, int32_t value) { assert(i < GGML_MAX_OP_PARAMS / sizeof(int32_t)); ((int32_t *)(tensor->op_params))[i] = value; diff --git a/ggml/src/vulkan-shaders/CMakeLists.txt b/ggml/src/vulkan-shaders/CMakeLists.txt index a22ea817..e1f613fb 100644 --- a/ggml/src/vulkan-shaders/CMakeLists.txt +++ b/ggml/src/vulkan-shaders/CMakeLists.txt @@ -27,5 +27,5 @@ endif() set(TARGET vulkan-shaders-gen) add_executable(${TARGET} vulkan-shaders-gen.cpp) install(TARGETS ${TARGET} RUNTIME) -target_compile_features(${TARGET} PRIVATE cxx_std_11) +target_compile_features(${TARGET} PRIVATE cxx_std_17) target_link_libraries(vulkan-shaders-gen PUBLIC Threads::Threads) diff --git a/ggml/src/vulkan-shaders/conv2d_dw.comp b/ggml/src/vulkan-shaders/conv2d_dw.comp new file mode 100644 index 00000000..938c74da --- /dev/null +++ b/ggml/src/vulkan-shaders/conv2d_dw.comp @@ -0,0 +1,105 @@ +#version 450 + +#include "types.comp" + +layout (push_constant) uniform parameter +{ + uint ne; + uint batches; + uint channels; + uint dst_w; + uint dst_h; + uint src_w; + uint src_h; + uint knl_w; + uint knl_h; + int stride_x; + int stride_y; + int pad_x; + int pad_y; + int dilation_x; + int dilation_y; +} p; + +layout (binding = 0) readonly buffer A {A_TYPE knl_data[];}; +layout (binding = 1) readonly buffer B {B_TYPE src_data[];}; +layout (binding = 2) writeonly buffer D {D_TYPE dst_data[];}; + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +FLOAT_TYPE conv_2d_dw_whcn(uint idx) { + uint i0 = idx / p.dst_w; + uint dst_x = idx - i0 * p.dst_w; + uint i1 = i0 / p.dst_h; + uint dst_y = i0 - i1 * p.dst_h; + uint n = i1 / p.channels; + uint c = i1 - n * p.channels; + + uint src_i = n * p.channels * p.src_h * p.src_w + c * p.src_h * p.src_w; + uint knl_i = c * p.knl_h * p.knl_w; + + FLOAT_TYPE sum = 0.0; + for (uint knl_y = 0; knl_y < p.knl_h; ++knl_y) { + uint src_y = dst_y * p.stride_y + knl_y * p.dilation_y - p.pad_y; + if (src_y >= p.src_h) { // src_y < 0 will wrap to a large unsigned int + continue; + } + for (uint knl_x = 0; knl_x < p.knl_w; ++knl_x) { + uint src_x = dst_x * p.stride_x + knl_x * p.dilation_x - p.pad_x; + if (src_x >= p.src_w) { // src_x < 0 will wrap to a large unsigned int + continue; + } + FLOAT_TYPE v = FLOAT_TYPE(src_data[src_i + src_y * p.src_w + src_x]); + FLOAT_TYPE k = FLOAT_TYPE(knl_data[knl_i + knl_y * p.knl_w + knl_x]); + sum = fma(v, k, sum); + } + } + return sum; +} + +FLOAT_TYPE conv_2d_dw_cwhn(uint idx) { + uint i0 = idx / p.channels; + uint c = idx - i0 * p.channels; + uint i1 = i0 / p.dst_w; + uint dst_x = i0 - i1 * p.dst_w; + uint n = i1 / p.dst_h; + uint dst_y = i1 - n * p.dst_h; + + uint src_i = n * p.channels * p.src_h * p.src_w; + uint src_row = p.src_w * p.channels; + uint knl_row = p.knl_w * p.channels; + + FLOAT_TYPE sum = 0.0; + for (uint knl_y = 0; knl_y < p.knl_h; ++knl_y) { + uint src_y = dst_y * p.stride_y + knl_y * p.dilation_y - p.pad_y; + if (src_y >= p.src_h) { // src_y < 0 will wrap to a large unsigned int + continue; + } + for (uint knl_x = 0; knl_x < p.knl_w; ++knl_x) { + uint src_x = dst_x * p.stride_x + knl_x * p.dilation_x - p.pad_x; + if (src_x >= p.src_w) { // src_x < 0 will wrap to a large unsigned int + continue; + } + FLOAT_TYPE v = FLOAT_TYPE(src_data[src_i + src_y * src_row + src_x * p.channels + c]); + FLOAT_TYPE k = FLOAT_TYPE(knl_data[ knl_y * knl_row + knl_x * p.channels + c]); + sum = fma(v, k, sum); + } + } + return sum; +} + +void main() { + uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + if (idx >= p.ne) { + return; + } + + FLOAT_TYPE result = +#ifdef WHCN + conv_2d_dw_whcn(idx); +#else + conv_2d_dw_cwhn(idx); +#endif + dst_data[idx] = D_TYPE(result); +} + diff --git a/ggml/src/vulkan-shaders/copy_to_quant.comp b/ggml/src/vulkan-shaders/copy_to_quant.comp index 9c76437d..e06547e4 100644 --- a/ggml/src/vulkan-shaders/copy_to_quant.comp +++ b/ggml/src/vulkan-shaders/copy_to_quant.comp @@ -6,17 +6,25 @@ spirv_execution_mode(capabilities = [4467], 4462, 16); // RoundingModeRTE, 16 bi #endif // RTE16 #include "types.comp" -#include "generic_unary_head.comp" -#if defined(DATA_A_IQ4_NL) -// 16 invocations needed for init_iq4nl_shmem -layout(local_size_x = 16, local_size_y = 1, local_size_z = 1) in; +#if defined(SET_ROWS) && QUANT_K == 1 +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; +const uint BLOCK_SIZE = 512; #else -layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; +const uint BLOCK_SIZE = 32; #endif layout (binding = 0) readonly buffer S {float data_s[];}; + +#if defined(SET_ROWS) +#include "generic_binary_head.comp" +layout (binding = 1) readonly buffer C {uvec2 data_i[];}; +layout (binding = 2) writeonly buffer Q {A_TYPE data_q[];}; +#else +#include "generic_unary_head.comp" layout (binding = 1) writeonly buffer Q {A_TYPE data_q[];}; +#endif #if defined(DATA_A_Q4_0) void quantize(uint dst_idx, uint src_idx) @@ -221,15 +229,56 @@ void quantize(uint dst_idx, uint src_idx) } #endif +#if defined(DATA_A_F32) || defined(DATA_A_F16) +void quantize(uint dst_idx, uint src_idx) +{ + data_q[dst_idx] = A_TYPE(data_s[src_idx]); +} +#endif + +#if defined(DATA_A_BF16) +void quantize(uint dst_idx, uint src_idx) +{ + data_q[dst_idx] = A_TYPE(fp32_to_bf16(data_s[src_idx])); +} +#endif + +#if defined(SET_ROWS) + void main() { #ifdef NEEDS_INIT_IQ_SHMEM init_iq_shmem(gl_WorkGroupSize); - if (gl_LocalInvocationIndex.x != 0) { - return; - } #endif - const uint idx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * QUANT_K; + const uint idx = ((gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x) * BLOCK_SIZE + gl_LocalInvocationID.x) * QUANT_K; + + if (idx >= p.ne) { + return; + } + + uint i00, i01, i02, i03; + get_indices(idx, i00, i01, i02, i03); + + uint i12 = fastmod(i03, p.ne12); + uint i11 = fastmod(i02, p.ne11); + uint i10 = i01; + + uint i1 = data_i[src1_idx(i10, i11, i12, 0) + get_boffset()].x; + + uint src0_idx = src0_idx(i00, i01, i02, i03) + get_aoffset(); + uint dst_idx = dst_idx(i00 / QUANT_K, i1, i02, i03) + get_doffset(); + + quantize(dst_idx, src0_idx); +} + +#else + +void main() { +#ifdef NEEDS_INIT_IQ_SHMEM + init_iq_shmem(gl_WorkGroupSize); +#endif + + const uint idx = (gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x) * QUANT_K; if (idx >= p.ne) { return; @@ -240,3 +289,5 @@ void main() { quantize(dst_idx, src_idx); } + +#endif diff --git a/ggml/src/vulkan-shaders/flash_attn.comp b/ggml/src/vulkan-shaders/flash_attn.comp index 454b3411..45c6e773 100644 --- a/ggml/src/vulkan-shaders/flash_attn.comp +++ b/ggml/src/vulkan-shaders/flash_attn.comp @@ -100,6 +100,10 @@ void main() { uint32_t k_offset = (ik2*p.nb12 + ik3*p.nb13) / 2; uint32_t v_offset = (iv2*p.nb22 + iv3*p.nb23) / 2; #endif + uint32_t m_offset = 0; + if (p.nem2 != 1 || p.nem3 != 1) { + m_offset = ((iq3 % p.nem3) * p.nem2 + (iq2 % p.nem2)) * p.nem1 * KV; + } [[dont_unroll]] for (uint32_t j = start_j; j < end_j; ++j) { @@ -145,13 +149,13 @@ void main() { } } - if (p.mask != 0) { + if ((p.mask_n_head_log2 & MASK_ENABLE_BIT) != 0) { [[unroll]] for (uint32_t idx = 0; idx < Bc * Br; idx += gl_WorkGroupSize.x) { uint32_t c = (idx + tid) % Bc; uint32_t r = (idx + tid) / Bc; if (idx + tid < Bc * Br) { - masksh[c][r] = float(data_m[(i * Br + r) * m_stride + (j * Bc + c)]); + masksh[c][r] = float(data_m[m_offset + (i * Br + r) * m_stride + (j * Bc + c)]); } } barrier(); diff --git a/ggml/src/vulkan-shaders/flash_attn_base.comp b/ggml/src/vulkan-shaders/flash_attn_base.comp index 1d3e6387..7defe72b 100644 --- a/ggml/src/vulkan-shaders/flash_attn_base.comp +++ b/ggml/src/vulkan-shaders/flash_attn_base.comp @@ -24,6 +24,8 @@ layout (push_constant) uniform parameter { uint32_t nev2; uint32_t nev3; uint32_t nem1; + uint32_t nem2; + uint32_t nem3; uint32_t nb01; uint32_t nb02; @@ -34,14 +36,12 @@ layout (push_constant) uniform parameter { uint32_t nb21; uint32_t nb22; uint32_t nb23; - uint32_t nb31; float scale; float max_bias; float logit_softcap; - uint32_t mask; - uint32_t n_head_log2; + uint32_t mask_n_head_log2; float m0; float m1; @@ -50,6 +50,9 @@ layout (push_constant) uniform parameter { uint32_t k_num; } p; +#define MASK_ENABLE_BIT (1<<16) +#define N_LOG2_MASK 0xFFFF + layout (binding = 4) writeonly buffer O {D_TYPE data_o[];}; #if defined(A_TYPE_PACKED16) @@ -100,8 +103,10 @@ ACC_TYPE perElemOpComputeSlope(const in uint32_t r, const in uint32_t c, const i { const uint32_t h = iq2 + (r % p.gqa_ratio); - const ACC_TYPE base = ACC_TYPE(h < p.n_head_log2 ? p.m0 : p.m1); - const int exph = int(h < p.n_head_log2 ? h + 1 : 2*(h - p.n_head_log2) + 1); + uint32_t n_head_log2 = p.mask_n_head_log2 & N_LOG2_MASK; + + const ACC_TYPE base = ACC_TYPE(h < n_head_log2 ? p.m0 : p.m1); + const int exph = int(h < n_head_log2 ? h + 1 : 2*(h - n_head_log2) + 1); return ACC_TYPE(pow(base, ACC_TYPE(exph))); } diff --git a/ggml/src/vulkan-shaders/flash_attn_cm1.comp b/ggml/src/vulkan-shaders/flash_attn_cm1.comp index ad7594fe..486735fe 100644 --- a/ggml/src/vulkan-shaders/flash_attn_cm1.comp +++ b/ggml/src/vulkan-shaders/flash_attn_cm1.comp @@ -125,6 +125,10 @@ void main() { uint32_t k_offset = (ik2*p.nb12 + ik3*p.nb13) / 2; uint32_t v_offset = (iv2*p.nb22 + iv3*p.nb23) / 2; #endif + uint32_t m_offset = 0; + if (p.nem2 != 1 || p.nem3 != 1) { + m_offset = ((iq3 % p.nem3) * p.nem2 + (iq2 % p.nem2)) * p.nem1 * KV; + } [[dont_unroll]] for (uint32_t j = start_j; j < end_j; ++j) { @@ -178,12 +182,12 @@ void main() { barrier(); } - if (p.mask != 0) { + if ((p.mask_n_head_log2 & MASK_ENABLE_BIT) != 0) { [[unroll]] for (uint32_t idx = 0; idx < Bc * Br; idx += gl_WorkGroupSize.x) { uint32_t c = (idx + tid) % Bc; uint32_t r = (idx + tid) / Bc; if (idx + tid < Bc * Br || idx + gl_WorkGroupSize.x <= Bc * Br) { - sfsh[c * sfshstride + r] += ACC_TYPE(slope[r] * float(data_m[(i * Br + r) * m_stride + (j * Bc + c)])); + sfsh[c * sfshstride + r] += ACC_TYPE(slope[r] * float(data_m[m_offset + (i * Br + r) * m_stride + (j * Bc + c)])); } } barrier(); diff --git a/ggml/src/vulkan-shaders/flash_attn_cm2.comp b/ggml/src/vulkan-shaders/flash_attn_cm2.comp index 91caa184..274f48fc 100644 --- a/ggml/src/vulkan-shaders/flash_attn_cm2.comp +++ b/ggml/src/vulkan-shaders/flash_attn_cm2.comp @@ -130,6 +130,11 @@ void main() { coopMatPerElementNV(slopeMat, slopeMat, perElemOpComputeSlope, iq2); } + uint32_t m_offset = 0; + if (p.nem2 != 1 || p.nem3 != 1) { + m_offset = ((iq3 % p.nem3) * p.nem2 + (iq2 % p.nem2)) * p.nem1 * KV * 2 /*sizeof(float16_t)*/; + } + [[dont_unroll]] for (uint32_t j = start_j; j < end_j; ++j) { @@ -148,14 +153,14 @@ void main() { } } - if (p.mask != 0) { + if ((p.mask_n_head_log2 & MASK_ENABLE_BIT) != 0) { tensorLayoutNV<2, Clamp> tensorLayoutM = createTensorLayoutNV(2, Clamp); tensorLayoutM = setTensorLayoutDimensionNV(tensorLayoutM, p.nem1, KV); tensorLayoutM = setTensorLayoutStrideNV(tensorLayoutM, m_stride, 1); coopmat mv; - coopMatLoadTensorNV(mv, data_m, 0, sliceTensorLayoutNV(tensorLayoutM, i * Br, Br, j * Bc, Bc)); + coopMatLoadTensorNV(mv, data_m, m_offset, sliceTensorLayoutNV(tensorLayoutM, i * Br, Br, j * Bc, Bc)); S += slopeMat*coopmat(mv); } diff --git a/ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp b/ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp index a7e39568..0a17a9df 100644 --- a/ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp +++ b/ggml/src/vulkan-shaders/flash_attn_split_k_reduce.comp @@ -2,9 +2,9 @@ #extension GL_EXT_control_flow_attributes : enable -#define BLOCK_SIZE 32 +layout(constant_id = 0) const uint BLOCK_SIZE = 32; -layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; +layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; layout (binding = 0) readonly buffer A {float data_a[];}; layout (binding = 1) writeonly buffer D {float data_d[];}; @@ -12,48 +12,80 @@ layout (binding = 1) writeonly buffer D {float data_d[];}; layout (push_constant) uniform parameter { uint D; uint N; + uint ne3; uint k_num; } p; +shared float tmpsh[BLOCK_SIZE]; + void main() { // Each workgroup handles a row const uint n = gl_WorkGroupID.x; const uint tid = gl_LocalInvocationID.x; + const uint iq3 = gl_WorkGroupID.z; uint D = p.D; uint N = p.N; uint k_num = p.k_num; - uint l_offset = D * N * k_num + n; - uint m_offset = D * N * k_num + N + n; + uint l_offset = D * N * p.ne3 * k_num + N * iq3 * k_num * 2 + n; + uint m_offset = D * N * p.ne3 * k_num + N * iq3 * k_num * 2 + N + n; uint lm_stride = N * 2; // Compute the max m value for the row float m_max = -1.0/0.0; - [[unroll]] for (uint k = 0; k < k_num; ++k) { - float m = data_a[m_offset + k * lm_stride]; + for (uint k = 0; k + tid < k_num; k += BLOCK_SIZE) { + float m = data_a[m_offset + (k + tid) * lm_stride]; m_max = max(m_max, m); } + // reduce across the workgroup + tmpsh[tid] = m_max; + barrier(); + [[unroll]] for (uint s = BLOCK_SIZE/2; s > 0; s >>= 1) { + if (tid < s) { + m_max = max(m_max, tmpsh[tid + s]); + tmpsh[tid] = m_max; + } + barrier(); + } + m_max = tmpsh[0]; + + barrier(); + // Compute L based on m_max float L = 0; - [[unroll]] for (uint k = 0; k < k_num; ++k) { - float l = data_a[l_offset + k * lm_stride]; - float m = data_a[m_offset + k * lm_stride]; + for (uint k = 0; k + tid < k_num; k += BLOCK_SIZE) { + float l = data_a[l_offset + (k + tid) * lm_stride]; + float m = data_a[m_offset + (k + tid) * lm_stride]; L += exp(m - m_max) * l; } + // reduce across the workgroup + tmpsh[tid] = L; + barrier(); + [[unroll]] for (uint s = BLOCK_SIZE/2; s > 0; s >>= 1) { + if (tid < s) { + L += tmpsh[tid + s]; + tmpsh[tid] = L; + } + barrier(); + } + L = tmpsh[0]; + L = 1.0 / L; + // D dimension is split across workgroups in the y dimension + uint d = tid + gl_WorkGroupID.y * BLOCK_SIZE; // Scale and sum the O contributions based on m_max and store the result to memory - for (uint d = tid; d < D; d += BLOCK_SIZE) { + if (d < D) { float O = 0.0; [[unroll]] for (uint k = 0; k < k_num; ++k) { - uint o_offset = D * N * k + D * n + d; + uint o_offset = D * N * (k + iq3 * k_num) + D * n + d; float m = data_a[m_offset + k * lm_stride]; O += exp(m - m_max) * data_a[o_offset]; } O *= L; - data_d[D * n + d] = O; + data_d[iq3 * D * N + D * n + d] = O; } } diff --git a/ggml/src/vulkan-shaders/geglu.comp b/ggml/src/vulkan-shaders/geglu.comp new file mode 100644 index 00000000..f4268ed2 --- /dev/null +++ b/ggml/src/vulkan-shaders/geglu.comp @@ -0,0 +1,13 @@ +#version 450 + +#include "glu_head.comp" + +const float GELU_COEF_A = 0.044715f; +const float SQRT_2_OVER_PI = 0.79788456080286535587989211986876f; + +float op(float a, float b) { + const float val = SQRT_2_OVER_PI*a*(1.0f + GELU_COEF_A*a*a); + return 0.5f*a*(2.0f - 2.0f / (exp(2 * val) + 1)) * b; +} + +#include "glu_main.comp" diff --git a/ggml/src/vulkan-shaders/geglu_erf.comp b/ggml/src/vulkan-shaders/geglu_erf.comp new file mode 100644 index 00000000..cbd4cb36 --- /dev/null +++ b/ggml/src/vulkan-shaders/geglu_erf.comp @@ -0,0 +1,27 @@ +#version 450 + +#include "glu_head.comp" + +// based on Abramowitz and Stegun formula 7.1.26 or similar Hastings' approximation +// ref: https://www.johndcook.com/blog/python_erf/ +const float p_erf = 0.3275911f; +const float a1_erf = 0.254829592f; +const float a2_erf = -0.284496736f; +const float a3_erf = 1.421413741f; +const float a4_erf = -1.453152027f; +const float a5_erf = 1.061405429f; + +const float SQRT_2_INV = 0.70710678118654752440084436210484f; + +float op(float a, float b) { + const float a_div_sqr2 = a * SQRT_2_INV; + const float sign_x = sign(a_div_sqr2); + const float x = abs(a_div_sqr2); + const float t = 1.0f / (1.0f + p_erf * x); + const float y = 1.0f - (((((a5_erf * t + a4_erf) * t) + a3_erf) * t + a2_erf) * t + a1_erf) * t * exp(-x * x); + const float erf_approx = sign_x * y; + + return 0.5f * a * (1.0f + erf_approx) * b; +} + +#include "glu_main.comp" diff --git a/ggml/src/vulkan-shaders/geglu_quick.comp b/ggml/src/vulkan-shaders/geglu_quick.comp new file mode 100644 index 00000000..3a2a6897 --- /dev/null +++ b/ggml/src/vulkan-shaders/geglu_quick.comp @@ -0,0 +1,11 @@ +#version 450 + +#include "glu_head.comp" + +const float GELU_QUICK_COEF = -1.702f; + +float op(float a, float b) { + return a * (1.0f / (1.0f + exp(GELU_QUICK_COEF * a))) * b; +} + +#include "glu_main.comp" diff --git a/ggml/src/vulkan-shaders/gelu_erf.comp b/ggml/src/vulkan-shaders/gelu_erf.comp new file mode 100644 index 00000000..5fd5a5e7 --- /dev/null +++ b/ggml/src/vulkan-shaders/gelu_erf.comp @@ -0,0 +1,39 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; + +void main() { + // based on Abramowitz and Stegun formula 7.1.26 or similar Hastings' approximation + // ref: https://www.johndcook.com/blog/python_erf/ + const float p_erf = 0.3275911f; + const float a1_erf = 0.254829592f; + const float a2_erf = -0.284496736f; + const float a3_erf = 1.421413741f; + const float a4_erf = -1.453152027f; + const float a5_erf = 1.061405429f; + + const float SQRT_2_INV = 0.70710678118654752440084436210484f; + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.KX) { + return; + } + + const float a = float(data_a[i]); + const float a_div_sqr2 = a * SQRT_2_INV; + const float sign_x = sign(a_div_sqr2); + const float x = abs(a_div_sqr2); + const float t = 1.0f / (1.0f + p_erf * x); + const float y = 1.0f - (((((a5_erf * t + a4_erf) * t) + a3_erf) * t + a2_erf) * t + a1_erf) * t * exp(-x * x); + const float erf_approx = sign_x * y; + + data_d[i] = D_TYPE(0.5f * a * (1.0f + erf_approx)); +} diff --git a/ggml/src/vulkan-shaders/glu_head.comp b/ggml/src/vulkan-shaders/glu_head.comp new file mode 100644 index 00000000..41a29889 --- /dev/null +++ b/ggml/src/vulkan-shaders/glu_head.comp @@ -0,0 +1,15 @@ +#extension GL_EXT_shader_16bit_storage : require + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; +layout (binding = 1) readonly buffer B {A_TYPE data_b[];}; +layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; + +layout (push_constant) uniform parameter +{ + uint N; + uint ne00; + uint ne20; + uint mode; +} p; diff --git a/ggml/src/vulkan-shaders/glu_main.comp b/ggml/src/vulkan-shaders/glu_main.comp new file mode 100644 index 00000000..85cf65a9 --- /dev/null +++ b/ggml/src/vulkan-shaders/glu_main.comp @@ -0,0 +1,29 @@ +void main() { + const uint i = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; + + if (i >= p.N) { + return; + } + + const uint row = i / p.ne20; + const uint col = i - row * p.ne20; + + if (p.mode == 0) { + // Default + const uint offset = p.ne00 / 2; + const uint idx = row * p.ne00 + col; + + data_d[row * offset + col] = D_TYPE(op(float(data_a[idx]), float(data_a[idx + offset]))); + } else if (p.mode == 1) { + // Swapped + const uint offset = p.ne00 / 2; + const uint idx = row * p.ne00 + col; + + data_d[row * offset + col] = D_TYPE(op(float(data_a[idx + offset]), float(data_a[idx]))); + } else { + // Split + const uint idx = row * p.ne00 + col; + + data_d[idx] = D_TYPE(op(float(data_a[idx]), float(data_b[idx]))); + } +} diff --git a/ggml/src/vulkan-shaders/l2_norm.comp b/ggml/src/vulkan-shaders/l2_norm.comp new file mode 100644 index 00000000..deba8c39 --- /dev/null +++ b/ggml/src/vulkan-shaders/l2_norm.comp @@ -0,0 +1,41 @@ +#version 450 + +#include "generic_head.comp" +#include "types.comp" + +#extension GL_EXT_control_flow_attributes : enable +#define BLOCK_SIZE 512 + +layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout (binding = 0) readonly buffer X {A_TYPE data_a[];}; +layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; + +shared FLOAT_TYPE sum[BLOCK_SIZE]; + +void main() { + const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x; + const uint tid = gl_LocalInvocationID.x; + + sum[tid] = FLOAT_TYPE(0.0f); // partial sum for thread in warp + + [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { + const FLOAT_TYPE xi = FLOAT_TYPE(data_a[row*p.KX + col]); + sum[tid] += xi * xi; + } + + // sum up partial sums and write back result + barrier(); + [[unroll]] for (int s = BLOCK_SIZE / 2; s > 0; s >>= 1) { + if (tid < s) { + sum[tid] += sum[tid + s]; + } + barrier(); + } + + const FLOAT_TYPE scale = inversesqrt(max(sum[0], FLOAT_TYPE(p.param1))); + + [[unroll]] for (uint col = tid; col < p.KX; col += BLOCK_SIZE) { + data_d[row*p.KX + col] = D_TYPE(scale * FLOAT_TYPE(data_a[row*p.KX + col])); + } +} diff --git a/ggml/src/vulkan-shaders/mul_mm.comp b/ggml/src/vulkan-shaders/mul_mm.comp index 26163b16..f4815499 100644 --- a/ggml/src/vulkan-shaders/mul_mm.comp +++ b/ggml/src/vulkan-shaders/mul_mm.comp @@ -18,6 +18,7 @@ #extension GL_KHR_cooperative_matrix : enable #extension GL_KHR_memory_scope_semantics : enable #extension GL_KHR_shader_subgroup_basic : enable +#extension GL_KHR_shader_subgroup_ballot : enable #endif #ifdef MUL_MAT_ID @@ -104,6 +105,10 @@ shared FLOAT_TYPE buf_b[BN * SHMEM_STRIDE]; #ifdef MUL_MAT_ID shared u16vec2 row_ids[4096]; +uint _ne1; +#ifdef COOPMAT +shared uint _ne1_sh; +#endif #endif // MUL_MAT_ID #define NUM_WARPS (BLOCK_SIZE / WARP) @@ -172,7 +177,47 @@ void main() { const uint loadstride_b = gl_WorkGroupSize.x * LOAD_VEC_B / BK; #ifdef MUL_MAT_ID - uint _ne1 = 0; +#ifdef COOPMAT + // Spread the search across all elements in the first subgroup + if (gl_SubgroupID == 0) { + _ne1 = 0; + uint num_elements = p.nei1 * p.nei0; + + uint ids[16]; + uint iter = 0; + + for (uint j = 0; j < num_elements; j += gl_SubgroupSize) { + // prefetch up to 16 elements + if (iter == 0) { + [[unroll]] for (uint k = 0; k < 16; ++k) { + uint i = j + gl_SubgroupInvocationID + k*gl_SubgroupSize; + bool in_range = i < num_elements; + uint ii1 = i / p.nei0; + uint ii0 = i % p.nei0; + ids[k] = in_range ? data_ids[ii1*p.nbi1 + ii0] : 0; + } + } + uint i = j + gl_SubgroupInvocationID; + bool in_range = i < num_elements; + uint ii1 = i / p.nei0; + uint ii0 = i % p.nei0; + uint id = ids[iter++]; + uvec4 ballot = subgroupBallot(in_range && id == expert_idx); + uint idx = subgroupBallotExclusiveBitCount(ballot); + if (in_range && id == expert_idx) { + row_ids[_ne1 + idx] = u16vec2(ii0, ii1); + } + _ne1 += subgroupBallotBitCount(ballot); + iter &= 15; + } + _ne1_sh = _ne1; + } + + barrier(); + + _ne1 = _ne1_sh; +#else + _ne1 = 0; for (uint ii1 = 0; ii1 < p.nei1; ii1++) { for (uint ii0 = 0; ii0 < p.nei0; ii0++) { if (data_ids[ii1*p.nbi1 + ii0] == expert_idx) { @@ -183,6 +228,7 @@ void main() { } barrier(); +#endif // Workgroup has no work if (ic * BN >= _ne1) return; @@ -500,10 +546,9 @@ void main() { const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 128; // 2 values per idx - const uint ib32 = (idx % 128) / 16; // 0..7 - const uint ib8 = (idx % 128) / 4; - const int i8 = 2 * int(idx % 4); + const uint ib = idx / 32; // 8 values per idx + const uint ib32 = (idx % 32) / 4; // 0..7 + const uint ib8 = idx % 32; const float d = float(data_a[ib].d); const uint qh = data_a[ib].qh[ib32]; @@ -512,22 +557,16 @@ void main() { const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA; const int16_t grid = int16_t(iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)]); - const ivec2 gvec = ivec2( - bitfieldExtract(grid, 2 * (i8), 2), - bitfieldExtract(grid, 2 * (i8 + 1), 2) - ); - const vec2 v = dl * (vec2(gvec) + delta); - - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + [[unroll]] for (int k = 0; k < 8; ++k) { + buf_a[buf_idx + k] = FLOAT_TYPE(dl * (bitfieldExtract(grid, 2 * k, 2) + delta)); + } #elif defined(DATA_A_IQ1_M) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 128; // 2 values per idx - const uint ib8 = (idx % 128) / 4; + const uint ib = idx / 32; // 8 values per idx + const uint ib8 = idx % 32; const uint ib16 = ib8 / 2; - const int i8 = 2 * int(idx % 4); const uint16_t[4] scales = data_a[ib].scales; const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12; @@ -538,21 +577,17 @@ void main() { const float dl = d * (2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1); const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA; const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]); - const ivec2 gvec = ivec2( - bitfieldExtract(grid, 2 * (i8), 2), - bitfieldExtract(grid, 2 * (i8 + 1), 2) - ); - const vec2 v = dl * (vec2(gvec) + delta); - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + [[unroll]] for (int k = 0; k < 8; ++k) { + buf_a[buf_idx + k] = FLOAT_TYPE(dl * (bitfieldExtract(grid, 2 * k, 2) + delta)); + } #elif defined(DATA_A_IQ2_XXS) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 128; // 2 values per idx - const uint ib32 = (idx % 128) / 16; // 0..7 - const uint ib8 = (idx / 4) % 4; + const uint ib = idx / 32; // 8 values per idx + const uint ib32 = (idx % 32) / 4; // 0..7 + const uint ib8 = idx % 4; const float d = float(data_a[ib].d); const uint qs = data_a[ib].qs[8 * ib32 + ib8]; @@ -562,63 +597,81 @@ void main() { data_a[ib].qs[8*ib32 + 6], data_a[ib].qs[8*ib32 + 7] )); - const float db = d * 0.25 * (0.5 + (signs >> 28)); + const FLOAT_TYPE db = FLOAT_TYPE(d * 0.25 * (0.5 + (signs >> 28))); const uint32_t sign7 = bitfieldExtract(signs, 7 * int(ib8), 7); - const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (2 * (idx % 4)); - const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); - const uint grid = iq2xxs_grid[qs][(idx % 4) / 2] >> (16 * (idx & 1)); - const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + const uint sign = sign7 | (bitCount(sign7) << 7); + const uvec2 grid = iq2xxs_grid[qs]; + const vec4 grid0 = vec4(unpack8(grid.x)); + const vec4 grid1 = vec4(unpack8(grid.y)); - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + buf_a[buf_idx ] = db * FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x); + buf_a[buf_idx + 1] = db * FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y); + buf_a[buf_idx + 2] = db * FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z); + buf_a[buf_idx + 3] = db * FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w); + buf_a[buf_idx + 4] = db * FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x); + buf_a[buf_idx + 5] = db * FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y); + buf_a[buf_idx + 6] = db * FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z); + buf_a[buf_idx + 7] = db * FLOAT_TYPE((sign & 128) != 0 ? -grid1.w : grid1.w); #elif defined(DATA_A_IQ2_XS) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 128; // 2 values per idx - const uint ib32 = (idx % 128) / 16; // 0..7 - const uint ib8 = (idx / 4) % 4; // 0..3 + const uint ib = idx / 32; // 8 values per idx + const uint ib32 = (idx % 32) / 4; // 0..7 + const uint ib8 = idx % 4; // 0..3 const float d = float(data_a[ib].d); const uint scale = (data_a[ib].scales[ib32] >> (2 * (ib8 & 2))) & 0xf; - const float db = d * 0.25 * (0.5 + scale); + const FLOAT_TYPE db = FLOAT_TYPE(d * 0.25 * (0.5 + scale)); const uint qs = data_a[ib].qs[4 * ib32 + ib8]; const uint sign7 = qs >> 9; - const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (2 * (idx % 4)); - const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); - const uint grid = iq2xs_grid[qs & 511][(idx % 4) / 2] >> (16 * (idx & 1)); - const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + const uint sign = sign7 | (bitCount(sign7) << 7); + const uvec2 grid = iq2xs_grid[qs & 511]; + const vec4 grid0 = vec4(unpack8(grid.x)); + const vec4 grid1 = vec4(unpack8(grid.y)); - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + buf_a[buf_idx ] = db * FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x); + buf_a[buf_idx + 1] = db * FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y); + buf_a[buf_idx + 2] = db * FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z); + buf_a[buf_idx + 3] = db * FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w); + buf_a[buf_idx + 4] = db * FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x); + buf_a[buf_idx + 5] = db * FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y); + buf_a[buf_idx + 6] = db * FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z); + buf_a[buf_idx + 7] = db * FLOAT_TYPE((sign & 128) != 0 ? -grid1.w : grid1.w); #elif defined(DATA_A_IQ2_S) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 128; // 2 values per idx - const uint ib8 = (idx % 128) / 4; // 0..31 - const uint ib32 = ib8 / 4; // 0..7 + const uint ib = idx / 32; // 8 values per idx + const uint ib8 = idx % 32; // 0..31 + const uint ib32 = ib8 / 4; // 0..7 const uint scale = (data_a[ib].scales[ib32] >> (2 * (ib8 & 2))) & 0xf; const uint qs = data_a[ib].qs[ib8]; const uint qh = data_a[ib].qh[ib32]; const uint qhshift = 2 * (ib8 % 4); - const uint sign = data_a[ib].qs[QUANT_K / 8 + ib8] >> (2 * (idx % 4)); + const uint sign = data_a[ib].qs[QUANT_K / 8 + ib8]; const float d = float(data_a[ib].d); - const float db = d * 0.25 * (0.5 + scale); - const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); - const uint16_t grid = unpack16(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(idx & 2) >> 1])[idx & 1]; - const vec2 v = db * vec2(sign01) * vec2(unpack8(uint32_t(grid)).xy); // vec4 used due to #12147 + const FLOAT_TYPE db = FLOAT_TYPE(d * 0.25 * (0.5 + scale)); + const uvec2 grid = iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)]; + const vec4 grid0 = vec4(unpack8(grid.x)); + const vec4 grid1 = vec4(unpack8(grid.y)); - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + buf_a[buf_idx ] = db * FLOAT_TYPE((sign & 1) != 0 ? -grid0.x : grid0.x); + buf_a[buf_idx + 1] = db * FLOAT_TYPE((sign & 2) != 0 ? -grid0.y : grid0.y); + buf_a[buf_idx + 2] = db * FLOAT_TYPE((sign & 4) != 0 ? -grid0.z : grid0.z); + buf_a[buf_idx + 3] = db * FLOAT_TYPE((sign & 8) != 0 ? -grid0.w : grid0.w); + buf_a[buf_idx + 4] = db * FLOAT_TYPE((sign & 16) != 0 ? -grid1.x : grid1.x); + buf_a[buf_idx + 5] = db * FLOAT_TYPE((sign & 32) != 0 ? -grid1.y : grid1.y); + buf_a[buf_idx + 6] = db * FLOAT_TYPE((sign & 64) != 0 ? -grid1.z : grid1.z); + buf_a[buf_idx + 7] = db * FLOAT_TYPE((sign & 128) != 0 ? -grid1.w : grid1.w); #elif defined(DATA_A_IQ3_XXS) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 128; // 2 values per idx - const uint iqs = (idx % 128) / 2; // 0..63 + const uint ib = idx / 64; // 4 values per idx + const uint iqs = idx % 64; // 0..63 const uint is = QUANT_K / 4 + 4 * (iqs / 8); // 8 values const float d = float(data_a[ib].d); @@ -631,33 +684,36 @@ void main() { )); const float db = d * 0.5 * (0.5 + (signs >> 28)); const uint32_t sign7 = bitfieldExtract(signs, 7 * (int(iqs / 2) % 4), 7); - const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (2 * (idx % 4)); - const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(int8_t(sign << 1), int8_t(sign)))); - const uint grid = iq3xxs_grid[qs] >> (16 * (idx & 1)); - const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (4 * (idx % 2)); + const uint grid = iq3xxs_grid[qs]; + const vec4 v = db * vec4(unpack8(grid)); - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + buf_a[buf_idx ] = FLOAT_TYPE((sign & 1) != 0 ? -v.x : v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE((sign & 2) != 0 ? -v.y : v.y); + buf_a[buf_idx + 2] = FLOAT_TYPE((sign & 4) != 0 ? -v.z : v.z); + buf_a[buf_idx + 3] = FLOAT_TYPE((sign & 8) != 0 ? -v.w : v.w); #elif defined(DATA_A_IQ3_S) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; - const uint ib = idx / 128; // 2 values per idx - const uint iqs = (idx % 128) / 2; // 0..63 + const uint ib = idx / 64; // 4 values per idx + const uint iqs = idx % 64; // 0..63 const uint iqh = iqs / 8; const float d = float(data_a[ib].d); const uint qs = data_a[ib].qs[iqs]; const uint qh = data_a[ib].qh[iqh]; - const int8_t sign = int8_t(data_a[ib].signs[iqs / 2] >> (2 * (idx % 4))); + const int8_t sign = int8_t(data_a[ib].signs[iqs / 2] >> (4 * (idx % 2))); const uint scale = data_a[ib].scales[iqs / 16]; const i8vec2 sign01 = i8vec2(1 - (2 & i8vec2(sign << 1, sign))); const float db = d * (1 + 2 * ((scale >> (4 * (iqh & 1))) & 0xf)); - const uint32_t grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)] >> (16 * (idx % 2)); - const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy); // vec4 used due to #12147 + const uint32_t grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)]; + const vec4 v = db * vec4(unpack8(grid)); - buf_a[buf_idx ] = FLOAT_TYPE(v.x); - buf_a[buf_idx + 1] = FLOAT_TYPE(v.y); + buf_a[buf_idx ] = FLOAT_TYPE((sign & 1) != 0 ? -v.x : v.x); + buf_a[buf_idx + 1] = FLOAT_TYPE((sign & 2) != 0 ? -v.y : v.y); + buf_a[buf_idx + 2] = FLOAT_TYPE((sign & 4) != 0 ? -v.z : v.z); + buf_a[buf_idx + 3] = FLOAT_TYPE((sign & 8) != 0 ? -v.w : v.w); #elif defined(DATA_A_IQ4_XS) const uint idx = pos_a + (loadc_a + l) * p.stride_a / LOAD_VEC_A + loadr_a; const uint buf_idx = (loadc_a + l) * SHMEM_STRIDE + loadr_a * LOAD_VEC_A; diff --git a/ggml/src/vulkan-shaders/mul_mm_cm2.comp b/ggml/src/vulkan-shaders/mul_mm_cm2.comp index 91846575..29e4b5c9 100644 --- a/ggml/src/vulkan-shaders/mul_mm_cm2.comp +++ b/ggml/src/vulkan-shaders/mul_mm_cm2.comp @@ -162,17 +162,32 @@ void main() { _ne1 = 0; uint num_elements = p.nei1 * p.nei0; - for (uint i = gl_SubgroupInvocationID; subgroupAny(i < num_elements); i += gl_SubgroupSize) { + uint ids[16]; + uint iter = 0; + + for (uint j = 0; j < num_elements; j += gl_SubgroupSize) { + // prefetch up to 16 elements + if (iter == 0) { + [[unroll]] for (uint k = 0; k < 16; ++k) { + uint i = j + gl_SubgroupInvocationID + k*gl_SubgroupSize; + bool in_range = i < num_elements; + uint ii1 = i / p.nei0; + uint ii0 = i % p.nei0; + ids[k] = in_range ? data_ids[ii1*p.nbi1 + ii0] : 0; + } + } + uint i = j + gl_SubgroupInvocationID; bool in_range = i < num_elements; - uint ii0 = i % p.nei0; uint ii1 = i / p.nei0; - uint id = in_range ? data_ids[ii1*p.nbi1 + ii0] : 0; + uint ii0 = i % p.nei0; + uint id = ids[iter++]; uvec4 ballot = subgroupBallot(in_range && id == expert_idx); uint idx = subgroupBallotExclusiveBitCount(ballot); if (in_range && id == expert_idx) { row_ids[_ne1 + idx] = u16vec4(ii0 % p.ne11, ii1, ii0, 0); } _ne1 += subgroupBallotBitCount(ballot); + iter &= 15; } _ne1_sh = _ne1; } @@ -414,17 +429,31 @@ void main() { fetch_scales(ir * BM, pos_a, stride_a, block_k + BK, tid, false); } - coopmat mat_a; - coopmat mat_b; + if ((ir + 1) * BM <= p.M && block_k + BK <= end_k) { + coopmat mat_a; + coopmat mat_b; - coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutAClamp, ir * BM, BM, block_k, BK) DECODEFUNCA); + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); #ifdef MUL_MAT_ID - coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose, decodeFuncB); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose, decodeFuncB); #else - coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutBClamp, ic * BN, BN, block_k, BK), tensorViewTranspose); + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutBClamp, ic * BN, BN, block_k, BK), tensorViewTranspose); #endif - sum = coopMatMulAdd(mat_a, mat_b, sum); + sum = coopMatMulAdd(mat_a, mat_b, sum); + } else { + coopmat mat_a; + coopmat mat_b; + + coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutAClamp, ir * BM, BM, block_k, BK) DECODEFUNCA); +#ifdef MUL_MAT_ID + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose, decodeFuncB); +#else + coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutBClamp, ic * BN, BN, block_k, BK), tensorViewTranspose); +#endif + + sum = coopMatMulAdd(mat_a, mat_b, sum); + } } // Convert from ACC_TYPE to D_TYPE diff --git a/ggml/src/vulkan-shaders/reglu.comp b/ggml/src/vulkan-shaders/reglu.comp new file mode 100644 index 00000000..0073d8f7 --- /dev/null +++ b/ggml/src/vulkan-shaders/reglu.comp @@ -0,0 +1,9 @@ +#version 450 + +#include "glu_head.comp" + +float op(float a, float b) { + return max(a, 0.0f) * b; +} + +#include "glu_main.comp" diff --git a/ggml/src/vulkan-shaders/rms_norm.comp b/ggml/src/vulkan-shaders/rms_norm.comp index deb8ee99..6428ca7b 100644 --- a/ggml/src/vulkan-shaders/rms_norm.comp +++ b/ggml/src/vulkan-shaders/rms_norm.comp @@ -1,11 +1,13 @@ #version 450 -#include "generic_unary_head.comp" +#include "generic_binary_head.comp" #include "types.comp" #extension GL_EXT_control_flow_attributes : enable #define BLOCK_SIZE 512 +layout (constant_id = 1) const bool do_multiply = false; + layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; shared FLOAT_TYPE sum[BLOCK_SIZE]; @@ -25,6 +27,7 @@ void main() { const uint stride_sample = p.nb03; uint32_t a_offset = samp*stride_sample + channel*stride_channel + row*stride_row + get_aoffset(); + uint32_t b_offset = src1_idx(0, row, channel, samp) + get_boffset(); uint32_t d_offset = ((samp*nchannels + channel)*nrows + row)*ncols + get_doffset(); sum[tid] = FLOAT_TYPE(0.0f); // partial sum for thread in warp @@ -46,7 +49,13 @@ void main() { const FLOAT_TYPE mean = sum[0] / FLOAT_TYPE(ncols); const FLOAT_TYPE scale = inversesqrt(mean + FLOAT_TYPE(p.param1)); - [[unroll]] for (uint col = tid; col < ncols; col += BLOCK_SIZE) { - data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col])); + if (do_multiply) { + [[unroll]] for (uint col = tid; col < ncols; col += BLOCK_SIZE) { + data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + col])); + } + } else { + [[unroll]] for (uint col = tid; col < ncols; col += BLOCK_SIZE) { + data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col])); + } } } diff --git a/ggml/src/vulkan-shaders/roll.comp b/ggml/src/vulkan-shaders/roll.comp new file mode 100644 index 00000000..b9abe8de --- /dev/null +++ b/ggml/src/vulkan-shaders/roll.comp @@ -0,0 +1,46 @@ +#version 450 + +#include "types.comp" +#include "generic_unary_head.comp" + +layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; + +uint wrap_idx(int i, uint ne) { + if (i < 0) { + return i + ne; + } else if (i >= ne) { + return i - ne; + } + return i; +} + +void main() { + const uint idx = get_idx(); + if (idx >= p.ne) { + return; + } + + const uint i3 = fastdiv(idx, p.ne1_012mp, p.ne1_012L); + const uint i3_offset = i3 * p.ne12*p.ne11*p.ne10; + const uint i2 = fastdiv(idx - i3_offset, p.ne1_01mp, p.ne1_01L); + const uint i2_offset = i2*p.ne11*p.ne10; + const uint i1 = fastdiv(idx - i3_offset - i2_offset, p.ne1_0mp, p.ne1_0L); + const uint i0 = idx - i3_offset - i2_offset - i1*p.ne10; + + const uint p1 = floatBitsToUint(p.param1); + const uint p2 = floatBitsToUint(p.param2); + const int s0 = int(p1 >> 16) - 0x8000; + const int s1 = int(p1 & 0xFFFF) - 0x8000; + const int s2 = int(p2 >> 16) - 0x8000; + const int s3 = int(p2 & 0xFFFF) - 0x8000; + + const uint i00 = wrap_idx(int(i0) - s0, p.ne10); + const uint i01 = wrap_idx(int(i1) - s1, p.ne11); + const uint i02 = wrap_idx(int(i2) - s2, p.ne12); + const uint i03 = wrap_idx(int(i3) - s3, p.ne13); + + const uint a_idx = i03*p.nb03 + i02*p.nb02 + i01*p.nb01 + i00*p.nb00; + const uint d_idx = i3 *p.nb13 + i2 *p.nb12 + i1 *p.nb11 + i0 *p.nb10; + + data_d[get_doffset() + d_idx] = D_TYPE(data_a[get_aoffset() + a_idx]); +} diff --git a/ggml/src/vulkan-shaders/rope_multi.comp b/ggml/src/vulkan-shaders/rope_multi.comp index 4f5b1a0e..5808710c 100644 --- a/ggml/src/vulkan-shaders/rope_multi.comp +++ b/ggml/src/vulkan-shaders/rope_multi.comp @@ -14,21 +14,19 @@ void main() { const uint row_dst = gl_GlobalInvocationID.x; - if (i0 >= p.n_dims) { - const uint i = row_dst*ne0 + i0; - - data_d[i + 0] = data_a[i + 0]; - data_d[i + 1] = data_a[i + 1]; - - return; - } - const uint row_x = row_dst % ne1; const uint channel_x = row_dst / ne1; const uint idst = row_dst*ne0 + i0/2; const uint ix = channel_x*p.s2 + row_x*p.s1 + i0/2; + if (i0 >= p.n_dims) { + data_d[idst + i0/2 + 0] = data_a[ix + i0/2 + 0]; + data_d[idst + i0/2 + 1] = data_a[ix + i0/2 + 1]; + + return; + } + const int sect_dims = p.sections[0] + p.sections[1] + p.sections[2] + p.sections[3]; const int sec_w = p.sections[1] + p.sections[0]; const uint sector = (i0 / 2) % sect_dims; diff --git a/ggml/src/vulkan-shaders/rope_neox.comp b/ggml/src/vulkan-shaders/rope_neox.comp index db775c45..366a7b1c 100644 --- a/ggml/src/vulkan-shaders/rope_neox.comp +++ b/ggml/src/vulkan-shaders/rope_neox.comp @@ -13,21 +13,19 @@ void main() { const uint row_dst = gl_GlobalInvocationID.x; - if (i0 >= p.n_dims) { - const uint i = row_dst*ne0 + i0; - - data_d[i + 0] = data_a[i + 0]; - data_d[i + 1] = data_a[i + 1]; - - return; - } - const uint row_x = row_dst % ne1; const uint channel_x = row_dst / ne1; const uint idst = row_dst*ne0 + i0/2; const uint ix = channel_x*p.s2 + row_x*p.s1 + i0/2; + if (i0 >= p.n_dims) { + data_d[idst + i0/2 + 0] = data_a[ix + i0/2 + 0]; + data_d[idst + i0/2 + 1] = data_a[ix + i0/2 + 1]; + + return; + } + const float theta_base = data_pos[channel_x] * pow(p.theta_scale, i0/2.0f); const float freq_factor = p.has_ff != 0 ? data_ff[i0/2] : 1.0f; diff --git a/ggml/src/vulkan-shaders/rope_norm.comp b/ggml/src/vulkan-shaders/rope_norm.comp index 4ad35e54..9643bca9 100644 --- a/ggml/src/vulkan-shaders/rope_norm.comp +++ b/ggml/src/vulkan-shaders/rope_norm.comp @@ -13,21 +13,19 @@ void main() { const uint row_dst = gl_GlobalInvocationID.x; - if (i0 >= p.n_dims) { - const uint i = row_dst*ne0 + i0; - - data_d[i + 0] = data_a[i + 0]; - data_d[i + 1] = data_a[i + 1]; - - return; - } - const uint row_x = row_dst % ne1; const uint channel_x = row_dst / ne1; const uint idst = row_dst*ne0 + i0; const uint ix = channel_x*p.s2 + row_x*p.s1 + i0; + if (i0 >= p.n_dims) { + data_d[idst + 0] = data_a[ix + 0]; + data_d[idst + 1] = data_a[ix + 1]; + + return; + } + const float theta_base = data_pos[channel_x] * pow(p.theta_scale, i0/2.0f); const float freq_factor = p.has_ff != 0 ? data_ff[i0/2] : 1.0f; diff --git a/ggml/src/vulkan-shaders/scale.comp b/ggml/src/vulkan-shaders/scale.comp index 4663428d..f10b0a02 100644 --- a/ggml/src/vulkan-shaders/scale.comp +++ b/ggml/src/vulkan-shaders/scale.comp @@ -18,7 +18,7 @@ void main() { continue; } - data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + idx]) * FLOAT_TYPE(p.param1)); + data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + idx]) * FLOAT_TYPE(p.param1) + FLOAT_TYPE(p.param2)); idx += num_threads; } } diff --git a/ggml/src/vulkan-shaders/soft_max.comp b/ggml/src/vulkan-shaders/soft_max.comp index 51fc2dc7..5bcd3b1e 100644 --- a/ggml/src/vulkan-shaders/soft_max.comp +++ b/ggml/src/vulkan-shaders/soft_max.comp @@ -6,6 +6,14 @@ layout (push_constant) uniform parameter { uint KX; uint KY; + uint ne00; + uint ne01; + uint ne02; + uint ne12; + uint ne13; + uint nb11; + uint nb12; + uint nb13; float scale; float max_bias; float m0; @@ -31,7 +39,15 @@ shared FLOAT_TYPE vals[BLOCK_SIZE]; void soft_max(uint num_iters) { const uint tid = gl_LocalInvocationID.x; const uint rowx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x; - const uint rowy = (p.KY > 0) ? (rowx % p.KY) : 0; + + const uint32_t i03 = rowx / (p.ne01 * p.ne02); + const uint32_t i02 = (rowx - i03 * p.ne01 * p.ne02) / p.ne01; + const uint32_t i01 = rowx % p.ne01; + + uint rowy_start = 0; + if (p.KY > 0) { + rowy_start = i01 * p.nb11 + (i02 % p.ne12) * p.nb12 + (i03 % p.ne13) * p.nb13; + } if (rowx >= p.nrows_x) { return; @@ -41,7 +57,7 @@ void soft_max(uint num_iters) { // ALiBi if (p.max_bias > 0.0f) { - const uint h = rowx/p.KY; // head index + const uint h = (rowx / p.ne01) % p.ne02; // head index const float base = h < p.n_head_log2 ? p.m0 : p.m1; const uint exp = h < p.n_head_log2 ? h + 1 : 2*(h - p.n_head_log2) + 1; @@ -67,7 +83,7 @@ void soft_max(uint num_iters) { FLOAT_TYPE b = FLOAT_TYPE(0); if (p.KY > 0 && col < p.KX) { - b = data_b[rowy * p.KX + col]; + b = data_b[rowy_start + col]; } FLOAT_TYPE v = a * p.scale + slope * b; @@ -111,7 +127,7 @@ void soft_max(uint num_iters) { if (idx < DATA_CACHE_SIZE) { val = exp(data_cache[idx] - max_val); } else { - val = exp(FLOAT_TYPE(data_a[i]) * p.scale + (p.KY > 0 ? slope * FLOAT_TYPE(data_b[rowy * p.KX + col]) : FLOAT_TYPE(0.0f)) - max_val); + val = exp(FLOAT_TYPE(data_a[i]) * p.scale + (p.KY > 0 ? slope * FLOAT_TYPE(data_b[rowy_start + col]) : FLOAT_TYPE(0.0f)) - max_val); } sum += val; if (idx < DATA_CACHE_SIZE) { diff --git a/ggml/src/vulkan-shaders/swiglu.comp b/ggml/src/vulkan-shaders/swiglu.comp new file mode 100644 index 00000000..a28e7c6c --- /dev/null +++ b/ggml/src/vulkan-shaders/swiglu.comp @@ -0,0 +1,9 @@ +#version 450 + +#include "glu_head.comp" + +float op(float a, float b) { + return a / (1.0f + exp(-a)) * b; +} + +#include "glu_main.comp" diff --git a/ggml/src/vulkan-shaders/upscale.comp b/ggml/src/vulkan-shaders/upscale.comp index 6f607380..74771def 100644 --- a/ggml/src/vulkan-shaders/upscale.comp +++ b/ggml/src/vulkan-shaders/upscale.comp @@ -3,6 +3,7 @@ layout (push_constant) uniform parameter { uint ne; uint a_offset; uint d_offset; + uint ne00; uint ne01; uint nb00; uint nb01; uint nb02; uint nb03; uint ne10; uint ne11; uint ne12; uint ne13; float sf0; float sf1; float sf2; float sf3; @@ -15,6 +16,61 @@ layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in; layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; +// from ggml.h: enum ggml_scale_mode, enum ggml_scale_flag +#define NEAREST 0 +#define BILINEAR 1 +#define ALIGN_CORNERS (1 << 8) + +layout (constant_id = 0) const uint scale_mode = 0; + +float fetch_nearest(uint i10, uint i11, uint i12, uint i13) { + const uint i00 = uint(i10 / p.sf0); + const uint i01 = uint(i11 / p.sf1); + const uint i02 = uint(i12 / p.sf2); + const uint i03 = uint(i13 / p.sf3); + + return data_a[p.a_offset + i03 * p.nb03 + i02 * p.nb02 + i01 * p.nb01 + i00 * p.nb00]; +} + +float fetch_bilinear(ivec2 c0, ivec2 c1, vec2 d, uint i12, uint i13) { + const uint i02 = uint(i12 / p.sf2); + const uint i03 = uint(i13 / p.sf3); + const uint base = p.a_offset + i03 * p.nb03 + i02 * p.nb02; + + const float v00 = data_a[base + c0.y * p.nb01 + c0.x * p.nb00]; + const float v01 = data_a[base + c0.y * p.nb01 + c1.x * p.nb00]; + const float v10 = data_a[base + c1.y * p.nb01 + c0.x * p.nb00]; + const float v11 = data_a[base + c1.y * p.nb01 + c1.x * p.nb00]; + + return + v00 * (1.0-d.x) * (1.0-d.y) + + v01 * d.x * (1.0-d.y) + + v10 * (1.0-d.x) * d.y + + v11 * d.x * d.y; +} + +float interpolate_bilinear(uint i10, uint i11, uint i12, uint i13) { + const ivec2 ne0 = ivec2(p.ne00, p.ne01); + + const vec2 c = (vec2(i10, i11) + 0.5) / vec2(p.sf0, p.sf1) - 0.5; + const vec2 c0f = floor(c); + const vec2 d = c - c0f; + const ivec2 c0 = max(ivec2(c0f), 0); + const ivec2 c1 = min(ivec2(c0f + 1), ne0 - 1); + + return fetch_bilinear(c0, c1, d, i12, i13); +} + +float interpolate_bilinear_align_corners(uint i10, uint i11, uint i12, uint i13) { + const vec2 c = vec2(i10, i11) / vec2(p.sf0, p.sf1); + const vec2 c0f = floor(c); + const vec2 d = c - c0f; + const ivec2 c0 = ivec2(c0f); + const ivec2 c1 = c0 + 1; + + return fetch_bilinear(c0, c1, d, i12, i13); +} + void main() { const uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x; @@ -27,10 +83,18 @@ void main() { const uint i12 = (idx / (p.ne10 * p.ne11)) % p.ne12; const uint i13 = (idx / (p.ne10 * p.ne11 * p.ne12)) % p.ne13; - const uint i00 = uint(i10 / p.sf0); - const uint i01 = uint(i11 / p.sf1); - const uint i02 = uint(i12 / p.sf2); - const uint i03 = uint(i13 / p.sf3); + float result; + switch (scale_mode) { + case NEAREST: + result = fetch_nearest(i10, i11, i12, i13); + break; + case BILINEAR: + result = interpolate_bilinear(i10, i11, i12, i13); + break; + case BILINEAR | ALIGN_CORNERS: + result = interpolate_bilinear_align_corners(i10, i11, i12, i13); + break; + } - data_d[p.d_offset + idx] = D_TYPE(data_a[p.a_offset + i03 * p.nb03 + i02 * p.nb02 + i01 * p.nb01 + i00 * p.nb00]); + data_d[p.d_offset + idx] = D_TYPE(result); } diff --git a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp index 65dd82de..293aa644 100644 --- a/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp +++ b/ggml/src/vulkan-shaders/vulkan-shaders-gen.cpp @@ -360,9 +360,9 @@ void matmul_shaders(bool fp16, bool matmul_id, bool coopmat, bool coopmat2, bool for (const auto& tname : type_names) { std::string load_vec_quant = "2"; - if ((tname == "q4_0") || (tname == "q4_1")) + if ((tname == "q4_0") || (tname == "q4_1") || (tname == "iq1_s") || (tname == "iq1_m") || (tname == "iq2_xxs") || (tname == "iq2_xs") || (tname == "iq2_s")) load_vec_quant = "8"; - else if ((tname == "q5_0") || (tname == "q5_1") || (tname == "q8_0") || (tname == "iq4_nl")) + else if ((tname == "q5_0") || (tname == "q5_1") || (tname == "q8_0") || (tname == "iq3_xxs") || (tname == "iq3_s") || (tname == "iq4_nl")) load_vec_quant = "4"; if (tname == "bf16") { @@ -497,9 +497,9 @@ void process_shaders() { // Norms string_to_spv("norm_f32", "norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); string_to_spv("group_norm_f32", "group_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - string_to_spv("rms_norm_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); - string_to_spv("fused_rms_norm_f32", "fused_rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("rms_norm_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); string_to_spv("rms_norm_back_f32", "rms_norm_back.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); + string_to_spv("l2_norm_f32", "l2_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); string_to_spv("cpy_f32_f32", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); string_to_spv("cpy_f32_f16", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float16_t"}}); @@ -518,6 +518,11 @@ void process_shaders() { string_to_spv("cpy_" + t + "_f32", "copy_from_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); } + for (std::string t : {"f32", "f16", "bf16", "q4_0", "q4_1", "q5_0", "q5_1", "q8_0", "iq4_nl"}) { + string_to_spv("set_rows_" + t, "copy_to_quant.comp", {{"SET_ROWS", "1"}, {"DATA_A_" + to_uppercase(t), "1"}, {"B_TYPE", "uvec2"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}}); + string_to_spv("set_rows_" + t + "_rte", "copy_to_quant.comp", {{"SET_ROWS", "1"}, {"DATA_A_" + to_uppercase(t), "1"}, {"B_TYPE", "uvec2"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}, {"RTE16", "1"}}); + } + auto get_type_str = [](bool f16) { return f16 ? "float16_t" : "float"; }; @@ -572,17 +577,10 @@ void process_shaders() { string_to_spv("upscale_f32", "upscale.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - string_to_spv("fused_mul_gelu_f16", "fused_mul_gelu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); - string_to_spv("fused_mul_gelu_f32", "fused_mul_gelu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - string_to_spv("fused_mul_silu_f16", "fused_mul_silu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); - string_to_spv("fused_mul_silu_f32", "fused_mul_silu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - string_to_spv("fused_mul_relu_f16", "fused_mul_relu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); - string_to_spv("fused_mul_relu_f32", "fused_mul_relu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); - - string_to_spv("multi_add_f32", "multi_add.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); - string_to_spv("gelu_f16", "gelu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); string_to_spv("gelu_f32", "gelu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("gelu_erf_f16", "gelu_erf.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("gelu_erf_f32", "gelu_erf.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); string_to_spv("gelu_quick_f16", "gelu_quick.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); string_to_spv("gelu_quick_f32", "gelu_quick.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); string_to_spv("silu_f16", "silu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); @@ -594,6 +592,17 @@ void process_shaders() { string_to_spv("sigmoid_f16", "sigmoid.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); string_to_spv("sigmoid_f32", "sigmoid.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("geglu_f16", "geglu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("geglu_f32", "geglu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("reglu_f16", "reglu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("reglu_f32", "reglu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("swiglu_f16", "swiglu.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("swiglu_f32", "swiglu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("geglu_erf_f16", "geglu_erf.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("geglu_erf_f32", "geglu_erf.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("geglu_quick_f16","geglu_quick.comp", {{"A_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("geglu_quick_f32","geglu_quick.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("leaky_relu_f32", "leaky_relu.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); string_to_spv("silu_back_f32", "silu_back.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); @@ -637,8 +646,30 @@ void process_shaders() { string_to_spv("rwkv_wkv6_f32", "wkv6.comp", merge_maps(base_dict, {{"A_TYPE", "float"}})); + string_to_spv("rwkv_wkv7_f32", "wkv7.comp", merge_maps(base_dict, {{"A_TYPE", "float"}})); + string_to_spv("opt_step_adamw_f32", "opt_step_adamw.comp", merge_maps(base_dict, {{"A_TYPE", "float"}})); + string_to_spv("conv2d_dw_whcn_f32", "conv2d_dw.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"WHCN", "1"}})); + string_to_spv("conv2d_dw_cwhn_f32", "conv2d_dw.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"CWHN", "1"}})); + + string_to_spv("roll_f32", "roll.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}})); + + // ============================== ik_llama.cpp + // + string_to_spv("fused_rms_norm_f32", "fused_rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}})); + + string_to_spv("fused_mul_gelu_f16", "fused_mul_gelu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("fused_mul_gelu_f32", "fused_mul_gelu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("fused_mul_silu_f16", "fused_mul_silu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("fused_mul_silu_f32", "fused_mul_silu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + string_to_spv("fused_mul_relu_f16", "fused_mul_relu.comp", {{"A_TYPE", "float16_t"}, {"B_TYPE", "float16_t"}, {"D_TYPE", "float16_t"}}); + string_to_spv("fused_mul_relu_f32", "fused_mul_relu.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}); + + string_to_spv("multi_add_f32", "multi_add.comp", {{"A_TYPE", "float"}, {"D_TYPE", "float"}}); + // + // ============================== end ik_llama.cpp + for (auto &c : compiles) { c.wait(); } diff --git a/ggml/src/vulkan-shaders/wkv7.comp b/ggml/src/vulkan-shaders/wkv7.comp new file mode 100644 index 00000000..88c1c02b --- /dev/null +++ b/ggml/src/vulkan-shaders/wkv7.comp @@ -0,0 +1,91 @@ +#version 450 + +#extension GL_EXT_control_flow_attributes : require + +#define BLOCK_SIZE 64 +layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout(push_constant) uniform Parameters { + uint B; + uint T; + uint C; + uint H; +}; + +layout(binding = 0) readonly buffer RBuf { A_TYPE r[]; }; +layout(binding = 1) readonly buffer WBuf { A_TYPE w[]; }; +layout(binding = 2) readonly buffer KBuf { A_TYPE k[]; }; +layout(binding = 3) readonly buffer VBuf { A_TYPE v[]; }; +layout(binding = 4) readonly buffer ABuf { A_TYPE a[]; }; +layout(binding = 5) readonly buffer BBuf { A_TYPE b[]; }; +layout(binding = 6) readonly buffer StateBuf { A_TYPE state_in[]; }; +layout(binding = 7) buffer DstBuf { A_TYPE dst[]; }; + +shared A_TYPE _r[BLOCK_SIZE], _w[BLOCK_SIZE], _k[BLOCK_SIZE], _a[BLOCK_SIZE], _b[BLOCK_SIZE]; + +void main() { + const uint head_size = BLOCK_SIZE; + const uint batch_id = gl_WorkGroupID.x / H; + const uint head_id = gl_WorkGroupID.x % H; + const uint tid = gl_LocalInvocationID.x; + + const uint state_size = C * head_size; + const uint n_seq_tokens = T / B; + + if (batch_id >= B || head_id >= H) { + return; + } + + A_TYPE state[BLOCK_SIZE]; + [[unroll]] for (uint i = 0; i < head_size; i++) { + state[i] = state_in[batch_id * state_size + head_id * head_size * head_size + + tid * head_size + i]; + } + + const uint start_t = batch_id * n_seq_tokens * C + head_id * head_size + tid; + const uint end_t = (batch_id + 1) * n_seq_tokens * C + head_id * head_size + tid; + + for (uint t = start_t; t < end_t; t += C) { + barrier(); + _r[tid] = r[t]; + _w[tid] = w[t]; + _k[tid] = k[t]; + _a[tid] = a[t]; + _b[tid] = b[t]; + barrier(); + + A_TYPE sa = 0.0; + [[unroll]] for (uint j = 0; j < head_size; j += 4) { + vec4 s_vec = vec4(state[j], state[j+1], state[j+2], state[j+3]); + vec4 a_vec = vec4(_a[j], _a[j+1], _a[j+2], _a[j+3]); + sa += dot(s_vec, a_vec); + } + + const A_TYPE v_val = v[t]; + A_TYPE y = 0.0; + + [[unroll]] for (uint j = 0; j < head_size; j += 4) { + vec4 r_vec = vec4(_r[j], _r[j+1], _r[j+2], _r[j+3]); + vec4 w_vec = vec4(_w[j], _w[j+1], _w[j+2], _w[j+3]); + vec4 k_vec = vec4(_k[j], _k[j+1], _k[j+2], _k[j+3]); + vec4 b_vec = vec4(_b[j], _b[j+1], _b[j+2], _b[j+3]); + vec4 s_vec = vec4(state[j], state[j+1], state[j+2], state[j+3]); + + vec4 kv = k_vec * v_val; + s_vec = s_vec * w_vec + kv + sa * b_vec; + y += dot(r_vec, s_vec); + + state[j] = s_vec.x; + state[j+1] = s_vec.y; + state[j+2] = s_vec.z; + state[j+3] = s_vec.w; + } + + dst[t] = y; + } + + [[unroll]] for (uint i = 0; i < head_size; i++) { + dst[T * C + batch_id * state_size + head_id * head_size * head_size + + tid * head_size + i] = state[i]; + } +} diff --git a/src/llama.cpp b/src/llama.cpp index c11affb6..0a81f2b9 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -10136,6 +10136,12 @@ static struct ggml_tensor * llm_build_kqv( 0); cb(k, "k", il); +#ifdef GGML_USE_VULKAN + constexpr bool use_f32_precision = true; +#else + constexpr bool use_f32_precision = false; +#endif + struct ggml_tensor * cur; if (cparams.flash_attn) { @@ -10157,7 +10163,7 @@ static struct ggml_tensor * llm_build_kqv( // Some models produced NaNs/gibberish when FA is computed with f16 precision on CUDA // For DeepSeek-2, it is perfectly fine with fp16 for PP, but I get gibberish when uding fp16 for TG. // Not sure if it is really a matter of insufficient precision, or I have made a mistake in the fattn-vec-f16 kernel. - if (model.arch == LLM_ARCH_PHI2 || model.arch == LLM_ARCH_PHI3 || model.arch == LLM_ARCH_GPTNEOX || + if (use_f32_precision || model.arch == LLM_ARCH_PHI2 || model.arch == LLM_ARCH_PHI3 || model.arch == LLM_ARCH_GPTNEOX || (model.arch == LLM_ARCH_DEEPSEEK2 && q->ne[1] <= 8) || model.arch == LLM_ARCH_COHERE2 || model.arch == LLM_ARCH_GLM4) { ggml_flash_attn_ext_set_prec(cur, GGML_PREC_F32); } @@ -10182,7 +10188,7 @@ static struct ggml_tensor * llm_build_kqv( //ggml_mul_mat_set_prec(kq, GGML_PREC_F32); - if (model.arch == LLM_ARCH_PHI2 || model.arch == LLM_ARCH_PHI3 || model.arch == LLM_ARCH_GPTNEOX || model.arch == LLM_ARCH_QWEN2 || + if (use_f32_precision || model.arch == LLM_ARCH_PHI2 || model.arch == LLM_ARCH_PHI3 || model.arch == LLM_ARCH_GPTNEOX || model.arch == LLM_ARCH_QWEN2 || model.arch == LLM_ARCH_COHERE2 || model.arch == LLM_ARCH_GLM4) { // for this arch, we need to perform the KQ multiplication with F32 precision, otherwise we get NaNs // ref: https://github.com/ggerganov/llama.cpp/pull/4490#issuecomment-1859055847 @@ -15449,6 +15455,11 @@ struct llm_build_context { } struct ggml_cgraph * build_deepseek2() { +#ifdef GGML_USE_VULKAN + constexpr bool use_f32_attn_precision = true; +#else + constexpr bool use_f32_attn_precision = false; +#endif struct ggml_cgraph * gf = ggml_new_graph_custom(ctx0, llama_model_max_nodes(model), false); // mutable variable, needed during the last layer of the computation to skip unused tokens @@ -15678,7 +15689,7 @@ struct llm_build_context { q->nb[1], q->nb[2], q->nb[2]*n_max_head*iter); kqv = ggml_flash_attn_ext(ctx0, q_iter, k, v, KQ_mask, kq_scale, hparams.f_max_alibi_bias, 0.f); - if (q->ne[1] <= 8) { + if (use_f32_attn_precision || q->ne[1] <= 8) { ggml_flash_attn_ext_set_prec(kqv, GGML_PREC_F32); } cb(kqv, "kqv", il); @@ -15720,6 +15731,10 @@ struct llm_build_context { kqv_compressed = ggml_flash_attn_ext(ctx0, q, kv_cache, kv_cache_lora, KQ_mask, kq_scale, hparams.f_max_alibi_bias, 0.f); cb(kqv_compressed, "kqv_compressed", il); + if (use_f32_attn_precision) { + ggml_flash_attn_ext_set_prec(kqv_compressed, GGML_PREC_F32); + } + kqv_compressed = ggml_permute(ctx0, kqv_compressed, 0, 2, 1, 3); cb(kqv_compressed, "kqv_compressed_perm", il); } From 13b2f193723486f46efe34297cf797186ab14bc2 Mon Sep 17 00:00:00 2001 From: ubergarm Date: Tue, 15 Jul 2025 13:54:04 -0400 Subject: [PATCH 30/63] kimi-k2 convert script and chat template (#612) * convert_hf_to_gguf for Kimi-K2-Instruct Adapt mainline `PR14653` for tokenizer while maintaining proper MLA tensors. Tested with this workflow using deepseek fp8_cast_bf16.py and triton-cpu to upcast the fp8 safetensors to bf16 safetensors then used this convert_hf_to_gguf. * Add Kimi-K2 chat template moonshotai/Kimi-K2-Instruct https://github.com/ikawrakow/ik_llama.cpp/pull/609#issuecomment-3071259454 * kimi-k2 add ass to template to get response --- convert_hf_to_gguf.py | 57 ++++++++++++++++++++++++++++++++++++ convert_hf_to_gguf_update.py | 1 + src/llama.cpp | 19 ++++++++++++ 3 files changed, 77 insertions(+) diff --git a/convert_hf_to_gguf.py b/convert_hf_to_gguf.py index b0a82c80..76f269b3 100644 --- a/convert_hf_to_gguf.py +++ b/convert_hf_to_gguf.py @@ -639,6 +639,9 @@ class Model: if chkhsh == "d5f1dd6f980fec569fb218a81a7658ac45fc56b38c5a0adeb1c232fbe04ef5ec": # ref: https://huggingface.co/ByteDance-Seed/Seed-Coder-8B-Base res = "seed-coder" + if chkhsh == "81212dc7cdb7e0c1074ca62c5aeab0d43c9f52b8a737be7b12a777c953027890": + # ref: https://huggingface.co/moonshotai/Kimi-K2-Base + res = "kimi-k2" if res is None: logger.warning("\n") @@ -3379,6 +3382,60 @@ class DeepseekV2Model(Model): model_arch = gguf.MODEL_ARCH.DEEPSEEK2 def set_vocab(self): + + if self.hparams["vocab_size"] == 163840: # Kimi-K2 model + from transformers import AutoTokenizer + + tokenizer = AutoTokenizer.from_pretrained( + self.dir_model, trust_remote_code=True + ) + tokpre = self.get_vocab_base_pre(tokenizer) + + # Build merges list using the approach similar to HunYuanMoE + merges = [] + vocab = {} + mergeable_ranks = tokenizer.model._mergeable_ranks + for token, rank in mergeable_ranks.items(): + vocab[QwenModel.token_bytes_to_string(token)] = rank + if len(token) == 1: + continue + merged = QwenModel.bpe(mergeable_ranks, token, max_rank=rank) + if len(merged) == 2: + merges.append( + " ".join(map(QwenModel.token_bytes_to_string, merged)) + ) + + # Build token list + vocab_size = self.hparams["vocab_size"] + special_tokens = tokenizer.special_tokens + reverse_vocab = { + id_: encoded_tok + for encoded_tok, id_ in {**vocab, **special_tokens}.items() + } + tokens: list[str] = [] + toktypes: list[int] = [] + + for i in range(vocab_size): + if i not in reverse_vocab: + tokens.append(f"[PAD{i}]") + toktypes.append(gguf.TokenType.UNUSED) + else: + token = reverse_vocab[i] + tokens.append(token) + if i in special_tokens.values(): + toktypes.append(gguf.TokenType.CONTROL) + else: + toktypes.append(gguf.TokenType.NORMAL) + + self.gguf_writer.add_tokenizer_model("gpt2") + self.gguf_writer.add_tokenizer_pre(tokpre) + self.gguf_writer.add_token_list(tokens) + self.gguf_writer.add_token_types(toktypes) + self.gguf_writer.add_token_merges(merges) + + special_vocab = gguf.SpecialVocab(self.dir_model, load_merges=False) + special_vocab.add_to_gguf(self.gguf_writer) + else: self._set_vocab_gpt2() def set_gguf_parameters(self): diff --git a/convert_hf_to_gguf_update.py b/convert_hf_to_gguf_update.py index f2e6cc37..d6541987 100755 --- a/convert_hf_to_gguf_update.py +++ b/convert_hf_to_gguf_update.py @@ -96,6 +96,7 @@ models = [ {"name": "smollm", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/HuggingFaceTB/SmolLM-135M", }, {"name": "deepseek-v3", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/deepseek-ai/DeepSeek-V3"}, {"name": "seed-coder", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/ByteDance-Seed/Seed-Coder-8B-Base", }, + {"name": "kimi-k2", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/moonshotai/Kimi-K2-Base", "chkhsh": "81212dc7cdb7e0c1074ca62c5aeab0d43c9f52b8a737be7b12a777c953027890", }, ] diff --git a/src/llama.cpp b/src/llama.cpp index 0a81f2b9..58812fc8 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -1695,6 +1695,7 @@ enum llm_chat_template { LLM_CHAT_TEMPLATE_BITNET, LLM_CHAT_TEMPLATE_DOTS1, LLM_CHAT_TEMPLATE_HUNYUAN_MOE, + LLM_CHAT_TEMPLATE_KIMI_K2, LLM_CHAT_TEMPLATE_UNKNOWN, }; @@ -1733,6 +1734,7 @@ static const std::map LLM_CHAT_TEMPLATES = { { "megrez", LLM_CHAT_TEMPLATE_MEGREZ }, { "llama4", LLM_CHAT_TEMPLATE_LLAMA4 }, { "hunyuan-moe", LLM_CHAT_TEMPLATE_HUNYUAN_MOE }, + { "kimi-k2", LLM_CHAT_TEMPLATE_KIMI_K2 }, { "bitnet", LLM_CHAT_TEMPLATE_BITNET }, }; @@ -23270,6 +23272,8 @@ static llm_chat_template llama_chat_detect_template(const std::string & tmpl) { return LLM_CHAT_TEMPLATE_DOTS1; } else if (tmpl_contains("<|startoftext|>") && tmpl_contains("<|extra_4|>")) { return LLM_CHAT_TEMPLATE_HUNYUAN_MOE; + } else if (tmpl_contains("<|im_middle|>") && tmpl_contains("<|im_end|>")) { + return LLM_CHAT_TEMPLATE_KIMI_K2; } return LLM_CHAT_TEMPLATE_UNKNOWN; } @@ -23715,6 +23719,21 @@ static int32_t llama_chat_apply_template_internal( ss << "<|startoftext|>" << message->content << "<|extra_0|>"; } } + } else if (tmpl == LLM_CHAT_TEMPLATE_KIMI_K2) { + // moonshotai/Kimi-K2-Instruct + for (auto message : chat) { + std::string role(message->role); + if (role == "system") { + ss << "<|im_system|>system<|im_middle|>" << message->content << "<|im_end|>"; + } else if (role == "assistant") { + ss << "<|im_user|>user<|im_middle|>" << message->content << "<|im_end|>"; + } else { + ss << "<|im_assistant|>assistant<|im_middle|>" << message->content << "<|im_end|>"; + } + } + if (add_ass) { + ss << "<|im_assistant|>assistant<|im_middle|>"; + } } else { // template not supported return -1; From 4803142300670088f10f61f9ab66d882e93df4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thireus=20=E2=98=A0?= Date: Wed, 16 Jul 2025 13:11:19 +0100 Subject: [PATCH 31/63] Bump GGML_MAX_CONTEXTS to allow loading more shards (#611) * Bump GGML_MAX_CONTEXTS to allow loading more shards This var prevents more than 64 shards from being loaded - Specifically relevant for large models such as DeepSeek R1. * https://github.com/ikawrakow/ik_llama.cpp/pull/611#issuecomment-3072175559 --- ggml/include/ggml.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index a85f52b2..644a82b2 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -234,7 +234,12 @@ #define GGML_MAX_DIMS 4 #define GGML_MAX_PARAMS 2048 -#define GGML_MAX_CONTEXTS 64 +#ifndef GGML_MAX_CONTEXTS +// Maximum number of model contexts (e.g., for model shards). +// Increase this value using -DGGML_MAX_CONTEXTS= in CMake +// if you need to load more than 64 model shards. +#define GGML_MAX_CONTEXTS 64 +#endif #define GGML_MAX_SRC 10 #ifndef GGML_MAX_NAME #define GGML_MAX_NAME 64 From c4fbced37db712dd222d8a0e0d6986e94811d214 Mon Sep 17 00:00:00 2001 From: ubergarm Date: Wed, 16 Jul 2025 09:24:20 -0400 Subject: [PATCH 32/63] Fixup kimi-k2 convert indentation (#617) --- convert_hf_to_gguf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/convert_hf_to_gguf.py b/convert_hf_to_gguf.py index 76f269b3..a4de237e 100644 --- a/convert_hf_to_gguf.py +++ b/convert_hf_to_gguf.py @@ -3436,7 +3436,7 @@ class DeepseekV2Model(Model): special_vocab = gguf.SpecialVocab(self.dir_model, load_merges=False) special_vocab.add_to_gguf(self.gguf_writer) else: - self._set_vocab_gpt2() + self._set_vocab_gpt2() def set_gguf_parameters(self): super().set_gguf_parameters() From 6950c82c302dd6afc838f4a405d86d323f35126d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thireus=20=E2=98=A0?= Date: Thu, 17 Jul 2025 07:50:26 +0100 Subject: [PATCH 33/63] Bump Windows max open files from 512 to 2048 (#620) * Bump windows max open files from 512 to 2048 https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmaxstdio?view=msvc-160 * Make _GGML_STDIO_TARGET dependent of GGML_MAX_CONTEXTS for Windows --- src/llama.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/llama.cpp b/src/llama.cpp index 58812fc8..0d29f24a 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -4245,6 +4245,24 @@ struct llama_model_loader { trace = atoi(getenv("LLAMA_TRACE")); } + #ifdef _WIN32 + // Only bump maxstdio if the user really wants large contexts: + #if defined(GGML_MAX_CONTEXTS) && (GGML_MAX_CONTEXTS > 512) + // Cap at MSVC's hard limit of 8192 - https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmaxstdio?view=msvc-160 + #if (GGML_MAX_CONTEXTS > 8192) + #define _GGML_STDIO_TARGET 8192 + #else + #define _GGML_STDIO_TARGET GGML_MAX_CONTEXTS + #endif + int _setmaxstdio_ret = _setmaxstdio(_GGML_STDIO_TARGET); + if (_setmaxstdio_ret == -1) { + LLAMA_LOG_INFO("%s: failed to set max stdio to %d. (setmaxstdio returned -1)\n", __func__, _GGML_STDIO_TARGET); + } else { + LLAMA_LOG_INFO("%s: max stdio successfully set to %d\n", __func__, _setmaxstdio_ret); + } + #endif // GGML_MAX_CONTEXTS > 512 + #endif // _WIN32 + if (param_overrides_p != nullptr) { for (const struct llama_model_kv_override * p = param_overrides_p; p->key[0] != 0; p++) { kv_overrides.insert({std::string(p->key), *p}); From b94f3af56f6fde4845c968115edaa0ac36e36bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thireus=20=E2=98=A0?= Date: Thu, 17 Jul 2025 07:50:42 +0100 Subject: [PATCH 34/63] Add GGML_MAX_CONTEXTS definition in CMakeLists.txt (#622) * Add GGML_MAX_CONTEXTS definition in CMakeLists.txt If this entry is missing, GGML_MAX_CONTEXTS is ignored * Update CMakeLists.txt add_compile_definitions for GGML_MAX_CONTEXTS --- ggml/CMakeLists.txt | 1 + ggml/src/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ggml/CMakeLists.txt b/ggml/CMakeLists.txt index 4dbd8d34..e63520f0 100644 --- a/ggml/CMakeLists.txt +++ b/ggml/CMakeLists.txt @@ -104,6 +104,7 @@ endif() # ggml core set(GGML_SCHED_MAX_COPIES "4" CACHE STRING "ggml: max input copies for pipeline parallelism") +set(GGML_MAX_CONTEXTS "" CACHE STRING "ggml: max model contexts (override only; defaults to 64 in the code)") # 3rd party libs / backends option(GGML_ACCELERATE "ggml: enable Accelerate framework" ON) diff --git a/ggml/src/CMakeLists.txt b/ggml/src/CMakeLists.txt index 1a3c1ff6..175f9c67 100644 --- a/ggml/src/CMakeLists.txt +++ b/ggml/src/CMakeLists.txt @@ -3,6 +3,9 @@ include(CheckCXXCompilerFlag) unset(GGML_CDEF_PUBLIC) add_compile_definitions(GGML_SCHED_MAX_COPIES=${GGML_SCHED_MAX_COPIES}) +if (GGML_MAX_CONTEXTS) + add_compile_definitions(GGML_MAX_CONTEXTS=${GGML_MAX_CONTEXTS}) +endif() # enable libstdc++ assertions for debug builds if (CMAKE_SYSTEM_NAME MATCHES "Linux") From cc82006f51e0254279bfd46c3c7d97cb12d7dc18 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Fri, 18 Jul 2025 18:55:43 +0200 Subject: [PATCH 35/63] GEMM for iq1_m (#630) Co-authored-by: Iwan Kawrakow --- ggml/src/iqk/iqk_gemm_1bit.cpp | 67 ++++++++++++++++++++++++++++++++++ ggml/src/iqk/iqk_mul_mat.cpp | 4 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/ggml/src/iqk/iqk_gemm_1bit.cpp b/ggml/src/iqk/iqk_gemm_1bit.cpp index 2c0a1bda..ece76f3c 100644 --- a/ggml/src/iqk/iqk_gemm_1bit.cpp +++ b/ggml/src/iqk/iqk_gemm_1bit.cpp @@ -865,6 +865,68 @@ void mul_mat_iq1_s_q8_K(int n, const void * vx, size_t bx, const DataInfo& info, } } +template +void mul_mat_iq1_m_q8_K(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { + GGML_ASSERT(n%QK_K == 0); + Q8 q8(info); + __m256i qx[8]; + __m256 acc[nrc_y] = {}; + auto scale_shuffle = _mm256_set_epi64x(0x0706070607060706, 0x0504050405040504, 0x0302030203020302, 0x0100010001000100); + auto delta_mask = _mm256_set_epi64x(0x8000, 0x0800, 0x0080, 0x0008); + iq1m_scale_t scale; + union { __m256i vec; int16_t val[16]; } helper; + for (int ix = 0; ix < nrc_x; ++ix) { + auto iq1m = (const block_iq1_m *)((const char *)vx + ix*bx); + for (int ibl = 0; ibl < n/QK_K; ++ibl) { + const uint16_t * sc = (const uint16_t *)iq1m[ibl].scales; // 4 x uint16_t, each containing 4 scales + scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000); + float d = GGML_FP16_TO_FP32(scale.f16); + auto qs = iq1m[ibl].qs; + auto qh = iq1m[ibl].qh; + auto aux = _mm_loadl_epi64((const __m128i *)iq1m[ibl].scales); + auto sc16 = _mm256_shuffle_epi8(MM256_SET_M128I(aux, aux), scale_shuffle); + sc16 = _mm256_and_si256(sc16, _mm256_set1_epi64x(0x0e0001c000380007)); + sc16 = _mm256_mullo_epi16(sc16, _mm256_set1_epi64x(0x0001000800400200)); + helper.vec = _mm256_add_epi8(_mm256_srli_epi16(sc16, 8), _mm256_set1_epi16(1)); + for (int ib64 = 0; ib64 < QK_K/64; ++ib64) { + qx[2*ib64+0] = _mm256_set_epi64x(iq1s_grid_us[qs[3] | (((uint16_t)qh[1] << 4) & 0x700)], iq1s_grid_us[qs[2] | (((uint16_t)qh[1] << 8) & 0x700)], + iq1s_grid_us[qs[1] | (((uint16_t)qh[0] << 4) & 0x700)], iq1s_grid_us[qs[0] | (((uint16_t)qh[0] << 8) & 0x700)]); + qx[2*ib64+1] = _mm256_set_epi64x(iq1s_grid_us[qs[7] | (((uint16_t)qh[3] << 4) & 0x700)], iq1s_grid_us[qs[6] | (((uint16_t)qh[3] << 8) & 0x700)], + iq1s_grid_us[qs[5] | (((uint16_t)qh[2] << 4) & 0x700)], iq1s_grid_us[qs[4] | (((uint16_t)qh[2] << 8) & 0x700)]); + //auto delta1 = _mm256_set_epi64x(qh[1] & 0x80 ? 0x0909090909090909 : 0x0707070707070707, + // qh[1] & 0x08 ? 0x0909090909090909 : 0x0707070707070707, + // qh[0] & 0x80 ? 0x0909090909090909 : 0x0707070707070707, + // qh[0] & 0x08 ? 0x0909090909090909 : 0x0707070707070707); + //auto delta2 = _mm256_set_epi64x(qh[3] & 0x80 ? 0x0909090909090909 : 0x0707070707070707, + // qh[3] & 0x08 ? 0x0909090909090909 : 0x0707070707070707, + // qh[2] & 0x80 ? 0x0909090909090909 : 0x0707070707070707, + // qh[2] & 0x08 ? 0x0909090909090909 : 0x0707070707070707); + auto qh16 = (const uint16_t *)qh; + auto delta1 = _mm256_cmpeq_epi64(_mm256_and_si256(_mm256_set1_epi64x(qh16[0]), delta_mask), delta_mask); + auto delta2 = _mm256_cmpeq_epi64(_mm256_and_si256(_mm256_set1_epi64x(qh16[1]), delta_mask), delta_mask); + delta1 = _mm256_sub_epi8(_mm256_set1_epi8(8), _mm256_or_si256(delta1, _mm256_set1_epi8(1))); + delta2 = _mm256_sub_epi8(_mm256_set1_epi8(8), _mm256_or_si256(delta2, _mm256_set1_epi8(1))); + qx[2*ib64+0] = _mm256_sub_epi8(_mm256_slli_epi16(qx[2*ib64+0], 3), delta1); + qx[2*ib64+1] = _mm256_sub_epi8(_mm256_slli_epi16(qx[2*ib64+1], 3), delta2); + qs += 8; + qh += 4; + } + for (int iy = 0; iy < nrc_y; ++iy) { + auto sumi = _mm256_setzero_si256(); + for (int j = 0; j < 8; ++j) { + auto p = _mm256_maddubs_epi16(_mm256_sign_epi8(qx[j], qx[j]), _mm256_sign_epi8(q8.load_quants(iy, ibl, j), qx[j])); + sumi = _mm256_add_epi32(sumi, _mm256_madd_epi16(p, MM256_SET_M128I(_mm_set1_epi16(helper.val[2*j+1]), _mm_set1_epi16(helper.val[2*j+0])))); + } + acc[iy] = _mm256_fmadd_ps(_mm256_set1_ps(d*q8.scale(iy, ibl)), _mm256_cvtepi32_ps(sumi), acc[iy]); + } + } + for (int iy = 0; iy < nrc_y; ++iy) { + info.store(ix, iy, 0.125f*hsum_float_8(acc[iy])); + acc[iy] = _mm256_setzero_ps(); + } + } +} + template void mul_mat_iq1_s_q8_2_x4(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { GGML_ASSERT(n%QK_K == 0); @@ -1844,6 +1906,11 @@ bool iqk_set_kernels_1bit(int ne00, int typeA, int typeB, std::array; #endif break; + case GGML_TYPE_IQ1_M: + if (ne00%QK_K != 0) return false; + IQK_SET_MUL_MAT_FUNCTIONS(mul_mat_iq1_m_q8_K, funcs); + expected_typeB = GGML_TYPE_Q8_K; + break; case GGML_TYPE_IQ1_M_R4: if (ne00%128 != 0) return false; IQK_SET_MUL_MAT_FUNCTIONS(mul_mat_iq1_m_r4_q8_0, funcs); diff --git a/ggml/src/iqk/iqk_mul_mat.cpp b/ggml/src/iqk/iqk_mul_mat.cpp index fb951e70..31de5c42 100644 --- a/ggml/src/iqk/iqk_mul_mat.cpp +++ b/ggml/src/iqk/iqk_mul_mat.cpp @@ -243,7 +243,7 @@ struct MulMat { case GGML_TYPE_IQ4_XS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ3_S : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ1_S : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; - case GGML_TYPE_IQ1_M : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; + case GGML_TYPE_IQ1_M : return nrc_y >= 999932 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_Q2_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_Q3_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_Q4_K : return nrc_y >= 32 ? GGML_TYPE_Q8_1 : type; @@ -867,6 +867,7 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& mm, int Ny) { case GGML_TYPE_IQ4_NL_R4: return iqk_set_kernels_legacy_quants(ne00, typeA, typeB, mm.funcs, mm.func16); case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: case GGML_TYPE_IQ1_S_R4: case GGML_TYPE_IQ1_M_R4: case GGML_TYPE_IQ1_BN: @@ -958,6 +959,7 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& m, int /*Ny*/) { case GGML_TYPE_IQ2_BN: case GGML_TYPE_IQ2_BN_R4: case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ1_M: case GGML_TYPE_IQ1_S_R4: case GGML_TYPE_IQ1_M_R4: return iqk_set_kernels_1bit(ne00, typeA, typeB, m.funcs, m.func16); From 38012f7290f1761f151c415d2dc11d1af04da927 Mon Sep 17 00:00:00 2001 From: Iwan Kawrakow Date: Fri, 18 Jul 2025 20:11:57 +0300 Subject: [PATCH 36/63] Remove forgotten change --- ggml/src/iqk/iqk_mul_mat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ggml/src/iqk/iqk_mul_mat.cpp b/ggml/src/iqk/iqk_mul_mat.cpp index 31de5c42..75ca87df 100644 --- a/ggml/src/iqk/iqk_mul_mat.cpp +++ b/ggml/src/iqk/iqk_mul_mat.cpp @@ -243,7 +243,7 @@ struct MulMat { case GGML_TYPE_IQ4_XS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ3_S : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ1_S : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; - case GGML_TYPE_IQ1_M : return nrc_y >= 999932 ? GGML_TYPE_Q8_K_R8 : type; + case GGML_TYPE_IQ1_M : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_Q2_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_Q3_K : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_Q4_K : return nrc_y >= 32 ? GGML_TYPE_Q8_1 : type; From 07673c6c33753487dd054dcff37f19d93d6c56d3 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Sun, 20 Jul 2025 09:49:59 +0200 Subject: [PATCH 37/63] IQ1_M GEMM for ARM_NEON (#631) * iq1_m GEMM on NEON * Set repacking threshold --------- Co-authored-by: Iwan Kawrakow --- ggml/src/iqk/iqk_gemm_1bit.cpp | 150 +++++++++++++++++++++++++-------- ggml/src/iqk/iqk_mul_mat.cpp | 2 +- 2 files changed, 116 insertions(+), 36 deletions(-) diff --git a/ggml/src/iqk/iqk_gemm_1bit.cpp b/ggml/src/iqk/iqk_gemm_1bit.cpp index ece76f3c..4ec4f44f 100644 --- a/ggml/src/iqk/iqk_gemm_1bit.cpp +++ b/ggml/src/iqk/iqk_gemm_1bit.cpp @@ -9,7 +9,6 @@ namespace { -#ifdef __AVX2__ static const uint64_t iq1s_grid_us[2048] = { 0x0000000000000000, 0x0000000000000002, 0x0000000000000101, 0x0000000000000200, 0x0000000000000202, 0x0000000000010001, 0x0000000000010101, 0x0000000000020000, @@ -524,8 +523,8 @@ static const uint64_t iq1s_grid_us[2048] = { 0x0202020202000002, 0x0202020202000200, 0x0202020202000202, 0x0202020202010101, 0x0202020202020000, 0x0202020202020002, 0x0202020202020200, 0x0202020202020202, }; -#else -static const uint32_t iq1s_grid_us[2048] = { +#ifdef __aarch64__ +static const uint32_t iq1s_grid_us_neon[2048] = { 0x00000000, 0x00000002, 0x00000101, 0x00000200, 0x00000202, 0x00010001, 0x00010101, 0x00020000, 0x00020002, 0x00020200, 0x00020202, 0x01000101, 0x01010001, 0x01010100, 0x01010102, 0x01020101, 0x02000000, 0x02000002, 0x02000200, 0x02000202, 0x02010101, 0x02020000, 0x02020002, 0x02020200, @@ -2336,22 +2335,22 @@ static void mul_mat_iq1_s_r4_q8_1(int n, const void * vx, size_t bx, const DataI auto signs = vreinterpret_s16_u16(vorr_u16(vceq_u16(vand_u16(sas, ms), ms), vdup_n_u16(1))); signs = vadd_s16(vdup_n_s16(-8), signs); auto delta4 = vmulq_f32(vdupq_n_f32(0.125f), vcvtq_f32_s32(vmull_s16(signs, scales4))); - qx[0] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[ 0] | ((x[4*ib+k].qh[0] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 1] | ((x[4*ib+k].qh[1] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 2] | ((x[4*ib+k].qh[2] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 3] | ((x[4*ib+k].qh[3] << 8) & 0x0700)]}); - qx[2] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[ 4] | ((x[4*ib+k].qh[0] << 5) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 5] | ((x[4*ib+k].qh[1] << 5) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 6] | ((x[4*ib+k].qh[2] << 5) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 7] | ((x[4*ib+k].qh[3] << 5) & 0x0700)]}); - qx[4] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[ 8] | ((x[4*ib+k].qh[0] << 2) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 9] | ((x[4*ib+k].qh[1] << 2) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[10] | ((x[4*ib+k].qh[2] << 2) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[11] | ((x[4*ib+k].qh[3] << 2) & 0x0700)]}); - qx[6] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[12] | ((x[4*ib+k].qh[0] >> 1) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[13] | ((x[4*ib+k].qh[1] >> 1) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[14] | ((x[4*ib+k].qh[2] >> 1) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[15] | ((x[4*ib+k].qh[3] >> 1) & 0x0700)]}); + qx[0] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[ 0] | ((x[4*ib+k].qh[0] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 1] | ((x[4*ib+k].qh[1] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 2] | ((x[4*ib+k].qh[2] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 3] | ((x[4*ib+k].qh[3] << 8) & 0x0700)]}); + qx[2] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[ 4] | ((x[4*ib+k].qh[0] << 5) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 5] | ((x[4*ib+k].qh[1] << 5) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 6] | ((x[4*ib+k].qh[2] << 5) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 7] | ((x[4*ib+k].qh[3] << 5) & 0x0700)]}); + qx[4] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[ 8] | ((x[4*ib+k].qh[0] << 2) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 9] | ((x[4*ib+k].qh[1] << 2) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[10] | ((x[4*ib+k].qh[2] << 2) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[11] | ((x[4*ib+k].qh[3] << 2) & 0x0700)]}); + qx[6] = vreinterpretq_u8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[12] | ((x[4*ib+k].qh[0] >> 1) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[13] | ((x[4*ib+k].qh[1] >> 1) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[14] | ((x[4*ib+k].qh[2] >> 1) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[15] | ((x[4*ib+k].qh[3] >> 1) & 0x0700)]}); qx[1] = vandq_u8(vshrq_n_u8(qx[0], 4), mask); qx[0] = vandq_u8(qx[0], mask); qx[3] = vandq_u8(vshrq_n_u8(qx[2], 4), mask); qx[2] = vandq_u8(qx[2], mask); qx[5] = vandq_u8(vshrq_n_u8(qx[4], 4), mask); qx[4] = vandq_u8(qx[4], mask); @@ -2409,22 +2408,22 @@ static void mul_mat_iq1_m_r4_q8_0(int n, const void * vx, size_t bx, const DataI auto idxh = uint32x4_t{qh[0], qh[0] >> 4, qh[1], qh[1] >> 4}; auto signs = vreinterpretq_s8_u8(vorrq_u8(vceqq_u8(vandq_u8(idxh, ms), ms), vdupq_n_u8(1))); signs = vaddq_s8(signs, vdupq_n_s8(-8)); - qx[0] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[ 0] | ((x[4*ib+k].qh[0] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 1] | ((x[4*ib+k].qh[1] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 2] | ((x[4*ib+k].qh[2] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 3] | ((x[4*ib+k].qh[3] << 8) & 0x0700)]}); - qx[2] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[ 4] | ((x[4*ib+k].qh[0] << 4) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 5] | ((x[4*ib+k].qh[1] << 4) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 6] | ((x[4*ib+k].qh[2] << 4) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 7] | ((x[4*ib+k].qh[3] << 4) & 0x0700)]}); - qx[4] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[ 8] | ((x[4*ib+k].qh[4] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[ 9] | ((x[4*ib+k].qh[5] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[10] | ((x[4*ib+k].qh[6] << 8) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[11] | ((x[4*ib+k].qh[7] << 8) & 0x0700)]}); - qx[6] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us[x[4*ib+k].qs[12] | ((x[4*ib+k].qh[4] << 4) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[13] | ((x[4*ib+k].qh[5] << 4) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[14] | ((x[4*ib+k].qh[6] << 4) & 0x0700)], - iq1s_grid_us[x[4*ib+k].qs[15] | ((x[4*ib+k].qh[7] << 4) & 0x0700)]}); + qx[0] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[ 0] | ((x[4*ib+k].qh[0] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 1] | ((x[4*ib+k].qh[1] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 2] | ((x[4*ib+k].qh[2] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 3] | ((x[4*ib+k].qh[3] << 8) & 0x0700)]}); + qx[2] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[ 4] | ((x[4*ib+k].qh[0] << 4) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 5] | ((x[4*ib+k].qh[1] << 4) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 6] | ((x[4*ib+k].qh[2] << 4) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 7] | ((x[4*ib+k].qh[3] << 4) & 0x0700)]}); + qx[4] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[ 8] | ((x[4*ib+k].qh[4] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[ 9] | ((x[4*ib+k].qh[5] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[10] | ((x[4*ib+k].qh[6] << 8) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[11] | ((x[4*ib+k].qh[7] << 8) & 0x0700)]}); + qx[6] = vreinterpretq_s8_u32(uint32x4_t{iq1s_grid_us_neon[x[4*ib+k].qs[12] | ((x[4*ib+k].qh[4] << 4) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[13] | ((x[4*ib+k].qh[5] << 4) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[14] | ((x[4*ib+k].qh[6] << 4) & 0x0700)], + iq1s_grid_us_neon[x[4*ib+k].qs[15] | ((x[4*ib+k].qh[7] << 4) & 0x0700)]}); auto shuffle = shuffle0; for (int j = 0; j < 4; ++j) { auto s = vqtbl1q_s8(signs, shuffle); @@ -2583,6 +2582,81 @@ void mul_mat_iq1_s_q8_K(int n, const void * vx, size_t bx, const DataInfo& info, } } +template +void mul_mat_iq1_m_q8_K(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { + GGML_ASSERT(n%QK_K == 0); + Q8 q8(info); + int8x16x2_t qx[8]; + int32x4x4_t scales; + float32x4_t acc[nrc_y] = {}; + uint8x16x2_t scale_shuffle = {vreinterpretq_u8_u64(uint64x2_t{0x0100010001000100, 0x0302030203020302}), + vreinterpretq_u8_u64(uint64x2_t{0x0504050405040504, 0x0706070607060706})}; + uint64x2x2_t delta_mask = {uint64x2_t{0x0008, 0x0080}, uint64x2_t{0x0800, 0x8000}}; + iq1m_scale_t block_scale; + for (int ix = 0; ix < nrc_x; ++ix) { + auto iq1m = (const block_iq1_m *)((const char *)vx + ix*bx); + for (int ibl = 0; ibl < n/QK_K; ++ibl) { + const uint16_t * sc = (const uint16_t *)iq1m[ibl].scales; // 4 x uint16_t, each containing 4 scales + block_scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000); + float d = GGML_FP16_TO_FP32(block_scale.f16); + auto qs = iq1m[ibl].qs; + auto qh = iq1m[ibl].qh; + auto aux8 = vld1_u8(iq1m[ibl].scales); + auto aux16 = vcombine_u8(aux8, aux8); + uint16x8x2_t sc16 = { vreinterpretq_u16_u8(vqtbl1q_u8(aux16, scale_shuffle.val[0])), vreinterpretq_u16_u8(vqtbl1q_u8(aux16, scale_shuffle.val[1])) }; + sc16.val[0] = vmulq_u16(vandq_u16(sc16.val[0], vdupq_n_u64(0x0e0001c000380007)), vdupq_n_u64(0x0001000800400200)); + sc16.val[1] = vmulq_u16(vandq_u16(sc16.val[1], vdupq_n_u64(0x0e0001c000380007)), vdupq_n_u64(0x0001000800400200)); + sc16.val[0] = vaddq_u16(vshrq_n_u16(sc16.val[0], 8), vdupq_n_u16(1)); + sc16.val[1] = vaddq_u16(vshrq_n_u16(sc16.val[1], 8), vdupq_n_u16(1)); + scales.val[0] = vmovl_s16(vget_low_s16 (sc16.val[0])); + scales.val[1] = vmovl_s16(vget_high_s16(sc16.val[0])); + scales.val[2] = vmovl_s16(vget_low_s16 (sc16.val[1])); + scales.val[3] = vmovl_s16(vget_high_s16(sc16.val[1])); + for (int ib64 = 0; ib64 < QK_K/64; ++ib64) { + qx[2*ib64+0] = {vreinterpretq_s8_u64(uint64x2_t{iq1s_grid_us[qs[0] | (((uint16_t)qh[0] << 8) & 0x700)], + iq1s_grid_us[qs[1] | (((uint16_t)qh[0] << 4) & 0x700)]}), + vreinterpretq_s8_u64(uint64x2_t{iq1s_grid_us[qs[2] | (((uint16_t)qh[1] << 8) & 0x700)], + iq1s_grid_us[qs[3] | (((uint16_t)qh[1] << 4) & 0x700)]})}; + qx[2*ib64+1] = {vreinterpretq_s8_u64(uint64x2_t{iq1s_grid_us[qs[4] | (((uint16_t)qh[2] << 8) & 0x700)], + iq1s_grid_us[qs[5] | (((uint16_t)qh[2] << 4) & 0x700)]}), + vreinterpretq_s8_u64(uint64x2_t{iq1s_grid_us[qs[6] | (((uint16_t)qh[3] << 8) & 0x700)], + iq1s_grid_us[qs[7] | (((uint16_t)qh[3] << 4) & 0x700)]})}; + auto qh16 = (const uint16_t *)qh; + auto h1 = vdupq_n_u64(qh16[0]); + auto h2 = vdupq_n_u64(qh16[1]); + auto delta1 = vsubq_s8(vdupq_n_s8(8), vorrq_s8(vreinterpretq_s8_u64(vceqq_u64(vandq_u64(h1, delta_mask.val[0]), delta_mask.val[0])), vdupq_n_s8(1))); + auto delta2 = vsubq_s8(vdupq_n_s8(8), vorrq_s8(vreinterpretq_s8_u64(vceqq_u64(vandq_u64(h1, delta_mask.val[1]), delta_mask.val[1])), vdupq_n_s8(1))); + qx[2*ib64+0].val[0] = vsubq_s8(vshlq_n_s8(qx[2*ib64+0].val[0], 3), delta1); + qx[2*ib64+0].val[1] = vsubq_s8(vshlq_n_s8(qx[2*ib64+0].val[1], 3), delta2); + delta1 = vsubq_s8(vdupq_n_s8(8), vorrq_s8(vreinterpretq_s8_u64(vceqq_u64(vandq_u64(h2, delta_mask.val[0]), delta_mask.val[0])), vdupq_n_s8(1))); + delta2 = vsubq_s8(vdupq_n_s8(8), vorrq_s8(vreinterpretq_s8_u64(vceqq_u64(vandq_u64(h2, delta_mask.val[1]), delta_mask.val[1])), vdupq_n_s8(1))); + qx[2*ib64+1].val[0] = vsubq_s8(vshlq_n_s8(qx[2*ib64+1].val[0], 3), delta1); + qx[2*ib64+1].val[1] = vsubq_s8(vshlq_n_s8(qx[2*ib64+1].val[1], 3), delta2); + qs += 8; + qh += 4; + } + for (int iy = 0; iy < nrc_y; ++iy) { + auto sumi = vdupq_n_s32(0); + for (int j = 0; j < 4; ++j) { + auto y1 = q8.load_quants(iy, ibl, 2*j+0); + auto dot1 = ggml_vdotq_s32(vdupq_n_s32(0), qx[2*j+0].val[0], y1.val[0]); + auto dot2 = ggml_vdotq_s32(vdupq_n_s32(0), qx[2*j+0].val[1], y1.val[1]); + auto y2 = q8.load_quants(iy, ibl, 2*j+1); + auto dot3 = ggml_vdotq_s32(vdupq_n_s32(0), qx[2*j+1].val[0], y2.val[0]); + auto dot4 = ggml_vdotq_s32(vdupq_n_s32(0), qx[2*j+1].val[1], y2.val[1]); + auto dot = vpaddq_s32(vpaddq_s32(dot1, dot2), vpaddq_s32(dot3, dot4)); + sumi = vmlaq_s32(sumi, dot, scales.val[j]); + } + acc[iy] = vfmaq_f32(acc[iy], vdupq_n_f32(d*q8.scale(iy, ibl)), vcvtq_f32_s32(sumi)); + } + } + for (int iy = 0; iy < nrc_y; ++iy) { + info.store(ix, iy, 0.125f*vaddvq_f32(acc[iy])); + acc[iy] = vdupq_n_f32(0.f); + } + } +} + inline float convert_to_q8_k_r8(float d0, const int8x16x2_t * qx, const int8_t * scales, uint32_t * block, uint32_t * q8_k) { auto max_i16 = vdupq_n_u16(0); int16x8x4_t q[8]; @@ -2774,6 +2848,12 @@ bool iqk_set_kernels_1bit(int ne00, int typeA, int typeB, std::array; expected_Btype = GGML_TYPE_Q8_K128; break; + case GGML_TYPE_IQ1_M: + if (ne00%QK_K != 0) return false; + IQK_SET_MUL_MAT_FUNCTIONS(mul_mat_iq1_m_q8_K, funcs); + func16 = mul_mat_iq1_m_q8_K<16>; + expected_Btype = GGML_TYPE_Q8_K; + break; case GGML_TYPE_IQ1_M_R4: if (ne00%128 != 0) return false; IQK_SET_MUL_MAT_FUNCTIONS(mul_mat_iq1_m_r4_q8_0, funcs); diff --git a/ggml/src/iqk/iqk_mul_mat.cpp b/ggml/src/iqk/iqk_mul_mat.cpp index 75ca87df..d7a5c1d8 100644 --- a/ggml/src/iqk/iqk_mul_mat.cpp +++ b/ggml/src/iqk/iqk_mul_mat.cpp @@ -279,7 +279,7 @@ struct MulMat { case GGML_TYPE_Q5_K : return nrc_y >= 32 ? GGML_TYPE_Q8_1 : type; case GGML_TYPE_Q6_K : return nrc_y >= 64 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ1_S : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; - case GGML_TYPE_IQ1_M : return nrc_y >= 8 ? GGML_TYPE_Q8_K_R8 : type; + case GGML_TYPE_IQ1_M : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ2_XXS: return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ2_XS : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; case GGML_TYPE_IQ2_S : return nrc_y >= 32 ? GGML_TYPE_Q8_K_R8 : type; From f989fb03bd12752ad6e93717ca4bd298d5001d99 Mon Sep 17 00:00:00 2001 From: Kawrakow Date: Sun, 20 Jul 2025 10:05:23 +0200 Subject: [PATCH 38/63] Adding IQ1_KT - 1.75 bpw SOTA quants (#616) * iq1_kt: basics * iq1_kt: CUDA dequantize Testing with LlaMA-3.1-8B-Instruct, we get almost the same PPL as iq2_xxs, so about 0.2 bpw fewer bits for the same quality. * iq1_kt: CUDA MMQ * iq1_kt: CUDA MMVQ * iq1_kt: AVX2 GEMM/GEMV * iq1_kt: convert/repack to q8_0_r8 (AVX2) * iq1_kt: slightly faster GEMV 18.6 t/s -> 19.4 t/s * iq1_kt: NEON GEMM/GEMV Pathetic as usual * iq1_kt: slightly faster NEON - still pathetic * iq1_kt: tiny bit better GEMV on NEON * iq1_kt: convert/repack to q8_0_r8 (NEON) * iq1_kt: very slightly faster convert/repack to q8_0_r8 on NEON * Adding frgotten file * iq1_kt: add to constants.py --------- Co-authored-by: Iwan Kawrakow --- examples/quantize/quantize.cpp | 1 + ggml/include/ggml.h | 2 + ggml/src/ggml-common.h | 7 + ggml/src/ggml-cuda.cu | 1 + ggml/src/ggml-cuda/common.cuh | 7 + ggml/src/ggml-cuda/convert.cu | 31 ++ ggml/src/ggml-cuda/iqk_mmvq.cu | 41 ++ ggml/src/ggml-cuda/iqk_mmvq.cuh | 5 + ggml/src/ggml-cuda/mmq.cu | 4 + ggml/src/ggml-cuda/mmq.cuh | 6 +- ggml/src/ggml-cuda/mmvq.cu | 4 + .../template-instances/mmq-instance-iq1_kt.cu | 81 ++++ ggml/src/ggml-quants.c | 1 + ggml/src/ggml.c | 26 ++ ggml/src/iqk/iqk_gemm_ktquants.cpp | 431 +++++++++++++++++- ggml/src/iqk/iqk_mul_mat.cpp | 5 + ggml/src/iqk/iqk_quantize.cpp | 265 +++++++++++ ggml/src/iqk/iqk_quantize.h | 6 + gguf-py/gguf/constants.py | 2 + include/llama.h | 1 + src/llama.cpp | 9 +- 21 files changed, 930 insertions(+), 6 deletions(-) create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_kt.cu diff --git a/examples/quantize/quantize.cpp b/examples/quantize/quantize.cpp index 7dd02313..3de7bc20 100644 --- a/examples/quantize/quantize.cpp +++ b/examples/quantize/quantize.cpp @@ -75,6 +75,7 @@ static const std::vector QUANT_OPTIONS = { { "IQ2_K", LLAMA_FTYPE_MOSTLY_IQ2_K, " 2.375 bpw non-linear quantization",}, { "IQ2_K_R4", LLAMA_FTYPE_MOSTLY_IQ2_K_R4, "IQ2_K repacked",}, { "IQ2_KS", LLAMA_FTYPE_MOSTLY_IQ2_KS, " 2.1875 bpw non-linear quantization",}, + { "IQ1_KT", LLAMA_FTYPE_MOSTLY_IQ1_KT, " 1.75 bpw trellis quantization", }, { "IQ2_KT", LLAMA_FTYPE_MOSTLY_IQ2_KT, " 2.125 bpw trellis quantization", }, { "IQ2_KL", LLAMA_FTYPE_MOSTLY_IQ2_KL, " 2.69 bpw non-linear quantization", }, { "IQ3_KS", LLAMA_FTYPE_MOSTLY_IQ3_KS, " 3.19 bpw non-linear quantization", }, diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index 644a82b2..5b90c9a5 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -436,6 +436,7 @@ extern "C" { GGML_TYPE_IQ4_KT = 155, GGML_TYPE_IQ3_KS = 156, GGML_TYPE_IQ2_KL = 157, + GGML_TYPE_IQ1_KT = 158, GGML_TYPE_Q4_0_R8 = 202, GGML_TYPE_Q5_0_R4 = 206, @@ -530,6 +531,7 @@ extern "C" { GGML_FTYPE_MOSTLY_IQ4_KT = 144, // except 1d tensors GGML_FTYPE_MOSTLY_IQ3_KS = 145, // except 1d tensors GGML_FTYPE_MOSTLY_IQ2_KL = 146, // except 1d tensors + GGML_FTYPE_MOSTLY_IQ1_KT = 147, // except 1d tensors // GGML_FTYPE_MOSTLY_Q4_0_R8 = 202, // except 1d tensors GGML_FTYPE_MOSTLY_Q8_0_R8 = 207, // except 1d tensors diff --git a/ggml/src/ggml-common.h b/ggml/src/ggml-common.h index 6dc439b8..1dc1ff6e 100644 --- a/ggml/src/ggml-common.h +++ b/ggml/src/ggml-common.h @@ -629,6 +629,13 @@ typedef struct { } block_iq2_ks; static_assert(sizeof(block_iq2_ks) == sizeof(uint16_t) + QK_K/64 + QK_K/4, "wrong iq2_ks block size/padding"); +typedef struct { + uint8_t sh[QK_K/32]; // 4-bit scales + 13th bits for groups of 8 + uint8_t ql[QK_K/8]; // low 8 bits for groups of 8 + uint8_t qh[QK_K/16]; // high 4 bits for groups of 8 +} block_iq1_kt; +static_assert(sizeof(block_iq1_kt) == QK_K/8 + QK_K/16 + QK_K/32, "wrong iq1_kt block size/padding"); + typedef struct { uint8_t scales[QK_K/64]; uint8_t ql[QK_K/4]; diff --git a/ggml/src/ggml-cuda.cu b/ggml/src/ggml-cuda.cu index b33c952b..7fee71d8 100644 --- a/ggml/src/ggml-cuda.cu +++ b/ggml/src/ggml-cuda.cu @@ -3506,6 +3506,7 @@ GGML_CALL static bool ggml_backend_cuda_supports_op(ggml_backend_t backend, cons case GGML_TYPE_IQ5_KS: case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: diff --git a/ggml/src/ggml-cuda/common.cuh b/ggml/src/ggml-cuda/common.cuh index 38b52fd0..15485f60 100644 --- a/ggml/src/ggml-cuda/common.cuh +++ b/ggml/src/ggml-cuda/common.cuh @@ -571,6 +571,13 @@ struct ggml_cuda_type_traits { static constexpr int qi = QI4_XS; }; +template<> +struct ggml_cuda_type_traits { + static constexpr int qk = QK_K; + static constexpr int qr = QR4_XS; + static constexpr int qi = QI4_XS; +}; + template<> struct ggml_cuda_type_traits { static constexpr int qk = QK_K; diff --git a/ggml/src/ggml-cuda/convert.cu b/ggml/src/ggml-cuda/convert.cu index c8e02a83..8c03ae1b 100644 --- a/ggml/src/ggml-cuda/convert.cu +++ b/ggml/src/ggml-cuda/convert.cu @@ -358,6 +358,26 @@ float __device__ __forceinline__ trellis_next(uint32_t& val) { return (float)(h[0]+h[1]); } +template +static __global__ void dequantize_block_iq1_kt(const void * __restrict__ vx, dst_t * __restrict__ yy, int64_t n_per_row, int64_t row_size) { + + int64_t ii = blockIdx.x; + int64_t row = (QK_K * ii) / n_per_row; + const char * cx = (const char *)vx + row * row_size; + float scale = *(const float *)cx; + const block_iq1_kt * x = (const block_iq1_kt *)(cx + sizeof(float)); + const int64_t i = ii - (row*n_per_row)/QK_K; + + const int64_t tid = threadIdx.x; + const int64_t ib = tid; // 0...31 + dst_t * y = yy + ii*QK_K + 8*ib; + uint32_t idx = (x[i].ql[ib] | ((x[i].qh[ib%16] << (8 - 4*(ib/16))) & 0xf00) | ((x[i].sh[ib/4] << (8 - (ib%4))) & 0x1000)) + 4096; + const float dl = scale * iq4k_values[x[i].sh[ib/4] & 0xf]; + for (int j = 0; j < 8; ++j) { + y[j] = dl * trellis_next_int(idx); + } +} + template static __global__ void dequantize_block_iq2_kt(const void * __restrict__ vx, dst_t * __restrict__ yy, int64_t n_per_row, int64_t row_size) { @@ -1505,6 +1525,13 @@ static void dequantize_row_iq2_xxs_cuda(const void * vx, dst_t * y, const int64_ dequantize_block_iq2_xxs<<>>(vx, y); } +template +static void dequantize_row_iq1_kt_cuda(const void * vx, dst_t * y, const int64_t nrows, const int64_t n_per_row, cudaStream_t stream) { + const int64_t k = nrows * n_per_row; + const int nb = k / QK_K; + dequantize_block_iq1_kt<<>>(vx, y, n_per_row, ggml_row_size(GGML_TYPE_IQ1_KT, n_per_row)); +} + template static void dequantize_row_iq2_kt_cuda(const void * vx, dst_t * y, const int64_t nrows, const int64_t n_per_row, cudaStream_t stream) { const int64_t k = nrows * n_per_row; @@ -1888,6 +1915,8 @@ to_fp16_cuda_t ggml_get_to_fp16_cuda(ggml_type type) { return dequantize_row_q6_K_cuda; case GGML_TYPE_IQ2_XXS: return dequantize_row_iq2_xxs_cuda; + case GGML_TYPE_IQ1_KT: + return dequantize_row_iq1_kt_cuda; case GGML_TYPE_IQ2_KT: return dequantize_row_iq2_kt_cuda; case GGML_TYPE_IQ3_KT: @@ -1987,6 +2016,8 @@ to_fp32_cuda_t ggml_get_to_fp32_cuda(ggml_type type) { return dequantize_row_q6_K_cuda; case GGML_TYPE_IQ2_XXS: return dequantize_row_iq2_xxs_cuda; + case GGML_TYPE_IQ1_KT: + return dequantize_row_iq1_kt_cuda; case GGML_TYPE_IQ2_KT: return dequantize_row_iq2_kt_cuda; case GGML_TYPE_IQ3_KT: diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cu b/ggml/src/ggml-cuda/iqk_mmvq.cu index a669390d..c7f5dfb4 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cu +++ b/ggml/src/ggml-cuda/iqk_mmvq.cu @@ -443,6 +443,39 @@ __device__ __forceinline__ void vec_dot_iq4_kt_q8_1( *result += dl * __low2float(bq8_1[ib32].ds) * sumi; } +__device__ __forceinline__ void vec_dot_iq1_kt_q8_1( + const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iqs, float * result) { + + constexpr uint32_t ka = 0xCBAC1FED; + constexpr uint32_t km = 0x3f3f3f3f; + + float scale = *(const float *)vbq; + const block_iq1_kt * bq1 = (const block_iq1_kt *)((const char *)vbq + sizeof(float)) + kbx; + + // iqs is 0...28 + const int ib32 = iqs/4; + const int32_t * q8 = (const int *)bq8_1[ib32].qs; + const int ls = iq4k_values[bq1->sh[ib32] & 0xf]; + const float dl = scale * ls; + int sumi = 0; + for (int j = 0; j < 4; ++j) { + uint32_t val = bq1->ql[4*ib32+j] + 4096 + ((bq1->qh[4*(ib32%4)+j] << (8 - 4*(ib32/4))) & 0xf00) + ((bq1->sh[ib32] << (8 - j)) & 0x1000); + int v4 = 0; + for (int k = 0; k < 4; ++k) { + val *= ka; + v4 |= (ggml_cuda_dp4a(val & km, 0x01010101, -126) & 0xff) << 8*k; + } + sumi = ggml_cuda_dp4a(v4, q8[2*j+0], sumi); + v4 = 0; + for (int k = 0; k < 4; ++k) { + val *= ka; + v4 |= (ggml_cuda_dp4a(val & km, 0x01010101, -126) & 0xff) << 8*k; + } + sumi = ggml_cuda_dp4a(v4, q8[2*j+1], sumi); + } + *result += dl * __low2float(bq8_1[ib32].ds) * sumi; +} + __device__ __forceinline__ void vec_dot_iq2_kt_q8_1( const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iqs, float * result) { @@ -1350,6 +1383,14 @@ void mul_mat_vec_iq4_kt_q8_1_cuda( iqk_mul_mat_vec_q_cuda(vx, vy, dst, ids_data, ncols_x, nrows_x, nrows_y, ncols_y, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); } +void mul_mat_vec_iq1_kt_q8_1_cuda( + const void * vx, const void * vy, float * dst, const char * ids_data, + const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, + const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, int64_t ids_nb0, cudaStream_t stream) { + + iqk_mul_mat_vec_q_cuda(vx, vy, dst, ids_data, ncols_x, nrows_x, nrows_y, ncols_y, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); +} + void mul_mat_vec_iq2_kt_q8_1_cuda( const void * vx, const void * vy, float * dst, const char * ids_data, const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, diff --git a/ggml/src/ggml-cuda/iqk_mmvq.cuh b/ggml/src/ggml-cuda/iqk_mmvq.cuh index d14c3541..5d62d02e 100644 --- a/ggml/src/ggml-cuda/iqk_mmvq.cuh +++ b/ggml/src/ggml-cuda/iqk_mmvq.cuh @@ -111,6 +111,11 @@ void mul_mat_vec_iq1_m_r4_q8_1_cuda( const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, const int64_t ids_nb0, cudaStream_t stream); +void mul_mat_vec_iq1_kt_q8_1_cuda( + const void * vx, const void * vy, float * dst, const char * ids_data, + const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, + const int ne2, const uint64_t nb02, const uint64_t nb12, const uint64_t nb2, const int64_t ids_nb0, cudaStream_t stream); + void mul_mat_vec_iq2_kt_q8_1_cuda( const void * vx, const void * vy, float * dst, const char * ids_data, const int ncols_x, const int nrows_x, const int nrows_y, const int ncols_y, const int nrows_dst, diff --git a/ggml/src/ggml-cuda/mmq.cu b/ggml/src/ggml-cuda/mmq.cu index cde5d044..d417fdc0 100644 --- a/ggml/src/ggml-cuda/mmq.cu +++ b/ggml/src/ggml-cuda/mmq.cu @@ -109,6 +109,9 @@ void ggml_cuda_op_mul_mat_q( case GGML_TYPE_IQ4_KT: mul_mat_q_case(ctx, args, stream); break; + case GGML_TYPE_IQ1_KT: + mul_mat_q_case(ctx, args, stream); + break; case GGML_TYPE_IQ2_KT: mul_mat_q_case(ctx, args, stream); break; @@ -211,6 +214,7 @@ bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11) { case GGML_TYPE_IQ5_KS: case GGML_TYPE_IQ5_KS_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: diff --git a/ggml/src/ggml-cuda/mmq.cuh b/ggml/src/ggml-cuda/mmq.cuh index 21b50082..aaf02fab 100644 --- a/ggml/src/ggml-cuda/mmq.cuh +++ b/ggml/src/ggml-cuda/mmq.cuh @@ -100,6 +100,7 @@ static mmq_q8_1_ds_layout mmq_get_q8_1_ds_layout(const ggml_type type_x) { case GGML_TYPE_IQ5_KS: case GGML_TYPE_IQ5_KS_R4: case GGML_TYPE_IQ6_K: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -218,6 +219,7 @@ static constexpr __host__ __device__ tile_x_sizes mmq_get_dp4a_tile_x_sizes(ggml case GGML_TYPE_IQ5_K : return MMQ_DP4A_TXS_Q8_0_16; case GGML_TYPE_IQ5_K_R4: return MMQ_DP4A_TXS_Q8_0_16; case GGML_TYPE_IQ6_K : return MMQ_DP4A_TXS_Q8_0_16; + case GGML_TYPE_IQ1_KT : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ2_KT : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ3_KT : return MMQ_DP4A_TXS_Q8_0; case GGML_TYPE_IQ4_KT : return MMQ_DP4A_TXS_Q8_0; @@ -275,6 +277,7 @@ static constexpr __host__ __device__ int mmq_get_mma_tile_x_k(ggml_type type) { case GGML_TYPE_IQ5_K : return MMQ_MMA_TILE_X_K_Q3_K; case GGML_TYPE_IQ5_K_R4: return MMQ_MMA_TILE_X_K_Q3_K; case GGML_TYPE_IQ6_K : return MMQ_MMA_TILE_X_K_Q3_K; + case GGML_TYPE_IQ1_KT : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ2_KT : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ3_KT : return MMQ_MMA_TILE_X_K_Q8_0; case GGML_TYPE_IQ4_KT : return MMQ_MMA_TILE_X_K_Q8_0; @@ -4176,9 +4179,10 @@ extern DECL_MMQ_CASE(GGML_TYPE_IQ5_K_R4); extern DECL_MMQ_CASE(GGML_TYPE_IQ5_KS); extern DECL_MMQ_CASE(GGML_TYPE_IQ6_K); extern DECL_MMQ_CASE(GGML_TYPE_IQ1_S_R4); -extern DECL_MMQ_CASE(GGML_TYPE_IQ4_KT); +extern DECL_MMQ_CASE(GGML_TYPE_IQ1_KT); extern DECL_MMQ_CASE(GGML_TYPE_IQ2_KT); extern DECL_MMQ_CASE(GGML_TYPE_IQ3_KT); +extern DECL_MMQ_CASE(GGML_TYPE_IQ4_KT); // ------------------------------------------------------------------------------------------------------------------------- diff --git a/ggml/src/ggml-cuda/mmvq.cu b/ggml/src/ggml-cuda/mmvq.cu index d0746031..012b3e5e 100644 --- a/ggml/src/ggml-cuda/mmvq.cu +++ b/ggml/src/ggml-cuda/mmvq.cu @@ -533,6 +533,9 @@ static void ggml_cuda_op_mul_mat_vec_q_impl(ggml_backend_cuda_context & ctx, ggm case GGML_TYPE_IQ4_KSS: mul_mat_vec_iq4_kss_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); break; + case GGML_TYPE_IQ1_KT: + mul_mat_vec_iq1_kt_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); + break; case GGML_TYPE_IQ2_KT: mul_mat_vec_iq2_kt_q8_1_cuda(src0_dd_i, src1_ddq_i, dst_dd_i, ids_data, ne00, row_diff, src1_padded_row_size, src1_ncols, nrows_dst, ne2, nb02, nb12, nb2, ids_nb0, stream); break; @@ -704,6 +707,7 @@ bool ggml_cuda_mmvq_type_supported(ggml_type src0_type) { case GGML_TYPE_IQ5_KS_R4: case GGML_TYPE_IQ1_S_R4: case GGML_TYPE_IQ1_M_R4: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: diff --git a/ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_kt.cu b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_kt.cu new file mode 100644 index 00000000..1a3590e5 --- /dev/null +++ b/ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_kt.cu @@ -0,0 +1,81 @@ +// This file has been autogenerated by generate_cu_files.py, do not edit manually. + +#include "../mmq.cuh" + +template static __device__ __forceinline__ void load_tiles_iq1_kt( + const char * __restrict__ x, int * __restrict__ x_tile, const int & kbx0, const int & i_max, const int & stride) { + + constexpr uint32_t ka = 0xCBAC1FED; + constexpr uint32_t km = 0x3f3f3f3f; + +#ifdef INT8_MMA_AVAILABLE + int * x_qs = (int *) x_tile; + float * x_df = (float *) (x_qs + WARP_SIZE*2); +#else + constexpr tile_x_sizes txs = mmq_get_dp4a_tile_x_sizes(GGML_TYPE_IQ4_XS, mmq_y); + int * x_qs = (int *) x_tile; + float * x_df = (float *) (x_qs + txs.qs); +#endif // INT8_MMA_AVAILABLE + + const int kqsx = threadIdx.x; + +#pragma unroll + for (int i0 = 0; i0 < mmq_y; i0 += nwarps) { + int i = i0 + threadIdx.y; + + if (need_check) { + i = min(i, i_max); + } + + const block_iq1_kt * bxi = (const block_iq1_kt *)(x + i*stride + sizeof(float)) + kbx0; + + int ib32 = kqsx/4; + int j = kqsx%4; + uint32_t val = bxi->ql[kqsx] + ((bxi->qh[kqsx%16] << (8 - 4*(kqsx/16))) & 0xf00) + ((bxi->sh[kqsx/4] << (8 - (kqsx%4))) & 0x1000) + 4096; + int2 v = {0, 0}; + for (int k = 0; k < 4; ++k) { + val *= ka; + v.x |= (ggml_cuda_dp4a(val & km, 0x01010101, -126) & 0xff) << 8*k; + } + for (int k = 0; k < 4; ++k) { + val *= ka; + v.y |= (ggml_cuda_dp4a(val & km, 0x01010101, -126) & 0xff) << 8*k; + } +#ifdef INT8_MMA_AVAILABLE + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*ib32 + 2*j + 0] = v.x; + x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + 8*ib32 + 2*j + 1] = v.y; +#else + x_qs[i*(2*WARP_SIZE + 1) + 8*ib32 + 2*j + 0] = v.x; + x_qs[i*(2*WARP_SIZE + 1) + 8*ib32 + 2*j + 1] = v.y; +#endif // INT8_MMA_AVAILABLE + } + +#pragma unroll + for (int i0 = 0; i0 < mmq_y; i0 += nwarps * 4) { + int i = i0 + threadIdx.y * 4 + threadIdx.x / (WARP_SIZE/4); + + if (need_check) { + i = min(i, i_max); + } + + const float * dptr = (const float *)(x + i*stride); + const float d = dptr[0]; + const block_iq1_kt * bxi = (const block_iq1_kt *)(dptr + 1) + kbx0; + const int ls = iq4k_values[bxi->sh[threadIdx.x % 8] & 0xf]; + +#ifdef INT8_MMA_AVAILABLE + x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + threadIdx.x % 8] = d * ls; +#else + x_df[i*(WARP_SIZE/4) + i/4 + threadIdx.x % 8] = d * ls; +#endif // INT8_MMA_AVAILABLE + } +} + +template +struct mmq_type_traits { + static constexpr load_tiles_mmq_t load_tiles = load_tiles_iq1_kt; + static constexpr vec_dot_mmq_t vec_dot_mma = vec_dot_q8_0_q8_1_mma; + static constexpr vec_dot_mmq_t vec_dot_dp4a = vec_dot_q8_0_q8_1_dp4a; +}; + +DECL_MMQ_CASE(GGML_TYPE_IQ1_KT); diff --git a/ggml/src/ggml-quants.c b/ggml/src/ggml-quants.c index e18cee73..e49417af 100644 --- a/ggml/src/ggml-quants.c +++ b/ggml/src/ggml-quants.c @@ -15421,6 +15421,7 @@ bool ggml_validate_row_data(enum ggml_type type, const void * data, size_t nbyte case GGML_TYPE_Q6_0: break; case GGML_TYPE_IQ2_K: break; case GGML_TYPE_IQ2_KS: break; + case GGML_TYPE_IQ1_KT: break; case GGML_TYPE_IQ2_KT: break; case GGML_TYPE_IQ3_KT: break; case GGML_TYPE_IQ4_KT: break; diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index b3982538..5aec6b0d 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -1587,6 +1587,23 @@ static const ggml_type_traits_t type_traits[GGML_TYPE_COUNT] = { .nrows = 1, .row_meta_size = 2, }, + [GGML_TYPE_IQ1_KT] = { + .type_name = "iq1_kt", + .blck_size = QK_K, + .type_size = sizeof(block_iq1_kt), + .is_quantized = true, + .to_float = (ggml_to_float_t) dequantize_row_iq1_kt, + .from_float = quantize_row_iq1_kt, + .from_float_ref = (ggml_from_float_t)quantize_row_iq1_kt_ref, + .vec_dot = vec_dot_iq1_kt_q8_k, +#if defined __AVX2__ + .vec_dot_type = GGML_TYPE_Q8_2_X4, +#else + .vec_dot_type = GGML_TYPE_Q8_0_X4, +#endif + .nrows = 1, + .row_meta_size = 4, + }, [GGML_TYPE_IQ2_KT] = { .type_name = "iq2_kt", .blck_size = QK_K, @@ -4600,6 +4617,7 @@ enum ggml_type ggml_ftype_to_ggml_type(enum ggml_ftype ftype) { case GGML_FTYPE_MOSTLY_IQ2_K: wtype = GGML_TYPE_IQ2_K; break; case GGML_FTYPE_MOSTLY_IQ2_K_R4: wtype = GGML_TYPE_IQ2_K_R4; break; case GGML_FTYPE_MOSTLY_IQ2_KS: wtype = GGML_TYPE_IQ2_KS; break; + case GGML_FTYPE_MOSTLY_IQ1_KT: wtype = GGML_TYPE_IQ1_KT; break; case GGML_FTYPE_MOSTLY_IQ2_KT: wtype = GGML_TYPE_IQ2_KT; break; case GGML_FTYPE_MOSTLY_IQ3_KT: wtype = GGML_TYPE_IQ3_KT; break; case GGML_FTYPE_MOSTLY_IQ4_KT: wtype = GGML_TYPE_IQ4_KT; break; @@ -11379,6 +11397,7 @@ static void ggml_compute_forward_add( case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -11858,6 +11877,7 @@ static void ggml_compute_forward_add1( case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -12034,6 +12054,7 @@ static void ggml_compute_forward_acc( case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -15537,6 +15558,7 @@ static void ggml_compute_forward_out_prod( case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -15953,6 +15975,7 @@ static void ggml_compute_forward_set( case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -16275,6 +16298,7 @@ static void ggml_compute_forward_get_rows( case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -16914,6 +16938,7 @@ static void ggml_compute_forward_clamp( case GGML_TYPE_IQ2_K: case GGML_TYPE_IQ2_K_R4: case GGML_TYPE_IQ2_KS: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -23989,6 +24014,7 @@ size_t ggml_quantize_chunk( case GGML_TYPE_IQ2_K: result = quantize_iq2_k (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ2_K_R4:result = quantize_iq2_k_r4(src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ2_KS: result = quantize_iq2_ks (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; + case GGML_TYPE_IQ1_KT: result = quantize_iq1_kt (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ2_KT: result = quantize_iq2_kt (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ3_KT: result = quantize_iq3_kt (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; case GGML_TYPE_IQ4_KT: result = quantize_iq4_kt (src + start, (char *) dst + start_row * row_size, nrows, n_per_row, imatrix); break; diff --git a/ggml/src/iqk/iqk_gemm_ktquants.cpp b/ggml/src/iqk/iqk_gemm_ktquants.cpp index 19c30e2a..57702199 100644 --- a/ggml/src/iqk/iqk_gemm_ktquants.cpp +++ b/ggml/src/iqk/iqk_gemm_ktquants.cpp @@ -199,6 +199,56 @@ struct Trellis3 { #else auto dot = _mm256_maddubs_epi16(aux[i], _mm256_set1_epi32(0x01010101)); aux[i] = _mm256_add_epi32(offset, _mm256_madd_epi16(dot, _mm256_set1_epi16(1))); +#endif + } + for (int k = 0; k < 4; ++k) { + auto v1 = _mm256_packs_epi32(aux[4*k+0], aux[4*k+1]); + auto v2 = _mm256_packs_epi32(aux[4*k+2], aux[4*k+3]); + result[k] = _mm256_permutevar8x32_epi32(_mm256_packs_epi16(v1, v2), shuffle); + } + if constexpr (is_abs) { + for (int k = 0; k < 4; ++k) { + result[k] = _mm256_sign_epi8(result[k], result[k]); + } + } + } + IQK_ALWAYS_INLINE inline void next_128(__m256i val, __m256i * result) const { + // Even though we only have 16 vector registers nn AVX2, this is still faster + __m256i aux[16]; + __m256i tmp[2]; + tmp[0] = _mm256_cvtepu16_epi32(_mm256_castsi256_si128(val)); + tmp[1] = _mm256_cvtepu16_epi32(_mm256_extracti128_si256(val, 1)); + for (int k = 0; k < 2; ++k) { + auto vl = _mm256_castsi256_si128(tmp[k]); + auto v = MM256_SET_M128I(vl, vl); + aux[8*k+0] = _mm256_shuffle_epi32(v, 0x00); + aux[8*k+1] = _mm256_shuffle_epi32(v, 0x55); + aux[8*k+2] = _mm256_shuffle_epi32(v, 0xaa); + aux[8*k+3] = _mm256_shuffle_epi32(v, 0xff); + auto vh = _mm256_extracti128_si256(tmp[k], 1); + v = MM256_SET_M128I(vh, vh); + aux[8*k+4] = _mm256_shuffle_epi32(v, 0x00); + aux[8*k+5] = _mm256_shuffle_epi32(v, 0x55); + aux[8*k+6] = _mm256_shuffle_epi32(v, 0xaa); + aux[8*k+7] = _mm256_shuffle_epi32(v, 0xff); + } + for (int i = 0; i < 16; ++i) { + aux[i] = _mm256_mullo_epi32(aux[i], mka); + } + auto mask = _mm256_set1_epi32(0x3f3f3f3f); + for (int i = 0; i < 16; ++i) { + aux[i] = _mm256_and_si256(aux[i], mask); + } + auto offset = _mm256_set1_epi32(-126); +#if defined(__AVX512F__) && defined(__AVX512VNNI__) && defined(__AVX512VL__) + auto m1 = _mm256_set1_epi32(0x01010101); +#endif + for (int i = 0; i < 16; ++i) { +#if defined(__AVX512F__) && defined(__AVX512VNNI__) && defined(__AVX512VL__) + aux[i] = _mm256_dpbusd_epi32(offset, aux[i], m1); +#else + auto dot = _mm256_maddubs_epi16(aux[i], _mm256_set1_epi32(0x01010101)); + aux[i] = _mm256_add_epi32(offset, _mm256_madd_epi16(dot, _mm256_set1_epi16(1))); #endif } for (int k = 0; k < 4; ++k) { @@ -463,6 +513,148 @@ void mul_mat_iq2_kt_F32_T(int n, const void * vx, size_t bx, const DataInfo& inf } } +void iqk_dequantize_iq1_kt_q80_r8(int n, const void * vx, size_t bx, void * vy, int nrc_x) { + GGML_ASSERT(n%QK_K == 0); + GGML_ASSERT(nrc_x%8 == 0); + const int nb = n/QK_K; + + Trellis3 trellis; + + auto values = _mm_loadu_si128((const __m128i *)iq4k_values); + + block_q8_0_r8 * y = (block_q8_0_r8 *)vy; + + const block_iq1_kt * x8[8]; + float dkt[8]; + float ls[8]; + float ls_all[64]; + uint32_t idx[8]; + + for (int ix = 0; ix < nrc_x; ix += 8) { + for (int k = 0; k < 8; ++k) { + const float * dptr = (const float *)((const char*)vx + (ix+k)*bx); + dkt[k] = dptr[0]; + x8[k] = (const block_iq1_kt *)(dptr + 1); + } + auto vd = _mm256_loadu_ps(dkt); + + for (int i = 0; i < nb; ++i) { + for (int k = 0; k < 8; ++k) { + auto sh = _mm_loadl_epi64((const __m128i *)x8[k][i].sh); + auto s8 = _mm_shuffle_epi8(values, _mm_and_si128(sh, _mm_set1_epi8(0xf))); + auto s32 = _mm256_cvtepi8_epi32(s8); + _mm256_storeu_ps(ls_all + 8*k, _mm256_cvtepi32_ps(s32)); + } + for (int ib = 0; ib < QK_K/32; ++ib) { + for (int k = 0; k < 8; ++k) ls[k] = ls_all[8*k+ib]; + auto scales = _mm256_mul_ps(vd, _mm256_loadu_ps(ls)); + _mm_storeu_si128((__m128i *)y[ib].d, _mm256_cvtps_ph(scales, _MM_FROUND_TO_NEAREST_INT)); + for (int j = 0; j < 4; ++j) { + int jj = 4*ib + j; + for (int k = 0; k < 8; ++k) { + idx[k] = (x8[k][i].ql[jj] | ((x8[k][i].qh[jj%16] << (8 - 4*(jj/16))) & 0xf00) | ((x8[k][i].sh[jj/4] << (8 - (jj%4))) & 0x1000)) + 4096; + } + __m256i packed[2]; + trellis.next64(idx, packed); + _mm256_storeu_si256((__m256i *)y[ib].qs+2*j+0, packed[0]); + _mm256_storeu_si256((__m256i *)y[ib].qs+2*j+1, packed[1]); + } + } + y += 8; // = QK_K/32; + } + } +} + +template +void mul_mat_iq1_kt_q8_2_x4_T(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { + assert(n%QK_K == 0); + const int nb = n/QK_K; + + Trellis3 trellis; + + auto values = _mm_loadu_si128((const __m128i *)iq4k_values); + + constexpr int k_acc = nrc_y; + + __m256 accd[k_acc]; + const block_q8_2_x4 * y[nrc_y]; + for (int iy = 0; iy < nrc_y; ++iy) { + y[iy] = (const block_q8_2_x4 *)info.src1_row(iy); + } + + __m256i xv[4], dot[4]; + __m256 scales[2]; + + auto sum_4 = [&dot] () { + // dot[k] has 8 values from block k + // 0 1 0 1 0 1 0 1 + dot[0] = _mm256_add_epi32(_mm256_unpacklo_epi32(dot[0], dot[1]), _mm256_unpackhi_epi32(dot[0], dot[1])); + // 2 3 2 3 2 3 2 3 + dot[2] = _mm256_add_epi32(_mm256_unpacklo_epi32(dot[2], dot[3]), _mm256_unpackhi_epi32(dot[2], dot[3])); + // 0 1 2 3 0 1 2 3 + dot[0] = _mm256_add_epi32(_mm256_unpacklo_epi64(dot[0], dot[2]), _mm256_unpackhi_epi64(dot[0], dot[2])); + return _mm256_cvtepi32_ps(dot[0]); + }; + + auto compute_dot = [&dot, &xv] (const int8_t * y) { + for (int k = 0; k < 4; ++k) { + auto yv = _mm256_loadu_si256((const __m256i *)y + k); +#ifdef HAVE_FANCY_SIMD + //dot[k] = _mm256_dpbusd_epi32(_mm256_setzero_si256(), xv[k], yv); + dot[k] = _mm256_dpbusd_epi32(_mm256_setzero_si256(), _mm256_sign_epi8(xv[k], xv[k]), _mm256_sign_epi8(yv, xv[k])); +#else + auto p = _mm256_maddubs_epi16(_mm256_sign_epi8(xv[k], xv[k]), _mm256_sign_epi8(yv, xv[k])); + dot[k] = _mm256_madd_epi16(p, _mm256_set1_epi16(1)); +#endif + } + }; + + __m256i idx[2]; + + for (int ix = 0; ix < nrc_x; ++ix) { + const float * dptr = (const float *)((const char*)vx + ix*bx); + auto d = _mm256_set1_ps(dptr[0]); + const block_iq1_kt * x = (const block_iq1_kt *)(dptr + 1); + + for (int iy = 0; iy < k_acc; ++iy) accd[iy] = _mm256_setzero_ps(); + + for (int i = 0; i < nb; ++i) { + auto sh = _mm_loadl_epi64((const __m128i *)x[i].sh); + auto s32 = _mm256_cvtepi8_epi32(_mm_shuffle_epi8(values, _mm_and_si128(sh, _mm_set1_epi8(0xf)))); + auto all_scales = _mm256_mul_ps(d, _mm256_cvtepi32_ps(s32)); + auto scales_l = _mm256_castps256_ps128(all_scales); + auto scales_h = _mm256_extractf128_ps(all_scales, 1); + scales[0] = _mm256_set_m128(scales_l, scales_l); + scales[1] = _mm256_set_m128(scales_h, scales_h); + auto qs8l = _mm_loadu_si128((const __m128i *)x[i].ql+0); + auto qs8h = _mm_loadu_si128((const __m128i *)x[i].ql+1); + auto qh16 = _mm256_cvtepu8_epi16(_mm_loadu_si128((const __m128i *)x[i].qh)); + idx[0] = _mm256_or_si256(_mm256_cvtepu8_epi16(qs8l), _mm256_and_si256(_mm256_set1_epi16(0xf00), _mm256_slli_epi16(qh16, 8))); + idx[1] = _mm256_or_si256(_mm256_cvtepu8_epi16(qs8h), _mm256_and_si256(_mm256_set1_epi16(0xf00), _mm256_slli_epi16(qh16, 4))); + idx[0] = _mm256_add_epi16(idx[0], _mm256_set1_epi16(4096)); + idx[1] = _mm256_add_epi16(idx[1], _mm256_set1_epi16(4096)); + auto sh32 = _mm256_and_si256(_mm256_cvtepu8_epi32(sh), _mm256_set1_epi32(0xf0)); + sh32 = _mm256_and_si256(_mm256_mullo_epi32(sh32, _mm256_set1_epi32(0x01020408)), _mm256_set1_epi8(-128)); + idx[0] = _mm256_add_epi16(idx[0], _mm256_slli_epi16(_mm256_cvtepu8_epi16(_mm256_castsi256_si128(sh32)), 5)); + idx[1] = _mm256_add_epi16(idx[1], _mm256_slli_epi16(_mm256_cvtepu8_epi16(_mm256_extracti128_si256(sh32, 1)), 5)); + for (int i128 = 0; i128 < 2; ++i128) { + trellis.next_128(idx[i128], xv); + for (int iy = 0; iy < nrc_y; ++iy) { + const block_q8_2_x4& yb = y[iy][2*i+i128]; + auto dy4 = _mm_castsi128_ps(_mm_slli_epi32(_mm_cvtepu16_epi32(_mm_loadl_epi64((const __m128i *)yb.d)), 16)); + auto dy8 = _mm256_mul_ps(scales[i128], _mm256_set_m128(dy4, dy4)); + compute_dot(yb.qs); + accd[iy] = _mm256_fmadd_ps(dy8, sum_4(), accd[iy]); + } + } + } + + for (int iy = 0; iy < nrc_y; ++iy) { + info.store(ix, iy, hsum_float_8(accd[iy])); + } + } +} + template void mul_mat_iq2_kt_q8_2_x4_T(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { assert(n%QK_K == 0); @@ -1091,11 +1283,11 @@ bool iqk_set_kernels_ktquants(int ne00, int typeA, int typeB, std::array; + func16 = mul_mat_iq1_kt_q8_2_x4_T<16>; #endif return true; } @@ -1124,6 +1316,17 @@ bool iqk_set_kernels_ktquants(int ne00, int typeA, int typeB, std::array; +#endif + return true; + } + return false; + } + if (ggml_type(typeB) != GGML_TYPE_F32) { return false; } @@ -1148,6 +1351,7 @@ bool iqk_set_kernels_ktquants(int ne00, int typeA, int typeB, std::array +void mul_mat_iq1_kt_q8_0_x4_T(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { + assert(n%QK_K == 0); + const int nb = n/QK_K; + + Trellis3 trellis; + + auto values = vld1q_s8(iq4k_values); + + constexpr int k_acc = nrc_y == 1 ? 2 : nrc_y; + + float32x4_t accd[k_acc]; + + const block_q8_0_x4 * y[nrc_y]; + for (int iy = 0; iy < nrc_y; ++iy) { + y[iy] = (const block_q8_0_x4 *)info.src1_row(iy); + } + + int8x16x2_t xv[8]; + uint16x8x4_t idx; + int32x4x4_t dot; + + auto compute_dot = [&dot] (const int8_t * y, const int8x16x2_t * xv) { + for (int k = 0; k < 4; ++k) { + auto yv = vld1q_s8_x2(y + 32*k); + dot.val[k] = vdotq_s32(vdotq_s32(vdupq_n_s32(0), xv[k].val[0], yv.val[0]), xv[k].val[1], yv.val[1]); + } + dot.val[0] = vpaddq_s32(dot.val[0], dot.val[1]); + dot.val[2] = vpaddq_s32(dot.val[2], dot.val[3]); + return vpaddq_s32(dot.val[0], dot.val[2]); + }; + + float32x4x2_t scales; + + for (int ix = 0; ix < nrc_x; ++ix) { + const float * dptr = (const float *)((const char*)vx + ix*bx); + auto d = vdupq_n_f32(dptr[0]); + const block_iq1_kt * x = (const block_iq1_kt *)(dptr + 1); + + for (int iy = 0; iy < k_acc; ++iy) accd[iy] = vdupq_n_f32(0); + + for (int i = 0; i < nb; ++i) { + auto sh = vld1_u8(x[i].sh); + auto s16 = vmovl_s8(vqtbl1_s8(values, vand_u8(sh, vdup_n_u8(0xf)))); + scales.val[0] = vmulq_f32(d, vcvtq_f32_s32(vmovl_s16(vget_low_s16 (s16)))); + scales.val[1] = vmulq_f32(d, vcvtq_f32_s32(vmovl_s16(vget_high_s16(s16)))); + auto ql = vld1q_u8_x2(x[i].ql); + auto qh = vld1q_u8(x[i].qh); + auto qhl = vmovl_u8(vget_low_u8(qh)); + auto qhh = vmovl_u8(vget_high_u8(qh)); + idx.val[0] = vaddq_u16(vmovl_u8(vget_low_u8 (ql.val[0])), vandq_u16(vdupq_n_u16(0xf00), vshlq_n_u16(qhl, 8))); + idx.val[1] = vaddq_u16(vmovl_u8(vget_high_u8(ql.val[0])), vandq_u16(vdupq_n_u16(0xf00), vshlq_n_u16(qhh, 8))); + idx.val[2] = vaddq_u16(vmovl_u8(vget_low_u8 (ql.val[1])), vandq_u16(vdupq_n_u16(0xf00), vshlq_n_u16(qhl, 4))); + idx.val[3] = vaddq_u16(vmovl_u8(vget_high_u8(ql.val[1])), vandq_u16(vdupq_n_u16(0xf00), vshlq_n_u16(qhh, 4))); + for (int k = 0; k < 4; ++k) idx.val[k] = vaddq_u16(idx.val[k], vdupq_n_u16(4096)); + auto sh16 = vandq_u16(vmovl_u8(sh), vdupq_n_u16(0xf0)); + auto sh32l = vandq_u8(vreinterpretq_u8_u32(vmulq_u32(vmovl_u16(vget_low_u16 (sh16)), vdupq_n_u32(0x01020408))), vdupq_n_u8(0x80)); + auto sh32h = vandq_u8(vreinterpretq_u8_u32(vmulq_u32(vmovl_u16(vget_high_u16(sh16)), vdupq_n_u32(0x01020408))), vdupq_n_u8(0x80)); + idx.val[0] = vaddq_u16(idx.val[0], vshlq_n_u16(vmovl_u8(vget_low_u8 (sh32l)), 5)); + idx.val[1] = vaddq_u16(idx.val[1], vshlq_n_u16(vmovl_u8(vget_high_u8(sh32l)), 5)); + idx.val[2] = vaddq_u16(idx.val[2], vshlq_n_u16(vmovl_u8(vget_low_u8 (sh32h)), 5)); + idx.val[3] = vaddq_u16(idx.val[3], vshlq_n_u16(vmovl_u8(vget_high_u8(sh32h)), 5)); + if constexpr (nrc_y == 1) { + const block_q8_0_x4& ybl = y[0][2*i+0]; + const block_q8_0_x4& ybh = y[0][2*i+1]; + auto dyl = vmulq_f32(scales.val[0], vcvt_f32_f16(vld1_f16((const float16_t *)ybl.d))); + auto dyh = vmulq_f32(scales.val[1], vcvt_f32_f16(vld1_f16((const float16_t *)ybh.d))); + int32x4x4_t suml = {}; + int32x4x4_t sumh = {}; + for (int ib = 0; ib < 2; ++ib) { + auto xl = trellis.next32(vget_low_u16(idx.val[ib+0])); + auto xh = trellis.next32(vget_low_u16(idx.val[ib+2])); + auto yl = vld1q_s8_x2(ybl.qs + 64*ib); + auto yh = vld1q_s8_x2(ybh.qs + 64*ib); + suml.val[2*ib+0] = vdotq_s32(vdotq_s32(vdupq_n_s32(0), xl.val[0], yl.val[0]), xl.val[1], yl.val[1]); + sumh.val[2*ib+0] = vdotq_s32(vdotq_s32(vdupq_n_s32(0), xh.val[0], yh.val[0]), xh.val[1], yh.val[1]); + xl = trellis.next32(vget_high_u16(idx.val[ib+0])); + xh = trellis.next32(vget_high_u16(idx.val[ib+2])); + yl = vld1q_s8_x2(ybl.qs + 64*ib + 32); + yh = vld1q_s8_x2(ybh.qs + 64*ib + 32); + suml.val[2*ib+1] = vdotq_s32(vdotq_s32(vdupq_n_s32(0), xl.val[0], yl.val[0]), xl.val[1], yl.val[1]); + sumh.val[2*ib+1] = vdotq_s32(vdotq_s32(vdupq_n_s32(0), xh.val[0], yh.val[0]), xh.val[1], yh.val[1]); + } + auto sl1 = vpaddq_s32(suml.val[0], suml.val[1]); + auto sl2 = vpaddq_s32(suml.val[2], suml.val[3]); + auto sl = vpaddq_s32(sl1, sl2); + auto sh1 = vpaddq_s32(sumh.val[0], sumh.val[1]); + auto sh2 = vpaddq_s32(sumh.val[2], sumh.val[3]); + auto sh = vpaddq_s32(sh1, sh2); + accd[0] = vfmaq_f32(accd[0], dyl, vcvtq_f32_s32(sl)); + accd[1] = vfmaq_f32(accd[1], dyh, vcvtq_f32_s32(sh)); + } else { + for (int k = 0; k < 4; ++k) { + xv[2*k+0] = trellis.next32(vget_low_u16 (idx.val[k])); + xv[2*k+1] = trellis.next32(vget_high_u16(idx.val[k])); + } + for (int iy = 0; iy < nrc_y; ++iy) { + const block_q8_0_x4& ybl = y[iy][2*i+0]; + const block_q8_0_x4& ybh = y[iy][2*i+1]; + auto dyl = vmulq_f32(scales.val[0], vcvt_f32_f16(vld1_f16((const float16_t *)ybl.d))); + auto dyh = vmulq_f32(scales.val[1], vcvt_f32_f16(vld1_f16((const float16_t *)ybh.d))); + auto sumil = compute_dot(ybl.qs, xv+0); + auto sumih = compute_dot(ybh.qs, xv+4); + if constexpr (nrc_y == 1) { + accd[2*iy+0] = vfmaq_f32(accd[2*iy+0], dyl, vcvtq_f32_s32(sumil)); + accd[2*iy+1] = vfmaq_f32(accd[2*iy+1], dyh, vcvtq_f32_s32(sumih)); + } else { + accd[iy] = vfmaq_f32(accd[iy], dyl, vcvtq_f32_s32(sumil)); + accd[iy] = vfmaq_f32(accd[iy], dyh, vcvtq_f32_s32(sumih)); + } + } + } + } + + if constexpr (nrc_y == 1) { + info.store(ix, 0, vaddvq_f32(vaddq_f32(accd[0], accd[1]))); + } else { + for (int iy = 0; iy < nrc_y; ++iy) { + info.store(ix, iy, vaddvq_f32(accd[iy])); + } + } + } +} + template void mul_mat_iq2_kt_q8_0_x4_T(int n, const void * vx, size_t bx, const DataInfo& info, int nrc_x) { assert(n%QK_K == 0); @@ -2284,6 +2699,15 @@ bool iqk_set_kernels_ktquants(int ne00, int typeA, int typeB, std::array= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ4_NL : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_Q8_0 : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; + case GGML_TYPE_IQ1_KT : return nrc_y >= 16 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ2_KT : return nrc_y >= 16 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ3_KT : return nrc_y >= 16 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ4_KT : return nrc_y >= 24 ? GGML_TYPE_Q8_0_R8 : type; @@ -293,6 +294,7 @@ struct MulMat { case GGML_TYPE_Q6_0 : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_Q8_0 : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ4_NL : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; + case GGML_TYPE_IQ1_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ2_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ3_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; case GGML_TYPE_IQ4_KT : return nrc_y >= 32 ? GGML_TYPE_Q8_0_R8 : type; @@ -442,6 +444,7 @@ bool iqk_convert_repack(int typeA, int n, const void * vx, size_t bx, void * vy, //case GGML_TYPE_IQ4_KS_R4: //case GGML_TYPE_IQ5_KS_R4: return iqk_convert_iqk_quants_q80_r8(typeA, n, vx, bx, vy, nrc_x); + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -848,6 +851,7 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& mm, int Ny) { case GGML_TYPE_IQ4_KS_R4: case GGML_TYPE_IQ5_KS_R4: return iqk_set_kernels_iqk_quants(ne00, typeA, typeB, mm.funcs, mm.func16); + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -963,6 +967,7 @@ bool MulMat::prepare(int typeA, int typeB, int ne00, MulMat& m, int /*Ny*/) { case GGML_TYPE_IQ1_S_R4: case GGML_TYPE_IQ1_M_R4: return iqk_set_kernels_1bit(ne00, typeA, typeB, m.funcs, m.func16); + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: diff --git a/ggml/src/iqk/iqk_quantize.cpp b/ggml/src/iqk/iqk_quantize.cpp index b38cc51f..1dfb5218 100644 --- a/ggml/src/iqk/iqk_quantize.cpp +++ b/ggml/src/iqk/iqk_quantize.cpp @@ -8552,8 +8552,273 @@ std::vector QuantizerIQKT; + +const QuantizerIQ1KT& iq1kt_quantizer() { + static std::mutex mutex; + static std::unique_ptr quantizer; + std::lock_guard lock(mutex); + if (!quantizer) quantizer = std::make_unique(256, 32); + return *quantizer; +} + +void quantize_row_iq1_kt_impl(const float * x, void * vy, int n_per_row, const float * quant_weights, float * all_scales, float * all_weights, + int * all_idx) { + + constexpr float kSigmaScale = 2.0f; + using Q = QuantizerIQ1KT; + + static_assert(Q::kNumVal%8 == 0); + + float * dptr = (float *)vy; + + block_iq1_kt * y = (block_iq1_kt *)(dptr + 1); + + int best_idx[2*Q::kNg]; + + auto& quantizer = iq1kt_quantizer(); + + int nblock = n_per_row / Q::kSuperBlockSize; + + Q::set_weights(kSigmaScale, nblock, x, quant_weights, all_weights); + + float amax_row = 0; + for (int j = 0; j < n_per_row; ++j) { + amax_row = std::max(amax_row, std::abs(x[j])); + } + + float amax_scale = 0, max_scale = 0; + + for (int ibl = 0; ibl < nblock; ++ibl) { + + memset(&y[ibl], 0, sizeof(block_iq1_kt)); + + const float * xbl = x + ibl*Q::kSuperBlockSize; + auto scales = all_scales + ibl*Q::kNblock; + + for (int ib = 0; ib < Q::kNblock; ++ib) { + const float * xb = xbl + Q::kBlockSize*ib; + const float * weight = all_weights + ibl*Q::kSuperBlockSize + ib*Q::kBlockSize; + float amax = 0; + for (int j = 0; j < Q::kBlockSize; ++j) { + float ax = std::abs(xb[j]); + amax = std::max(amax, ax); + } + float scale_0 = std::max(90.f, 124.f*amax/amax_row); + quantizer.find_best_match( amax/scale_0, xb, weight, best_idx); + auto [dp, score_p] = quantizer.find_best_scale(xb, weight, best_idx); + quantizer.find_best_match(-amax/scale_0, xb, weight, best_idx + Q::kNg); + auto [dm, score_m] = quantizer.find_best_scale(xb, weight, best_idx + Q::kNg); + + auto idx = best_idx; + if (score_p > score_m) scales[ib] = dp; + else { + scales[ib] = dm; idx += Q::kNg; score_p = score_m; + } + for (int ig = 0; ig < Q::kNg; ++ig) all_idx[(ibl*Q::kSuperBlockSize + ib*Q::kBlockSize)/Q::kGroupSize + ig] = idx[ig]; + + scale_0 -= 8; + quantizer.find_best_match( amax/scale_0, xb, weight, best_idx); + auto [dp1, score_p1] = quantizer.find_best_scale(xb, weight, best_idx); + quantizer.find_best_match(-amax/scale_0, xb, weight, best_idx + Q::kNg); + auto [dm1, score_m1] = quantizer.find_best_scale(xb, weight, best_idx + Q::kNg); + + if (score_p1 > score_p || score_m1 > score_p) { + idx = best_idx; + if (score_p1 > score_m1) scales[ib] = dp1; + else { + scales[ib] = dm1; idx += Q::kNg; + } + for (int ig = 0; ig < Q::kNg; ++ig) all_idx[(ibl*Q::kSuperBlockSize + ib*Q::kBlockSize)/Q::kGroupSize + ig] = idx[ig]; + } + + float abs_scale = std::abs(scales[ib]); + if (abs_scale > amax_scale) { + amax_scale = abs_scale; + max_scale = scales[ib]; + } + } + + } + + if (!max_scale) { + *dptr = 0; + return; + } + + float d = max_scale/iq4k_values[0]; + float best = 0; + for (int itry = -9; itry <= 9; ++itry) { + float id = (itry + iq4k_values[0])/max_scale; + float sumqx = 0, sumq2 = 0; + for (int ibl = 0; ibl < nblock; ++ibl) { + const float * xb = x + ibl*Q::kSuperBlockSize; + const float * wb = all_weights + ibl*Q::kSuperBlockSize; + auto scales = all_scales + ibl*Q::kNblock; + for (int ib = 0; ib < Q::kNblock; ++ib) { + int ls = best_index_iq4nl(iq4k_values, id*scales[ib]); + float dl = iq4k_values[ls]; + for (int ig = 0; ig < Q::kNg; ++ig) { + auto qb = quantizer.values() + Q::kGroupSize*all_idx[(ibl*Q::kSuperBlockSize + ib*Q::kBlockSize)/Q::kGroupSize + ig]; + for (int j = 0; j < Q::kGroupSize; ++j) { + int jj = ig*Q::kGroupSize + j; + float q = dl*qb[j]; + sumqx += wb[jj]*xb[jj]*q; + sumq2 += wb[jj]*q*q; + } + } + xb += Q::kBlockSize; + wb += Q::kBlockSize; + } + } + if (sumq2 > 0 && sumqx*sumqx > best*sumq2) { + d = sumqx/sumq2; best = d*sumqx; + } + } + + float id = d ? 1/d : 0.f; + for (int ibl = 0; ibl < nblock; ++ibl) { + auto scales = all_scales + ibl*Q::kNblock; + for (int ib = 0; ib < Q::kNblock; ++ib) { + int ls = best_index_iq4nl(iq4k_values, id*scales[ib]); + y[ibl].sh[ib] = ls; + } + } + + *dptr = d; + if (!d) return; + + for (int iloop = 0; iloop < 1; ++iloop) { + + float sumqx = 0, sumq2 = 0; + for (int ibl = 0; ibl < nblock; ++ibl) { + + const float * xbl = x + ibl*Q::kSuperBlockSize; + + for (int ib = 0; ib < Q::kNblock; ++ib) { + const float * xb = xbl + Q::kBlockSize*ib; + const float * weight = all_weights + ibl*Q::kSuperBlockSize + ib*Q::kBlockSize; + int ls = iq4k_values[y[ibl].sh[ib] & 0xf]; + float dl = d*ls; + quantizer.find_best_match(dl, xb, weight, best_idx); + + auto prev_idx = all_idx + (ibl*Q::kSuperBlockSize + ib*Q::kBlockSize)/Q::kGroupSize; + + float mse1 = 0, mse2 = 0; + for (int ig = 0; ig < Q::kNg; ++ig) { + auto q1 = quantizer.values() + Q::kGroupSize*prev_idx[ig]; + auto q2 = quantizer.values() + Q::kGroupSize*best_idx[ig]; + for (int j = 0; j < Q::kGroupSize; ++j) { + int jj = ig*Q::kGroupSize + j; + float diff1 = xb[jj] - dl*q1[j]; + float diff2 = xb[jj] - dl*q2[j]; + mse1 += weight[jj]*diff1*diff1; + mse2 += weight[jj]*diff2*diff2; + } + } + if (mse1 < mse2) { + for (int ig = 0; ig < Q::kNg; ++ig) best_idx[ig] = prev_idx[ig]; + } else { + for (int ig = 0; ig < Q::kNg; ++ig) prev_idx[ig] = best_idx[ig]; + } + + for (int j = 0; j < Q::kNg; ++j) { + y[ibl].ql[ib*Q::kNg+j] = best_idx[j] & 0xff; + y[ibl].qh[(ib%(Q::kNblock/2))*Q::kNg+j] |= (((best_idx[j] >> 8) & 0xf) << 4*(ib/(Q::kNblock/2))); + y[ibl].sh[ib] |= ((best_idx[j] >> 12) << (4+j)); + auto xl = xb + Q::kGroupSize*j; + auto wl = weight + Q::kGroupSize*j; + auto ql = quantizer.values() + best_idx[j]*Q::kGroupSize; + for (int k = 0; k < Q::kGroupSize; ++k) { + float q = ql[k]*ls; + sumqx += wl[k]*xl[k]*q; + sumq2 += wl[k]*q*q; + } + } + } + } + if (sumq2 > 0) { + d = sumqx/sumq2; + *dptr = d * 1.07f; + if (!d) return; + } else { + break; + } + + } + +} +} + +void quantize_row_iq1_kt_ref(const float * GGML_RESTRICT x, block_iq1_kt * GGML_RESTRICT y, int64_t k) { + assert(k % QK_K == 0); + quantize_iq1_kt(x, (void *)y, 1, k, nullptr); +} + +void quantize_row_iq1_kt(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) { + assert(k % QK_K == 0); + block_iq1_kt * y = (block_iq1_kt *)vy; + quantize_row_iq1_kt_ref(x, y, k); +} + +size_t quantize_iq1_kt(const float * src, void * dst, int64_t nrows, int64_t n_per_row, const float * imatrix) { + GGML_ASSERT(n_per_row%QK_K == 0); + auto row_size = ggml_row_size(GGML_TYPE_IQ1_KT, n_per_row); + std::vector scales(n_per_row/QuantizerIQ1KT::kBlockSize); + std::vector weights(n_per_row); + std::vector idx(n_per_row/QuantizerIQ1KT::kGroupSize); + char * qrow = (char *)dst; + for (int64_t row = 0; row < nrows; ++row) { + quantize_row_iq1_kt_impl(src, (void *)qrow, n_per_row, imatrix, scales.data(), weights.data(), idx.data()); + src += n_per_row; + qrow += row_size; + } + return nrows * row_size; +} + +void dequantize_row_iq1_kt(const block_iq1_kt * x, float * y, int64_t k) { + assert(k % QuantizerIQ1KT::kSuperBlockSize == 0); + using Q = QuantizerIQ1KT; + const int nb = k / Q::kSuperBlockSize; + const float * dptr = (const float *)x; + const float d = *dptr * Q::kScale; + x = (const block_iq1_kt *)(dptr + 1); + auto& deq = iq1kt_quantizer(); + for (int ibl = 0; ibl < nb; ++ibl) { + for (int ib = 0; ib < Q::kNblock; ++ib) { + float sl = d * iq4k_values[x[ibl].sh[ib] & 0xf]; + for (int ig = 0; ig < Q::kNg; ++ig) { + uint16_t idx = x[ibl].ql[ib*Q::kNg + ig] | ((x[ibl].qh[(ib%(Q::kNblock/2))*Q::kNg + ig] << (8 - 4*(ib/(Q::kNblock/2)))) & 0xf00); + idx |= (x[ibl].sh[ib] << (8 - ig) & 0x1000); + deq.set_values(idx, y, sl); + y += Q::kGroupSize; + } + } + } +} + +void vec_dot_iq1_kt_q8_k(int n, float * s, size_t bs, const void * vx, size_t bx, const void * vy, size_t by, int nrc) { + assert(n % QK_K == 0); + assert(nrc == 1); + GGML_UNUSED(nrc); + GGML_UNUSED(bx); + GGML_UNUSED(by); + GGML_UNUSED(bs); + +#if GGML_USE_IQK_MULMAT + if (iqk_mul_mat(1, 1, n, GGML_TYPE_IQ1_KT, vx, 0, GGML_TYPE_Q8_K, vy, 0, s, 0, 0, 1)) { + return; + } +#endif + +} + // ========================================== iq2_kt ==================================================== +namespace { + using QuantizerIQ2KT = QuantizerIQKT<32, 8, 16, false, true>; const QuantizerIQ2KT& iq2kt_quantizer() { diff --git a/ggml/src/iqk/iqk_quantize.h b/ggml/src/iqk/iqk_quantize.h index 75fa9b4e..7d789fba 100644 --- a/ggml/src/iqk/iqk_quantize.h +++ b/ggml/src/iqk/iqk_quantize.h @@ -79,6 +79,12 @@ size_t quantize_iq2_kl(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst void dequantize_row_iq2_kl(const block_iq2_kl * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k); void vec_dot_iq2_kl_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); +void quantize_row_iq1_kt_ref(const float * GGML_RESTRICT x, block_iq1_kt * GGML_RESTRICT y, int64_t k); +void quantize_row_iq1_kt(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k); +size_t quantize_iq1_kt(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix); +void dequantize_row_iq1_kt(const block_iq1_kt * GGML_RESTRICT x, float * GGML_RESTRICT y, int64_t k); +void vec_dot_iq1_kt_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); + void quantize_row_iq2_kt_ref(const float * GGML_RESTRICT x, block_iq2_kt * GGML_RESTRICT y, int64_t k); void quantize_row_iq2_kt(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k); size_t quantize_iq2_kt(const float * GGML_RESTRICT src, void * GGML_RESTRICT dst, int64_t nrows, int64_t n_per_row, const float * imatrix); diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py index 767637c5..32a667e2 100644 --- a/gguf-py/gguf/constants.py +++ b/gguf-py/gguf/constants.py @@ -1322,6 +1322,7 @@ class GGMLQuantizationType(IntEnum): IQ4_KT = 155 IQ3_KS = 156 IQ2_KL = 157 + IQ1_KT = 158 Q4_0_R8 = 202 Q5_0_R4 = 206 Q8_0_R8 = 208 @@ -1539,6 +1540,7 @@ GGML_QUANT_SIZES: dict[GGMLQuantizationType, tuple[int, int]] = { GGMLQuantizationType.IQ4_KT : ( 256, 128), GGMLQuantizationType.IQ3_KS : ( 256, 102), GGMLQuantizationType.IQ2_KL : ( 256, 86), + GGMLQuantizationType.IQ1_KT : ( 256, 56), GGMLQuantizationType.Q4_0_R8 : ( 32, 18), GGMLQuantizationType.Q5_0_R4 : ( 32, 22), GGMLQuantizationType.Q8_0_R8 : ( 32, 34), diff --git a/include/llama.h b/include/llama.h index bcd81f4f..1bc1bdaf 100644 --- a/include/llama.h +++ b/include/llama.h @@ -206,6 +206,7 @@ extern "C" { LLAMA_FTYPE_MOSTLY_IQ4_KT = 153, // except 1d tensors LLAMA_FTYPE_MOSTLY_IQ3_KS = 154, // except 1d tensors LLAMA_FTYPE_MOSTLY_IQ2_KL = 155, // except 1d tensors + LLAMA_FTYPE_MOSTLY_IQ1_KT = 156, // except 1d tensors // LLAMA_FTYPE_MOSTLY_Q4_0_R8 = 202, // except 1d tensors LLAMA_FTYPE_MOSTLY_Q8_0_R8 = 207, // except 1d tensors diff --git a/src/llama.cpp b/src/llama.cpp index 0d29f24a..2c251c6b 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -4429,6 +4429,7 @@ struct llama_model_loader { case GGML_TYPE_IQ2_S_R4:ftype = LLAMA_FTYPE_MOSTLY_IQ2_M_R4;break; case GGML_TYPE_IQ3_XXS: ftype = LLAMA_FTYPE_MOSTLY_IQ3_XXS; break; case GGML_TYPE_IQ3_XXS_R4: ftype = LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4; break; + case GGML_TYPE_IQ1_KT: ftype = LLAMA_FTYPE_MOSTLY_IQ1_KT; break; case GGML_TYPE_IQ2_KT: ftype = LLAMA_FTYPE_MOSTLY_IQ2_KT; break; case GGML_TYPE_IQ3_KT: ftype = LLAMA_FTYPE_MOSTLY_IQ3_KT; break; case GGML_TYPE_IQ4_KT: ftype = LLAMA_FTYPE_MOSTLY_IQ4_KT; break; @@ -5174,6 +5175,7 @@ static std::string llama_model_ftype_name(llama_ftype ftype) { case LLAMA_FTYPE_MOSTLY_IQ2_M_R4: return "IQ2_M_R4 - 2.7 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_XS: return "IQ3_XS - 3.3 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_XXS: return "IQ3_XXS - 3.0625 bpw"; + case LLAMA_FTYPE_MOSTLY_IQ1_KT: return "IQ1_KT - 1.75 bpw"; case LLAMA_FTYPE_MOSTLY_IQ2_KT: return "IQ2_KT - 2.125 bpw"; case LLAMA_FTYPE_MOSTLY_IQ3_KT: return "IQ3_KT - 3.125 bpw"; case LLAMA_FTYPE_MOSTLY_IQ4_KT: return "IQ4_KT - 4.0 bpw"; @@ -19170,7 +19172,8 @@ static ggml_type change_type_if_necessary(ggml_type new_type, int nx, int ny) { new_type == GGML_TYPE_IQ3_XXS_R4 || new_type == GGML_TYPE_IQ2_XXS_R4 || new_type == GGML_TYPE_IQ2_XS_R4 || new_type == GGML_TYPE_IQ2_S_R4|| new_type == GGML_TYPE_IQ3_S_R4|| new_type == GGML_TYPE_IQ3_KS || new_type == GGML_TYPE_IQ2_KT || new_type == GGML_TYPE_IQ3_KT || new_type == GGML_TYPE_IQ4_KT || - new_type == GGML_TYPE_IQ5_KS || new_type == GGML_TYPE_IQ5_KS_R4|| new_type == GGML_TYPE_IQ2_KL) { + new_type == GGML_TYPE_IQ5_KS || new_type == GGML_TYPE_IQ5_KS_R4|| new_type == GGML_TYPE_IQ2_KL || + new_type == GGML_TYPE_IQ1_KT) { if (nx % QK_K != 0) { LLAMA_LOG_WARN("\n\n%s : tensor cols %d x %d are not divisible by %d, required for %s", __func__, nx, ny, QK_K, ggml_type_name(new_type)); convert_incompatible_tensor = true; @@ -19210,6 +19213,7 @@ static ggml_type change_type_if_necessary(ggml_type new_type, int nx, int ny) { case GGML_TYPE_IQ4_KS: case GGML_TYPE_IQ4_KS_R4: case GGML_TYPE_IQ4_XS_R8: + case GGML_TYPE_IQ1_KT: case GGML_TYPE_IQ2_KT: case GGML_TYPE_IQ3_KT: case GGML_TYPE_IQ4_KT: @@ -19342,7 +19346,7 @@ static ggml_type llama_tensor_get_type(quantize_state_internal & qs, ggml_type n ftype == LLAMA_FTYPE_MOSTLY_IQ2_K_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_KL || ftype == LLAMA_FTYPE_MOSTLY_IQ3_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_M_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ1_S_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ1_M_R4 || - ftype == LLAMA_FTYPE_MOSTLY_IQ2_KT || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KT) { + ftype == LLAMA_FTYPE_MOSTLY_IQ2_KT || ftype == LLAMA_FTYPE_MOSTLY_IQ3_KT || ftype == LLAMA_FTYPE_MOSTLY_IQ1_KT) { new_type = !qs.has_output ? GGML_TYPE_IQ4_K : GGML_TYPE_Q5_K; } else if (ftype == LLAMA_FTYPE_MOSTLY_IQ2_XXS_R4 || ftype == LLAMA_FTYPE_MOSTLY_IQ2_XS_R4) { @@ -19936,6 +19940,7 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s case LLAMA_FTYPE_MOSTLY_IQ2_XS: default_type = GGML_TYPE_IQ2_XS; break; case LLAMA_FTYPE_MOSTLY_IQ2_XS_R4:default_type = GGML_TYPE_IQ2_XS_R4; break; case LLAMA_FTYPE_MOSTLY_IQ2_KS: default_type = GGML_TYPE_IQ2_KS; break; + case LLAMA_FTYPE_MOSTLY_IQ1_KT: default_type = GGML_TYPE_IQ1_KT; break; case LLAMA_FTYPE_MOSTLY_IQ2_KT: default_type = GGML_TYPE_IQ2_KT; break; case LLAMA_FTYPE_MOSTLY_IQ2_S: default_type = GGML_TYPE_IQ2_XS; break; case LLAMA_FTYPE_MOSTLY_IQ2_M: default_type = GGML_TYPE_IQ2_S; break; From d44c2d3f5aeab25a9405896f48a36082cee5d8ac Mon Sep 17 00:00:00 2001 From: firecoperana Date: Sun, 20 Jul 2025 05:33:55 -0500 Subject: [PATCH 39/63] Webui: New Features for Conversations, Settings, and Chat Messages (#618) * Webui: add Rename/Upload conversation in header and sidebar webui: don't change modified date when renaming conversation * webui: add a preset feature to the settings #14649 * webui: Add editing assistant messages #13522 Webui: keep the following message while editing assistance response. webui: change icon to edit message * webui: DB import and export #14347 * webui: Wrap long numbers instead of infinite horizontal scroll (#14062) fix sidebar being covered by main content #14082 --------- Co-authored-by: firecoperana --- examples/server/public/index.html.gz | Bin 1263655 -> 1292690 bytes examples/server/webui/dist/index.html | 347 ++++++++++++---- examples/server/webui/index.html | 2 +- examples/server/webui/package-lock.json | 37 ++ examples/server/webui/package.json | 2 + examples/server/webui/src/App.tsx | 29 +- .../webui/src/components/ChatMessage.tsx | 17 +- .../webui/src/components/ChatScreen.tsx | 57 ++- .../server/webui/src/components/Header.tsx | 86 +++- .../webui/src/components/ModalProvider.tsx | 151 +++++++ .../webui/src/components/SettingDialog.tsx | 268 +++++++++++- .../server/webui/src/components/Sidebar.tsx | 382 ++++++++++++++++-- examples/server/webui/src/index.scss | 4 + .../server/webui/src/utils/app.context.tsx | 99 ++++- examples/server/webui/src/utils/common.tsx | 36 ++ examples/server/webui/src/utils/storage.ts | 198 ++++++++- examples/server/webui/src/utils/types.ts | 8 + 17 files changed, 1560 insertions(+), 163 deletions(-) create mode 100644 examples/server/webui/src/components/ModalProvider.tsx diff --git a/examples/server/public/index.html.gz b/examples/server/public/index.html.gz index 4a29a9212d8a9d97fd83df55c355862d06c6af48..d358fdf780ec6eae17f885b781d385883e6304da 100644 GIT binary patch delta 1283980 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
  • ubB=85>7l92$o(OOy>rSB4ip12r7Fk7=3grBy7Rk0|0`WPD%mk%)n+*V; z@l#XaXGk5+GB!HtjyHk4)2oAo`I#k`-JQ_IeHlYki;94wtf=?$vcC9XD$93TmWEh}OWRLO#c z=x%j4iqP4I15SqOo(h5URvbue&T?qT|^H zm4+Zg${0aI(5$L{@x5vWK#j(Z-=mu9>|zpJ{`}dI z_!V|K=h|bYu}GFtoaP4V-GIV}j8KC~)^58xwW-E`bXhbqF2Z$FCa_#&K^_#OvAT`D zTL`SP$mUabn%p2>Oi|<3%^PVD7q>xXfXav8VO4Ol%+Lp9oGG|GQ?7x)N6Zv5OvcWv$JOYw;c7hWj(exK=D=#T zPH)XAwXmXK9+0U84)|7MXXq1Fe6!)|6Vo++W4cXCk}nxcSe^qFg@`Yx#IOKS5V8u6 zc7QtbWdSEU*bX%ie)=ox=k!%;;hoaL_S)jHtlT6K^}#mUpoFr)w%K{s8KtLL;1+O_ zhVtS=BaE}WAdTrg)&ghRxUd^bh}k7Fnbr+nzyz)jh$TPVbkx31xjJqWmDhyY9}oS1 z{rC-$G_Sncz5`??eRM3<)xoGBC4OsH1i znKSM1WAuPbEXDZAJae9I7$=>%xQdOObg_eGR{b-@X7LOhZe1?TGjKKY!?)%cdAP{j z2pY0~?eIq;QO8b59HsLtc$0p1li0s1?x}gnuld^kweu_J{^sj{oId6R%!1#7&&}om zJ_G4PdlQN3m*zFOAalxzN%uVvGOg8`OP1k6n%{H5)vP~Pf?VVaRHwQiUCUO|hZo~o zhfB;Vg;rC!lnNBuI4gE3hJ z&Icc!dgdw+`t>V+<=W|*+oGZ;hiV1RipwzH(qLh6K(4_}$fKijihi@GYXYP^wdpj- zNiz;wt+Z}VS}ijUoMy^r6FTyx`HR3`6Q8FYa|vYQT8SvLW5&sa>d|3PA)nmYfnkFR zr<%|=Xf!L4@LvXvBpNGvgF;4vhsUx66-m&LEMB^0nTnTxlxj!Pm#i$W)*W!ZW2&mb zz^1Dn$IqkM;9HtcpyJ6#5urF_SUu^OJypUNFzs>dCiT0neJ5_4D@sXSbtNXo`VXoZ zD#v`DPg-P%fM~;VG!%hWZGZIdgagZv~Bq674*!N`QC+0ax(4^r+htI9v7&TJTs$;4Up zSJiM5FsZINC6oR{zm1;>3ui@tLkIZm)|`UjLX3SLI2W`+5(mx$ zKG`A#VrJpnVp%|ZdGF2!ji?#%#~ZBwtuuui#0wyq3jV*~_cczuS1yX)ncG)*4C%hN5ia*d_OOI#92;~_grp-+Dh+2-)y^m|t#YhhZ5~M|t*$)X?Hzu!GrS{pHRFcj?x?x}V)$|{VVo{U)(`sd3_!|H=;S6>=k zx2PpF9f=NZ9Ygu3cmSpGiU|hgq@qH5f8U_$6i6DcxN~()PWk)eqd@%KF@)F3M6BaN ztM&rFA%`*??lXC!J=!1bm#fvv>^q~5Wtqdh&S*7mTjubW#;6!&qjdbWwI9WQwlTUJ;2Pi*|$fd4tufMmO+eYX;|df z^>|DkC}U&~4TZ|c;LhN*Rr+9Fb6;jem^B+1WxDzIBdVpm|I2DWro1ldZ-T{HN(!)| zQD(s+&1YbyWmT=fbLY3UnYJ^3>K_=4`>Q!T=P~q7+C>{(0zB$vl;+t;e*<9r-v{5{ z+j-&BW^8+kBk8sD=*Bwt_ahp)uPpb6dn11`ezs3xkXrp_*M4+CQfab{^8Np1w9_wj z9W!YJ;Muww{xOLQQ2XT!cGD~rv#nw%El9!0Zhyi$t9`J_vbjHW_kMqWwfC=)Kd#MU zX_X!Bs_gK~l^ue|d&S|WHlqDu(`bEVk&fLvdD$P0H{`Q8mVYATr0QgC2Gg-4nLMJcSx%4iYo9%JLIgaJIOBmpzNfKJ&3~D#df@-AJ?Sz1A2{SQB}Uz@|=R(zJG2dvAq9UbAF+| zy`P`Z-cQ@@{e4$^|IiqSw_ji&hWhq9R2VYGauFj_=%eCJ@S!GuSX6OW6F4h4RD1N} zjt#uVdmxei0AVY~{ye&;e-ERjRu34e!&JWgq^&Yx5CgUlU@82C{gt{Z11nhQgj0}I zaaQOgu35j+TDrG(*_)pq***XH1qjLgY6pOHp#19*p#0;1E1>-S5ugNzavxH(Gx4r` zkh$Jnkb!SzO2yoN4v3;nWB7|8bvZ=;Lul5(5sbveXNm4IPGFl?nRZ|enJIXun|rYf zeFG(Si-7#!?Rd*91G6)W^ScRWb;riWvWRC|BsYOFicXFV&3{*LCk;x6iomS6`^y2K zI_gv*Ko|ah)9BTa+YrV=@!hu_x%r?E{_71iVP?T+kJLJU=!TOP@8UGb!O0)B>It%o zWWF-NB181aBI%vQpfACi-f=OSBI`Wp2eyeect)eqXc$(T`-#r(^i!%IJS`}u>zMob1}UkN_+pez>qU z11c4NyS6s@a5i=Z#Dkx+jp_$VxiXdNIf+os$t)rF_Ip+WKA)~4)V8x!H>m?mwR&5b z2b)N`#99IHrb?t^%qOaV0_=9wFvumGIS1g*^0;rFIUq^7g#VU3K&$KT`j|-Hx<{>+ zNk6k7EnASJlHsoX-YsrBGk0xvNjQwgduM!qU%wR7#i4!HHuem-jtJbsytdkxz54k< zFLS(}_I3MGxTbpvP2h|~W9J$ivD4ob{9bHwE~o7hxC|hk`aZQNGRpWi5-;;@yo4zx zXAVqpPl5U64sc&PgJCp=3q&U9Hw-cl*g5}kG>iiWA!nXp4JdZUxqC~eqJIIgS2)~% z;=r=s(rJu?|9RLqD_{2y+nsMLY+Fy>>wIHb_I7s6dja=?m1Z_+$LBr10%KV=InAim zx};0NDAA+K!u27XE&p!TBTK7w?VzIr^rBl+by-H1th#|!*W(Avb77H7z9zqvcOGo_ zRBcM_(s}Ch4mBOe-|Jf1h&L?GkY0j+E{IDJ>sj8rHQLYiiD6i_{3yie6Pk4Mw;T0# zN~77#MZRI!;%-xBy^8AMb7_&dbmM6IK)sB8@h$ZWczoPHK1L@^-@c$JKoPnJ-(lK! zhb*mo)bDnWY$aBPU&~Fhtx*O{Ht3eQ&1JG3?Ilb>!WgqdmDPNlElX6k?DkH7Dt_pj z<86gGGhP~P&X*xmCjFk=XNz}l6EM&rq<5WhVHl{csR##ZvJ-D zYAx=7iHCC>QS$K~><=5Gf(xvFvJT~EECz4Zxtr1GZ#N46e7Nf#pT~8Vckp1+%G^91 z{HbgHd^r`j>56=+XTkW~e!HE#%+dQ-V%doU{_iqzt*=R^FfK7??-U;|8WuG{k|-j| z0sGDgVn8n)Tdii$N!&DQwe~@V4HE2quKGZ4HCwIb{x8E((HMVi_U$2mW+|UprP;TC zDe0?4KR>IKRBe&(bdjglr?NC|3=y~Y2J8{x;ortiEp!=Y6-W#-xnLUC;XG^HX!YL^ zX2cCHd~O;y@DDQmTeYE)eZ8+CEYThHkj;jMYI?Z?F1U;vqi=klxu1hqo(Fn5wlRnk zKfnRuY^0XF?iU2gV~V7IX%YAac$3xXO+r3Pk`h7Wyp0G+*E5(QHF5k$4@7y$c_KId$BsWsh#+P1oN^S7I) zbc-vkiCSUTB;YMZCM9i1RGSVh0={o%im88PH>jS_<>t1iUoW_&mE~8)SA4yEWqiff z%U4fXFL+#kWWitq+JYGwHyD=e=BxVUGObxI{(>$SSRh{+U-bS0VJP8CK@VU-sAGYw$r#&!VIT-YJWA$}LHYR`H4UDiC*>CEJ~R`GrotG%R%VS=Ts7be`N&&_R?z zAr`EbtyU>0ShiM6Y4Zk?o;@U+8?A5X-M6lN%)iwG_tBAmy4XGyiusE1%#IBwm@RJI zJkHC~_*(8cU-La@@{~2i>v&`t@hsX(`kF1I$&P(zDS2bYE2B3AK%$ zB5PS4=&E#?^En6PcHvh#$IPTN7FRx|=oa4SKg4MsqmnO~FAMg#u|;xMCU-YBRM7n+ zWezqrx>-|yoBpfnW@Y|tt=(OFP+2(wsO{?zyNuNbH6lw zs~xgi(ynMH(%T7@N>;Q%>~f_q5!Am@>kq|+EX10ByI-1-C0!aw7>SVWc-}4`Msqw* z&vEa*T4vdNnZo({O&ZP}2CP+w%_Ilfj3;b}*AClL#X7DkLr?1|hGHLgr+R@EVJRzd z$1)m4O9bD^TCM$2)*q$iC=-Vi$}N{=RtYgBPGdBr;|Ai9n`SfU_`w1MpzPt~xz%cA zz%XEcd?w!SJODie2xG4B;pa7*wO|?PL!6o~h-jm0frfVN2|5nVJDtCsN%X%BT$qk4 z>;wk!5TAtTowB{V#L~&OSQ_>p!MANR{&)sFGH_sRlP+@uWQcoI7y^tjkNCAGS>%=O zWp)I?M)Wk~=-OT3KQ(uZ{}O^KSG#dy1AbM1tiktf-DtVUA#VeV%9xfNCp%M(e+|Df$nsk@< zH!-7!SL)@?p(f}TCnQByq+Ai47#o*WGEpjV5C3yEl4@H1=Nx47F%}Z6w~9Z(HJTcK z(+KAqWOx4m!#x_7@xLwisMHTyKNV(jqM&cn*vuLFeo)YNUW2}1Cc$n^K@_BN2Z*W4 z?LE7@+kvv)E|d+$p%+n>GXS-i8tRy;opO7jIJEk0V?3lF=t-)M^0prPrI&8C+6MBl z{-xvAqumklOkuO9ZO-u85hX6+GD(bovV;IrAT5vjviDINlo62AGxFPcR(MMYDXcRY zw#<*J3!x&b)Mq+jGd)mdIyvO50u>LcA|V&VK|}`9)-*tWDTlw@j4h+>wha>=%V(Bh zF($z3S#BFjW5KE{E(4mr|I2VIai1kU6KQ3+|I1BzBNHt2Jp{`pqZ|H)EnWksLa!D98Bxg(2J^rvD#|N+8XJfa#JUHq zmYzzz?{}ZKTK?W1$-tErn={|Sjfy9*O50saxJ`E3S=&{N$dqZkQTCy{BI-r1sV8Km zP02lF0W~rPQ(&OgNV1!PPCcrB@*x6F$e5j5;X2{W#iR#Pqf{iq%>DxUmt*+X?(B`* zHdoW-8Jcw8IC)vOb6A@tL)}vab(jCi9$QO*AkYC|!r>MlxJ5CP-9%`gSS*rJF846O z)V05GAYybR()YByBD@o|z@CPCjU*`1Mr9JPKPuJ{ZqpXH9 z3E>}Q62dPt3AxTBbDHe5K9Bg>JgGH3J4JoTB;k5t;ko(iuC>%+o0?E|L0tT&NMuR!~chScmntEYKP+E z?G9=FbeSYUu|pKu<_~*+PmxK+MKF6zAW56r5=Y*&nM`u8UMBfb6Qkld&rpRB$`!xywb3{B44Vxv<-<$)@X|jyymZI#upeI-BXk5JWIf_N?uG%YVKPu!Xb*X# zHiF+${6-xx`*DbfTu3-7L0;b9J%#}o=sxhv5<+HiMCkDOxBj|+`DYDjAnMS|P^%sR z!o&KGXG_?XY7uwu4++zuqQ^Q8-?yi9?{QK3uae>IW2W)QV1kshUY1&xzb z%+bx9F0!)3hdt1LZ<>K2$xQJlqr8B17Icj2!>3hcc&Gzmvop`3$nyrg=I_k+{0Vg( zZP$fd{T0hBU$h<`JR#%ZQ!_qi8O;z4yu(8pPbP1*6psN?=WdJ97ssZRGF_lQ2Mz#Q zt(D;Vm0_-wlfz1#n#!v@G28|-w}`#hR3`iYedRInHk%NCl|?+*=`>_^^16+k=`LkT zv@{(doqVgJgt$7R^JWJv@AW}mXta`ObczYVSIc|V{|^DDb&H}AFA^emIPtK*rVOG z+NKoA#;KQop%0jMabCQ4vpZCVYIgev5R<#=3?i_scEVXh?jNJw?V(&8r=cwIk-{GC z3~GCyFS5Y(;g*3up&%irw*_7hCuY8XWPN?~D7Pt8BNYA4e2;g^LOoejyvtSTtU{;X z(C8fg7uE4RRUL08rWVc(zGSy&CPt)|-WMS}Gt~`$6Wz0{c4V8=J{YI&=yp3&i~&A9 zw%07&%#AX4acgLogUS_1zJu}3v@0*FRY?fHMAFFmPtXr+!C(@y$4KH=@5^B^_K zZU2rS?X^Ed1XTy`?}*f3v!{22Q(`+iB)4wnzvkK5EwO!mN5EmJ9Ul^;!M4jDq|Nbv z{E$d$Y$t~VJ+v(8ugvB_LSERHcZ6@4_Sqc~8;||zj)3z(`}aFSQOEWV36Nj=`i^MK zrTy$q2@Cq$-Ilp|0bbSZAMOY~oVkT-4VL*V*BCSEV+EBi-bxCcOj9l`#d6}8{0 zbzJ*e9sCvQxb{`MyB{ieJ3+gP-nJos9+o!WlaIUlL9x|2RjEl-B?xA zJsG&L6Q={H6(Sl)+w?7azM29o4w*C`-(fw-2mOfs;I+ToesB;yQtfGwB#&90W0z>G zXU&AVw>2Cz9w?-V$!KH_N279V?MLLNJ4-r+da~&?b?RA=`eFT~n?;~psWke3h3duW zXB{ulkT7+Mju`qUYJ3AhW@zH4coDn;?0`rRnq496nv`;s++Lv8pmdZ~EJ`JuHOE1q zx3N1PyFdeFG^OrRx-0r04SR2_*9f2gXpOe0ac_5~J=v^XLaVAFtU`-cY!T-~v}}iR z&3YS!isaxjj||9}m_gs1nNv)EAyaBNr3Eq&*}2tQ#B*OezKQ0QtfFf{tFOi32NiZy zXM0=K4LD0Ap$1hCYFP6NXHdiaOi?@OtZE;gNWt^9X^~44{8}o}S*BznK;Yd$EtEP< zNX2-}&Iq#=vs0pCrtPY}eP(oMd|=>*mM?E<(aJ3ZhhuW#Otg_3!p8G|^5jg&Gp@nl zG%~?36>H~1x-czrt(bHChm8Z3+ueRh+n+wxgB9-qH8Z_E>_`MP^^yZddSrl2W$MvQ z@0mi*O6kASB4^6x^G|g@#BHr`^E)__pWX)E-H$-U@G0=^Q`iQpAFoqSewO?5KQue` zf7RKs|B2-)c!9rb)t^RxTi!Buk?2FkB^T?s6G*AluCXgj=|ArNNMpciRs|7EW+r4O zydRD+ozIiNO%26<{7L(bh&Pm~!Zr-92KorvHN6s*Q%7%5@E{`KTXN!7<$<2#4il`^ z6ICjrfQQ`ixCjr$!l0tTom*?(Ai*V(=13A0c2R^cLv zN|-uxjL@L@0N%>u&6DLUZMVse((N`$D_$TQ6Qv+7zkmUM-Pi5CaXIqaqmE@VYr4immptEC`^1NnyjR#lu!4b2CPkO^X$+#Z5=Mgks|2sqFn$VicYVPSUmNza{! zVtyB-@$Z41p9A44Vwc9+SR5+fmio7u`pwh7Me4Uu|CXtL?fLq*`$Oj;MgQrm)#{aS zVIs26&&eVSKF9NAZch(4`XV9pF{3MERR)!~M?b6zL_#hjWFu2N!sxFG|GYObim zo-1xW;nXv5H|VKhoj6C|QL3>{PP&KBd)B}mu9LCj&dEAyx5*lUj(_uAf1NllzOnJ` z7@QKU6X*DUTdOy4heyvLH$HtMo?h^$W0Cgl;n*3vbMpCc46ogTBkldWZ|Unj``kU2 z?@}fAyn5WmNMmTjOA>L-t}=U(usr>EYewKkZhc6_Z5dDk1~scJ7Yj4%1fMbPYd?h$ zgJvKFznV``15`iiKcRO=RKtdeLV@#LUjgjQAGx9KU>1mhgN0O1Y^ZX3GGl^- zE{#nEpfC`mr@J7u<1<9U1=!JXD;{p@r=DxusbLhQ3>N$zeD`gu1;5?yaalH}Pn!Jv z&rSY+PpcJvrSp-VlK|y#vqfPp4waYLAp|ePFrlUvH7!y4z5_nIjorY@Rj?(GtQhK2 zQyPlYuNxDP=-WezOx=SctJPZ70kPF;YEb+$00bYt;4;6>Ox`g_#wqvN0BBfUHTvqn zWd`~bu?g-oI2UyCjU}`)pI9?+N)eJid86uo>OR(bECL+*BsI!XJmb#3bqc!OW3VkcdEPf6-hc!Y#P_u997$rU1=o?!RXFArNdS0% z`Ht0=GvLw1Us*&;y~AYJUgJxV0`{XUeI&qwL`R1tB%WpZmhFq#`ZYCuI!*8c8em7? zv|67IOyBB*Cw;q0w|$G`)liE{yT{-3Ad`^pOn1#x7p5|Q?ZZT1!t>{JmY*N7-|yJ(G5tO2vfo4Y%klxJ zb6l!c%7)j zmGUb)^%%LY}>YNI}=ZAKCx}vwr$%^o;Z2qOq~2V`>VdHeXx6X zpX{ox>aOnVUhAJ$#od>WXlx$stH8{i`G))>SnbUgl+1VXV3RYLIqk%$5mQ^yLk!JJ z7XN656GviHgJo)PSjilZ3?S^GkL z#vilatB2O)>aqnoj5-8I>6XsfmK6m-A~^5tj8o>d`a2Vf>FnH0Jq$4P;@%eG>)2JTyxwgJwWca@_PNs2!Mfz( zMNMMAk~*{t4BVL2Er4x<*X6qu@*m#!Gl9)EI5w&?4zg2Q&$g+@*fx-2W~nGpzX?Kn z4o?>xR4Dhk-zvdBl+DE zn8YN`#y@A@Bb;H7(FVkRRM}DHV+z8gUb&CDOJ+W zB9_Uw9pNMsHB&%W>#EDxtNzs1#Tb_-3XAKx@JusnzC4lossDJo&F}ADUeaN|a@%z3 zm8Cj_$X+kT8_}&G(%kR_+X!BMH6uM1Yk2+#Qb%+5qSv9lY%5ATr2;7ixNE*1huDHm z%BweE0gcEYEdr!kTC~9M1#`{b83WAUpALT^DP+ch_t5lMwZY;&yP}Mr_IdaQJWC$J z;sbL7*ODYP(=Td!Sy4J6)%I_-{<$wV-cWZ~mpZBN%63h@(&SFv$>HghodES;&}sxb z^=yhFJ_b^F!TGW+Ra#*g_OcoFU=4c-d`qX?Nz!h_v;n&}{Caa8t+|xH#8K9q|IDfNB)|!{{?0~zr7OSm6tT$}sEOe5 zt&*YN^C>eb`4&^Fo+wLHuASBTHI zA24&S(WuQuCa{5NB#5nAM;;k?Zdmr`x(GraQ*c$D-QiC2DvtdQ>rp9CoBcgD{y;R9Cg9?XcZ&9H)>6{uydM>7kCsG?OzdL{*G%Eg_k>lXL13~Ob$&EC@!uj;~6MTo!cKb6EqjB zxdXS;X`BAsPe|rPnOppMp)xw=W|bE;cWPlE#+I>8GM^z4 z5`qo(J+C{W`p>{=t+PCBtJD8m(1vKOyqFz%O`mhv7~ROdK7dDo_%hRMF8bS`+y#&? zeN1+Cf+^Jd4exCd!L=#}dNsx075tA9Y|$dQoNH#PvD*a?TE`M;{CAO+g0oU8c&?u` z-?kg4!QqJ~@Z&>x|A7xEJYs%5_&b)f_9jd2{puoH0=}dUSD-bJXW7Dx=arAPSYKG= zC`65g5BtV=TE_er$VS`t)x&M57t{~`@Xmqod@3k6<(gZ+{Tn*A*yu6}t5~G9^=%V> zD)iv<*RCh>qf?JeO={wU5KK7ML&yZ_{Bt$5hmjLSILv=KkQS+4B+sQh_uytty*zbL zkU~lSD0nP{)|B9WJgEH7WJ(9YNdeSEYNMZ(Aid$_E@QUP5R6w(4s?gU@JoQnm@T(X zTpeme-WYzID!reBxx>>Y9{v%xzrhmiQZi_2s`L!}`;^+L|YCXx;NQb@`&rT*%pHuyLaxv*Z#v5F^0z-ev(&-~6?% znA#)}+4aq{s9VEAz*qEpg{Sp~MSy1|^=`IZl*FH;Nl;B4m|uofgPN6GBROZ`5lKYZ z23Xnsxz=Sq{Jg4M+$~pz@DIxul#E^Z#qL6l3JCNTQ{n?;%fBy-oy!>m5}!_)vhqp z)JQrhn|~Bi3O9WYYG1f0G=$2Nhys~3DJ(^n)yZu%v5f_13rGM*ff!Aw{H2n4m0%l^ zTw`ed35`{1M4)MJWopTeP#chHPVyWtg!%pbji$chNXY_JK*24EdDfb3?UEZJzXI&; zowXYJn zO;Uf6UU7j|+*bhYfwQpVd&3EXOLtd!-h*d7|G6_h(u+<(?tWNrNH*xf4YP7MAzp^Z6n*9vugs9`D8e`)ldI=lg9chA2 z=5j#_S2QO>O*1-k+s}p{S+sTYzVKH8&EQg1qnpQ`_!6@qK^f_<<6v7U-pw-*KZ!&q z3w9e2ge2ddN4w=K%1XY8UzQ`lfRImzv0MpYHJ>~pR69BtifJ(0Nbv(JOg=tBL29=r z5hC5)p)Usvsb#_n7j3M$5Ke~ubY$x3KAQO|3RhD7NMJu;c_usSrM7%q!VbbzBgxLD{~yro)P>&uh} z&c9##DY+RC>Xc4LC91NytHF!8pL=3ZOg=tyKiyY@CRM>`0}; zSNRM=rrsp8`OrWZzTs0!1jik40`7=#nPasuv*y2C2!>QX}BL^~r56n+D zV-OEps>~Q9?*C`XYy zEELww;u9-O-k{nc)P<+)=Fz745LTHNwVf^SXKD8)Gf1?Wx`%T5{YF6pl2ciFvM*7aHho=m#b6I9fG{<3BLvwNSlM{ zW7Tx~`1XjtGKj0BxRo@YFmCq~&rdN|M21q_6jWYL0zpHoR^KI<fh$=9S%hHZBU7zIxB?|Tq4I$A zsH7mti!oF#2nVXMizCVL!r3Io^=hhE3S(6&DI@CElKZL9ZbkI@C0>k3Am8_;Go+J@ zn#*v&0i|WjB3>nc<~XZNV*Hc zh2i*A|M=0A2U4t=zNtLus74=l$7O#icM>K{jc<(QJOB3?-rWa@$5dL++7q$=I_4au zmuE_|PLpR`s4Ns}$m|(jCh^EF$K;YL9PL6dT?*<8$LfxG^pXzn*6#NIy8-qwe&5#J z4(%BYs^b(9m21b`8YaA(n{+cbhS|YeOyALq>}QE+;*XdfR`OF(z#LB8!!rmECx$Sm zuf)sfS0{}?=yg11#}ao7x`g_ox&K4!Zo-wEqRU5aguCsHQV)LkD`8Zx|KbkwojcS= z`tpqU;XNP}uwf4<`r8`}x_79{9JHE91m=d$Ky^zPtQ&wdvyHu(33-kxbRyz@q69*t zMaH0)mcOBfZ2x7tPiM`sQ*6MXkUCcYT#^W4lKv;h4Vv&fx{J@VMF>vey10@*Ay z)fZ6*81H}MX^m`)o*d3-rr=pe4%@8YJLjle*(b2OKA|1}`xc#!_MSYWPmht;%uXX4 z0wq9p-8`2vzUn8gW&QO?+=nOb=`!g|6Jd1>7k`=$EdhDt& z7L9j4{tM*=@Ik`6BZOTCeWdv2NyAF4zq%5Xl@_Q(RSnViEYtkH5CnGT>t}TL@~ka) zQ7E_pL`)CX`#|Zzo|6{KE>|;7!DnREP8H22jHLDLLH_{fKQOGDg6%;F;^Fc?38pQk z?&${W%Lz%Fh(Nics{PKkKmHr-4NW9c44!n&+gwm(hct2x~N1mJks z2HG?s%~%l4P-9tgBUu_nB3Z7Pgp*-0oclR-0DEGn4>8}MAN<`6suzz_O;S_>VVP+G z(q^ztM2pi{_2NR_A?>mL=b-u&6A?wh93F%dTIC8P@o&CjMcpO-8pc&-O4l?BxW;+n z=1t-NdbynAFz4|8;0tlsJNk1J8!jD!?z7z3)G%o1)0c0sFT&o8=K2Fb&)jcbMc1KGIRA=1gGZ3%E2E?3jKHe^ zayWdcD541XKI*OS`aqaTo)2Rie3q+z+^k%se$+F^io&ohAjzC;C_%uAY<71ZYxFPk zGx@d^Yl<3;U2Asuf*XjXNcT_`@W=!Ban%6Kqt9YQCmW5poN}j{V4P^$6tn1NcC}5w zzW{o8bZCu=OcIm}y2e+M@ks3G00NF49}Fx4mxu-!R)1^MQP$ zz5k4@dGgFjxO3`Q+y{Dv2y`84ZVQmDywgWCDye){MI5WprA`HnQ8dc*sgl!E;8#Pk zAZs^ib-L>NHQ}ij|AV{K0gYSfi18H!C>7#=mOEy{K_mH&AsR?`sPjqq^)(Th_UhDh z{u3rtyTkUW^^TYgq|!27u3U<{*~3iWX(cf-~Mlvgyk+M9!?@%7SR%_Lmyd65XC6Ut zVXpn;!r3Itro=`A!d2K^3i0~_^FGqS$I!;n#mf7`L{-(q<-^UM57R3`hOch3A8dk} zybYUmG$E4I^T;Sp#=F+>*LbBL%RkOl5Ae2pxMu8wozPU~zc(@O=6g_pvKVOZG1De{ zz{(iq<>f-TYTDnYsfF^U90bp~Am&vqO-ou^_v?G3m$|2O_St;e-X`};nvyLZwFm}^mIbS@T;xaGBbVO zjb6NX2nbv}OZ1t0fA+X)1h>uh2e#`qm#a^xi@QCSY0`^rG9H9qm(PxUYAVDHh9WF{ z!i-~N@QM4Z?Vk0>^X8($DcT@u&Is_|Hpze(6rHUi>Y;Xv_alaO!x>h=Hp2BJ+hJpH zGi_n8pDO4u#AbeYoT+8x!O_W?MXneeP$@f{e6LllKXz=+xJdxTM@}SSLp&3=Qakg% z<4Bt&aYSds=eF@9A?HarBn=H0DzDgzJciGP*Y+^w%6SR~eeWJ`ZiAL*N1tP?L@=~D zY71yw^tDNS`41-ullr-r_`zK*Z$3gA_jQt_OGIcEmizkEQDYt+nPIoVWyYLOlmqr2 zm3af-CIV4C5zqj7vdMQJj-V~#uiV+77OZ?aP)pwIZ(yJXS4pA15awEDw{AtY*Nm7>qTm#Z_C)%Q=+Nzee;BoyozOLy{^J)wA{2MvVTGv=)tf-e=x-y z70j5l{UZTIQFKaWMDTvPqrYXchVf2*)O{ve20|Xu5m~3g8sqNTnRait{&FOI+hx19 z9AWSneI)svBl~hA^utS;WX{OO(Sy1#Guv$L31J!jz?;ls*etz|=3;K4Kaf-h(8S)6 zzW+exp{W%oi}|@RuzX{iOd{j~xs-M&K)D*b^BVvTac?ORVNw9A81$5XXq(-rUne64 zq_>YB6+zz+C7`$1nUKOc?GXAy(ei~7p(>Kzlu=U&DT-dTeO^2~0$L9O>})hW8x&va zW+O32>2F4-HYV^x0k}MKP3g(xjMe6x>?#i=L5Ax^4`Q!bk*r#Ry?$+O+KNEijOR2Q zyZ}Ts>-aLM9!{AJV*W{QANg~_@Iq?KsfVdX2eTVi4}eK*&tI+C2!<6lmGOQcf!EV2 z?Ngxx9cOL?FPxNac3~w<(^463X7(wLnMs92Nr5dXmm-))vUmKOwTF99e;zoWYq_qv|J0wsCDkHmFEvfrV*r3Ayf z$~i5tF9dtjsYsz%l$N}?c6l8*@`+7oR~xNN!vYB@8KSJwVnA(`@Y99r=DmvHXpz$< z66ENZ?8*+7A;E8wE53;y3oh#~dbGu8cdyRD*z(p+ut?!A!|uggh76c=dzqR^ z^95uK^%l4EcUD-`>4~1fE`XC=NVHau+l<1pFAmt#4G6aybxa_V{~p)u0lYZ7kEt^o zyg7l)=Yesn5ptCGTR-O8HuBvmD}(m7AVfIURN#U&)Fs`%t231<-2@Pw6Hu*&K6AWe z@6v}x4wv^;R-S|(PHbB-(3q0Fva-UtFk1b6-~2Z<5*I z%20*jdX$V=?EtHi%&3Q_it>jwTs+RkM_`~s?)vZI4qc3js28`@~E2k`I$g0wvL2ZIY) zH|)kYET_Wj{qU&04(~tl3ta(ABSzdug6yd{2P6-AQ`kIDqB#Y7?!Td~H9i&53DDA( z{$Ke{#TDI&aZgQDVmze_vs0+5$HRdCVzF2H_Wr4j|@!VU7O%$jqX<&sSr**+~bW9b3aN&Z7a`M161V=>viXvVBuC z*a;T6MHu8MniJ`&BzQu-*xsO}TS9vLS~g9M0>7B;P^n7%?@COJiR*TJD6cAo1k|(p z{?5GH^DniS>9tkxIeKpE7Iy#a47lac&<^fmwC)=qplwL#5@5GBzFNCB+K!1Eo#Yz? zL)2^HDzH3{wzdC9I*Bowd$11do|(u|XgATAjEsk9S~#{H!k|^muVHy(9Mx?SHKR50 zUf_6IKiN|$Ia!pEdrQr!v~u~SRs~oxY3o+CZ9XNl>`d+0Mb9m($D*TpzmS$~&&a)I z7qERWe8s8Q4)C}yQC5U~+4fdptDIyMVyjNxiieI|9r8s73bqY>+V zs`xVAK|l|CB)1)WSM~^|vRVte*ao$j#-GX|EESkU&PcFYd~2h{F4g>{5;^;2>J_I; zQ8Q_DUD3RAVe256)0Ke?SF(Yp{v2`V*EiCj;Aq&+Rc9?)Btc++lwzKj%MCeSL3$4ezD@S`+B>AD_7uL5C*U zhy#m{t0!wUG7BYm)hjBbCNfqapxek2J67DncN zMzHP*@+&SGr&!j~+DC+gHU036hh$wuCW4W|z*O zcVJ}NIk|VD1zTW;=9xqAf~Q$wdA)6N`!o zoY!*++jap%Kp7i+u<14IlvlqNBo$9`wMtu^%Tur!t(CF3q@0$UP;EUDnIV*br#+hq zvFzb*QiJX2k_t{^Z%%_>P6ToleX35Jv%4e4*n0%S3tZ_ip>j^hxO;UU8tR!8fRC7F zPkr&<2A*hcxI#~`xdPAK2>a6@bqNn-My!#NYlD?hliB?ak6OuxNP{GO%RwgpsLIX+ zrn(m%wXiF&aCgWlg40r_>MfJEfz+e|LyNwuB0IO!i4=UYTfyGbJJ7zu=L&vw#W^Im6@{?Zo-VSh! zT9NJtSC=yx?(%3LmA(G*Xf{ZT{CovSrn9mJ#aB#s6lfBi?reKNX*otPbPpZ4`LtdD zXfQF_-(Br&=8iK;I^LL1BfNTu+@2F$<{RP#Qa-qk5AYHDyro`myqUX1K$H@Qb?Ske zir$8f{d{GyRcvLbuuBbGRKmf{NJ6riYH9#Eb~gTD4c2}}>^fHS_q;xb*@jDG`b;@~yDG>N>Zj3m5!dTOys8oh5;No zd`YBdYwC8r)BM@m1pHfYbuEjB0COnZtjtC4?QeU!o`d-DaB zEPYe-MYyV!?~9*BZ{(MV`qOz5RngpBic%EoDPz1NxBKPU`F?RwsU@O~n6s64O~ zbi5W#hS+dMm=Yme)$=*Um!GGuE^<48u@L$RFCJ<<5?0BZGS9glN#{59V`WX&lf zmYq{gu)@Zd#q${}xI-Z&LPE#iRwQo(ajoS?m(KD23&@M7LfAYS7dj&RDH21r zuu_iGGANIoLCx{qF~;l0h>w>l!&{62E?&d=>*oP@0A6+C1gFy}>6l)Ijc-mCbV*7q{3mss81yb75B zOW1A^mvO*i_*Va1c%7oE&v+ML*y1s}?qq|#;)Ig*OHMoOlvFrI2@fhop9uUFy9rJAm2 zV4v<8U{@E0MQV+Uh69^8Bp--#xQ}+4C#FQ!mhS1kKH}3>0xMkzvb4gr5;k@d$M~!O zRVLZ9yZcVs-iz<9_{{JO)iZT{x8dEsm-AmvcHf$eOB};&R~qRnfzN_NxU&HEof7;O zWzk=M{jvgiAClNg#areD@*xr*F3p>y1uFD;t?sXZuY3~X9uP9H=CF(ug=z}J`9%5v z@2%g+>&j>z09$9qJ1k-JEVtz&yneU6V2HKY%yX03#ALHmU@JEmMSkhq%NEXxWbj0Q9x_6x7Z{ zFL0YD_D1K|t^@s&&SpdxdMmnt@{l8dIXFqxH*U86GZM;lU4uqhhICn_x?^)}TRLFv zUt>qdf|D(}xxHZbM(PQbY_mSf&f`DZB4BY=i^5h%jV^s4rBoZ?qZ?o0v=p-OrDwa0 z?36x(tWE*BI(^cbvA`~<+aGTRj}(-U;MNYco72yEC%mQ>g{I`b2MoYz6($WpeG-~j zV4+lZtip;^4UbfNvaS!}iGTjK3hT|E)-sT0Yh&g7OF0eu1cfH=X~xlCa(I3ykMSi< zZ2jdK=i40pu0jcpS;*CBW_M2V-P_{E2DzB0@w1}!&S6S@%y~&iCy%Z4d-X@$x+zF8 zZN=SYVo*ee@RcujRnTIPU8o2cp8`%Lk-iOvrO^Bs6R3p^brR z2F7RViA-4xoLllyNZCfu64hResvtumF)MLVrC{yBW2)(ut^G^>NY`cpnWYy6w$xg-j;M z-ImfGDk~EUDvTYCuGNWx2|la+jBSQfE_0BAX1Sg%#yD`4_$OuXENm^q_8V8;lrQU* z-E30iNT*RQKB1UeC~Yc(lTfuyHo~dU?vtw6zjZ7MqC@f=3|fq;e0%Qq8ijB*_Fusk zoRS6K?wdh=@JzvjJf|1{`r2)7s7tI^V{wFK{sCOB-2AEjB#^XloH;!rey;z-i7GdM z5#@M6LRl;rgFKkko+MFP7*WL1Nn|@T*iU8G*Drpt1>}t#Hv(kZfJ4{exPy6iD56x0 zf`YuP@0^!1I{eit-f0w?37vu~`8zy8tdrtR&V^F{t;hp)RFn)*andW1H28J)uowRW z(Q1g1gJf2yQ*bPF@@2;xcTqUfP2EuqV<535rzbI3B2f{grR_MlAk!OqbeqhGYEw;h z2;nb2?i1Que0&3wD1EtL1S04>h9p`v%u$YGbqm}dKbqy{#{$zlp*|lWD z04SxchK&o`F2VrX0{hrfQWMi3POUs6&cH&l8bHF?ii1~!qDhz~atK>8&rXkLMWBlS z8i);!vdY{AwF?Vj*N!^1P5SjHM|!_R{e;F;CS3yFMJ|ge890-0>4GDgTmwbC(#=tNtQHF6yEhtS+Ih@Y&ZSP3~ zgVS`y?n#9%VOAIyXuO6Ml?s^P!SChrF_o%)lKwqyUPbrBSftl1*oj;a*gT)Qt*`!ac|g5Pd9-mL3|*V@*d;s>7swKn8E zY0VK7`GEEGAV55Xf=BbYtBEFdO^;nzJt0y4O~K1M8r1`5QDe^h&*1dG*c`=NhvlA+ZF;D zJ34@VA1h%EuJhz*dRxoXp7^TmA^2x#-{W*yzDf==E-~g5+R_W`bGl?NivVT&0kZ8> z0#*i@1i2@MK87pl?`fHM0}1InlHwlRUzzsm%3oc-uQ|1xfIXwU^|)Z<(VAY_)#aHw zi{=&M6zNI<4GSNG|8ZVyi&WaVTE941FJDyQ6Yd?q9Ad=wNy9dZxQStiWGMWI&YH-| zB|g5MTU2@eP9a^x+mPAms#0~Ga)t4R@@O^`^yJ{}v%W10G?(>sL-V;W_O zFdKQ(0tQIl7Hms=^vUWkk*2 z`jGs(nZ(^Iqf4DMtMPZ{3xgd*akUmY>+cQ_sCy6u75`KP+#ohK0_ctL~sPQ{W#FSs6jh3i1j^8^Y?=wUGPCRjkuOp#sL4EkN^!# zs0}UbKgPxmO>jZD>e$=GgZoezP@H8Wm;4zf@b;7GiP;GKd<0k_|QP4qG_y~<|O#Q0^>0@nB-wbxUM*F7=lmW!xA3wht zln}W$Cv9Hbjh;z`{U_fD5bqf%JPHfNDbF;{G_Y^}^CrX8E*&_4h>BnrYZT8MC|n8y zwNB7aD5`~q&3UNV41Hx8-T0bTuz^cIuzh-|^Pu^?BJ&V-fp;UIY|(q4Kv^-}XCwF# zl>$WmPPh9wXsaBhm~eJtLz0_YMu_}yw0DPM*SBM(IZdk$ zuA_-n+256Z_}NuY5)PVcC+N=rLX9&#@o)GfY_GMhO}DG-`@i4cN3SMd(SV-??|+{E zZU0aA|2Ov#zmMv~pCu0M#*7uYHujUobDA(I^k7xCFPHI?ozZC+y--F9AwQk4cv~~> zH6x<($-J;WgunU&;o9AnudBR$pIQtfukXARp9%Q)a05ZF!_Q1r07)r$$T4O0;V&(^ z`tcDK2`r3cUtk{dcOqzb6#v+fqWyNONOwg$^}X5GSbX6uBFa5;9*Stk984da3~H0{1#r1A%$(^gwwrLMSw2WXA)K~vUv3J)pYteZ!K=%m{n4+!RnT+D zLeN4OE+o?+XQo<0Ve)GrU=&^gVMc}o{{dQ8$s*LN#tCnSo7e6MWCZ186#tMzdr+IsVG)z*SL^i<4EnvJJ;< zT^qFYT_EM8Kb}6XDw;_?32CK;)2H10WHL@BiHc;8-2Ct~ma(5JNeit{a3pVxwOc{urlX*GNpB=7%qqWLB87Ye#4C$NBc}Z14IaP z6$CBvY>*#{HqR91xQ50wd>F%eG5_1D{(miszDc_YfPXbz&B!e`y>x!hgjFsut)*>? zbd5WG&Cvg*&1ZU|9tb!iN<&6|I0-y`d^E)|Yp~&01scc1);j>vl*}A!j2S%~yRybH+iD}%_h&2rne1du{Jvqt?i4dTpNdbwZe?! zTP#oqfRCn)&<)#l!qcIB-gw*SpeclUSmK8(wSo{Po5^szmP`_?F}xX-C(!Wek?g5% z4W*{M!awhF?Z@S@V0rWdTWy8xwRQcY$*8~F$}Pp7S5rFhU-*+7Ml_a8%F z)w&K0Jaq95{uva?ksgpx;jMtCY&AU(FI!kq_3j|F8o!ld0U8;|wZo zsaHXDi<)8QiXPoTG+c(Z6p@pGhNHZ1NZBLO@#(lc&D3&$;hNhe@2^%KD&sm6&VbM% zKoMS<%jZ>e@^`~z&Hh$a@r^c4j=TDaIBZiUjw5W|IG@h%Lsvt+8Ssl*L9nzv9#+#6 zhK@e%Rhy=N3jZCvpgTzXn`LMtgo!QSGBb>)BM_67?NU1Zmr4I{TC|5Wt2o=$C?E_5 z|6i(3OcBZz`)&ZrdS0rAft+_!Gt~~*1Ays$XJupH`0jOM|F+$|!QJ!rp>_8uv4+fG z-rWw@$Z6Tlnn}((Eo}$*Ny`-zrx1(8Fb8`q#1Y4U<+ym;DA%%h9)+^p3cdc{Q^)JSB?+q~rV~{u0OY3eiz~4A-L=MW$h2(DA0nV4~%}uTg;MH{%y`NY=_f z;s}V57^-B`^Dc=zIO8TV0P7JcK%UdQjP3_?nV|?|$|XXJ$%z~DVQAdVj=?NQL*Mn7 z$Y8m0NW5hb@UJ{*gy+= zUOco-rY>d(Bo7^jdf<(&3sIN_TyKw2YMdUQXSt7@ zV`sA3vF_;0>L4p7(vsIM@45Ya004T9KzRHQHB*w%JWf(ZPB=}B}8 zC<8cYYRCtJM>a56mbw10u(S3Yq%Meqk;HgYWHZC|;QV@kDJ?!b7~4v5>{75Gb()Z9 zAWESS&>o!ZNpB4S*e`_uW1vjLbW4awphIR|>JJ*Shze6EF{rK^cor&3i3;2rx`wvz zYwW;Qu0e!F)+pqQ?pAUkJ8dyneWeR^R1H=t&`D96*0c{K!vIh1@WCe4$t{Iw?WY-j zo_Xa9iE#qpgbB#vP>(T!3iyb!9P;-SFu{^faiYMqxx^9`1fMF1&{@HiFMw=^hhC_@ z!h2yt+yzGOM{fKEUg0f)LHKA0RD_;A;+&FwZ{@>xWJ?iGaYYCz>&zq#2Q@VYXnK8O zgPXfINFFUrrI}(|=&iF^z*NrCR#>`9*;o%3RucpMNiJ)bYKO~)9}16}s}ywzH;P5} zzpj87qu6s3qj@e^;!q;iuAPey$o(~A*~Y#zZOUfo$8SLwlQf`ilhUAtl#*<~s8ahg z^pM7I*7V1qBL;DMMwmlYPJyi2j<{r?-P)ZQW8fI>T&O)TN3n3u|CMwbRKnI=1`9eUU);!}c=3^yhPE+xiy6zSQ1 zSvy777OWyG|9iyv3?-sM+w}SLx9*a4Hc02WxL_Vvl^wjdg(63P|-WHIm)U%0K z?wKdDc%na^Q&#S{xWVzrf2c>6v*RfaMuMTRkz^ho19J%sL>v(Ihrqs04g(HD`^Jd~ z>^OS-xsDm;U931Q+60#fWbEE5z(52@n;Od{YN8{O%%UDvr-w#U$RYNC6rGgeez3i) zU<^$J;_94XNi>cL%fp%A)s)_=a;J3oZ(@~q;=qC*8@y#M9{)uTi^?ce@JI%#KCB1t z6H^!BP@5pu46w+{LGa5X@GAm2?FnejoiGTIE@nkHR))X387_Z*{e$p2Enspt#_>m!YL$}K*aNQh{WK106o zTl4KM^{Ce3K`P&jIn>c6&U>KQMr(zCNOs0?z_H=85UecjKR{URVgIYRG7x*^OMoCX ztZUZ@Gr%b(Dda>(Yaaq@s5Ap` zYL6LAGdh2O?85DUsgmF~gBrUXr`-OJ;g(PHLN6T@OSXN#GB$9zBg~xv<(O4I6gT%f zPMiieefAKWG8=P=1{{sRgy{avx7@lbu8|t(t0y&IaiF3AcY+ai1X@4OyBX;gZ!D z17gcR+sL}o(C~l5(jJ0&9BirDrZ|)XSnCjjlYfnRAW3UuLfw5{tQ>k-L$I{BmAdj} zfJs{9WOp@m!pP{R*`-SWRS3jTs}EeF^zzE27Y)F#!jLjHn;8*2K@xpwdfy1S(->%7 z>h|!$^92z+r${SL!MsM8%M7o4av2l2jL7o#^t4Hr$4wEfyzEVedN#z3+Qc&rQ z11|=^nsD?1eH6!8L*=dP{mq3k8Wpyq58n>p;S^*~C<=F|PW8Z!wm)X~wwhXT!OI(q zv~GhAjiA1T0Sk&qsr0Xj+Lfa2G&t$PG_k^baZkMso69>B@sh8TitauSx`dw_E7Tc! z5@{yd$OxkRUC;!8cD{Hsr+%4CErcNA#GiQ+ldlWu``rr4Nt?1=>A0-20S z&{Vu3@^=f8t2jmjSg7XTSuq27;Ml^oD-ZqR&9gzrRbQUOh9}k86Vsb$F>1(5NycIL zx1)jL6y5tuQr9>nwK$__!ypmuXIwJ{Dam3Lby~F5gO@4WbQ)$_EFr2XEPiE@*Pg-S z5-e7fBvC_y-MKY=b z1L6WTZ7X>637^5p^7LjBg|7W=pi?TWAjgrbglu9P4!yiV%jy1O6|p&Przu*Wj{Yyz zm3oNR&7U)j(pI8mdrM04kr8fbWH#d>zP8_xw7sYeJ#DkFMLTzfPrNo;L{FhT zQcXa$(rMU*`Z$7GOD+|yfu`f0yhK`i`bf1YovO1YU1lk{tYSn%j>=tlWwC0ShTYzb zICT*)wWHKQSM{*kUGWo|Y0;5kcofI+bmmTZY<6kE7A){gqzI=eVe9T9s*yU;!;m5H zio~x|p@3INts-;ODps|hwVH$y(k)hXnh-j-Rxw4FBHh%Ysx|zz$i2|=vehrEkQv<` z8flFtw#-eHbE%vUS{qVKiIqYYCy)!ZHzg zE}^(u#_kudC3(~m((&V8oakCom6IVpjx0rP%F17i9LlBEyynbBw<1J4BpYZSCgg>H zkt`~5>PRTyTlWyeL~^NCfO4?(kzmr}2U9>k9-NChb<(w zQ$j|~kR*v66+GvfBh+A=+B?$bQxrB4RAzyDO`$klN%&WToVY)7gluFXXaDs9X5Mcb z7*;L%Qh059@Vs>)leSLC)dq-p&={u)wf^u!A*19u-TD3il%pn0^WUAciO=N#Mn}G? zdC^yC9N)4Y_V9B4dvI!mA)FRnj&7tzA4~vf&(XTIKL$iTUSMMD8kDyNsX{c>EP@Iu z+*Zww1hjs0M^+1z$L-c%Py(8^uD|Vk{VVaH+m9788|1iU26N2=23{aZP^ZI)OAGe8 zpKf218xFEm(dGNz18u>!Y`N@!Mr=BBjbA7lva&tSOsD23+2Rl5pT<=QI5j3l&? zk^bkz$ye|=n@_7=??|uBvE%R*RPs%^n1oT8HZJE?wAp0{J2f>rj<##loolMSAfOo< z8-H!rT5A+$s{fC)Yl;pmShkti$;7s8+ni)#Yi45GCz#l_Cbn(cwrxAPx$AzvueVm8 z{-|E3`lrw7RaLw89^6OSGN>y)Em{4edvDM*1nbklUQ2*cx=mmPdqlii{-N-dGVohg za6|rAP-Rh-TTqu$gq31kTf8M;9!56i#dwPoMpgx@Mm>1G^5y{0(%iVd6i6IF0am zA*64FMa?&G7V&B}(#WZzfF6+^yrWrBS@ z?~S(`!v|Go#c9=^#1e}C4~+@{VLn1w;k2?Uewb~}KyN0bK7cK(PE*LQ#eiXKpu`O3 z6r~te!e7@U>MPJ<9VDGhbCJqG2}iKrN&(eAoJu!TKv!HZaB+ciAGo_{HCT!3RLJ1p z+DhMgKfU}H2$U%RH*o;7$BhU~oHu2|!KE(+zZ&OnQFALpkKhVaHeLmMaIU+|mdhV{ zkseU=udjMzac-`9QNp;KGWVc%tEWxn{K6+k7XlBUp);3WZtZhb35c8G(D6dO9Z%@b z-PS?S4HV$SaV=yj)Lujq=AhiZQ2s@)U-!I|T(d2JULdL-F_4Bkc!uR+2#w(tHmqW3 zPlpUim*#rnyh3s7WRv^|-ByS(t zsV!maPI#KuO(wx^KTg4`6SVpn6p^JKvsp@aN?XKeR|4!n&Ss6>wCG%RmQ8POp+l$} z)(cC9X{H^Kz{hmHuVn8&Ef`OkscKt~z{)z!S+EysdhFqYm~^}ll-?$A_8)4X=7b2U zHBg_D%|+O_MF8$|W(##eWfO5H_Uz_G>+W+;>JGI&t8koZKR7KSZ=-EAP9qY-o~RYr z(<9zgrXkSdTIV_So9XLL)p5^V$0PFQ36bT`9-yGVI0vINbaJJ9^4`2BNy? z4;zK8jcyC#)%A5Gd4wu4+IIV+akr-WQyP96k_DR^X96={>Hzul+8~Tza4V!lRyIBN z*<8+Qc>E3R#C!_fVdNGc@V2D+89C-LnARj~$@SSmT_z@-$2&2)=`E^AQnTxr20G`K zyjF#mO%wicyt0pm7P|Pbe>9Dm6D%ojz-Jc{} zk%8v;O}Zl-N&G_-HkBua`JKnmT4T+JAsMT$R3)e`|Kn`x;cPC_G7?EEePP$R)bsjr zmEI?a`SwF{ww_}=k>8?G?_RLOo>Ra6Oj=uM_oxJ;Dt2!za|xVomrMR{Vl`!hnN=z+ zYX^W}ib$x>Q@mPJw&U#X=Iw5TtCu`5aJ^jJQEGf`x!zDx<>KCN!?@81TZKknsGr1N zApfZC(VvbF!F&ARZ(EkrX-M|6sN0icze^s7gh%-ghNBr1dG>?J8~|mc!bS3KsS{Yf zlvD{O#k%^(2Z^L3mk9~?02AHpT3^31&w5@I?hc6^&4-r_S|(F2zs$73otTjvS$}7!3DP671R?Yr6E*9CcwXVePEj?EQZ4w z%w4oiexqIISdzm~fAT^XLkyGmQ}0iGD+lOa-YGJ<>ZMdCS!yBDg^nDEg^ZN+cJm*^ z#O~xt#)DwZqBwIuiCr?>81o(babK0~$nj{^u5S4-#bRri z4FWA$x0XQFxAS<;9lIHW`?vV-PD)|AsKu?VGJjv%H58f0y-s(|Oz)#N(u~u^y=orw z4W9D1eV#j(!DYvE`B@HpliEKR(|NS+`wbnh(7n1oX(1K+Pz~Cg-!tXrL@d5gMJ~JB z=a_B6?Df{MVbbkK<2Sh7;{cjmE=Z)`RO5`?XyMKUI&mmWfX0TIy~ZoI!MKEXDwr!> zs#Bg@pEWt3-JPSUk(+p=q9p!;!RSFC|aN|!l3~lyQFZ6gdLPV@PZXnoIzhFF7-6TkI zeWTm$(UfQ!%olpkRW^Xpz4jzsS>JPh>=ZDMyUOChWTg0HQ7jJ&IhWNakCR^Aqjmq) z=@T9iqi2HGeE!$XJcQ&df_d7t2eFI9c`gQ^!upo=?YDX-q-Z ziA}(s1eWU8F-o`(03-;qOjI3k%?jW$P@qPhDuI)!_5IC;;ySbK{*w79L?K-!+AAfZURL-I8y$k+Ds6DS><3e_lrA5-H59^^lT$#ipDde>V`R z81nEtUi%YAdbe6LI3L@@dL?oU~N7ymB)x6;pkkLb?W0XVP-X!M>VDOo5Lnrwl+ z<1^27-}h!}hQ0esfQZqJ@jlXK5h@xyQ?>SCBY(M*wSGm7bDdK- zs-t~PBM0#YzQ}uePkwj!W3o3$V#-bzxF0LtY97C)pg=L>B zR{!$Ftz>QS!j*;YGZrr39YW2GE;h%IUQCF2g+IZ71ZyF$Ms|{Q4)tG=|G15Hi_UUkkw`(lbR=mCAlb6Vpo!`IhD?Q$5~@6YMJR#W+$%Yl=xU3ZiJ7-2Qp zh6|kDkh9j8!|VGc?-kav{OlsCom;Is*l*KC8qD}T4diXLQb4?yO|?+ptMgEJ4<0uc zNyFx^dR z-q{n6&O|~cjPlFAs=ZmMbS|m1dUx6rv(uUyWaM)~FVFl+Szjo{|c|&V+YX$c% zGSs*9$i2fSzYJDL>xnWenFId=JWMX=wD-<8UV>BGbbwUBL}Cm}|M2LEJa7UFi?UP> zNW!MLE#!uiRJ(#c6?-X*YA)ORr0Z-j14q&dkVcX9soVk6zV0<}$>RxbuZMc#UG6O=2X^+-r?U&o~N2QLI_Q&TpKP>OjLI)qlceE?L!nOWPeUJb13@T7H@)FwOy zLSVt$E!?7B>lXD}X8j|irKa-_N>|b+qi!N8@Izn1R1)19T9nnYl!k+V%HX@syo(PR1pjDm&YqotXG^kb@WtEo?;4fCXZ=S14 zMdijeT6vqn7K!l5B4zfE(zM>w`)AGhg3H!;yM6qAvL86u(f2zG{c2neyK2&frWVq+ z$_y6jUoouf;Dsy?)XJ#|4Q44Ahdp>T5B|x9E&d~q>{!jWoF@aln#k4;2jdonW$m|S zyW8>f%^pt*L?ik!F8?q`fO)rnPpkp!FH$dSR1C`PYF7MUU`i&q^E#z}H1iIV%PiSL z@!|bKlYh{7UB)`&25=z!{=CyhP4um8n^7szEVoG|Q|JWv+=!HeCNPn7VJR z7JxVS&qo#ZV9O}m?=aZC?%3F4ux>Er1q;vnsy8VpK*3&V31Q_<84wLba|feB1RJH3 z=OOw^02X0-+tG@B=T~{6h9v_LBY~*z#txMHlyZXUA3Bixdma?lez9R@V{7Z}-0b4H zu!@-MWm~g&iqIl?8QCIf0wuY6Xj#0lE1N8Z>(5_TMHOw*o)z`*II*$VmznTm8QIQs zc=)*iJBK?sl^M{}0v@1Vaf|&+RbN2(_+Y(oV*8at@+zYInsuGem?q*CXp@n2U3c{! zZ;DoXi=%rppj=b9o!lbdAcSqrC8`VdND1X@k~>&6f@KBv)iVwf^^vcL2e90RuxRjRiS95U&+q$3)$iaV^29pwR{lNHqNEe4LiSR z?CvEZfo9)yXE2SYer?yofMlwL72UI_^H4`V{xU8Wx3i)K!bjsIKKpEXdUf0liZ_b{ zB<>ibMu*x=K;;KQ^xHNfg3O-XzZkkdAuGAKrCvj4!OM+f1WZYh% zEWep3vt9y@c(c-50`+D}vkh?0Jlf-n+Oktas4EdjqaC{|M+{Qh3oTl|a!_O0QQ)r* zsGa-&1*WCjhZqkk@u)?At0bhdW1CTkhFZ_fIqQdC2Ouh~Hwg5QoZcsFPy(sz9R`n6 z@&wt-XR=;YPZZ>T0w|iP)$#u9dxoS*GQzCL0 z-VZot-r)u_F)NDsCFO+gAMX@SMZpF2E56Tcq<8JJ*wyLvndVP#{`&dA3I zkrKUTPw(uOESe1hq4cZU>BdAme zOAoC-k0`PLfGnoR>d~(FF1EWhfgB34g%3<&ZQ!m%ns3z)fJkz|;9{>u;5yqOi^Jb2 zSLrct{qso+6yEU4!My;P?Z1-P3sci1x!5!rJMtxov17VN+2tAukK;nYEAeipXnVNvk5mPA=xST%h@af-aySbn!fRS zYMMVL^k- zgypDHZ5iB;hVwca`OSIOI44m}6u}ByTdcD=z4aNBih@1$1^m-2qx0W1DvOPcx_g&DP1>By8}7IA+=EO@g=8f3{eji$*1B2Aw}uYSX{|hI3oJ2u zjCHET&VLqy?~@9$@-SB~%Z&%MHse5!&3LZKX6j@I`)9Dt_{M)tpII*pc+ocFq<7`Z zr_B$`U$#$)4t9l2zSjlMhw|snQk(IMv`SNpmcy%`_Jqo7=Ee)M$|)xRX-(>zoMN* zU(>naq)2&74UJz|WHs-6$2==G0U75-(i-NsWpf?tez?8SEBpB0skQav?WGVhwsK-emdRS zrsxFmsE&nu2t7zv&pzqzOU~{qQnK*Dg0#7sRG`VE{ekql4)VXOlVn?0_4-A812#OH z-`jWZTy&}*uEF+OMFchpzluJ9e$COW9tA?|i_K~!huq^V=>%G4+aQ8rV>BrePXrT* z{;~l9tg@3Lv+5$Zg07lnu6OyK0ehWU5G|J=hkojPRWjYy&~(=Ih^R)wb34rOGU2Ut zSu>k}SMAQsle9u?>+VGwJ7SEs#XF>hvh0IPcM)Bw8i=!`>!Hzn4EMT;O14ShfOucLx#2eNuH7qLfe#A%zTYNp;zqIAi-?mn~r$xz>l?m zf=s1*UT?pDUj1Z2!qn6OgluE}D%RJ#k++E;kDSLuvgK)f+W<9W*g_K06B7W{^&!Ra z>H0#_C2WP5%fX{KV4<*ui4TyB_)TqP!lFs_ZM8FV@w^(q3*b3<3?7;c82C6=Fk^|G zse$`qa6tOUUmjDiMa>IZdKQ7{3L5t!2se4Q%OR7?dkBIa>Cz@)n)&Y}N%?wi4^L0-ya zEV#GdkWic;G#Km%9^sI&10Gd$0k$C@v++j8cErwHG6TgJw3jm{=Yj7x>J&_Qgk&Ls zG$C-5LJ1r(WzuUB!OZKdc;-zk%B#I#h@5XSd?7Ke9oq=Xr0?m!nXm@}lOSW5{XeU1 z!nYN$6dLq!0lfop8xU=XlY!*#U`I01!xg_l9{ju@+CeAEwd(y1|23Q9{X`0J#f@#MwKpw-w*mQns8zT5H4$v-^*b<=2%eG`Dh z*!qnpCQt@|fkC_d0dX^V3R_-FRs`*g#o4lg<%ms50B6NxV6}%QpVdnm zT+rQy0H!QHdkwGatC6?U#k^_3M{0gBG~T+hJe4o7TXF}9z5vbIAP+l>9hB6$>d_ID z(-!dyQW+_%P?~A^)xH={;2RXyGh1yA!5f%6DWn#+Axc#(^A^-lt#6hiGh`d(R6rlZ z<+FgojVEC^ia#${5yvhE^m|NFm;1el&dLT8(67(4Yt65c!8}6^C+g3YKEQQny(7lZ zX#fu;pa|dwwW0hreNs~eLc*%BRL?u1wVP|XA~0hCxK|L6E0dd+}tkqd0ug{X~~_MqMp$Iowej zs0a{saghhJfg7W-wu0%yz{Ty+j`v(DTAQ*5KHpt3UtcdfEBCz37kIPoT%1=3Ee3kC5}S8_C#w1in43Sh?cmf| z<%Y*Kf}(Qh{5`Ujb6`59J)`*n0hwYJ{@ z($hKQ4)J|@kKc_~!tN6#o{9;;C8u`ArG5)7<1$VBdS4A~fL>)yP@N%~RIyhwIm1?? zN=6Bfzc9gt7k3UCuRB8O#0iu7!cpSW?Ix33AD)i-Wo`uhLhH_hN|%FalQBBO7!;CC z;#LM({Zm^2_%aWhCkoto}H8oSF~8!;QIcX>)D)rb{1sA%3Pd#FD^6wyOo`H-Ie zp#n(Pa(N;*?VpdmB;*%sdJi?3)M&6`!&buOU)`HWuMcCHOO4hJc$AVGrdp>BE(9&G zSMm`3E!bK^{e+=hEo4cQ_V)58!7Cx*Ek%6Tpj%39?z<>`T_-U&*ZaMR@3}moDhRzh z8;G)VAus2UJn>6K8(YLctF4S@{46t#N`#MF48Gsyeb3uLHp|X6{!0IR+)9iYCA3rn zDB)Pr%VWKOuJY8W$OnqA0b#=#pnbsj+PQvwkyQm(mK6#zGH7uL`sX**-tC3g5Yoeq zzsqy?>)RHWAlER`k6ZuRw=EXIcXGk@Aq7TYSb%`ZH zbkLR*n!>QTsVH3$@X7F=^DeSKo@eB#cCeBT5pS?}qSvvI!HmnU_4%Ol?ex)Do(UlL zO_i=p50eVc%TF>p?zV40uHru$s69%GYjvq`HkWTIHJukIz3G!aLs20ya=B%~$}vJ< zQ#&G5^?nXVg@I7 z-}zxGiMqnAn#p-YRya?IGj8z;Bk&jm3*f z>PGGSnf)DZiOYzc&&*wMTlW&bYm>A`U&>?^w&Eq3VH*0eR^T#swMVoN!FYN~fJ3G9 zXvUhsh^`6%>dIqu{(ZvTzc+W|`nC3}Z@9Pndii?)dSmz+z;mL$Jh8m&-MEGs(xcAtxN9ukz4&P} z)!Kp_&?1?nzFxbr^>lVt#M{IrDA0GZic z`I+~4dfhrY?|gReu3jkVUwd0yTN)SF{W1NzTRW1TTPr#};xcF=8RYMBs9T~^`DuB1 zSA;Cs`PS_5L2Gl2UKL06cDu2>9rDzYTiYx0*1Iu0|NS0P;cMr;Ye~H2&Q;#y?p4NC z^((+%1ork)a_QUQ)#1rr-cc?AJc(gG;*Mz_BsM2TfBYm|0~NWQU@yx>0%|tKY`vk3 z<>NTf2-`1t1M8XJ@DyxNss=K$9C=nFl6e+O_gmPOphv%^Z`ZJIqdB7AZ*Ni8)NdE7 zC_tET!DW8Qw~7nqJCoN?TElx%>~dhD)=dEw;Fo0b#Vo6SRXsu;Z`neW<3kTdVuA?I z+Lf}o@UGB15Ra@%%3D^WbX7hb(r1k$GdlbFYE|4>fllq(-vo6@8fdU1$sJcg8BfSv z_eJ_4gs}DhNJ?)+c14&Fhs^p_cR%wE9mSM!8ubysyz*UBuvYec5_kNlCnblfs*?q- z>Oy_r$$r>|2@=U^stvH2%lX4=I)uJMec9};g?X`NO@4=VK1 zC6bvr;ET9iTjxP<^s=W{3N(>}7@4yfIe_}zD8|f@wvk5Pbd?}MSCIvSdn!t~2aiyD zV8wd9#YZnn%wqfDMHVoVNPSJ8-2m>msZ0QuanjOvMKuaGM@S|_EVLrsFoPG~UEuU^Jp|c8{A7t-Frz(a#kv^Jabm8y55lUF5+nsZO&-Nd zCtSLQo7$T7k=iyT@84W!GdU)2z4My_;O*! z*Rl{gkb8<%xIos_y$qh&32d7T_)0&co5p4boP(Da{(MHKjGp@97v>6<b%*h*a| zO{UG^wsrcn{R@C&5Oa?$Air&mputcHUXQM#449I^yKp{{|B`w0KgeMUPEYfJGf(_c z#9!+u0^(Nd7#nU)6&)*02M?#oiy}k(L);HB97Z-#4f{>8{&#dxD4=rfH`d+co8Ck+ z=FcsxF)=J6tMNNTpY2v@<3rA%%f}ZZ7AuRKhCajOz@+KIvqO|h+0sE|sQOBj-Y?qO zYEKtNcq8`jwmN0FzRloMk^nso|I3;Mz1BNK5RW z+s`O6N#mwsN*uZ0rGe$}F^{I|7_H&r4hm(f;(U9%{DA%h42&NoUxU$CCF`!ooiiiU zSzf%gfOTX1*pcFLZB~2$Ta{XK;xBv>#GF)=AqbiblZa<1H>Z0b2zjtH$O@F{y(riy zWkc7AY;AzTQIF_L8i|apyWlQq`i5v$5ZcZyTf2gI@1-&`fbwV-2r_x>Mbkn4YmI;s z-YmMt2c9`OQU-5q%7}?{G#JA6Zpzj0FVIJ#XPawBmVA{&m>L$`7(b^U%ysC6Xf750 z8Hgh4(!CkZG8!LF=<`D|+Vd@Cx54F9JcY>v6gHxZ?l_2xZ%6dfR&{;5qY_TqXK8E!prns<)Njtb#tBLT=uTng3xbt$!c44 z(yV#GxbTm@YJu~4pVo@#21aT7SNCV2)|qgtU_)u%N-F7dl+_^yUS}kR=BS?PUwtj- z{9SzZPGj^NzsdK>Mi-bS&Rqeucr@9?lIl`m6f;j*fl7Y~Hd9d`Y5$fo9nxw_jmH%L zIhj$ynKmBs4sry9{oS@y$1PXOyqmTCs2IK6)pxP_0Q=BQRWlrQul3Yg)vnk4;I777 zYcG+o5B31XI7v2&v#6(Q2iX&NId>jiE^!B+KNTJ?WvN7Rvv%45+oRWBun$P8Q)B$@ zNZKziY6@&ofDW>xkG^LSj6mvJya@v6DwvW{OnTnb?np`)6u^=A)`3Jh(_pjsf&Bi< zD;E~th3*9cB<@=VAyk+2fUB^&DaI!$B#e5S6s>qkYwNhYJWnYt%s6ruvV;(xT23q@ z(wRz>Eygi~Y|pfZwkOzwSg1cGpI$nYATlqWt8L|v!b=w+p?EdeMll|bbOFG4XMTXUJ3l=KRpM2rhs&&Sf z#DjmFix&;A2L`rZg)`vP?)q%oE-7dOKMOC!;OActTW@zePy0Fiw>B4hZZ6=l!o_j8 zR*^)gdp378YZA!~96Y=|tQ{=IZF!xyz$CbQOk!4p*(qR6G*C*ckV}up14i_pPg4h+ zOLr({77A3RC#@a#TC~o5BGup%r1N?^kniURTk zlxscsi?p1U(Xe^Pw|r=Rf?H_QgmCm;j*+Fmxe7GZf1>T9rIA6A$dgHO)*=dq6jC5u z$l6UBpOSQ1sh|Lzy(Y;bw<9eArD4%o+i&GA8JAQI(D@{!a{^7RVsU6<7)|IiNiYFGOVz4;8|BA|2-FNbBsu*dK)2Oad;x>SpgvFovb%t|L zr&hv=G;R3&E{&|q`uW$nXoK%>vnyW2FZ4KB)Lj=~Y;#vq!G_>tOwn~NEvRrK0|SNx zJ?GFvGdt~oYY%tbMAk8tZ~k5DmgAQ6=)g@`0is&W7g0fS zb3O5f)J4c>EZ;taloBPTV_3L?8xf4(dFd-zP0Hhq*uzD>sdot)%hzENqZPa?V{5}A zJ@p81L`tH#8eRolvhuH0y6vGfn1BDlXOMD*#g%Yq^O@kbsB1eiu>K&Nz6LomEFEel zs1F}Ws#pa!{jlYeb#~N>ux~c|3^El9iSj*@Rze11lI`}GdNEQ{`^3vJKUVoXSX%AG zr~dVZz`ZYTg>^JIn8M?EtVVNTYzMU}hVKdhnJ!$nt}V-zVXJ+Dm1Cw}Tw&NVo$O99 z>Pl2QpHk9NR+r^9urgivZZXm3X4SRA3)WOlqV&6be=kyh({#DOO!I*e;uWUl{$Bfg ztJU&N1y|j8i`gi>UG0nwXag@8%JgueM+C~(&m#gEU3*Q)_Vq2r0wN5MX&nC-qIOmD^YG1X8C-|_} zf}1nJxx{iK&Lu(5e5)0Uv2&~2>cuh-$()7}8?UmTD~+wPucGsm#gnc`sdKE(e>(iE{quhH~75t{VexqQ#Fo~d+D?O{=&xI0gm|q0_8)G zsC+_rt`*g{Z^|~d;W~=O5^&(5L=^cMFvdG>F?EbK7UQ9W=!)3IW z_`#PlU1=2&{ot|~!L#w`+_;69!@KKW4Yu^t2HL-QP6k$5N>W@{a_vmG;laiV>8Zco z^X@Y>N7Rd?-`M^1L-8k53w@daKbo#C$rA!q>@Z&=1FclVVwCJ=*{du)W5N=8(a;>u zE*UWL%wl}zkxA17ePh{Honws3 z`ZAVK)12i3AeT}T7SeqNQrjz3x0{7UNvM8JL9m-|56t|LmCASRTn$W7jxEnDHeVLV~}7^eh&{|2^Bm z%+U7Rwc_jvgGs8W{1zQ+*2K}Gn3TAHz<^jl;=6o}52flcMqNawO1Q`oM2xUNR6=m* ztI)&+%WQpf?LoUZhCl7zcWbJWnRj-PlHhe5T@LP+v_%j*>yIm7^?ExS>af>-EA;8x zp&i3^ofe3yzg|DNega4WlTZOV!D6|R<-7`K5A~JYVBYU=%bz>8_7unX>Lm*rNqseR z%rp=|EC)YK;|mX$ryjwBV#FZT)!>K?$L=FLCfq{f+Wa5tlFq3 zp6yW9I%rQqfgLsg0$4{)d8y|k214@U2b}7JhZjD>3^r)seI*M|b5jw)+ffDf*r=A) z(1qj;?8kwk3bOmE-Z!_3L+?#NV#R6ROe1Vro1A&>6I1l)>tkUwOQ~6G!_o&@bJA}C zb`QtkT{%_WI8-;;@i%qFK`X_|7!wIMjBe1W4sgQu2xQ5?c%O(Kd_F!VJMr(B9kSi6 z0vVUZR#Aj6`p7jfM>1}XpIXhK)jCtd;^b@GEP)Arc=gaDJ{)r_S=cGe(L+Vbw`>r38gcnOG_GJjlmGT z;bY#X$7JsSbQ6*NZo!wGWXnjLE-SreF4+`QzCK8z9Wc%ahyEGRyhb}GM3j3vn%oad zhY*KtcU4FX&+0le>N?`TQ^85r>P;EzGcq#P%z6YzP0N?IPi11n`xaqO^A<)ia29Bp zuSBKee$RNTjF-xc7s>q0?`*PnKqfqR&yyvFCHta>BT+k?FI8_V$8txDF+HpJo+!A@ zUqEdaC3hRuY4Y}?)b(v*d^_r1p3rd8F(bO($y?c9{iN?hs-=P)cfq~wGP^7gzP^Ia z`C8_(B+0YA%zYU3MV0+y`VugT68QcUYVLs(j#ag{LP0aU0Ez!r&mkY(x9G#!cx~HS zSB5ABlrkreiVd3iC4ZpWigOU4ApE#fh7r{mI&j)?`BQ9GIckB6)SLfDdYhB{@$*`} zQTeovlK@ioH14ciK?TR5UZn_u-F04lzw)$R_^`g-?7laSJpsn*o2U6`{mJ{)Z?EpB zboEageOkB2G*jqB6xX`87lVY$#Od(;b-gQhfbC#bR_y1RwPtBScrI*@9-6xHRsIqX zG~sQ5K8mO{Yo#u{Wd>HdUlM_zF!QanMQjIi*+-!bDoU-g``7DCriz^<+eK6k$d8rx z5HFb5e4@e2S~DFXJYi)2Vg6|R?sR+IwANojKUIpwZ-PtOowS-~t8X46JM?mV6%4ZA zfo%sV!#2kl@PAE3-jrD(aU?+OF!wq&J7*T^t(8?dJ5g+`ds> z%v`L*?a*Ijc!$kWjzAwuu;U@LHE=8J0N6U7j?mYM-x%q9LX+mnpX;<4XsP0(czJoV zVNIJ1Buf)#CI8jcmF-CCl&f2M}LV=WEla{q6KZ=?h0L{0kPnAiZGM#;-xeLHwso0svJ$ zqSpDob3W0qI+3w9e0$kB+1S{~`@Aag@nA)2b9S~D@nv?o@y_iyuH#|k=$LHWY;bWF z{J1!nD5zZ)!I!x29;LxKav7(Y5`q9F;!eSf zO0iA*ZkC+OoZHTw&2f8L(g#2SPvEHkjVPzrT&eEd^~lGPAxJ?2H>{ZbKnw5`Rt$WiYv7c7fHlazB;% z`cj4)I$pP7=2%AwD=0_+@_)e!JUIB=_(=6igRT%HkaLpog{pp}4e@k=_&o_h3zAQL z$!_8k3?U+g;v@c?Zy~aZ-9ZT4`yC+s^VrD8PbKpY7Ua~d5Q0`ThlySy_|wf$ZYQfm zrv`O6_4|wlq*h90~Ct@i8Qp-JF=%p<6mfE!N9KG9@!1T{@&` zj0KTw_Yq5<>JKat)5#^d20w9>4G7~4E%44qv9ixMa6 zMU5Q`ZBCd>T4|DjQ^WL2OLA%b=mlT0huL-4th9RlBG2?-QYEy4vpSxn6Wqh{(XaB` zoqgK)TFibrnGWI&I!_lOFLO1JZUJ*t>GMdmh32`XCdk>J}G?yr9yfI=@hiX-$? zot{%y0IHVeY+S3BR6K3x2g+9jBv6gw!)FN=)*{f?;Vflls@zF!=47=`T*=HAyy_iK zTR#Rb*Tydat^LA-s%FL}$%as<-X1Vj_D4aPmnv@C+o&hl^Ay6mg5g4vAIFUw99+|t z^u+h%7A-||he`T{jD0;x^^{b^-hWN%=@ZY1@9qXv0v7mynHi2ogR{U%hz{TaZ z(dITIqwU>e!}`A;^}~-1pmn!F_!XG7 z!Wwzgw`lFgY^2iI=6!|k5vpqK9_Q8oNMUqPm)~L*1E8reUDM0m&%{^JkOda%xooiG zJdra+bG+a?_#r7nM*SQRQ_DErv5?xR>Ljxug?QhmHTuxer3?CeC56O%e(*V-AyQMs zDgu}|4gIFwccD;Ba^HN%-K3~m)K9zNU@*)Y zS|O&`viTj0u@oD@kmk9rPni&3Zsi7$FNk8^d7@e1J|2A2!T)VS-t1Ju(Qr+r)d|BO zUs$RbAS6T?$uB~HL-IZ6*T_LG`&{@Ok^?7;M|b_fh!UDRzqI9YqpZ#*M3!TDGkg5k zM5gQ1>wkTbV61D$|7teQ@D>Y%LjsoU~L?OAiZmSjVv4Jf6cFy#A_U5(0?} z<`cR=<@JO`I5)*bS_uo>VU9B0!|sfxGmT6p2i{?JjIu#I?*z0T_ou^@kI%fz#YUSo zm&@nCni4{!GVVT9RMHVwI}KUnSKcUMbA6)phb9=hvx6e<+q_8pqdX<(1T+#To_EW! zCATP1+Wl}-=1DgWgiUyleoBAdHQ+-Mz;cWK7q-+du$vGWT?)}HVh@Fg?r6@@uG`jZ zKV%+;CzAC|rDo$6X0^C+#FD@){#Acw3r^LcJ0SLpF~qUg%ikVCUMrV$!2bS%FKT{AEZ4I zEm!ONCW-?;?xy}eW!e&bZ}-5OV80p~N)r~p5cC($1};tIxnbcSgX3Hc$GIBGzhF^oL7n~<4WTQ37uHb=Lj&&^ScHb7 zjsfjGRRuf7C~QTp5^_nHd10821V&U3W1e-D6!qu@t-O=kwwf7ffE(B*E|N{v$m)Rx z8+4mt_X&j&Lg81;SEVpp`Dg!z*k~exv65hM=T$~@6cXx^7;BxemgUXkCSK$9G2%0> zM#lA)-8pE70TFHMx7p2QM>py*OAY*sO7Yj?@!>pN#YoS_PrJc#(RmCQOFD=AW^)#F ztqYnI3Mg4HDiC51Km-2LNz>R*Bf=8WXQc>s|5lMBzg3B4?kBU7)rrq*NRQmlvNqJFgc@euL{^~@Y#q}p>1ve3r#L`vznFb z&uv99ha(m--`OzabzDkry`vk0^xk>aL3%7pTgytRzr+VPfL3c>7nlaP^*Q77Lew*o z%?;sayv-NsCF0hNnm~nNCtjVLO4#~5nES;E z&h(tFpc|7uFdWu$0!F+d`EndpeXWI&x;KOB>se1Nf75hho|#>Y=BXY->q8|i^|^S+6D5<+_b=Q()<&>G#$+e*G~96fr!;v7w(3@3i7 z_+u+}<0fgRG>I(;iaK)Tdx^kcA(w#UH8#wgF1g90*pe&d84{k)5h3;aK@K7QM|rOa zRZlQ7?1c#?SN1Emss~E0`R8|-83L+b5Cz5!dHh0p%Cop`!a;Uj{z}$Bv?w5_s}=3x z8T7gbAX8JT59h0NQ~GYRqn})NE-D_e6H0tgX~+F5N5+Dee2Nph14BPiWP}%*01!gZ zh~SG$Id*rz_&RzC(ayqm*yGXx z5sNi=jA;?xVVr3(+`>kd<%=U2+(+wu}rN z$TBWnBeURhEdLYtb}IH04=PlTeNLs;pkrk2UFP<1bM`#;BDb?tk_b7@dvu{;F@XP{ ziB4s^3iy6(7G7cf!wmbAH0}8T=S%sV+x19&H$Oo%*x3Zf)wJA-L}$H<(NAiGi1)gQ zT3N_ps>_P@ssS*&F*b6! z)ko}*CL2qDCtstP_-$?9*O#E~$}IUm0B=B$zxdQ70|mme-KFfCc4HXJ=T_P^o^#)O za;=s>vR|yVDh47~IJ5d6c|fJHm#vR@E}IX6G?Q5ljssiY>5Qq&tsY%-b5N30jf$*3 zj2nN?)u|tE|1iYVj5=Wh{|7^@-{P_Yr`1G^p#YSpAZ(&Q^q_zP77#l3|HlU^&*f!) zA_$|=$Bj6YDvP1Smy$O2fB+tK=X1i0|GxCNx92>aoSvUuT0~;g@%3AI~nDRU2B8zU?@syRd)P>}L?oEx~r?F2Tt@t}-TdaB_JL#PsHK z9>j#-RG}w5XZu%I7bkD8;jldXc=+z>jC_Zv=1C7sHPXIV=8#gI=88-2GV)0y^18&lbtxR(Ptj z`w5yF@6Ylauk(Q)-}$7jByacu+0%a(94F8|^a+)D0(@`;_&NwM3H?4yq`L>w zw;6^bUF$F$N#S}1?No5-G^ zvHx(8Q+JdVf3%N3A#?T0>zXo%pUhHW8{RLuW6MAmEhX#kP*z%W%Ed(GXr-M$oX5~@=0YVgzJ)DJ?kJ_8{?G5}dl&R@cGAdG*=fvOiRMQW7r z(}2#MfnXCoj%f8H(WCO=fNMjjjM76FBIi^l7i$H~!G)t(Sq~aS;S{rU+2>2IU9Z>Q zUjm!@!)2Ep;~5b@*2W1LErKv=DN+omMtLoTdyC$0Nh*J9BcBKW6qCLm0)7_`c&$=W zK*t;gQ^)Va0Gl4*L_UAkgl`=bkPK>AF)qRs^$JyK+1N0?t0iQa!zLPXm z-n58L0d|vW(gC3YDBp^@et%J6rrsY zT1$pCLD(72q9_}r90e+dvs|A1gIOkjYeN22#X*%9PvtS*N8l4g{NVJ^CebSe6sprn z7}KDJaZPH0hGc(QPHP_T>oOH9 zOZcfmL<#SmlpLZ^K+gsk-Kyy^Rli{tl6(shkOpVa_L+iV1osM&SOcfq1%Txl|?}jFYq`yz%&PIFU!03fBhW z+N{DsGyH$C3_&xUDpbxZH<4UeHKhU%5U^-MCk*;(70{8?2iFmJllX%% z>EoI3J|H}D)C@S>z7>dAB?d?$0R|{ZLy~hcV8(w`FM-w`R=~^Msgbft8763Zat+p` zGakGvRceybUZH@xNX@A3oe8A*t%6qOt!4RR#Fr(=ORtn5*U2Jq`4=c@={G28#aEW( zujWkh9O?0;_(CfP3fD*tP(-}s%4vA&u1c)7grJqC43a4F3B}Y9vlTF$@UQw28h;pu zYKnharAD-t%yPn*OHjSWOsF)YPzK7UP6=A+jY82%@oJX@w6xkZY<2GHh#DzN+fiL{ zCUnJDmae%{+Nv)tD^bZS5E3I+Z3V(Abs?-$Q+3Ma?Qce_brY~sIRPuRgJCAZZY2PF zzHAlB@mjVHE1#mLm5x-~2cV^U4HA}bG)RA0{7SVuI;wX4Lk%x<5f1nu5qG9!<09C& ziXlEEYc4WalN1C1z;tIKoTLHpZ%gU)#t{+WOAUhA*bmVD2}Z(iV%VV-HHBkgOrcj4 z4P!wP5~P@#il$so{UG9gD&CgjrzW1R7*1!xRE_yy#K+Y%i6q9c1S)RjOr=iKWEg+y zx@sv0`?u7a%HwR1M6-#;PDFG_UM59sgj50%(T$X`n$chdlMBIw$*C7G@$we2a-uYr zL?k2;f?lUE)Pq{-id{@rPrJn=c|@!#x-vmG5L0++h9xqm0pf|F@mUcnBTP8%ctj0S zK9Ly-CLKu1xQHoyUam+88|Z#YQtf{O*d6$2Hg}Go8KC?Fyz9y+G`>V@10Es$k=~=V z5>AJNN4+(~IzikwfpZEwg;B9i44X-~UvaPYeKOdC5wm#+0P=zik5V1Z#wooQF?OF4 z?Mj+r0t%K|i4-$hB&tlv#d#9vH9Zm-9r}|n(lPGCa~g&mC<~c{-*R+cEu()@pQC1o zb6^5IEa8Ex2MVB5AKzRuDp|uaT=Rp!W|?YWHc66vT#gx)WqHc;fle3ujUtb6KIUSK zO8^rauB2oWKZGSx=kG+j+k5uJ&n=y5u(86>mXI7!2Aa0o<8lY#UW zk}qCCpM#&8pgU7|mM1lR3Tl{G#2Nr9*%Ckn$}xe{nGlJCAx!iEf~l@LP43Nt5G|F` zMiI+#>_oNzt@K2}MdQbQJc5U4iPdKiEgz?29%DUHN4o@#z(oP3WeR_eR?-GokHEG| zBu$BH>nl-04BBEi;qqAuO57n3t0cXo3{bdB`CL!1&{iZwQdeYL&{y;^C#iPSRgH>9g1)a#T>QAi*D#{y(1_Kt z99{f^YPmX8bfl)~`U-z!>{tUTZr6#QjwF+56vk?3&8Qfq5=f4c1WH^~#MNk*;^m4e z<1L_KyhJQj1ZIrpLOPHlX*emfi6EfA0g*{)M2s)pW}2@AKQ%>UFk*83njrP=G=b{b zX#(Y|vjmfmP7|o9>)EZO+fdkGP9Z=}E=J78DXI;|j0wkhxp{wLdtq2Df-H&C$I>A= z@$+#l;8W4Ge5{Bw6cI}gDE}o?(qIKpq`a%EEQE5|5>LTcB05=@eJInuV*jotoMA&y z@`WHQmJ|f#dV(-MW?~YFj6q&6Qhe3gFw|xq&GAemqmBYKB9`iS5GtFK0wSI#GFGjs zmL`H+sc|j26oG$7=;L9W%yO}xL`a<)GOimY0CIw4Tn?OMKbf2;-HVmXDtun4!(x$# zr62;URPhHh@+cyNHbN*Hq)8Oj`h4u)g{ln|XsJ2Xv{DnQi4QB_k4TRX0y>LDNPVUh z7Y9liCXW&YmFJ%XXy#rCP^qkP1WK@2urewat&GztIQ4%8pJgPj4fUKcKQF z>W6@7i`6#uiM5NrMqLoo)$kPQ+QiB;V)_U|{)TZ=Qe57X6ce|kV0_m2o$wE4Y!5|7 zR*O?XO7A}ueXZh_DCvN9d5Pso=SRx3T>Pm1VMKLLbDhMd1l)~~JkUN+m=br43;ogfNMk!T1XPOLlvHn!@+G#!hD#WxT2auXaVCJt{2G zQVmdjlv`8DG~lMsli6Tg^Ccax)Fc_Mk#2vMj;l*ogVbjL5}LKqu%aC^1w8Ym84djnHnm!?kmu1UGRSzUsmpj1!l&sLGwSIE3CuiP}E16nQi=I2Xoc6-?v zFRy2s@fj$GDm8q2GcDC)|7gLc+j8v9xLSCy+^DmjxP`gs&c*yl>2_9?ZbyG>ot5r? zS?qpU?*}&}?#TkwXp8$AJvIsQBevpqPPQMp&2>s-?-qk44yz zrenWQw@#sjIrAbgD-d&Y}6fpe{h6F|VC zeN1O=i7=%DRtBCo1Hua(JvFc1L1E7IiOu`_DcrkzBK{%TfQJxl2 zTFd(de1|3yLt-K+OcNO;38VrM7T&`Jb^&iAu(~xHjVZ!mY>+<8(*m9u#VzOXVu%WX z4HaSTN8zBL=QAASBB&NtL9hG*FTa9bGUA6GP=(MSEW(&Xa|>0LZW$v^D-JnU22?PJ z3<&j7GjNJ=7z8{nz*m1u0sdf%QJTOI4#Def!G+_ILJc&Ti!B0_gDilUM*GqTipCiL zBCVScSePim0Kh>Z1%?YDQ(Odm5W-@B*8>lVL7HUQ*bmb}UaSz1Z6e|M0yrcEh+Fcs z82D41fN#7Yk_yg%Ai_jZAvRt=$;U+>B|Y({pn(T8Nbx(1K97Hr`$Dpi3n0N3esu3Y zW(9OZ>?6OAtQAgsR_t70GnWsgMzbN^(9OXQooRo-JRM8d7aOp=E|s;GTw}{rOqZxU z<#nY&#`5}ts+QIiwEyVxTz) z^`zi^wq%U8@r!>ix&pf#^C+?|$?USJ_Y7EDLIfp#=w;5vJ8})$Qt%E<%2L2 z9669o|8}zX~&yP-vQ+j z3LXI(W(j}zKnj3}Q_&C!5uUWj^tK44oclsi8a{Uf^>en4*H1|;O9xU&Jz2Bwt}q5C0-F6h6DjA;m; zX@kUYofd&21<8vGIUC`fj(n;iSy&RC@VDoWMk;?i@gI5vp9JLSu_%nI$QK4FJH}*i zWisJ8jSLPi*o(&>u%?dMkU8F+N;DqT+@#@2{Ow6qLW+S(ffCK;`8{c}{J`qylVD8$ zQFwq8Kcs_G>d(N>27VwC$YLsuD;TgBKSC}}uecuBL9ebq86;^c zet0&8x`fyt<<7=Zq6~lU{IoYEEjtVg<;p?IMMD9(K(VquNtaD{FCeFATG>g2dILZA zqhw@2#Aa1d!eDxe-qVv(nKFkIhZND2&UJqsy*FYg!{{3Tu`$i4+@L>Jf2Cc$VUqTw z9G}Pn1fP$tHo)k!6er}CK<(H^bpi;+4o7Zt=A@1>+{7VuO!js(58 zKBbeAR+y1>Aix^cx`D|GV+!K=t@X}=$JnQ>3pP|xzfy`IN{dKJGmRW025JLC*xY}< zC>Kv&68YaVaz-dEVc0-!c{Ckc%A5~;Fe5*U4`GHZG_=?zOfU)8i_-3sGRGvv-jrk^ zoS3~kKcc(K5C}}Q>r7JbL|2Xego~9lOgYznH9?;ae-s&TI1~3AX>BRTo1>KE+~n%T zU)pCFB*CUTf(WL=I6;M4wAw>w6FGnEjDv6>3B&0P8#=>7&68Gdip(AuxU|h`*#?*~(#Ei^;&uGFiB9*Omq&H20c|n~) zu$;We9|>*3nGgi>Q}Js|F&v`gjxi$DZ1^e5D}}dQ{PYml64FD|#weB=i1L3|oE$1F zj}1D_qGW`QQ}Hou+Vz6po-}_TqA4FFqgaZIt$kFVWmhFEa6->J2NQfks8k(jXQd5RxCWJz`l&w%A7`Vx_GzQwG z} z#6`3Uf_T2tX`Lqbdb0`f(R3CINyW^+Gz*t27L2ZWO_!kvFbcriGgfgj>h8n1+m)agOOBpi~}J`t2m@xLSbOV^?h#rQjt z3ZU8F(Y-I_Fu|b>Spby3(h^`0@H>IRiHJ0iG3y(L1Q=&m0cliBh1HVHW`hCexWa^E zUIXpV9?IU2xJ4!wjd*Xk#RB?4O;?)I+ut3{Q zPMr#??nsE_>X9HJxb_(dyNTgM{HW_s*-)It0)v|=Oh%hf1VXLxLWWRG0y@eD0TRIl zkC05kiFYBLu=tzFKo8GKjgA}0xPC~kcxdtzmaAZkN&gBw=5$;tTaLhD>-A@YTTXBF znApm~ySLIs7mt5-;Gu!K64}Blzdg-|q<9{R#~{A>Rz9)Jr;vE1{70`61CVX$tmo{scjl6&M|GiiC;=B5XpT*Ui^O<|1 z@@O~F@MRD93TobE_b?<#rm*Bzqj!-d-ZuiNvTpgKegKLXaP9?Wi*z$pg&zb~iPR#W zc2>sm97tlzkl4|V1L<-Fk_$NFgSt@-WfUhVS5f@6B!!P+g3gDs>M9ACF@cJAS>Kzm z9$Fy^zzBcQuv@3suM=`_Z*5W+23a#F z8{SXg?{j0Lg>FJy#TvL}a#~GquT{J$_S{yn*WUAhNM2&EUwDGVTs9l6oHW(z^}frb zP3Yye;h&U^!2W!$0O7+8rq#swrRUAe81mt zg*Cw=Z-w8vYv;afZ(TPf;ZDfelfvS%<_8AXZ}Xndy{EY(`=4>|o=a=wAG{Am(e5(Q zzR%v?=Q@7KX>^KCu({rFi{gWx*3WM1bMuVD@7MLG&+}sIYxA=^FY`zK{qcDb5%kMi zya9i|Gs`$joqoG>->I9trGz^@_Jo~*g%6z6ookDGo@AV~c$3#jX@v~Ps-phP zDEcjSY^UYfj5FJ{U7hP&3~R{v22NJ&?VW$@II-&rUYl8h_ey-8wj8k9wlYL7nwfi^ zw1T&>k&~wjFvFRop68JjvX;Z^*%b6}99<9Fc3JK=pNw(H!%{QBhk}C*se?B9EaffR zZrZJ;?QT*JQtUyhdLSiJsNJI}Sk(L$({AFd(Yar5)N`KY4tHAs1P43~m*qXLZJ&Rq zNuH1?rYo4?E`DJ&b=fz#w1A`~?U?JN7)tKPkJ7Yxm;Duxk*y@v%!@2b2BDwxK-@JI zo9_)j>wwo|KU-@E#zj9#)8yXJ+BeDmM6;0&)1a?2sj{8TCK5x{cH)7s9*4qMogl84 z$h5*inCM~<2A5n?T!~#87-r_Hl-7T$#raqe1%`eU32_RWH9(7BxE$*^8P7pZ$Tol` z--zg(GaMp8ubla41zlRJPXy7BG_El?1Ve!h=mL%<1Yk4;-LZivTI@&q;}W9imzh#F z#Qw%fY{bC9tg?=;%;L}B^@`&iC$Ww-fC8kyBGVJI3gIl3Yl4O55c1TiO z;sKYa4;YrizAg-B*`XY*@}T2@Wq)X}hLE*??1X?R)0Ou^u(D$8A7n5u z5$${nTiA47Ctk;0mckAOrWb$N;WD;sct_OjaX1?D^lI$K23Z!K3IZgkkVN+BvJfhK zfr8f`LrLC!p}1o&f-C_M9BkkVv3>9t7xxPu2O=Qsmc0-LF!1-}K!%LEAu5bOzA$M1 zFQ^{W8ZdI-@<*9j$nL(7f`1ssTjnG1d_*;pcGG1?BmICDHp(8A33`7O2$T5852Kl2 z2lZ#8^OR7~V1^j*5b*v((Y+DRKl>l)DI8`WU}CS4CJ{YeNCIF`c^V4R?K@%G4rpcf zVa8AWhf*{Yv`Lc>X-0J`r=o#?tbUZ%Heq`ls&{zC|DK5>6i!9buec}mhWl`s_hxZF zc>sS5mk|97&!U?!A76h7-xcuk5H@nfEkNt}ZJ3LGQ2Zddj|JHQ=ojR~fd?PMAs3Gd z0AFL?(-~s>=gMxSPAbFH2n&+PK4_>%(c>YIgXjSJ7Q$QPV8_ctr_pYBo!aKwtDoNN zZ4`h0cMH7Uw>z_~t^Ms9{`{&T|Al|wYQQ`Ed#C_!xA5<_2K;}5f8XNYBlvspEBrl@ zweDUt?8UuYZwM zZ6CY?$o7H$+}3{qbxlEzr~yZZTN<)Mkews=#(Lm=i{TsRJIsD%yX>QwNa;#I&CYN5 zcOU;A;9s19w>vnoZ~uXRf2GL2p0alYIfTF1-mR?zoW_ISFmi;EBN36U+}ftz?i|5K zUjK?6{pHsq`1>0S;P!7@2l)30hv2Om6zcHykufM+Z*hN6puo=7&OR-NLtFw!82Nb% z=lW;(`wNZWFS_`z1bKG^tAOTn`!|UEOnHBXHtziTE3Uj>|4Xf*ca--4lMjExh;G*F zt*xJFA^eJyPpe|*2&bPSuQBp76g>Dy${Rj;|_b+qUH2u z0DuO1yK5+@k9Q|pM8q>1geE~+1P@inPpBuHwICp#hYp>U(y}0+qc*%--G)otem@Q1 zL{nZv1itysk0L?W5Rg-3Kz>Y;TSSVuKFEL-4$6Pufs7{K5dAv-a1tX;LsWF~c3<9< zCvOipAOI?*n)7Uy6XtjF_L7fgd|xx8qfizTR>I>XPWpcVj`Znre+sW2yh%?f_0uJI z5Td4ix;*t`e*{AZg9W8vnC^W!BBCDnq5cx%jWmC5QeTkZ1Ok`!vOGz7(33fOfCOiX zZS{Y477Amh;JrvPH(;zNczv?i+*zz`0vj9xl;efF?nJ6{0+P_1#UL>OoZdjVCAPaP zfkhIYUBYOcnIm#&JQgPY0CV8)>OAiNb9l`1a%@HZdw3{ets=A{Uw(&~;Ace+TC`nF zDTzw2W960;y-b*Nqmo?Y_ua{)-U?NhxC?(Gkjlqq9rsebUe9|#MEf>!ORg<;O3pSS zSr8w>s_0*VTc!iC%=;^l)VTHB+Y|5m^<2{-lz+Fj-7B{2uFD3i3au>`ihHhlI1fvH zO_xaX3IYo?b|AV5(w%{)Nj-4Ib^4uq@I~?heq2TI$>dkVo~H1;9nFCWsR6m-?&uGdZ7G+ zeg)^aold=2e>&fpyPIEOln%Uhk6m@y1vsYzGHLIXyJ@p)5fzR-2zd0LxaL*g1lPP5 z$~EuBf@@xc2)Det(AI;q{&cO1T~mLt>G?Co8pPiG;L`;QObXtbt5TSc?5UaeW`USKV-FSTjYO*3LwVT zbJKZr!W{sF^z#A!LWj?usnV=)MRls4&r2Pt>xsGtQ``3(Jj9D%9e~goq@RiOGnsxS z)4}D7x6Enk(=z8W%at{jdR<~MSCZ)+5T(z$=!Ld{uDBbn_KU7-dN*gs9vqe8{^-S? z7_v^I;j&K{#UksuE0rhd8@+!R>-!WN?W))7@03q45WU6cs&JtF!fCD5U#&lVis$ZE zYRfw8kvTiyia{XV%j)4img9OXM)H_OHs;+qJLKlE`IYdMudrKse1-C;+^p-JV6!o2 zJbyOd*G^}B{pn$AzWH^|hPl^1h2NXY8&UD>Ra4^?Srajza?5`ob8qRoTFM7BTPNJ2 zzUK_vdB9au`%ErBWRvEi`OtWFmp|KmLAtVtLSGpQtl&YNT6yUBGpE#3T)zskDc&QL zB<_=D;|JDZWtTKM{T^N2OMGxsmU|!O_KthcZ&GsrAH>MXVN)Z9W5pixZpG8RW+B2A zKW7owc(nugeSv?(edRPR51m6!98DOA^}zj4JOUamz027hXSw#$-Nsv|@l&HaXWxug zbox%Ksi^7&yy0LgwWvw2;C^}IblsJX_n!S|qth;aYRuV<@j;1k$}X=5-|Zs2D-P8v zY&R-g3R%;a!4K4AH1`uX+8C|JHzE$=PsvRQ&m|7SMW;)S(l0J-3pf z^|>zb4Of37LhHFcmWN>+I48iPj_Zi+dY-58U3a$^*JU%kKpftmViYY|dV+SLgz_H` z**?YJvtJ<2XUq#|Kv_(INLj0|ortqXz`?1r<$Tzv6^I;IILr?mYyxsC_vGmt_U3j;s$Sa$D+dWf@hyyFRXvmk19u>2V1n><; z6LN+Xzwjh+EHBIb6#Z5GL+R7EU(k&wT9J%*4 z+@%X9IkKTf!l_x=;ksgJD!#JNqTvrBj@uC>iAnOc%iiuRs+bBXEHDxw{bYUeKcV~W zAsm0=pgnm6<&YB{57n$Ulq z%8p=NqP$^7OLgj}89x$wXBasVPT+ubd3|wWhLtBrl>g8fRJfEu3!aN$m#yRZla6K+ zVRkYflkGeqMxfQ)&0HtUol-;`Q?;Wq*m1M!ccG%Gl zyWTNOCuP0my6w&>XHRITviX_MUG;x*|LB27@y%1--s;xT%&@a9U+mT?_y(WO@;X{> zIvYA4*=O#qd0uUM&QkAoODnb8Z}x=ogf|WJ3G6lAXoRKHsrQ<-?j{Hq0-m2~{+(NmNHl;bg{9DDZ0h7%hD`f=_SMYW8(8}Z!w#O0GreYdWpo1Kp? zwBQr>-b;DIKRekgui>t4LO67)1vbUmPS5m>jZdPpp66|?u4q07J6VbfeXCw~&2KxJ z*1V(T2>;$;ip)`0N`cMwojHFSdN$H$ogO+T@4ByS7I{tK^lxXwr354m6e>JaUAGIt$k{VABcMW<7DTLnd2lZHE-yMh!e%BrFepaPvv zzf?h~09t2SXuTURm~h%^KYZyLgjJDQ#N1bLYe|v*TPU(EGHmbDWO<2Kz{qH{k{6< z?7CEuqMPd7q8WFMPNRSGs`JWetszBMGVoSVK%}9(miJF_26s1I`v>SHK{7B6zvkqknr7!yKX0I zR33jo;$I;Ny_DbCowFnF2i>`|KI^e7cA#mCg33JV?%wP7-jRR2_tlHm6iOcu#^oILmmCOb6PmVmQh?lD4-D z^HHzbFYWFuPXv-FfM4*jzLI$OP2i|`*W~-F(m0*$s8|^=!sEVEe zq#l5-q~1Os3_2$eIpd|XtmYKt;s753zA;;J8j>ml*vBw*WR9KFCF(l1(^|9HDc5QU zq<}%k#Q|TgK6LEB%>A{aUp#^YLHY%!+}r!Q{&dRca1wVq&R1ZBu)H26$*m6-Bps=7 zv}B!V`b>Z6v_90N|I#)!Yc=+B!)dLVWFsIvOEy5daMWlP1QImqrZUeiWwf}|rk+8J z9`U@$cwSjb&T4Y^cgXIVzz0ll_MwaHN3dh-wEuM6?yF^?PRFHyTL~8SCa+(AIyk(z ze0O$n*gH9ZE9>GAjgn@sygeHjmilyp=`ZelupWPzmrhYQ4LtgBkRS!ec&j`OJa-Lp zxTIVCk4E7`w_=9(U;dqcDa7`*{kgwLKNtnAF+BJSB)E(_Ll6;~Pv`p=`=^(^cW0lj z_D?=tHbc(decZpi>|Gol9bO!MdUx17<8!?qffLQ_;&x(u_Mo{ zY|MZA=!BhA#hZ4FQqy|H`~w6A*nfx}Trc7W?2IeMIT!|%BhZmQ)6bg9rp#4!A@&f6b@GindVwX5|bdEp%XAyHen?3TART0fksKzIzXXFScMWQ zl7_xt=I3FCX0f^@sn!xbQQ~4lcLilpX7JsWG{(u2;ZbILH`6&Ac@A8X7n*+veC=J8 zS+OTT7Iluiy(7hqJwOudwFfk9m+r8b-&@GJaO{B}qhA3iY=J)mD^Dz;x^BC>M)g89 z_?m6A3wORt{INRevy3$ia=qsS5glqEMghv8#yu4h>^ybT#;0I z=gBeXEgu8LOIPQz;#u_SYSVaItTGQwppL+&T0|X*e?zDvh6j0uGVQTG00%1$z||zZ zhV9sP(f+d$cU}7(iVvmFX4lq%wZu!@Sn?harhX>AFs{6KuLqTWn`;y>j+Xi}O=JaaGNbjsaH`AC|fhN!82+v_!wq zURbXTa}W{pUDmK(y+9G=rFjS6NzcBMUj5dl0m|4weV*j;e_VQ8qK17iO&#>QuN)Zqfc}qwAWvHr}^8!G7%s zKJr|)GhhLHFVoxh*7ou|-ReP$JI%1neZSd+cZZ=9(s=puWrKm($J37xg&S`=jh2%5 zL$d02=?#1CLVm&U_Rem9U4zrmbS#N*+EF4(%Pls3LZolh; z0qi9fI#kp5MPBu)Biv-Z3vp@}bp#yz?Uq%qQbhN+816A`4u&`Y9)iIF=M7u?Dj&PbQYQx-B7jVu4Tzem)2% zmb5!-1qq5&T4a9~)&c<+i}bcF9tRfO?-ozt%c#0-p*KZ~KZNiHuDB2{Ly)Bb^xPVP z3$4HcX%kDGkt3d4#IUwTNuF3JPiN8aWPs&soWmk&QD%j)C2(m7OLPj12U&QwL7fIPAC^wAQYx~v)4F0)YT$O7Xv7Fsy4=*f2v7I-lQjMc**^51EJ6Df{;65>z_ zTZF9!4qTF<1)iV$IPjw^u}~DsB4Zk$dk(7*uwj4reV9agzQfE4GZc8T!VHi*un;oi z7MQ1nRfJ0;8PaM1pHiunq_|P?^buBZlGj3t%H zV?1w{TEI07&l-))j7CaZugah*=PFHFP?aVzQn+FWiNg6X5k+Y>TrKXs z4hmRqck@5u6`+FbGrVx9wsYU>0?B_k)7nQJ$7!wYx<$uzH%r{3Dbzgkm#|(2-$j(A z<_w^{s0PppoK~~fLe5~T*{K_Gw*^{*QdXywP;5Q4JAo9W0l1EeidLi_bY;a-BePVo z3!*;#FdpJ>?8i>4*zyL}<>zAfdZ!rv^0NzK74@>09$bG6)rZBR zI*B8yC`6Sm_RMKD{eD*XK~R9BE3nyG45DuZor%K9M6aFAx}8Sow3@GXieG+q3owfX z@7!XLe=7n$Npjw4K;=Pr2fcyzZ9=`T$N&$nfMRIB#eKH$t)^j?t_2qBIcu3k)*{mnGRyq8W8P#y;G!|WaCqw zcN*ffa=_rZ1kliY9Grroz`hJ=^!f5{ix7{0TzGSvs+!MQo|-^ z8Jg!?C?w~uiKchye<(}2?iaLdae7a*_gSk0s~O$X`m3= zoWW6NQZ)o2SH3w(Kw!7nc!2_R7?wIRhCb4}iDfb`9G6tYCl7p*qw#`v{w+vK;h zOg4cRZRTl0eY8|vVh(>s08DEB0$*+k!DbE?0L(&*^Rm2D;DJC{29}kUD0RL05ydp( z^+`U%QduTq&3?ZsNq#DeM=id-mwK)84er%aH&|u{xZ3QO-kZIza1#+TsJ!3aU!8tr z)|bg@-J_zmPnQgq5fau!(={ZnWZ+FPAd-T3xY3p4SybY{&*ITdtY?KlzSXbq19SMw*FIKD>UnR;x8wqXxzqp3J7r zUDcE~Yn}GHgZ-<0qfMP|r7LshFTu|#cWbY)WNp0Zv>qnW$^jV~i{MQMx2!aIODmx) z9B2}Y&;>OTc#3~LcZs5?SUBXV+B|%NZrMlNn@$5WVPBOL=T?cq*+zj-hI~#CLR#G_ zq#gf2vxvt0y>?-)=NtByf9ES3h4i%V`{@rgb`Pw~?lo5C(09U{6*4q2GsMcEpZKqn zff$W6&(LV?tyH@&!l`7&daa6 zap`I`U&@a>v*JXUvW`8w-Ra!F*lo0$|J?94*IE6)U%hnPcBj)t=gQvVdA_)@+MWAX z|Lo#ltLeC%dIN4{5L2}}dAC@14U(w6G_$=T_sgZZUzT%|+d^|<_+$#^L~Htqv4k@I zWC*5q=Ei?Ve=;Rj$<5)itH_*+AM~*(%_abSq%IY8DjN6McR%*rt!Gf|FX7O7UOwAL zj;_WIvgHKrWu20VFRLQR?72q4<;tGsZCG8BtiJ56rll#s2RfX=3J$z>x{|DA|5>ZmK*nU< zu3WXx=mNAmono)+pyEjjUb1ehZGj9+>{y#_`%kM2j!$EPbUHf}+w64Wmix+(oO$z8 z`zL>|)@@1ewm;Rnt)KSnvTRQ}0|$=J%P_4JzAwr1uXQ^2n``!F{9K+l_GY|k?>(m% z@VzP)(@P`1u~I^4-F~JR7&!aUg8f;9D!Za+4bRRlDjSrBir3%6(NIzvs0g0q2JRrK zu=#vmp_G<4v0|yq97wJ0Y0rD|(_j|HN%QwZ23~lZUk=%z`Nts}OsCC%AF=^39;VHI zK`3ixmn;Z}!{+Rgjgsczk_nBO=J1k*ao7wl8Q?(8G5r!Q)V#Z7;Jc;Szht*b9)*8# z^Wl<3JjpT@ zo?kM1I-b_#ZD%(>Ub1NfPAK?8-u!mSrjPkJiJNaBBL>0sdt^6{E?L^VzGSeQnt#D> zmN(ZgSq5GFmXRxF`R`!&dgN{EEZn(Ka^E+WR%5qL z{b}o_j%v5wO`Y`7y&E9nda|(NJ}rpHO#CUZQ-J+cLkS^w-YnI7$@7g3=ca$|2Z6Ux z|8q41f2vZmD}_10IOaF#iUf>!es&+93r-pAl+3wt>%$~H^ao?-oGXc-WA5Fw&pDvr zp5Wpf^Ia#)J?#LXC@8APtM10en)p(f9ib^s=a{=28ytS-F1wi%PceToMe)wL`*hCh zKxX$m4`ku2t&I&wf}Z9s16_Y%iU}w|!VGmaPf%?$@Yc5HB@ND}rJ1%26g4*IS-aZU zXpES>;ZLT!wyU9U5E|tr;2r`;WuT3~zh_Aq{1U-09(I1+HN7vS&JCz@oGWDcm`h0| z@)U!-e%COnk%6}u>&89i?JVzlH}F@USm#{Lr&>2z?mp?#U$AtRL-BtvdDqKw_?f%x zn2R&X2VLiE>c@LFi@Y0eZ*A>{#Hm>3IXCQy%+fc{NkKXsIyZHCp#VPOC{LJ8+jSR4 z*GSbqGix@Am)&UJA$Hw%jRCnq!Lb~{qO0w%>rdx=zW#K~>)ALQ=8il63L|+;{vw<# zXJ2v`^(wM_zW!wQ>^gs$OLD&Co7?XEtJ^g^&r_|k(wq6$`L2*Bs4Q1@%*ER3qlE&` zwrM?L_H!H?@0goWcFybfest?VK6ma1!4-eVap@ZsZF(_)=HNr%Qxb4Y4~NcL1R*h$ zyJ}1_*dsJ8az?7nn7g|Og2}{9i2j{b-B|C&hEr;T@6OTBlcRrCUv%;uYg%ac*Eaws z`3uj+A+-0t$~$i8IXAG6)$wu;#^c6e6r?-`ZCSZ^%Tj3PoZYzWoXdF#O7kFEkS0kE z{qcs5I482)AKZHFQfhY&vKBeq<)uzx-nI^E$0t|-idRa=8etCgIONH+E;~f1!oobN zX&X915dpRjO%H$6b!Aj-bxsaVu$;U<=@~$!5;hgij z+%L!6ZNkP9BTcu28f6$kBUPP)8JMbtCa5oFxeE)+7>0jiju6#0bb3C`XzE0(&bhX8 zyRmUzZHM|UI*xXZxiXMzcE@cQS-rMdPCDl4HqV#z0_uAT>bhlkr@C`-r%t3ub!D4C z`%&XeZVzH%WZpS19YfGL&jznPazUQcRHZpei0id(uIf3D14XHg0C+%$zZH<70WQ%} z|J=Gb#O5f56@IIpXO+#tN{GS8L=2>lrW<2X-ZXEP`)Im1N?r*MO*a(}P5o+~Cgpi$ zX6miT)G{+&ff-5@hk=U^R>}xh^b%iB2T-j#g>Tw7D}6nGopaOK(>Y(^?de8}bl;S` zJ)QHiyQhm%OVQgCG-c7*6ZHZ1>g~z!rFK(V17sP=xvA#~Sxa))i_hBrEG;Gh550a_&*#(34~79FS4Y89YL zvn^>juh8y)Mnk_aLJoKobPZ4@yb7K`TJM;9Tf3#%gpqhU=9}L3uEgKGV~$2sqTItV zVkg|QZA1`vqg>t#Tf4Gj>!_!W-HLKVwAR+S`*gxLy(r&Bt6g)77&ce7*t+Pm%c8uT zCQ~-o4dXE`!&rN(3$KDs$KKdj=k4uo3#x|rrkEFhGH>NzqPzJecbg7m!O~O*RN&Y! z>YJMqF|$ti+*Kp;)j_1r{VLW6oJG{x4<1Mgzioh)yDeN|bUU5fj&da z`khX&3B)=0bz3%j=h;rJ1$L{2tr8M>KsHR_lna0ihAc`pv1^;%7S-h1pqET`QTkxH z8mvQq9DDX!vE~(Po>%--{NxoI#l}Xl;T4_EEBFV2P59>(tf&<=uV{Ehqi7bp#hW+9 zn>Sto{}-O;74Uztx3>p>yaIpr3i!Y1bf8sjA%5l*oz9=|59%)99|j=&-!_;BUc}ED zf4*2lB3h%N*CR>c;!71NE8Z2H>5V#AS!6PQ8C2ivuRu>Zb;@RNi5hdxmBg7zQZ{t$ zoMXJAaoy8GTl2iFjg2fXo9LO(*^O(eIoq91r_=6qvQFo+yF~F=w5CEnd@1OCFYOB1 zQd2Y!Iq4EFui>Tr5^I3pXKNT5wqyH_U-+Oe$_qc`#mUP_5oYnrya*Ed%Q1G3vHmQ7 zFaDZkd6A8iSril?`H?>s83+hJ7CZ*WYsDyuW4{v zm%;}h3y|R~CP~UsmIF*JtH&aoi0qgfJ|MH)(=%DII(>s3Kj&rRH^vWAN7 zlQ!B!_nfPNEAivB993FTKNM3EBXZ&b!e{8VTN^FOVF)s@klfOt-XOcAcQO15Mx}ii*6* z3Y1>a8EV4%g8@VU*obJT>t=D_Xr!*3M%#kIV0YsS*psh!TkU4I<+STvAg8u}El{_% z-KW=cBm-qRTCzUnj@@Y3%w7jqK@>H-Q@CX73ygkKmQQ-4l*y={%Ny$bifr#H*;Z8- z^F_nT6)WY++WK-s>+MlEnLT!2HA?&JKQZ(UyHXfgHVvN2FW*<1_`sLvJFDcoGf$*C zDuQoT@*rjMo1*jxTHRBxht?E-dOgyvu8P+*dz@8SXw5^;-kyBgzxdtsM%sK|gdklT@Y6x>a{u(Ow}07tdw6{Esi_YXg{GCC z_c!dxJoD*sKxaOX`071O!K29U4?t#6i02I# zIPZmqVBRHG zkAY?&24!znGDwo3WtSfbAZ6OAyJ*!4%++PC&2H+wUY~x#;64g45-(&yGJll`D_N;N=})3xI7jVm>eZ~0@134+fp z*<&EA1K&cglw+=cRg^Une9X;GuzLcG!q|nv)E;kz5xH{Pj=?8)NvH-4Ae2^>oR9KH z=ip4FO?I7q)Jh=3&caO@qARIHVT2(56h8uFcoGFfiizE2C$XmlNcG9_R^x^zv4I;d z<5iR?2`1s>3sCXcjj?y#W@SsbGLzd}F-hufiE{U;Jb+n$&Y+>~DDOgJqueD_NcZDQ z?nF5|5r>X*!o3q>7_4(|Z=KikY&B^;G?MKrkP-a41PDQv)d+t=`h z?RxDfXJ@g4F?Nlw-R|5q_Rm=?_K)J-w8YyOs3*U})!Eu=8uW_a&D-=-thpsOl~#+r z_Br;R=IkMV1|H6nu&`T4g+&J*PD9*^#CtL_M9Ikcdb5A=sc9h}MC1Tg=-nDZMdBE1_F4pgzaE5_;k559NiOA?=7Ud!E7WGsi4>=q<)$?AQ3xaEQ z8&2`aHr^-@H;k)@^Y0;cY{<uGMg>~9XItK6A& zoxWy&aCS|&=XtoPbvtw#s*b|xD@tPZIA5X$nlz(?jpr#HoInJV*%T?vwo7~D+lpa? zOK$lf9>#$l!b5czE)3vd9LV82jDw|vC#l=Zhfb!J2Tnp4hfStDH)voLh=xq&rUBz| zK*NO@Rt?q}43be zq+IV)5A;ZyCTwn0p$D#1fdZ@I5;Aug?lJ~z#Nemn&QsBI?woM8&X*C3N6ra%nLV*L zott`9ey3%JcGI?9NHc}tTlP%A*LlkxVb~R1m}9<-M~Qe7+En2g98km$gSvR;wYyAz zXWGxbZHi8l4Ef~l%Wo<-)$fy?KjvYZCVEY7{Hg+VjsUk>Al=chCjIGB>jY*q^wWQomOP1Hkw3)}0M z@0NJx&|G0Of1PVI&S_6_c93^nSPpf$%n|0g>>4;uV(GD^ABE+7&F84NAI780fgkVZ zm;QvGiycwr-K$=&Nj6Rx@N_?lN{d^LOJ&~~U7>A*@GdqK4l#H>6EQ`3H}x_t zFF#}0E8li^ub)}OfYi`(G?%S^sABaYD+8=?dPL|#FA^IO$XT7+qx_pp(dk3;6 zKqth;N|oc|Y*pS9UZI>IU9wG%j@I+;Gv##qytOU4Z1GGjKMzmzo7zND3~*g4lHz+! z=U#Z%8;P(^yk&Jryk=Q{8Wx)5MbSV%!$y|Mm*2)_lr3TpbbyHr=TtjgaFZNwvvqoW zO0ta#dX3K8qSJ3+d4y0g8FSg%2?rc#V?zWCEdZ(#kVRFC%nTLqI8c=#0*z;vxqQ8m zOe+f8W=lS>zOWmdY9*VVXhq8|2vw>Ua?3jdY7h}>pH8Hlaud^kIBCaT-BPMysJ&jV zn|mLy4)u6H$hDvohjj}WCm54xo$w~yz2$E%zW$+tD0dEWxEE-X6OCtM1NWCFhoO$b$wCv>>KQ+ZCpuywq6)76r)iMtKQapO$2; zTQ`;URuqsyk^-A+1~KGcrIO0S+{VTl?8d>E2cH$lse(LRpu9K?atsLOYGou8^8w<= zoKDbEb*(C(iT!F}6+(GW_5y&aLs+Y#b1AWDD(W_G=D;R@y5OF@yr;=1!sy!*yOSHMySiEQbtw&rL9n^tbceOLD!(H*L$_Jq^9P9%$0(THrNIh8VRb~EP*G;IBsDzV3%B%uqAqXo(sY+d449l zo8uT>GtM}6i(-(%uPJ>8w4@s{dNw0^MiXTnBP6To%lK0cu8r!EQkJO1!u_EBzs7k!&6g`OH5q*)AvVfnZOSK>*)o8wq5@8*|yzWYrvg_?Sj*mW)oK8D_Z zbzUcHMlBU;9>mVI9zS*sau)%IsgY~zF+`9jli)+-%FOuAW9YKS(3s;`%`qFRrTZmb zuGFEnV(#>FcBXe@KUe5w`z-J3`X57*1Yf(=Iozi(RZ`NYssnRaVtpW#>%0mVHK_u4 zz@6pZvTV2&Ph*!|5@$8hfYdB5Ca`2f4u#&!UMi zb{>1zxpSMdG{((;E=REaN6c=Lu6K^yL8H4Dxo8^u61UU1>pApW6kG1*wgA5I{td|S zB;E9G5|{lEmlRfdw(CM~unD_h+e^&aeTdDkATsSgp!PrF-AU|FtM5a1K1cI^Xu6vI z^5ImY&b~9=^Cjc!vU11usyOv&Rh+{9v2Dpn6$=1gU7B`%i^7~zr_~Tn$8~ki+vN=1 zRm-cNdk3*o&dg3@wzkDC{Dn%Ez`TB5@8!vq#;%`xN3nAnvvMv$YHXFEP1-=Wx#o=m zB@U;!Zvb(~7DUnEyW&P+HE8KTZ7Y9r4aczsL*0a3$WGzhHg3mQ?%{qer0HRy z8bb7Er7d zkN}g|AEsKjV0rVX3^q_OC1CP2J7HtPDaGr^GH5vyTvaRTtY)X`t5Dh1W+e@2k{cTi zPM47ay%$AXc3b6=_jC3{cv15Sx$e!|d_ISadJq#ai0neFfi(7x;3N2o2Po|5G{#Bq z=WQt*)m4~yjMOk(X1iv82Ink?iDc(-MLTk1!%1UrZQGrTnsIT_Co@R^=u4Dt*X`$? zj;X1h&#^(3mz<e3Vv)RB1qdNMQFX#qu24mM!SVS>ALm@)8etW5b~om%%y2)-H0BC%mz-wyXf; zcbOkL7dh+Wt!Nf%Z8g=oVHiO3R}9p7Ub=atDnJ^0NeK6IKbK2zEsa$tr5o4t*t^Z) zaF%D=#)c7*`x5(qhLf*TTMEN^tj!J`$yUp{sJiOBImPgYRu@td(yJaUb25?xS10_rUabVeDWa%h zXSug$p4c!*gl~o@exU>*)LlSLxq#1YY!Hrw2n+0FSaHNJm$ITT7h8~_A1<(0&T<8U z18rlYA1bDX#6UMTE^MJc=C;e$zNjXOvw;X`U$?;cvJ{WA@F23B z^``{2Pj-oa-j>D+g@D@y-ZN=j@B2vY_xhncbL7i$8;{7)J41}Q+&wu0pXtB|hmMg& zvI#ae*7UQu)ZUlkeP~7efls()zudgYH(%QL#KpI+{c_WhOSvfQH?tV1AHkmOZoaf% z8eM|i9-`uepOu>eBX6`I@MUvTV1|BBTvT$#ytEI0a)zWE?ReAs`oF%iZK&lS+}q~= z*w{D-_vAFadc8>AoF+Ms(Ij{n57EUrT03Xfz5i%|hJ!GR4zE=!ANw)QBhNJX5eFco#D+wiai^)4%pw1ppNuFA=b1pUl>o9?RP$jD&Q zde-{6iwbGG>P9MEL~jvY7kAM`?)@IZXl)*y=@i=rwfY&M^LKB{4cp2!hLAV$D zRoO~d(ttFF@zLKcDY3AgfWLigK8fm^`b!Llr1>^QiYAz4QRm>>w6?tkt7db1Ys+PS zu-&mBkUEG)a+w_YY4b9kn;o6QM19GByt&(Dn{lv7F2E>%(Cp_+M^GF=eUs697$fOX zpclFKq`sA`{uWkv!u3a%Z6#%X;9Nfn)e{XWKR2-QBSGD9pUz=v7KK5*%!gcugr*S<0YCJNs*rbLV(n7P? zBT6~?%;GR{hGhFPa^)fU`LNj&k6*eFnP$#`B@C3xVLBzA341-Qnz3zJzE zJz7TQx^%m{s5@`lXjG|V5Z zG|X;+d|m$9e?pSJ4{yVUtZ$*Ft1&n}pz%e?&~iJQ)dGkS0MmPcF=TRoXg}ru`G~-L z)WbODDb}`&Y?xhRnb+Zre+Nf>oC9fn7Pk&^XB->B7R_vPfd;cGK zZ?+uCk)@5@=Tms0+dyCt9`tN)g(6!Rpq@3_a78JS?SNB=LGW}1b_IKCb~es=fx%RJqqu!RK2 zdvB)8y&`S7yLs`K&Q?d2Bt^#WI_~<`;l7}s4gcvd?(XY*G}`X={e6&NXZQEoZr^vi z=``CZ(DraRJG@;L>gop zpFlEQ>zi8Te!&vzw15(~kiGd~HCd6Gk6>(aDlZoA-@m?|pWnU)NBtZht^s?U&Zmom zz0baVnyD3I#HSX2ljJKffch?k`=*bd@1~14b-)vY{{6J2yMVJ_{-|> zm$bFg*Kuh7U(G+dn~%So-rvnBGXMVlL4F#O$}v5;U7e19@8-qbyj)CPf7XlvTl@tA zjTG1Y&xn|n`I^D~{qN@o?ay|{Q^*wtYbS?0QEbkIO5Jr_T;Hw0mAcvt?h{D@bUYs4 zuJ-qvV@P<{HvHxF!TN#ES{v$o9dOYNJm0Ry2e&IE93A#!LKzM3-+wnf`4c^MI{Kb8 zvHl#tTirK**Y(`4dYR<6t1%iNwp7!|-JDL4p4`p*{hp4$>mlpqqOW^qyRcCk_xB%t zw<6jF%ud%`Y@V4;CdUV^s?cj!6{}p3vartvvjD*sEV!2A$xVT_}+=vA%a-R%lj8f@f(fni+DPwwWY`}^rHY@hCUFD6}DACA!z z9vCiaNc;rfCBs+dR@aN^><#YgdnHvV)&lfcwp4$V@cVgzF9@d0lIz>~@k@-2E}K4n zyDBE<=iklla8&E}ad-KDlx~=7@8LwUlEk^p<>X>I1QYmuD8fBbz>e`VzOteDK-q$7dfUOc$wTi}z-nH>>&bq@mXoff4-=E=2+8sKcuaWUOsZ1KuIG**XQ@K! zCANAzm*boF@BihpcwJwLdReB67dr=kT$6^V*z4wMlNaNT#(r>KyxUOyTVwO$o-EcEWyeReIo>ui zueB%1D0=>+V^KZdE8bO;yXEw_*W7*k#o`yOw*}Y070Eg`QT3uYZ`bVL9E)~H&cNyF{rgFFoW34&S-cpF;w%NxkB(k{d|96nt*bv9 zU!J@^9aza{hlh1kJ(o7O>}yg>ANy#Bg48-La~ zF3;Y-&&LITu)U&lhh~9l$E`7cl)C8{KQHdP0s79#n6kG`y4O9-5+2*Uk&8~M2-N*P zcc#+Gi%iM>gw-2xsEfnQcCIGNZ(n0m-5l=k543PoT%6pTc8@eJf87`|x33GGcQ)kt zG4Av}KV4H5LF>a~g&%BVxGgzhgdc6~`LfFjsOQV|o^Nnwv!e?iT-1wy@o0lv)aSrn zpY<|)SIu3F=`zPvd&lPZH&ckXzaPFq^|ZMuGP$&SQJdxij1OF>S}gF1@;scA`MMX0 z?jPLWUo=r7%EEoTNbZND@#=WKcEf6(XUf)1&R{6*oot)c`i+(O0y-#^f78X4tD=py zJvh(Fctu!ihWpX{@nU#??9wr zt8HxHG+BG^-#?PH_?>XT%d=uOUX^quJ~mLX#IJNEbTwXOkwntyBB?@kUiA6+#o57x z#PNK8|Gdv`4(5l&vL4mVc-dGtd$>sZVtg}(ee-yET%WoW#Z4nbnkBy}E)U;*e|K)Q0LE&FmYU1Ji@#-E=ZyrxM# z8;{42$0Vn&YeQ<-*17?>6u|r+u6n8 z`}bSQ)WMgF!$!=1t`1%o?_OVBuhOTIDer#oK4}%-lUwP3`|-2K=N-N4S@BtON%!*p z@VEnmvU<>g7Ktd1tNYq1_2+u2zZn0SaJRqz;kwfJVanG3q7M5V9=^M*pAYsvP1odf z{QpZRna_^)o)_$T_3!`sKW=E6#XATEd@yo(d~#O2#@FGX&3#djf9v>lbBMD*a>JMB z$9p%|OME?lnb%|5EAkb&dyDDSo0rpW3Vjn(Nb2Pm_aKDtv)YvYc0y5G)+T)jxV=RF zXsseX+%Xibc-`K>+!i?OU8V5(+J_;B`lt1tk2wXp9`(s|b=Xb8UDO)p{NvTShB+D6 zV(DalN_zv}LFk`2c>g}XYhUH&AIXm%E%x^(%|^F>hva;n%r80IUW;)JvWJI7zi4cV zCiL}+$2MNR$gJ`Am*WplepjA;*!h~q4`&C{q9bUgbZ&3~9*T)i#sXhfNz_wFPb}TD|9lhkQ6s*FQeTi(U$Mu!;g7>{i-L{ z7CljxvHAVg_}zV0G3#$~w0M1@fY+|xG2h?+^z2~XIWsUhz-JE2vaFI{`vL~dIVfnB zld0aFZ&e5HKWfCsM^(e+ZVsDNpY!n#X9u%?Vs%)Y*Ia$vJgxa@7yJ9)UzPY)^TDDm zjyuiTx{H(M`Sh?jJ3Ck&9=07XhqdwLVcqVMY=&<@Zs(odSlkp#G8ys)yZE?jXza_Y zgY#y47uCr{>jpV*)0pxaLde!bCG|6Z(uU?xr3l3qWVW5$7w4VJ-A@mT^Lh_;0@P=J z#9FQ|4(dB%-oMYrL+>h?J|#Ebe|RK1iTu+ngBy#eVG0fBDw=~QytMqgW4RKUtcrQDXeal7S935e=1EA;uv3eE2$3I^lOo~apLEaRL_3PCZhZtOaP8wBz+R}6q zn!XVF_}LkH&ys0DVyWNGvN4IPI=A$rqodi!%XRs7u`#CQ$?Wv-qv~XKI=;AHjw=Ka z`-5nh^4|J-ca9u(2C)1HignB0^X#g_`_)O?^67Zlk?>z$CCSwl;;T#zEirV0NX<4~ zbqHj-)fjDz&FpAk8z@{I9uBB~1!-KQ3)Iy*{WhN6^pQ6lS3PV~D~T~ZPA#+><2Vm; z)r&xO&xrr>a$4aS_?!;+;ooJ!ZWk=gykM8NE9i@>qrK%F~{FT0x`Hc9f$8!X1bw9NbI{rhQo`)azFQH1!9=_RB~I_&g+{{79}!5qrW z%^i^1a*^7Z-T7idPp`{okLN_ba|oPiBXGbh;G{~Iz08a0$^5kbUeGaiTXT&?e)$pW z;^xy{M_C;rI&0RvxsdK~b%NH{gOGUFbdt4(Kb(zE_9nB{pJs1fUg56C{P@}QqVwy^ z)%1ogg1o+&tfrsd&gkxc$Ncl@Eq$)5`TcA$nJ+JH7pPIqu3vsPS)t{N=^tm)bdzLi z;pt?xxc(*ozIk~&pUzjQE-rPh-!89L)BJ1x>UQ>O+Nt*0^~J^Aa{6@+|KxW|GAJN~ zpH5!Z?^Y8e3D5ycyja}6{NZYHe*2n!elfefO#}PlZeIPNdHQ32^Yo|Y>3e$m)8uZs zyq?VeIJ-+@{qlwkl)a1T)9Ir7^bH-K#;@DO%d6Yj?d2Q#`7M2vo*uuuz3vX~hnLgp zZZ=u;ruDZ*R#~c zzfMSUjcQpNV4caiEMCU%!4`zSiaK;_^coWBf3GOMLn2a;S(BLVSoXhj;uX-)DQE zJ`e&m_TByAcE@#xBU9myE%9Y)s|iVAH&Ot(q1eqgv~7!j&W6v8yj#A$hAoXV?&s5I zZ(d?^B6uo~bMtR=Z}e8zZ@^m zxxl-gt+9r<9}})Rwa`_+3U1nmkmwYm>GVr=Wmdw@k9dY1*QxmRX2s@H01wrDyKW;= zo(pM0fByb|OE`wd zn=F>o&TXoHTw9DUh?whRX)rK5$<93)*5qKNLyS2U;GjixMh zMpDz$m15Ihri(nO#=W~(_1@riqweoiXVon}Z%Z!fPkJpT^V*YN^OMJq;Ize;(yRCH zAI;N$U;3FE#r>G=ugA~~DS`ac>w`|IB0W>jMJkW`la6tF8Gh9voF6x)U4J}o`b&R? zv)iiodwx6p<>h2;+AA!=AC})wXOmz005rF1TbkbwOnv&A{dj#aFFw64Gn77{)qYQ` zT5TCErKolLYc8YgFACib*?qN`yndSek@+=$eF9-I-ur6uZ2A}W5_HNaQhdzzj#kA4 zjw5(I2&Yg8m;3v9g+CtC>K@{H9;p9mCDM)dA5F%&R544%3h;y4E%118G~UB~N4N?7 z_JUEJW43o(zpv-R_KprFNAmCp+8&MdVq7&2safa4o+tl&icfp~e*gdaKlcuc^N%Kf zpGf=oe7yJX|N6i09W_bM^pO_d|h(+A4Zo$rr%XT3r#pF@G8Fp4b z9MqBV@r+Lni_7kEu8Pb1`)*^MKB(J&7DDs=^I4lN)1}HbOKW~e8Cv(nzicbo+!FG5 ze!RLbet$Op@BklGIX(RFviP}MtJ8eFV!uBt_W1ARdb;6#@#Jj$Zf}3@IDh@M*!u*} z_`GYe_c0#v`Pbruy$_D-@4FUzAK-oZs_T96)!F#Nll@OV-us~ECH=7@Jy|w?45uvx zeRWo>#-BVnJ6W9`(t7?$jXNJB?oOe$^llgDmy6rGm#|8kmldglk5}c3+w(W=4XyI= z^dP-E5vPa8tK+uD#qE5x*MJX!%0KmyhvCe}e^Lh>MXafQGg)2XmiYJY=e@w~`n$>M z_Ga(C_|N^ODXHRcmo+-)l;z5QUfiw725r6}w(6K)_r*UA4f(@=KKbbvA^1=X_~Y#_ z$A3C2XqQ#Dvo996H-BEtj{oWGzWC~#ZoGOqo4i4u+Huz1YDZOZp1-Dz%(%Vpr}Oja z0w*M|U<>DZbZWF-hDBf{ye|^Rk&_&oY6@&Yh=!* z7b}kMeqCQ&PtVzEa=AP#_wI`el=|D7znI-EuNWFdBed_nO?SWzw3Td=MTuBL6_{{I;|!#CU$xKYC2~x-Y}kOb9&v}A(arkxP6VQx+biZ zTDY-&`Z9f9^J+S0(>dJ^J6%x0dFl*Pq6e~x>j~8#YOCk7_q(bRLWp|xs-iy__A&kW zWOHJF$dgDd=DFnQ<>miiarxo{xXnITEG{o!y!e0}%x~F$?+)`Zrj$a#&ihoBT7@q^ zp=?12oSp+ufb&(Zm?-YM#cefRE^imd)A1*JzuP;S-WNBMYH_=)r<^^6d4e~XAQfOA zpHD9aCPqgKrmVVKu5NEwDw;_h^I{+T^wY)d?J=pKNN4?k9U$SDu3&gMn=+0aeo2-qJ~-3=~tOEnAf>fJ08^SJ=Sq}(^waX^#p*e3zHHvTo4`GL z|D3%-jH$v|`lj?19-pVj^U1RF^A79Q{v>~8`ZdXa_ZPmnU7Um0-Cm%;#f#ftQqdQ; zzf8|_IRJ=e(l{C*n?Hg>rZNCkCS&e{6zV! zd&OSjQ21|#2>hi&Q7fz`k#mtMR{eKhm^0rO3N{r5Hu63thOyJa)qUo#z)Z%0(H>3s5n zu0Wj3W^|CS9Us0CiF}Zse!5%Cn$bMNXsFvgFqmI{xPCj`+=OX_@ux}-QG?Y zw*~chx128cGH=s!2J&1MY+7EH*quN91p0kvg_z#l=RZYr8lsxK#OcS?Ez85eZZ6q> zw@8+MeZ8C(^~ua7Z6I(m{U3j#?&``3uJ|*~jz2jr8Sw zMR@s~Ec30Hnd&}fzP`S>P79NYVrL|l+wj*Vriv0RzEar&0G#f{&dIpTS6-whaPh^m zWM5veWx5ab%LIQ@WPPUT2O^sAyIQ<|LBWeV9IH(r(8Be+AI;%}cNrTvU_2$MfVgZpL=p#@q2aS3j0rv+tJ~BUX`ScuK8Ymp5OM~kiOV=5_OcnzIUxrp?a^ADDS^o6VW~3 zx`0{p>4C|ud9&`8tF<0!v#-DVeA5%wp`GUac!k@h$&*UfASn8)bHsJOI$z7VLHzMu zaz%Z0j))r?J(-`55rb`9tdGfmiIE7p`<$}2j`8pDUl21#<^ov!H?)Y?)v9)IqKhV5 z7Jv@zApHe{wZaM3XVbs%>v`w1 zMoB;spG=aDB=7aI<`^GPLm$8ccQ8NNV5Gj7Ka~EPb6g@=W*wML+>B&-R+CO0pq{X*C0P3Qx~=lzn4`{mus z_N>q6lav2+c9QFzp58C-Ui5(f*agB=`sVJYS77?hT7l1|^Im~}Rkr|*q6eOL!BFXY z&_x$|y?jQQ)BR8QkYO`c_p~T)UXDfaxfsjhayeGT^meR^S9fDme04px#f#q!?z;Ds~zFZcv3!mQNcME@YSEw%ht84sj;V+hj?!p(> z_$>}ki~n>sK6!P2SA2C{q<>#5i$(tTwD`xf@yS=$Mf1N!`@hp-`px*{a#>7ohib0A z8J|pV0UW3~|7LvhIZ#w=6ge#x-;7V*yaX^c-ud^m_|L2HyU)J-;k&Q@@K48|Pfp&v zJT0Dm{+DNXzFeLbKYaTAm*3H^S9kTV_T7u+>3#9p)%fIpUAk5u9?$t+k#06QJ~>g= z6*kJ#;>5d91RqaN?~7cvdb7Bm&919XaVeB3r0Nx$EN-Ur>q)m&sZ}VXQMyy?#bR=G z(`!s=VG5(H?UcHl-YzctjTwy5Xe+xz`lTBbfGW;lPOM|RY4Ta zYVSJrVcy<<&AOc!p;ck6k{HcttKVLK1O2vEUT}Z+>f_I@>R|Bd=;*LfY{s8movd)U zN_@2VcwVNq>ynG3qgq1Mpq$}3{bW2j5vTk6(~rj!xU3tE7h}Eed;pDh+Dm}|^=DVj z`FE)Fb!YXv)%cT_qB)3!Jgm-Vr`6_+UW#@`V|AE+M)gvhtkSUXbkvNjxeDZwq!Cri zaS+Aio5AqV-qUD{y`uxC)Y0l_et7hJRB=`MLKNJW(iilDOI_N6hl<-W6x^1&;1O@6 zs2|Lz5(QU<08E#>@ za8((98d@lQL4Bw~iqTSfU1%SQ{I?QRNYgOAETk|6S5j9l&|Hivq^2>bU<)OvJEP*L zauHyI8U&WU^o2|Xl#-*_^P|;=subQH?J*7k`+QVoY|v=9G=&m`jwc4*Q}OEg(SZ?1 ztHYz`PlBA4{&ZElhBKMg5SL1M}vw!0=(1<+L?Q~#z=j)qi7Pou!@Q7%K4 z9FOgPOYaJ9W0C&QFDHuhClQepSovQ`MYFA}Cupd#Qq-)6R#TT!cNeqZj);cHUDBl4 z=H?nJkc76VPx zoQ-QLDT&H}@`@*3BUSn%64E^tR?-yQ8#AhC{1|{Nl*JkpIxe|Zg^oq~gKeF-t0bO^ z!P0_Id6BA#QKeD`D(y7xG%Ze)OZp|!OR-cU6ke$!{~cA<6zx2FbFk^e3|k)SMp^54-?iC92i z%74?4(=urX3RKo$3O-iS#U$`(No^u$;XM^X`yylsW=f^nEw*!qjn>$uDcxwv1G>BF*(4K zfG}Tzk3`(0;I)h&c!|stWoPmMCV@ zhiK+5{ZfLe3o+_dPb!itw8(NqB^?g`8kN{i;mnfC=u}j%3y@KNB5a%ZlC(Mzw#|fX zWl|TQ#Q_6KK$zOX2~#;>)(DaGgu)3$Po@|-;okl#rjpSPim1LBNOxI%s6J{agDNxf zm9Qs*eVv>qg3X*|#6|Y;G<Z(?*l zmQ(!?^N$i{_x9@W!YYRs5R!g6xt{MGPsWpP4(3I*Jp3qMi(SLv9G56?yQ6?Yf!U4% z8U>a+3K$f)+fv}!WHtl*BEjL-Y>qn?SL=LhZIb`~Z~s#hDS4`*WMI$IvmX<&K2cG= zW!nHbwDRwN|LyDaDJqS9%eDcUHvYH2qm843y{FpwG)B?DwDWJ-Ho)Ft z?)l&T=eB2KsjLmUDQhem*#f9X|8M_G+lH2r`V(zYEh7dp3~1WuU_d#IqS|y2?le|n z7|^uwe{{wX3=LVBw!2_3j$uIE#(($Ucjuz0J8L_CLsm4GK|tNczy1%Mxg^wS(c)hb zPPYJPHH{B6MkQN(`+$WQ2JEe$4X}~5+%T=kF z;Gg7JG24G4$uEK~(!>unhQ`Ed2YG1Tmgs1K}rNa z;t8=cPDsDfF?tw^OsF_a5un=H(sQG^l%BiDROv@tF$Y_TNx?1C zC@3BCs?=Q5RE6ixV1Wa56%@L9JGu!>yfV3aLGNw^lhLfbd|o87S-|^U(@h#P(^1WT zMwqV@71xGo$3Z-hTEQ`?G{hVW9QZFa{x~KW(1!&LObHek1}T6~#R=1(6-i=ObID8@ zIOxgaEmjKD!(&=RNt4B@DCxP9j;X+*s()^h}kw3nMNQ;f7LwanKLhyq1H0IOvCiemLj{3W4H8Kb*)1?kgT( z@I-s3`bz%}-GJ{cQFsZ1x3&bnL4-Q1CR7jg#8BdM{jLI>e zR!Tw<2pA)1HZcPao`Oe^H@J&`@kFMU1^a`Hjv0f2C=o`?L{VW07~WW>SX|0d(axX> z70pF6Fg?u_b4vxDRa#;thl`;!29s?154+6j+bk zfoBurNXQ?t8P{B6F+&t@pUSjwd3~ekuJ4NlF5h|n)G=$qj63dLacyURj!Rit$E7e> zQX+Pmxei=um3L^Mwf7@#pcqGPsRQf%E2#vug9_V8GtYx$(sC&^Q)pCR?`oKpVAhf= z?V0ojt2<(rI~Iv6X=2NqmV_(8p^Tq_3nZUBC{4lawSLsxiY1 z_>|O)C<0B77^Vfef_VjhQ3k1#+>qK4)j?udOYLc$W?DjDvzEjTRuWEl6d2Kd2Z>_! z0@Wc#>KKuhSIh!6#)^a*6@hD65r1(ZKoV=q;j945lUzFasS~9Oo=JFEnN}q<6<85q zD&}j!jQp|22c6w$w`mZgCq~;(onb*R=>qMBSQ@4zQ%=A`6PW~mf1_=Pe-sm3a|z0M z#dY}9JLV)K&1S@mwg7=Ze!na&uCv`P>m{h!gHuh%q?=IB603rqgQAZ4K*vmS&GaiB zD({%IfjU+)rmmHY{m!o@i4e-2(9$Q4FYfKLz%gtq$#bv4t(%fO9@yE!fccbT)1K(I`~ zAoV1}0+X)dMzI)(XA@m}gCz%VQ7Vw4WC#cj1pWpk1FOfu5tAHzdn1M5$_;MljG33S zyXD`2ogQ*Ve=m0W$Qk{e*jY!;=r>{KsQ@M6Wwxx77A2Av)p^%Lf8+V>YY>?S|E$RG z;K+&(Wby--Ng>jjoCgu&KrZRUD7|Mi$|?#fU=5SjK}4}UE2dMa1W&EY^d~|fDV8dZ zn8b@KTjiqI*E9+RrPTok^d4>wye9N(MQ%vADpc}PSn^hkxU`BZDH}-{jnyJt@ z>KI;rP4nNxOeQjDecx zdc;X*;?Uh7CJ5!ED?5(02ow|JP%62L+{2)hGwzeE7llnM+Ri)=qe_vgtC&?}NU~I% zHVc`kQ2w<|Mu7HAaBM_$#xaB|uGFV#yb9{^2-dV#f6#)plW%VXm)_Lt7!xwUN}04~ zliF|Rm(!o`CNn~j73`{AmnY&aOBO|XnO=>4Wx40Y&GmV$l`0`X1X`!SASN1s!bn&% zTm_&Ya7(|T8%wg@xYQ9I^%;*GVJ=X&K~##EQ)JSNxFy?`)MiEModwU3aMW^#y`>$O zWP)2qfBp@{oO&XDRMK2Y=pvz#o<;+ujcG{^0|-7NG*?10$ht`F!+1?5VitCi91W1J zI-4G34G3nTLdp@OhJj?Xk=P-b3W7MI2T97MG{jF$((ITMG$^m2Uv`jKD`*J_${kfn z|0c~0h-Ahv1vOESZmXG5)Fa#|#$lc+>f02(HU;6NuQd~)EED;2pDX{p~nFK(}|=gB>O zfBgKZC0*9b(p41G!|qWcuTH3+Js7uOVB+vHz_{_H8}SG*GTxa<|0%L{J#N zFtJe=WP!nFC_M{LQ%LPe6GHGEkTj8a z9R>#TJivA&AbxNiKqG=1OA;ITNBNoHOz@~m1G+LC&1IN|CT9geN{dQRh+9GI8zeH6 ziW4wBFFD-B(mDD|uSOL(xnKdm9ZT=sGF6feZ&G!aX5OI(7qD1F4@QI%ZgE2%f5}7- z`MFCEC|lD*4F)|Zp&EKf&pmqZqNV|6$m*}@!78#xyYvuT88Qt3>hrVF9s}f78QMrO zKV^CtfgZpSL#BZmN*-XHCYRa+J=85X^w1#)DHQY>t1BloZ4xhtM3BIip9%Af5Dzy) zshINQ^Qpn`<~ad(wI|DjD(7c{e}1Z^WJ-cCjI`7rYkGb=y769=X@w9{AH((@0>gc1r5W|^L~7NsQ0fO1OYr%{=Cq!y*;Wokmk^gcD`N^p&yzqPAHh6qan zJB?(2FwB!3g+4}{)H{s{LQ;UC!Vo~L2>S*|f)IhJmE21_ds^XE0-CdLe-?;=H%>Bg zhG;lv$@2{#TlUS8HKoYKhWAn?wVSL&kHVKe@uEJSk{?F$pFmxa1~V!=yQYDw7HbFBFFtD*2wt2gS(; zg#;@}Jj{~28vbbbohnX^D^BhQ2*KnY<=$~a{6TS>^%e5U$(dtve^g1@)qyE(nIk8< zmP|UyG(@JR<%ggpDo4ayh8a-tO55J7Yt4du35JQ8WA2rf#6_~T$(AKcb zLBDHU42U@f3cxJBqB_)`G!ZHP*q4`qSjDi{D2};pL%FcnIWJf8+Op=M> zab?QuLELbec)Lh3B>SYDQlQW!c{3bYOr8TxcEl6@0!N65c`_FWwYgs~3q-1!bi;n0 zO*CbK%Bb?f?nKpS4Of3BszzO0{hg>9^>Ot#qAEL5e>alcczVeG9##KiZPPUB9Ko5j9n30$%7#+{9FQAceUm?3plJTumP#63d znzSWn2uTHqB!|e0LvTrqlI}xd6bu>vYAmLQ!hqcuAs#J_4<2=jX~-lmQVD1nwWkcp zzA!5xe`FQ>+VJaDT#+YTbC-(p-00UtfN$AT(Q~KS_^L%(-=7BTJE}zyMsh6Shx1ol>53<(7vjAn>fx^zDK-iU zCl3o8kdS7i6Hp}8MFxL{kTahn)YotQVcv9{R)H(sYD4?#4(NEbo%N6X0UpFi!Up7qv8oMNxD?Ad#AQ6YCS8Y)51H?NTpkAbv zTHw~FjAE`SU&Kfi>sf94}I2#D0XLNM~eILD%!MHbuq5Q&vzu_6aQ zuxSFrI&mtSjE#gy#1mOsCr<5yLS*39P>xg%z~@2DBKJgLy&c!taHIZ?(+}=BRgtwu ztK`XwVHww0r|a1{c}^7UC0kljW0Rf~nAc^r;LpB(#Ht{~Q%Y|+>`J5k*NR1$e^-q3|T=~9=%RuHdFmjZdf(v?wrhLa@%hMZ>J zm1Ok0P%7ukU{FePnz`aK%KTWPe+{k`Z4A(+C^g|BV_=>X+XW9N_|4?hs{lR_!T z>U9c2k}~)x-y#|PPJInusz|t$6#s`ZY?WY}jP#PXTmGBe7%MJfX07ug{Fi}a9 zj1z1|l}t&cmRcGf$w$Ir#=+M}#y0aa7%HVCH#CrHC<6v^6wZi{Vul8Je}S=d%5lo} zabQ|XrL;Y#)ThD1^@@XX+AHQQ_y`roND+lgJU*+ zip*FWnFi6=Qo#+b>&J>{OhPL$7WO9X2<^WvVVZ)5B}YD5j!Em8jEL%$=2M&iF)6O* zaFh?o5cIdwIwe;~NqV(sf8MzKl=8qlv>2(FC!dI7esH5P@o35`Z?piu#d{!<;Ge_p|3p*@NMhv^|9 zkr@$3jM#=T^tXdR%b%BF`8&+bQl*~#T($wmBB)D_lOXX zR~=m5EAGAP{AzGEVsw;DX_v5;p5Hz%UQH`(W{=FiiV|`m|LDvDlKIGG^@FBlbsfRG zOb+^o6y#6;DrQGXe{`yxK9I5y;7yGAmr6BZRA>t1;+K&OK>UZ9(<$f1Ask5Rt}(1S-rHL7>qS zMMpKfM5rhwb2vJ=p^|_jxhZmo={$(cGlC!QN?V*Vg2`|5VG(XD{oXIf5WpyyEI>s}*ykCP<4H6-O>* zOku4!<2I=;f0X_p6?nF8M?k)K86*=|Y9=8HrFWG}o4^v8$QgVR*m%srz=Iitb-&{B zYaC0X&Mi|4Z<_s^f@)$039M81Ce`Cow*Bjk{+0fX{fFPuzuD|R{iy?nr-e z$WkS`z?rvL7%B(KC{hEiP&iQ=iiR?1WHoIRSlWag9Q1P)4$b3mpG}7yfuJJIvY?Z< zbkuG{gCR7{pxWRFsHP`6yQUMe^6~pLBtln_8ghjx=vC22mu?0X+CdS`{I)@*ZBBzy z^0yAEf2N`WM9>T>{`Nunc2NFr9Mp@+V)Ekl)pQ^?+hL2QoZp#dIYFCsGPD^|w2{us zC`-69EGKC*%F<>yq%9bw+j10^46zal-9R2twl+gvQj@Sv*I-b}Hmh^CS(CF})k)i| z$=YU=wq4bE+pJF9W=-byXo(<@V&oU&b?$Xaf8J&}dz+>7?P@c9yV^+K9@R}Op|FsS z%<8@>u`_>LtS4}fwr6nfNZ@8UgByrMIFT#*UqVMhIy_C3%FVd5EG2UT-D#m_9IIJp zbC1Yr;narvchH5o%dbh~L&WrAviKW1-PE~NHTzgz-7Z%BL~1L1k@7eTI_sWKIpfrSB?_E+#&P2a zVS*?kj?dFuTVF9l8J&eSg|x1aS`;$6La9J!!ReGV8bwBD5ew-@m7*4H0ZAw;+?-|8 zf0W$`-byz(C^|dtDwQtDfefS*)?n#$e`2OcN9`%ivq*WK_(PXSq;^p_|8J&a)K(T^ zCJJtFm{-SOeJT~B(Z2iimOZsmQx5togA;x+TG6;wQ!*ib5G0B~d5LTrpdV0Z7b5S! z0{+>VD2%9dj8Z`;q>xqTAz$2L(hVFj-HJj>L_hMi8~L7Yz+q@APE^$4JVP$0ThL{+5dR$@gB#tD5jk2Bu3h_yKrbSvO_Q6spKnk~iu zm!BD;(N21g!q@Z;e{#>H#T(jcp5Bh0cB#FS0*;L!I?M7aK^gxWWS=PB zYLI+Q@p%_Eo3MWP{{_YOFo>DAG!M|=l03gJUOsRreuh+yzjjWA3-V}1_G2*YiF1zq zDCq1q`;lJ1q8mimEBbMTv)QkBpliBtWV@~1uS7Q%)Ro%v*Ne5z(Ogqqf21Mc6!<{b z2uA^|=|Zkv#ZHYa{o*()1t(+8d_@(w_;j_JV`N*2;0KQ`?}yoD8oWe0De z7M>q*YJz@M>C8oa#anu$JJIkrU1pSs1|R@LA?f%(9Hy4e{O6J7x#0QAG{@l6+1>xo zPUv|%p%L9)AP1oTRmY9He-too3~tv#%r0iPw~PMO2u>)XNV*0AKUxx&mR*5R6A{b! zcJy>hm4=3C6zwGni@&YInDz|+&Hc@)>GkYyXB21?TW|CbbEpf})9ZKl>sUkES-1QZ zCcU$>*~z5B+kbF{3?w$P>kAiD!HvbmeNI*Bjv(oDbHSW8kV)DV)_Q1v&v89+FzLEL+-xKY z64y>t3T`A)E()El9WsTn23L*YMnJebL@|m6!pL~sqvk9LPe<~JE@Mjrt#1~BdLe7= zTZa4(F1s?gQwcSBe@u6P(Tvi4U3s5D(#m|PTavg+Te>DPUlb;S*lQ^{XsFTXvq;*#obW4pvxIYAVFJ2x>Jl473ozO3a#m;G==NhEYd$Ki&@HO zadBKI45B+ly28yl+-*@wqA0qkOM>?3Rwz$|Aqw1Ki;gv21!`4H<8 zv^tE=(KUMsBV5r)xq+7FNcR?W&m6TYF|(}XN}2zuXnW?{>1ad3^Omk0O{-YnK}J{L zjjFUudD^CFmvSWXW0G`DnUiVJxO7w`?N%aR4ac4he=SW)LwhypiU}RisMA%P$|S<1 z(?$iy9wh?gX_JmPwkfB5N(wG9qW0p%G~g=TVn+WYm6r5RF5ffN8`f1Tq) zXUo-Mx~i_;u=D8*9}Af-%Duz;`;XG?;h)_NejTFzEO7t2aMYOgzsqnng=XJ-bv}K$ z_NC67f5|Uj+@`|;Yu{~nGh4fnyzY0^@ABld*Ilotflhkuzq`M`nk+v>OPwzt{+zxd zi*Mx}bi2aWqE@%~ita)8e&Mxm)qa+LezBNPI@ZBqF&~SM<{$TFQC~+qKRP;GmH6z; z{QOhE4tmAXm)cX8ov#qCZlBTz<9g%R+k3F1f1~k0>vdDz=AWhe(o@6p@h9`Le)m!L ziu9(Fo5{&&d9eYIQp(f9%Z;YI_u;hgY8ybW12i5_3vZ53 ze@cn|dQf{>c)P8wZBzFfQ;)_NG_`H&J`VPtI||$8ALPzzYD;fn0}0kz>rRVcw#+DO zTmIm-0oHMV;clCLh+6xxofRNZA%CXL*h7+l5>P!WvNTc#9D*tU~{iD4ThS)sPllGy0Wr2P@B*iM0R zqn6XOb%TxS_=F<|C5ECj&Ir})-e9BI4s?QQO0A_XO6^?m4Y4{5b1TeY9i+CVe<-a| zI(9%|D+tsv04inP&Q8jQ3dFVbqqj;7zLnkadmln>EwjAf)Q;J!yb|rcAcQG9_*#n& z-8F4!Ir!Ej8pe89`qSfDPTL3IK(GW$?Ty38L?}+j-EgBGfa?d~#5RHmiKR62GH%Oz zzvcb#JVM&)!I?N*&x+mktlUa~e^zY=?VxsRcEId*m?MnnB%kO{3-a4RahPra^J%9$ z1FG^hJ*RnlvlZrr?eSS6S}(S8FE4iT+2EyLqwLbCC_x@x?O;Y;b!fk{c1^p=?e16W z_3hV!+yIMoy8EnGhU-_2uva1X%!Zg{P@4bW)>MJN?*0GZ*>8obkW zlx}_MfkdyeHfX4Eb{)3?f12S=c<4}^^~$Zo<8HWAgY8>_VcnIm-W8>%KWlaE18}#K zZUWfOPI%af+aTj^xKbM;rvucxfMJNAci?e1T#MZ!)A9kh+KpK-&RuZgV>>WQd~6q- zFsE&#`QgtRTt5K!9X`CdVS@>~;Wq5tkio{?a3>#ttHy>}1L$o4f3po>w*YFZy~EVA z-W$B$Cc%Q=P*g(}E@8kzZyNO5L0iq#;Nwg<BSV>N`> z(HJ`_ORen$V#%8tWrLBZcEY2On^t8SRup=tAdA920Cx|-{Wd`pYxQmj6o+-Rrhr_x zs7mjIAyg%R0+&%zz55WBc@UT;6 zMbgc8z#oul@d23@qZ!=xE!^&cM?>1ofPYOS-<}CWE{14Ae;9lnlXU1P?CG@|dTm2@ zY%ROaq9IyRa5KDv`x@@_u)K>->n#Ag$uhDNlPvOWAhU}lMCZ1*>bAG)9%warKJkA; zd?S*XIk2+XjV*-`8}c~2AMnu{w-x3|joaF>6v1@YrPZ#psF8vM_x4SX0^xxIL>gNS z1Qc)&74W;1e>oHg4;7%T>qx9^8W~a~k-f73Flhq5cvVLFvtB^$E+=J6xiuU zK>@W(Q9=Q|D>Q%tZr5U=fPbg}P;F$i5~e%;tQXiRe{rqXPCQgVKG21GXcq3FS-9{} zf%rfHFLrHz6p%X#+!uSFPG;Aai^*`lUWwi#Ph;LdTE*Rel%>r5qEsQKmiI_=I zI_rY$1Zh(d8?XaZQxb32+J`I)gNg+3`4QOe>H5{cAlaiHKqc}8p^)|x}E8Sj=L*g zk5Jj5J3-{mBuM6~H{kZ|_2Aa#E`G}C~RGB!3m7SJRMUQ6(Vpcx@xo0AbiW`e|rEY zTmIggD>b!=1Y4e+ZpStjn)3v!x%B}*8*$?RtF44W}j=fj!|hWZhhUf)}S~kH>pE<>L&Z=JL8iQ z_^VTTT7ZYScUnj#1_z!6wp7Cs%)}7jY*E7^Oh*CkyO|~zlyqA(k)WjCe*&_B(7#T^ z9{MX_dVs)n0u7U*)*5MNC}6h`dQ`auw~f?IF0e_OX_){En@ea!9`%4WA-smBhi~xm zKiU!^u}N5N~}IzjSG_xz^~G}-`_l{_D{y-}yFKp`iO#~Prn6V|(eF=jd{ zV>>c*T&s+>ZOIr9wwsj2e}VUDv3mo`u}xB$olZ7H+qLOtJ*XuxZxbZniIV zH;cRhIApza+y^y4mLfyK(2(LLT6O4VkGE3}uFW2=LnIs3)Mk6C>keqgo6~SNrXD)h ze`ke^?eqL)wGj$&++gJy&$Tw$sZj?<#Fi?JHrc78ya-vF zZ0eM7`s*aO$g`KV$u3`M*NVn3h1uGv-6C^HnH&&&O{acSe_*<3x*FwXlN(scBC*jZ z&Bg%bCRTi_Pi`>NrkWlG=P}m$WD9|BPj>Xl4#Z|i-VNGB)f2akJ~=Rqt}JL*r5Q#X z1ZU1E)h1SQMJ2Z{c~eGhqd}#Iwv1F}c+W^>hs#qUoGnVdzBmKNJ2pg6aDmJW7Y28v z^c%zXE*Tk(fBD{ND-ATq9k(bsGNtc$Ax%BD8Y3}m@^M3aTqO;6Tbrbhm%;=Gf3Jp% zx(8O9qBj!JD7~?`dD)fOISZAt%#xebnkI;p)J|cyC?8sHPEooH+Sr%5FPk#JH&vFz z1nQGC>ucxprgfQ%w(k=*Y-}ZOdT+M0V~5|Xu;u+We+}Aev4v*pLq8jBZQ2P*7D&5A z7ie;PIwC)@x2QIRT1IeG8&Nf9a zs2;Cglc7OLH3XHVG%@+Sq}#H39n*Fbq{J4>Ehr_ogUq0G%lsfHWp~4~iDf&Mk0Ja7 zlO>~9f7zNcl-ZH7U^W?{bKa6_<~FFk#;kE0^Uv}MirU~7^+qU9aJQ{hD>m?xb*=ie z)`q>&u9l5@7(>2uplfG+yR*J~u>PQl8Egzg?RG21-36Qw4;7FP6wnWi-eDK*E@8xj zCFDaT?1SU5esC3PI&d&%A7~-&Zoxe`54Wz_f7f;WR=qWN(Ism{4k&x9bc(|2!4K%C zP1U%?X%ia3wZX!Jm%}D@X3BwN)h>8)^=*^t!7Kd$d{7C?r;&!<6NTk~G!#|U2Zsc9 zI%a0l2gjXYoxGk1KdhlC3!6<{B6z*7bhk9H^I%jQR!j4_rGcp%z0RDQRmh>xL6F@J ze{$PF8yl#UgmaX4Aq~ixo!*<^T^KgD>Y1jz3qiqfE1I=z>U)a+D#}y|4Xi%JREi{v ztlC_Zu)F0T9)c%9nvybNlYiF2?QXanbbGaw5z=wn9R>1nye+=35R~5y&qrOi!|em` zuzQC2sOwhvcH#==fvWkG>2|o>+O$>Me?hxBQLyF#xP1Wb9)SDZaObwEEn!nnYC+rF z?jg9i4HSjg#Rn-pa|m2-+?dX;Z{xx-r?GW7Sbbc>#cdETwnF4KNLI&Ejtsn@>q40F z#CMfQ3DQGak7&}QcS)R-3ca(w+gYDv^A4>mhNRQ0==9K9BE9wjxO)KZcf+$~f3y~i zi9ruD_ZA*^!SSVCHyq~y$ZrFMO+%IZcKJlcHl~3BI~f`>BL`iBq8EDmay6MReEElVWdjer4uVZ7wqRR!Ee40h zHa0mt2-*$AmC^>`vMENvu+Hu)e}&e4U=xxnrO6q5Hq!1)kvWmroyd8hxpp2^FFc0@ zuH7&RYI}yYO6y%3nL>LxMz>kb4^5^XR5w&tN}b$H4K(h8_5ydCP`MM@J;k=Ah~C+N z*$K4|H}7^f;CDj%?q26&mwGnie;Y*x!h9`(XJT;c`^T%!5L|!%L?yc9e?1h}OMrf; zCz6YsQcvAlY_F82ZZjo)^a6aPh&ay|qCHX?EprMRMae`Ds&Zt*D`H~3cpq|v zO>&P%tNdEfuav$XRisd%?g5cWopxgi&YAv%Y)Vlh7Sjs?b|xDQq|8tx(0jiY32a6q zOW{fX=!F9}1{;SlXic3+f3~?aK6o`4AKa|3`tdd#^&)6eQTm9I%9)fTmh=KMygoGS zV29@vL@!}DK@phj&|5!vSVLtgZPw}sm#?ner>U6oQ)_4xgA3>dg(bUT#8T$iqqZb_ zxV#vljEJcz+wEV45}A?diC>`V82 zYN#|JhY-6_$x=j@fAl4tlJ177E-O=O(a8Da_ht$ zG2woIGMgThe3l#NhZi>_-B6S zAvh5O(OEwZxWOCy;Xs_}@UjQ4qk@@8((1HeGpMjP;LR9ehNv~x&{w`P)RvIdd%aX*~6uA212 zimm>ZX`>%oe=McQvZEeUFThv|>$K|CcDrl)L8UZR-Uv6YN!*QqV}>I^Nh!GzaNMAP zwW#9&T=gZd^J%3sdtHk^uG_M;vHYtIWmOx>g3g1j8OknZxs$BEK||TeWK>F8_zgo@ zXW3E1`$|c4DVm$zgzJWKe{g+6+2ug65fp)0Gn8E)f7msYV?L!OTSHk`@=MrsR=BC1 zN7XZwMH`#Vqq4ozwJOw1k`Aaf$DKB+`Ju_wgIY6`Q{@I4cR|+;2^}(&*NW(! z4Vax!`*8DaX9IpGw0{MvO@}`-zI%4^Urc}>JPBm41?AudNt$!|8YMs<5 zXOm?q`$sR6n+N9;$h7R8#FcfJG|#7h2)FS8>BN7%>CY#R$|}2l@V1?+OCr*(BhY1w z-VY8ZByD}|xb6C2<1hkq*g_00O-5ngOdf8ae}86K2bX4~`et%!US`|Sx_rs*;0ooH z@1L$+pH}~1tqduK&_MklG{%08ZGZjhx_zq3C-rM+{}gSrf=(vrpqZR@U(ZaIB3G<| zYhuZn?!Ir$WR>=H?VqaQzQ-55%bKDbGLv1plCh+7U9rzloYggG!$7X}K-o8t>prbC ze{Izv`#1}LJmJ2LoEt#`b=%0AOS?a*#zeLjr^}^~vDbRnLe52ualTikucrv_Ix`qn zf>mu@$3cW=6`-+?*Vn^k3$c&7dO_-$_3YzqWgfy_Z5}6BJ2{n%NZFU^A=6XVCK~ft zT3m@JVot`=wTZih-gG|B7KZzF9qV`vf972BET|slq!K36Dv64|b-X_9#C{w5xNbrv z{kNW4YadG=$hl%eSH|tIk6o%DjPI&4Ly5IosyJvL6Aoe+lv{|oZ`#Jm_*>(;L$JT)w+G#SFBp|c1>AH z^1n52+pxaOW~kUD-dppwRViZfj;g)@wJLTuVr$+GO5fJL?Gr{``PRP8a=-C`Wdqjq z?`BE2c(t|N?%IA>os_npPpb!Ie`Ran_Tf!Lebd108)=&c?mB$kz^w_vqFLA2$Q8-g0&O1A%){C^qM0v!+DK8W z->)6fY_ISDDcFwXk=q|OZ0p|b`c3CZo6$oyZCzs{dv@@6=HTJX!K0aje+M%Mk7W)X z${akBId~v*@Hpn+Vazo%vpfAw6SE6VM=^)*+#E1HdtkMrs@_cEP9N1VTgYv|5VdPo zXijpXi*cOa0IYq^rv)TEq-S_0t{Q}OYc{8-&CRf8ZswDUbXd@e8+X2Nb%?Ggs6`Qu>;0JtKKssd_HfFy50iX3% z3WKY?cJY#|<(J*Kbt!{nN}*b_4%_zDF05)kwG%fHP|Nf+UXi!S=E=)}bC-45A-26? z4K|6hYnEVBVe{Ni!fDU^>wc|f;Jju14I&}8)=_$Kul2@1WU8$<-ZRyDw6uBFa_FRGy=I$9 z{+otg^ZwVIvh*(Ef4&Uq{FWTUG|HY~_d=^OObkm)Mq<*p}_Yo4myKd$FCwNzSqIos)Ck zJ2Cw)=nu&G{)F$lb*q3XRG~>Jit{BFr&0ITe(P4-<)>vm&#Z8exqh)4&ZK@zzoHea(%}GR- zOqoV3?u4>bDtV`ro@9mPgX}_Qmsu54%Tz9%itW`|Wa?#6y)|Z4{1khvkv#FF;Am)2 zXNFmoGRw1oe@?t)LD?LuX5ZIJmXz#d$x?E@>}a=ES(uc(J-6F+)wesfd3v>Z>JEB} z%qZ-rioD2Rw%+!VM+eZ@UKSunM`t>_%kB!BOCDFQ&gQa!GrF-IzD}sqCY>!NiPjv$$gAIAeNqLhgrnZtJoKC7o9xpm~4#6)@9*Jf4kl5^z;^)#Q{*Y$mH=GxJ9Ne zhF7gEreKMw&(~d%ueTzfMtZEZyj)>(xx(6Vg`Fjhu}6(|sLNSysX&waN^*;OO&jzu z%z_rwuJ0;0)YQV5iKZTAuL#HH@TTB>Gf!U8j2b&lP95A%Q=fOZI&W`9Hx%1Uo~vJb z%2jMLfANZi`Ec#Ft)bpNvl7=$xvvqdGppR4TW40}?jqb6o)YSyj=UB zNVJ6a9suvJhF6S4*|k=!k!T4Yu7c}~Lp8+2Jd2OSkq1+!|IZ4Hc<*->GGE`#-I+cL1Vx9x>}Y<*lHW*@sMa>y$Cf7pEQ z0rs(-f!5<)XQ)l?TKZ&L>lLVQm0AmHuYlD%O|8vR?>V(D%fq=Ig-g9QGbrnIswRq7 zZ`fz5%+yMzVxq_$Qw`e#AZXb{(du@(Ob5yWm+KW1#V*tQ>){eoU6R7K*REP8LL7@B zDx5e@)i-JR!oXE5WUD*N>Y?6vf7^Bx1I41N!1c7QO1W3nenpYr;qJGn8}|M{2W}0) zQL|#9$OmxHmUS=XA?iCQ>(#k1MaT8>I9VMB2fy#MtBy=t7Qeyi4V}KNSSJ=!)9&@! zig_aM(ZE8-SQ0f+bvV=)?Mv}Yq>{n8EA^WznZe**sAwx&v%Ue>P7nrmx?3 zx_zCi(O%nukUE;DFNfM$>RgSsJC5Gfs6~U`=v<95Czl$9N84t)Yu(ecugZTGDX z3n(+xI~+wXXR<*c^O@fn=uH8w9_li8`n0DNJx9wPphi=Vxy_fgL#+Wm+I0qYSLb`w zZdq-oqxC)7hy7dcdlcWge`~#uTGr6f8~q6*TU+0F@?m7d# z8`6PoIjS4dqAARwX2lIDzcU`RZ8|d=H>BMm#O2VsAuS3Y((BZUl^?9{HoNV?hpFl# zR@FeNSk+z1${*ItqQInjsCxF0t`=KXpV`(8I&{P<22xd4Ua^oWf47f8*XpYlQbl)= zrZp}Y3+*u3ILc-!&3#bBSB;~J?XXYJi>k}^e$T>?89mi9sLhn^dR@vNh8>N?A6J~~ z4lS7bVMktW?Sai+L|Ncal`S~~kadP#OJkbk*r-}&;Z$~45EhJ0SAL-{7Ecehz+qSM zLDm5UT!1Kke;HpIe|D8ie?CLqp5DQt)u(*9E8E!i21DG+`@I1MIn@le<=9ehhc$d= z*t4_?w>NM)AkFmjr@S6L2@Fve37;bi^JHdH)j^Ny!(O|lf-W_d@5#2wZEnlRww_*B zpPM-m?bVDNb9__dT(*x6<%d1p$gvvwY{~bA+6MIPJ|(rje|iBiv}w}@dhxQ4D}JDL zRoWV&gkTLvD)nKs1dynenQjl;T^c=dXzM4lL){i~(c!^jgQU9A8EO){mM+oO zD{)lB1sT$=h14nY)u7jD^y$%+kcuq!TUUvv*tP6_840mF=&JD)`*ycoqS$oZ>EkKl zi^Ra`4;>|*e_^qOx9h*mVjQ&ot(fY?B3Gpb!)29k>kC>+kgk7{5wk;62N7+N%CuF?>3)rNCh{Yqe1>sUJB+gpi@OVwfc} z$xhd{d#Z+CIh}*PM$M1cz*K~*x_-P47;25ef1f=17g-sT`DoyS|?B}ZVRT-I{)9nrGL@-(* z*J;B*AcY)O=~mC7@o1}ZSTTA-8$G9Lgs~EbhMz7(vWi~gz!}h8OBTxXvs8*^e^o-T z;LIS1XBC=kJ9NXT%4n5Z+JlZo!w+8bcTE&scBDL7(&!-(OS6a zP29jbgvQj=gduFxQ=ujdA*vOtVF*$CT@6FX(knJ@MHE6Cw;sE6EsLsOXyit1)gbC| zMXQ+Ya5B|`r!%*aj6p{OYee^zed5SM0da%$JorrO$6N1NK#rgpTcU2SSlo7&f= z4wNCnkw6tdi=EA?P_${YhM+gp>R3IeD@}_ge4st-Xu}8g@kFB0pk;tw9YE{2dmu!h zE&+ICQPo6x9cot6w`#Ob`gTp_eW#|5zPe6vjr2P;L(*4!j+S<+(r;Imf1QOz&Gh8! zdfp$_00vggAR>ds>DOd)>aw-#^mpneeo)u_fvgg0bAK^hQBenl7a9!NF{rCjJngTCXmb&&+|Hb#vZ$kMf|6^+-Z2b2MNjA7eBSFm0yms;1++pnRh!-eJ&zr$5D ztePx^s4UdMJ&IK9*SJqee>6;#W#cY3o=-@(#(=F?apzeoM{?6PeYikp!0J@_6|N+m z0UIw;8I%DtKjH$g&~+{{s)M3fuxWC&SA#o3q2*Y$`^<@mvN3^kl71=Qb_YXeSUh&x zeL=L!2{8Dx1m3M7D(zz({#ITPP_+UANGs;Tc_P_(VaHQ1Gx0AFXa5?>^diw5T|IwA$$I zt|lr%*BbQeePDq6*6ryXVZdc2I!4ra!=U3h;BRo%sO4}Ajm^^d#h~u;J2lQRz!JUP z(|X7N-!-_iYu#j&IVE2i^m3|H?yGpp;4xE&ou2A0LzAtqf9r-IP2lK>qsk=;6~d(o z4aBa6IJJ;=Eu>Qm>DEGewUB--MAj~Gx|XB3+HktH2;8FvY^Va^>YQe@Y{}Y z;M$U@TH!fC6+<{cK8+5XVOxY&JdO|1Zyt*u*BfZ7g!Z&6Qc0PY1%2(y{&d=H?nMw~ z2U}k+wyG~5f9eJnb9{=fKl*KL$=u|&qs_|(QIc7NdYQDL3NB2}>T3(7H~am;%Ek`$ zL&zLwSo+CfvVhIWsV=*t&)(?{Iu((Ix=iY7Tys=LkvjtEYCFY(yveSXdUjVbP|^V_ z&v?~JSyq{#`VRV7;uqnTe(F@m9iVxHYJ3h;DVKsBe+>GlzQcjlC_F>SWd{w9z(%20 zY(te82jFlSPjGl(QFamL+ZQ`haX{Wij;{6MLEZSZh0N6$2R$CaKU`Z8+~^>J)Hx`viDpD9B6xA)KG~c z&f3@Kf4(#3^r~ zR9sH#V<*?drvM6b%NcW(50b9 ze*4qAG<*m#&3dmAnxzxYES+3t=|nP1CyiM;LCn(0V3tn&vUHM{r4za=oxEk~L@jHD zlx5WkSntyz;d_#(tU6)Js*|IvIuXjMf0Lf9I>E`RlbNhKamlKal&m@-$$HQ7k);=n ztU9U4suPH;6|#_3Ck9z{5|C9V{8)8zk5wn~6h6_kGEV{32|ZS=yu;iR>ZG039tu?% z$Ep)=tUA#~rSn^k}DS zBM&P$Snoq-uxiBxt5#C5YJ~)=e^x%QYDEL9Rw}So2?ScVb~5Zw68a2 z$TBE`G1|TIZx?4No=yEI;hJVToW@PDy} z)K;GQHKpdzBG_(OUAtTQcJ71d<6szCa4pg)PEk^s{WdkEF9)KFH;OjMvhC7l9g0KW z53QkPmkKgeHaf2U_zJ@I%o zEL(ueAAOwFVKD$s$7?@*j$oR7$J?^;J-p zu>f5z{;XY}t6iH5{qI(@@y)ec4^uWmz6DT7r3r~Rz9DmrXHipAs z0}l39#laQz^=KnZJ~&fvj#>!yv?D=yY1B8M7SgxT?+_gvethQC)px8_KwAOYcq>u3 zs*?xZ=I-S-z|qoh2;G+B7@&_i6eV9*AAmsh z?^jkb81~eG;okTL%xz{3aDT80IIIVvmUfl=S%c7hR2{HytpeJ$z#%;qDm2QEfXo?@ zJ}>u2R0r*M9S!-|T(zy=ZLbD*R)g#32cWfcz__9FKyKLUT9!itnM-#UlpWT=`Wo0k zkZh|kJ`2u@eC_&t$P=qTK6#WW)&c9eVzH77Zdj)D6&%j}g!NDPO@Eh;J#Y)|9<6Y) zX{`p^Ixu&8hD@i@DZAhsgC4vp*{yc3^baSnmI0#FBMcvaK>5bXN|0|T?YFtRJjyv% zfCsC=!&PA99|~=<7!t@pYN35=CDg8maxS5eTA{>h_g8_DPbj?t9ayJi6szE!2f$ZN z31=2HaK8IfTq&FOM( zp@lqe{khyU8ig7i7caPZNl9%gzmTW2v;y3>R)g&o;32)3gll}p5WB*w!jRrgN+)@q z-d~kzunIWTmq@qbx=eHrqsUL<$) z$z6T2;3!#g!&f}K*T4q);)dE}dMcmZ`YG<~ zr?{`5;(xw=iu?Lr_VvB&>wDSP_p-0=WnbURzP^_OeJ}CV9tlE$>AO16cXgoe>OkMs zfxfE)eOCwit`78F9qPL}T*0u0&I(w21x(**`g(5-yXCVZChI$`b895nXI8O?TI}K_ zzk;rbEXdNG8hm=CMQ?&NnL0I@x;5#&vM?3cuYbujs7bHsxh8@jrq}eGzSr0F&|cMj zHF_XR@7ARA_zmsuKuYh|;16ojYkKa~^c*j}YdWEZ2W06h=p0YGwZQHwpq}XI8CRDs z30Rm^!x!1>{*cE|C=N50emd}Fzh+qY3x2m(_)ur*JS1ILI(HPW_{z3X!`q!2cHOSo zet+t=rMi8oW{`$8?I~XJtLaV+_jKAd>2>AQu&=gVlU`GP&AGUExmVI_wh*VL!{y_< z0_Zq3T|=Kn=yk@iha$l*m*mF8JI*3M&Y8X!{x>Gs!k+|;xW^>R(;%PhmEU`57~d*B zk3JfNvpp!H)27aY@Siccz3)%mkxk=xz<<9~g(f)4Q~#P&e!M@Y(r>>HmvtbEK^x-z zIeoeuqK_E(r%zL1@uSL1A0iaMTkkZ86D(suRd^lhucgZXw3rSWWW%xC8Ix>(0q7mj z?(AA^R!p|Pptul(0=vOdDW`>lhXdt1Lz=onhZdf*z{G+Ux`SaM`V0{>Ur3V$lz%!v z_fO!53G*`myog!Q6&uCc7Je6Lc_?oM))QG8JEC9O6lrTbAJV=l?FGw=AF&$z}T26^WTu5rO2 z?|j=e5`(<+eb?{}^3E?@V``9h{)r~u{{qFl|3%k$)FAi&0{?u;H7*(C{(qMd_7&H- zXpsAFy2g_Rx&KwyXdC4I*IZ-UAostHf4+gRzr?R^y2fRL-2awqeAFQKzwH`V408W1 zgnh>~o;Jw+@4Ci$gWUg~Yg{+T{l9XJI|jM`*NFLj*LdC__kZ9T&lu$X4_#x=AoqXd z8qXQz{*Up`+t|*ZAm&f;>wjn1vY%t(-?+wAgWUfG?ezU$y2g${?*9tE{-}-Rrj7XHXI$gRAb)%nGrWd>UU!W{gZ%L>{(pIcw)2noXhnbg zEPnktZP_0`hl!tuJ}ftP_v1+(Ch^+Aq7jgs#O86h+c@cwwvt7)3x0sUE59K++8!8dDCba=H`K)uBBekn(X=M`D7YA zk~b`q_#Q2Il#Vx{7Jq+zJs4TzFkX9hw!Yp-y=P}5NEp{*Y?ht>z@yzW-+S#EI7Yj5SA?SJN;Lry(Ag^{CZu}43= z<4KlXoIf3;m-pQplNRg~qkMeE9xOL^le9sHYAuY{ZcNM@lh&S}T{(=OPLoBD=6A4j z@hBa8HzuQW423VTb8ED8+S1v!H-eo9E}usZ``c!JJH(-XyX*#fb`*q4P0k99+Ssr-l#=yctIy<0C$qWm>v480*u=k5C>f169*K0 z$K<)0$H%QfiHbEjZe`)i!C7Z3cW2w9e8V1(FloacFE=NVpJi(|{NqUyXL-6m$&<8^ zo5%THn6H*u`pC75*B-xdu`*0~@$=-Q$S055sZ%-sEeu^w|D2o{hBAD)@F63xfy{*u z83BhhFMofR;L6xOHX9Ym8}?Wpl+5 zV*~0+BTeYsxaD*aHm0sP*o1P`VmL@SkZxs^NjZdWWqe67dagXMgpG2ng{vL2 z3hTR#2M7+=ZupJZT<-Y?VLZDAV}Az2$>0J_dtSZ;pV$I6@O->+n4g<9 zdzO!6f2O+m#Qu*Y)v3X!z`K>zO1$k=*jc)^>umStZZvp1K>AIMj`@f z5Sg4^AZK8SyeW_RSx}5r?&W-S3WaVWJw7*UNXxqzc(M7h+I%4s13vU5#Bwvkm&170 z;D0-1b{OW9J#m!7sd+r{vtX^`(m!1{_u88~Y2e@5qzOGt@4LBYvvhX8cXO||6#MgV z1HCkthhe^V9@bfPLU{>nJu=j%as4&)xO}OevKTs?i|Pu-CCm`72S@p(V$rV3!k0O+ z0K=#hfJ=K-0h}4s6hJw^s{D*&2-!0_vw!DdlMXU5D!3A*2q9)gBWR$1^EV~ z8coC`2K(aZV|O%O?i94cYfx9-DTz*NYbkgyt4PR0s}k6Hr4o_jpPV$*U0}Z5D2g{t zb(>huf*k2gE|`(bmXW7^oGtt`h;u_=|I4M&NUuj1^V56Y@gjF^GM~GB$LXJOx_=#u zOv(=u#%|wfIeoITa0gcV%)qk9V&d8knND5XX%EiWAUsbduH6}Qd-xSk-QJ*krq^*u zJaO%I-#TMkeUdF)`%Diae38WwFKtQgY8CXOH+T!j$ouxFyYGi^zh@Gl;TattblWobMZE>QxIU59%}vZG#VOh&k`duG4jA zZuwp;Z6mS7cud##Vp3KY96@z{r8;(%q-kC-*WrWYfXJm}Hpv^t^(Q3k3IEg*^v?D>tn74Oe?g7m{FiTM%1T$00FGyToH zl_!_NqhQ+Tm`&)zl02Gd>7=zAMtP7nV((mRwq8oYxM8dr=8`<`NMt}#Dv#niLAC&! z--sRX{5(&?o&7w>yyGP%p?{d?vBNQy|Ge_dO*tQIc+%lHJvljE0?jGY%(g;Sb!)Mo z?KO;f4nQX40v(iVe$xkn7fuxPB<`DV`6#a#+^wg{WPcvSd25meejZ$m0{Cj==4OnQ zZu|4Vdo+M1&42avxRnL@BOImS zSEpy>3zbBkwHcko9_@wEG!5cb6vVT9Z!>B(&A8<+7C}5c53q)WHj2irJlRgBLBlLh zluL53?VTCDm>H+fo$+2gvaF34kL=y?8S*jRm>Xw}X1*!SE7lGp)bviT(Nxbk-MpQ* zf@}i&WOWA2=4s1zi zX386f6e~3@Wvwa3S2u}#71hsUWYV>Eu-(doEQe1$mnlkEi~V^3>?T4^6E{6$4Zcpx z?W@v4G^Pz+0{*#j>@v^V%=BcD0a-LXnHDmjh0A_=Yk$!wiGQK#8E4PXYp8PuiTRzv zB}=|j0M0^ucC)}sl*DR*wMcgkj0uTpd+L1v@*OdSUM^Ly019@b3iK@Hd8ak;qlk_n z$!VjB+~^qC;Zj)0M!BZ^J!7ocm#%Ni+_k6klr`_lDRSBU|{f z0Z4ojINHZ_Xn#wbi6@-@>X~@&;~uM{o|c=CH1x(^8tfV{cK;PK;y=W6_~l&eY^!s@ zZ`;y|JPA?$Cmj8v%9s?b$>oYi#ym-<##q|N-}h)zS+#CAHp2PLFgJ5-25S$=X#;sn zNiOWy*tCMN#SgtH#IPx_tGrPx?b301g_4VNj4eNXHh-MY)}VbV=gray<+sho={0Dw zhBrq!ZXqNVH?#M8x~Obssj``+d^2Ob8ai9Er^T#6dDAmapE+lc9Pi{0x4q+ce(oCo z^2`78NrSxeH}u!*26^Xa^w%d0^3G4`uU8Dt`}chv#~~5P$b{@NdWU2CdnaamN090G zR&e+}8GpZSO{vR*wltR-8K0a;O-ze#)M@!g zfu>%#UEagVk2mJ#RCkD;HjSIReiZHalUs&K&Wzsq`8$8}&d=WY>G%vDKZ@c^exjxw zKinP_A7k@_UGH!;Lg8iIB=+L{DB2VT^PB~=UVqCgaJM5|l9>DHER3(xX*y)R!gBcS zfqVvKrN<{H53HbGK6w8E!b4SDCq(dNz1653;Y|{ou7+!!vVq~8r3Kd<$aC+MMWj5;#iL&Q-x(y>MS;dtp=W@ zp?|E1;29W36;ez$;`{xjq{<23&$)}^>gDhl7)5oV8GCuYaL=4MJUnb2wp&R$JL6cE zbtXHQ8KiD4ZC`8T!~hf>Jqx1Em7SM@N#0tdNuIzBRApky!;g@Oq^i`KDpIQ?8hh5J zuNP1J2S}~HR%+F3;@QD$?Pwmw*~$?+t$#UL{6~iaPaY`1#SaqT;xQx5T$bQc&)Q7& zLzFg~W?q%xQk?{sBlRB4aMMT1Js;Ij?!wRaC=aZh9D@{=pZx60QS&NR`~lJ{)MChw zE=5IK6@mjr8X3cMH7HNAw@u!Gu}NahF~3sR>9c^pHr1c^Sar?Q#+h@cT|KT^FMp!* zNqJ$WeWO#Tg`57p1)GXO(8Z%gFv)}IT6Sl?lSD9~Ydib-+APV}jOI1^2G9shsuNUJbhNFj z=#uqN6)pVu>__u?bRn5Tb?55qgMZ<^we216gt2RrNt9%PYm+dJgVeQ2vIrn~0gZBP zk_M4$FUiGi@7VAslOWDF^5j+!8}R<(=X*&yb!}oKi!wPwwLaIT54jX!NuG?oW59Re zxEvhi?(tI4Av!`OD-=M?<0s=$Fdq41kG&F-S(@xG+?b@nA_AS!bV;K1b$>W2AZj}H zcpmKEH8{)Udj`1?FqJ5B8Ir=-AU8b2pJxUMQcvy@xtx2(4xoggXV8H$$hFKf=-3$K zu^dYUDVE$yy|UNjY6xHO>lw>4=-?UT3C~D_$RJ7L8EjAtGGPs(qVQ4U8o5lKAjZ3Q zziSZV#TSFy`{98>PFbc1`+s{1Tcp860sR97W&0Ba^!o1*6wa%VH@=VM1?j>N)8GD^ zqMqP(HPhR_C~8uHcR$7JQem(E6@|^isgmn$3W*{G@DmD{%@n|&Q-Gh{nJ<)jSg-ul zkD?%wdUo%13foBz^DwAp{46#wn}?ACd*h1;yPfUtWI?X>?v1}F5Pue0gu7p$2-8FZ z`|S59Y&T5~W2HOyC@c;Yz_-{eC5t>!nu8@CO#N(6fnh%ZbWl@Uau{dDz&&FTqlGgx zP4b15{_efcP{>4rOafy3H=6$6XxfcHlgJU*Y1+DsC?;~mcR&5NIO|cckUB+yufKw0 zn836v&`*D!Licw3RDaEhL>nB1S)QrT*Kqv(oyb>!U;i0a8u__e<(IHnO>4gXb5>@) zpZXdwPS7OU-^unvP03%Q@WX|g6IX7w=cgJV(!@0M=Se)(m;6nNay3vhBVXDJ{502R z#TD}ST+R9&Y}CS^2D+@j{~?86}$Fq`63eUe1Bakyz&{B~Hm zrkP*GF7AZ0Nq?A5)H1)0;Qc5Has?{Pk2tFob{DzFVXEZ%(LZB5=YBMk@*swR)vajJ*@KhcAt=}SiRT*#nx~PZV(&#I~P3dYa!drh=)Kp)} zt2iUjlzODMek1jJMVr1{bbdu?e=m)|injd#>DFIl>VGEq*6)fo=@DK<8jJ&d**`{> zmn64pr{UGN3!D{=M1GysRP(!Hc!6yvNxZL|XR)zihE4W5J5=X&pYLjM2&@YzI+al!M zw{g3UVt?_J#j5*J0lKYJhfV%SbP%L@TrKq84_Hp=5X~yQ%V7RuktRn~@EbUDv3zJ} z#eS!Rsm;Cjqv8~`^EC8fRRdwjgZxt!K^>Jh-hW`?2OPuIN&fd&zJWbE@Y51UEZ`^i z~~9;hHQUa$cNf`|Gos*kS)??JW1l2(%;uax~+(KjCg;*78M6p zdw<3z?^!L8{zRt1lxeaF7(dfsXvpwuyrE1SlxOA*PK1jZD*j7>1{XRi{;XVpTEf@W z5-M$A-1k}CQhxhyOYWkU{_fkqE@x3!`I|-WcPhQdGv5EgQ)3+MO)HSUWsr1F=1H%9 zgYOl}PRtN+$YR|#j2N%sVu_!sE8;a=ynpf4+9F>4dD)5;6@9L(s2=Oh|A`{HpK@9% zIxLB-Sp@SVf!@TuoaduEw1n{0H`vMN&T@osF-3hD$VA?x&S8 z{T>sX_kuK>_)*QE;vh_t`2sKfs~GQ~ z?=s0v9R>z^G&$1J=>@!!kVz4*@qg|FvC!%|P*LDFQRJNL1(REIKfR^oRWW30L&mlv z3|0yIExR#@v``d)X5n1ka{%~JV7ebol9b*) zmzk;5|7CVi-cMBoEaA)SXj@wX+p8i?33Nkdr(exJ@MA7iu)|JuoA?U5%zvg(%`yMo zyT4)uWSQ=;@Ri((UBln?(WBq_UBJja@n`CxpAdE;6Ynym#+?qksmt zHSo9Z32+_4-7l6G!PQ3H{SuR$vM`=alRVQL2T`U6<)B)e*Z;BLeVS3d_va#1&HaX1{tB4}(d{U7_Bn%YJw35ynDCs<_m63`^20x1Mr9pyzuY}@jfYkBNv+J$-LPHmL z=y+5QWRiex3I7uZ>6h@E;u6-8Gah4Rd8(U?S2<9f3tXUI<{)Xq# zag=+1$)Uk*9sKRjmT)b?UEX8)ije`oTAYD2qx?;YY}93m#GiwaFbtNI_w^FS#!6a~ zuL|dV-J1L&Taydjn*4(FHl;NCAB)3$-I{z$T$4JP@a{hsW$4J@w*|CjO)6($Rq|q@ zK~?aQP*C>NN;K^GQGb8o@%<8}6)NxklphNY1NqcJhX;4q1z7U#Cgq`{DE?c#ckHoF z1b+1u^_;0Nq}Lfk+6&TPH%SAfhLWWRi!6*1nQ^@NYqbt_fL~`P=3wIQXG#_2ehF(v zzf$wGBF(YgU6Jx|x~nqY-A{5}qrO$Mm)j?ju)-6O@Gm5}W`FyC{mXo-mER{g_)UQq z2RXiQ$m|I>+wn{tIDV;Y~|N5DdCsfxht_ zKAXw_(JO=R6>st@?iIdMAk|)jy!Ki#YXy#4+pC%v9Tf{tx=+<#xgdq+hsj>xPwUaX zSJXz~xgRQL?pJ@pE-aD-#i1Oq+MauItLvT>Ui~$vq<@2;wy;*)05TRa+$9pnNQ0vKQ%-19g%M8>HXEeDod-UoS({+gZo+)={FUU z&}02Wm47DmXm~$zRYMeS6!QuH)%58&G8{w31USe)r&}?$d^?u{yPQ!cR7cc$PsVS zw3{;GibSYyKb{6@Hc5(`Dz5H>v{|`o%dqxEQ z+n4wi=3G%P`ZqkjTnM6Eh2e4R`d*-c;iNw0&v&LO5c}|ar~t6%Ppbf2hS$QGriplR zeuf=7t5Cc-dU{VS6XoZpGZlho_$%{ZrquR`L5zR93`v=OO8b zvdR;C84YHN>J(#sagxg<_Xa-U=E`4)sIdQLiSy$n2 z*fqEc`7M{OG%$Q-4-*Xtj}UliTZQ3P5-CfN0)NMLWd(qec&q}D2_Jl7Pus;5XPMRa#brnv*}`EvTFcD3skR zQNIdL>orPffWH9e@7&1+4iTAv_>XTX0#f@{Ek zl8XB4!fT46zs`tE(#l|<@3SjpLz}9oyTAGc2FWuq$2oQ}tLUV^&Q4twz<<9pP2G=( zyC0Q$J}Eq4C<4=`gqu_a_^R~up@3hLZebN^>vgUev!jRK<#4@;0DDxJC(|I3Muv}A zts3Ipzh-bln_8{uEV~s_Cgv|H0#^+}MTofjOQsK{xf1^cSD296kR-(TJ|HYI|gHSVP@rsCP z9MoPI{sZS-6)OgW;w@~V+XUXg4LH$jX(LZh6sC?`@sr$|CJ$v(1BYRRN3c0 z%T%g%qa;a{{rIzZH-DKbP|S-PLo^A(NX^Qw)~Y~g){8HePxXQt7+;%k2sqKC0h3_6 zf6>E}a{6^PP`FuF3&YfBmBKiL701n43i$shpnf(9!#s?pfsDa=h6RYdD=_{{E(5s7 z{#@P_zsRHxy%zcx+0}%8C;L)y!KTmsCHAgV1Ap}^tnT^}zJJ2%*J9jCVHCf>&Qyyu zDVYxi-TMURYj9STL9cKS?h_L5N1x_Ew8@ckezGv1@fQ`)rwY)11@!t)__Ih|dQ#1S z*Ak(c-176$6+|lWIFq$uUtI_%{ro zLVm#^3g}0#7Ju4(x9i50K0orDl=`n_uxb6Ep#LC>!bKLAy$}(=5LrS{iU6xkX=8sd z@E&&dBNIK8DF{}9lr!A>ITv*gC|u?nIw)ifQeymXrpz_j&jT5N%ypLf2QuLIKPnm` zr8D+ZaGj!{yZnSDC*vVzCk-m)|L@mIT|o(eylKyutABm>Q(tAwcOn<_b^Z)3Cx4@u zz_fa)_V1s@G5$z6M~4{#=yjCaKk||Ug5mua$n-D2l+ykcu>bWp@;v+tmL4km;J;$o zFR7ZM_*$*mI^RJ;@&g6(e~S= zHGRC2ihmXVStS)Udj3Zx70Jk}q+&DnE2%j5Ejjh~*#Aid7YQP*q#_X>R7&`fK~BH; zBDky&aq*?+qcScxn*?6M&f?5FZ*brp8yg!2c&;`!_>Yf&9RHp^4S$!iDJ#tB#)dKp z2w?mwo+`WfyRUrNz$(<7UoLabbvf~cNzM1QB7fiQ{Uk5X#sUhA{%K9tugh7>!?1t@ zbN_K&z2B5GPj@0+)i4#Ob#;GB$u6J8>Basp*bVqB4b@-0+&lrn_~fMap`fgLzKyaBrFpOmLUOyr0k zrD=aIBZ`R}ahs-nMMe}8IpWha?dvk4n8*=7M$^6_BZ`R}@hVOGmW(JSa>N@n?SHRj zL@|+XwtF<~b0wwAiIf5)r=UUTS(`y9%u^8ZdD=^bc?v>vGl)I($tT}rr31V?NS;B+L={p}tIUT3-ft1r7d@%j$4L+Fm^xM4;rkugx z11V?F`C!Ip*m>CT3C}vc_4USs#(%s00nt(a;l|rs!rJXR+Qx8M1vlEFO>8`1OAvrp}D2KRii5j`>Sp4#IK?s;(|dVgXfg%uQ>m!;hPkuD#~6M*a)0^S`@u+}sZgWvSzGIS&XI9ipg*qpads_8!`=6dM<;Gq zsK0_Q6XJV84)X#vthS;;7!QeBPZ4>}veO^e?<|7DG|U5a_#TWnCi$I*S(ud;{HKif z!?gC=wk|@Fmn*?ir4-vFk=IB!x?N}3Ge2xwPN&)MH|XKZY+}5p%zvX1Rq1uhmgU+I z@yND^18Z>Bi`Lhpv$kV(1|6(%;?dwh^dX?ph&B+>Jmd7ZbIDO)jV5D=t%^Ug@p#EY z9NCW5A2_U7&vvXq+s1NttL0Km^Nej3<>q%ryR=;V!OI0tl9A_mw3XeHlj3*JEE{C; z23a)YCbp$B=$+*~gn!x?K2G?i9RK7Qc-LMeDR`lT0rn?(kkXL15Z>n{O9@=WyjeaO zW8BvDb^fcx+&fYa(A7kf93S}6K7?Llk#^mK1uJs7B%xoa2R%t*0F{?4hDat})?(Q= zb1!SrBI$8{7rH*d98+(?++J@s(jutt$%((dj`8Gz^W@K&$xw$b^3T=JBrNz`hz1i}-2?sNGfZ zpXQz~#($cxuYWgorQlEVBB<8xlHA-@X0MT`E`r3pv09No z&(b;6vn1QwTAF43j!t={r_i!<`JQ;P5W7g7rGi6ZSARtV5RC}nibJ+^r98#h2-s{~ zmP>MdTUp8I|2uC1rICn5$t6M%l8NUR9Q5SG7vfXLEOM(i*}|W0EQW2JdWJ#fAYcO% zlUcdvdGu7fzTOy3$$acx+ipa}H%&4vq6Ki5xuM^P$dvdbCK;cDxk+h$7u!E0hxDsL zO$glawts2ake#IF=FHn^@ew13-Uz?wP%&OU*=o$Z^kB3*mJoNxrrVf#xz*Suu^5Cl zF5}Lc6tNaOrmcR-YD8p4{9@Xrp3dZ+9%4^}12v}A`uePuMd2i9Sj47dDr~QYdCZUf zH@(rAT=%Ta>t`c=@W0+{nm2LLL#?ChV@<`S^MB`q#!Yj%40n;0atFFnyQP!3T$FTn zA7h6Ko=gj(Gj#zr41YX|a6h5H=-2`N1;7WNzleJk=7BB5`q|hN8+cW2)B`h{#m;`A z;2S3=r!HUvo}mqZ4m^Ado{?MdfSPGFm!O&p4_W>tx%^A3`nIeDTV&3t_v3)OqlSGA z&VK-D(}2xs?%xWoz+5fK`E3uJJ)7P+IG;S4G=d^X#VL=5>?poZP6E1XLI_p*0}_N? zilz(SjHFJ{gIZ7tngNF&9_p@ujVyZN!DHSIog@4$Q0OUpDS1#2Si}ojM{UfIpa=kh zt>@7|iYCf|G|Dpb`Y0Mf5h_C{(-+EQKYy$xd1TuQymQ4W&OK{0KO3;2*swQqF1p8F zFv`ayg+EPuycx?r&ezw|YQp*LMod`TL?Gd&mm=SfdE6b0lIb5ccnV3`4+xWjv3LX= zJR+s|7cf|Ko|OF{K`UEOR+TqxVw)u2*eDJU!IJDOq-chPM|sa8sb>-2vj_{VsDF*C z$j*ql7)^1L#}GOf)9^1@(S8<7=p6VSPrZycS_=Pj&Zj38Da~BwMOY$|^MFJomrq?w zG7mK;Aq;f_EA5h1r1I6fvuH#niIyZk@VFaw(>uqoc>=jow|&pU22j9gOyZ(UUzy7E zm5#(xBisS(SMDo9|zXhW;CNN+$b`N=cTdIaG;6;*!kN_Jh zaFZ~m*4q1ibZsw$2Sb5IOR^)WH;PBrcuah61AeqJz{a0J6wKK|i9DZVo`1cWot5H1 zG9h$>27ttz5q=1HcfH9*BOYZNHcQ5_Z;DAs(VLMMH76v+ZT^_@bK_Q!#s&rt-(8v< z2$k^lc+7j_ri2#c`WT>Wx~Ux+szOu@$J{G1F8H}mW}dY<)2!PW@9?3xZfE1o`G$Ac z%30yGxm$-+lyMKG4j&4AU4Kr!`Lc{PTy5eGrB}n8dK+@<%2>!dVk>Y<*`cj~BRo`O znAOel^rbM(@->=kZN8u7YkU3y%7bf|rFGiWk6DI9H1#%igkIy6QXj)1(!w;@J!|u3+2EVJ!PmWXbdxstx=gR;PSd+iNw%b~3*L3wd~(&h z-Z})IIzh^!!P8(<&wrH3H0m}DN_Pp`ewB=-^cj~1|AI8*Bh6lXl;<_i5Mk5^_-|=!0>Joj!EXoG%lHBr|Dhb>yfo!IrEAT+cUBQ z5>YWnFPwD9O6Ah7{D0M&RRI^Pk(xhfsajcSSe@p{S^qP5M@3WA;sa+9Q9 zmQt)js?!JZOMmHRnp-tz4a3;X4#8ax?3EKg3z#6~`W{@G7@O3DVv|CccmyE0nowZb zE`=30#|lE8Qv^Y*Wf<(>;`&}r2`VZ&#pTMKU1NQ{kTS#E*or(uxKD9KOb!!LSq_dJ zc}8&^G;cp6dW|~v!UH&^ zXY|Z}K5Ed*e<~CujZrox$MhoJ1qs9?$QoU`mwyw=*jxkQMiVg(!r<`HEJzQ6M>4nox$5U(;u=Sn!}x{EVQehn@;yIjjEv+UNF)Ca@YRVZ zaPh;32d5JCd{HDG7Gjf0c9-OOfFZIj`wKTcAaKocjox3np^rp#XYStIM!>?4-Fb+= z4}WI#Gsiqng)xG!AnGIWWG_kG%lLIE^=IH;){PGcoHB~$7H*UhsK>n+kvRl3d%-7jjCU5L zO9B{(40sG(g9ara9+ZzIk9~Utja&|j(?Zr zrUn0Q!@p(hxa&DY&Ew(&6;yK)`|}`kV*-x%GB+iAemsqW)b+_;K93&V2NQwRjp!OF zzq6$mkcn3mvOj+$on>y?V!w!=&VX}568}l4>1Qx~Jbomd(NK);sZ(i7NiFdpp0bPs zDJ2{>OILuxcku?cb;_#3pq*D1Fn<<)RJK=4fjHJ-yc-_TYUwWm{%XQJJP2r7@l}r0 zlI(ic=5Be*&}{CS{=q07?T*LZWE0N&(fWGhrZvjP9`Mce^~N^+$V?%s;nfJ{N0=LN z2I9&Lq)RW@yq-7Yc^r+|L>}`gv6j4{4G6DU5mvA5CHv8IEe;NXbZsYCgMT=Y!4zcE z2ULy%#&t`&)8RKkg`Ae8Q;epxzMi*slIb1cig^oDM%EZ^hYr$*EQw`vNBMY3(!{$C zCu`){n}#COm*$4}V&fO%L|=Qz?H7 zi`b<@j2A!Ehl{zF!|l?%AfGIJ8MN)Ure56I^AEy!24|$koL(Q8u7H@|p?djLSE0a# z6Gh{t?a>?$7w{%cUqrn$X^i}lH9k2h>5knHlS2lz0a_9m2k&@PY)X?PHwv-pP9q|X zo8&r|G2uR=e1RcXy?>kHgUp5EHD-NXj9UN9Ho0nUi8sPmK!pjW3d?_^^wjSLcT^Nt9j@_5} z51=!c#b@~3vK0-7qQ*01s?-lx)^`djUJFEx03R3)r6a#2-G6$jr6jxSB?pZOf9Vby zyX7q$luH*wWNyM(h4FrXm$crgiP$~v2_f8VOgRb04Y(DCrlVE|>?c`}=8x>=LAoV< zHRh(<$Xoj{y|HY}O#+QHm(wjQz?-0u;dFKwj zbH_PG6}5v0bLzbxmi9X|`MQP#ySF@^Z=Y0`)}W(rC&=VRqADco(G%FQwZ?K&JoD8C!? zVJ%Z=yXcV9xYhV{oFbPz_B~o>CN(HE$;hXCpS?C!^r6nAm4r?Hj`d+LB0gTQeb|fm zc>C2SbAQmBdo0P<==Q$`Ppk2*I5~{j%Q+}^(Y90FE#b5q(LZ5`R+=8(3OYS;7kDGk315EvzXq5a%8|R-ematrgwiuL(@BALn%8H z?ker|^#IrN`$y-46_tu>Ec3O{JH- znX+(-Cq({IO6JAFnbj^Fj$G(1%*&M$9e;p;#Lr6jLLHb(+WECB;W6lg!nJ0eq?`lN zF!prqu!o&WTze^*_eV}-Lo24y0&}G-h}bTb6Vpd0shAX!meM%Wy`WMS2#4`X*bZbJLwOquwN88sL#$KK;+%snm4-Z?1?N*Y`&e+4@;C~E= z$Mm1ePZ?z&OGXe=vHfF^LR)U!6zv(j{M-jyQnl3=5BEF4>|!9hp{H*FcALan5*H^2wXJN$0~>3}w?Z&Yls*t_g0GV1RK7rGNEYR5SM% zjodqz7c*_PUP{8aVZf;rdvwj0c^&6-!BH;rDM-jm=D_N!a0jS`A{2Q{kp@_%%5)Ts z)At5S;jR7Xwzjo+Lof4RroJzwB3@4Nb6(5pcDvp6_53XU>}^%@8SlRGhT#IH-Rt!b z(eCy78oaxR=Qxgoc#h+=HGg=YVR-$1pW*fU105c(dIOtAk@0s|*UWc6@mCBT8pyDr z)w;Hp$k0lL3{6*&Kk=4;-0u%Ka=+i#wwfZ#=~P@Ph^Azf3~oLQ8I{nx~C3 z=T6rxY+jT6=^ASWs(i({cMKhc(Q~hagpZ_q%_rBOTKe(PZ4w8E7uYZsZ%fg^k~|i! zupNpE+o4#t9jX|9ohqyaPH7b3b8~&2s&Wd(2kYzN7t@mOkRDZ%&%q7|;T%uJFimd4 z6w4+|u${$utE4G&Nq-I(`a5FrP8qI~SzbP(Aaa0fF(~3_Q4zu6DnRH1S4+r?dja89 zc(VpM+bu2;1nqA@!+{%dpo+Mt5FtM2gGK{?(|7d+ZE2qW-P*Egfx>&Z^f+F2=Am25 zM?`FBeK8zcL0nm`!6ewYFiAL-o}3i+5KNJy7;X@jMcbN9(SLYC--xtozoNV~aC-?H zLBmx#T-2a6UIOkEKw0NP!UFY<0#BV?36~oDa$K%cA(u8u4Pm$@6nzz2d`(i)(4{J>g){ zh)70!b4$kK8h;*iUn_5jZcIU(1QM$nL~u%&hXxoER8D~9J45aTk`S!BB&D(hp2R%Q zXc>h9tx!!;R}CafLZFca5PvNPpWc*KK`2+TBDPxsiWST?7-b2gkVc54S!X`uWbITy99ees^C-t(+kU` ze8a`Aw{r1%i#=M=7Ebuf)^4?FnVdj7x?47v8S!OG%5G&oV3{yFrIV7af}6*Jyih!( z6-mNl1t&J4NwM6X*m&=y-Iz9Z&Hr#Il{Vd&HZs#Jb9kdxt5udsq~hom7u>NG>f2&* z+5W;fIe(E7b__JcmDkugSYi#SA15c+5N_bSD=mm=b^fPvCmPdL?VqacFYVtlneAlt zY-jFeRW15?b%oB075aaEYfzhFVF^iN6Uv{lVe%V3x$CoP6*F3eD0E|r#{h-Zq}hZ< zG^J$QEJt9uWH*$%a4WjYZ~mesc_yhl*d8t#vwx7KnM?AaSUuR4PapadAzjehmDiBe z+pfHZaK7|GJxqjmxUErXqcaN|0Xzz4n~}u*qmebP5S+Z#;?dTa=l)IvZyOPRD=@b* z4?bMf>(iWvBivLcD%_9b1XR%=I><;piI2_ANrl4(@g$j2e|CnyfY(Ku`^?cs9vm?{ z_kUfro-COAaUM=GgN!l)ck)wBW9dl(?1I6dK&tg<9zk%shY=u6lEPY*^D|`tKS030 z4sc2nCDef_Gsxe<+i}BXx8$h(QasZOIwy_Md`w2uF)9Q+xvi5>pi4LW#xbf(<}Ft3 zjd*fGSB#b4h=m-PQ>=LT%-XBX*1Tf4m7i=60Nb zpoaSJ^wWUXt6lh60_dk>p(Q9V?P0(WXISF*1K8?rX2`Q4o=7>QlnFzV-!{AU6owzLzAo zq$&6@OO!kGwn2{O{vyj0`1(PmR&aR^1%5(qIZJ-^A33@J%K-ng;^2vZdj>hG#u;@n z0_l+wN7BU*lSfekAxZZA$c5-PM|lDs(OisDc~pr}DJ2KD_roaMNyGiQ*s4nMJr;j; zNeGwX79mn5LOfKr2;efA7Hu-1QA_f|c8z(eyh|jSt?D^Y$6yj< zG|rKwt2_dTKnW4S+Oq7?%*=XdKnyd=1 zZRlZE{JyDS7# zswKUz)*roxTz0G9Wx1YGa#dF)(JyZ(p=XVC+pM}~Ff5cro-~OS)VF(M-L@@>u%uP2w%WX`eKS3!z{v3gz_fx=f~dGQQlA@`v}F*ZkhR!v3~)jW6tj#m z*)6X1ax(XBY&WJ<$JQh>&@HDIY3I5ob#cZ^Jvk{pv1ssH)^RK{@tk(ALw3AY$03K_ zZqw)()OT6ib||o80kD7FA%~tp8_+S#(pAAtZ)6jjIK+VsXgr#aHy>2*#2bMRvYta| z&BZ_C(M|BBFtUi#9+I|Yk#^4_9mk@89RReP4r#UVe?8LbI1~h}zG=ExaL}NDCmeWDEXwSkc&Lqj{6r3UPn?(nFJ6DC|qG7xtxw zZCU@_5DZLr6kE~>wIiMBZAjxJ4vZx~*&kMG*-?a}U-j4qKRAYm}}o*_?qVQ|I{+Tao45~F5vB_PiN5>RcOW-iYe;+bJnDzJ?O z(hZsyh98q4rh(hoXKlIRw5E!x{n*FPCutf?@-=!V^7!1J1sNEvt|jT({$lFq!P*3T zYwiVUu$Cul%>U{CwWj&Mk2ep4rm9G!7`#SY z2nwQltR$+A1#dnARXtflRbikdt7oC`rm;r3511!k47@5;T?qgQXe;2)M2r?hTD%yP zRF?$2MNcj_FRG3-o;1l-yl=Z06mDW9ipHy`LR=k_s}fm@6;K@$%hSag zLPDNtWD}wPR8W5w{HyNL_a4#B7KM1broaHE z-e|me=FdhuN8<@xy+IrC>nTkoX`EK#n-T3H3V(`IX9TFY)H=F;5EJPpg7!vOPpPVV5% zn~+Q)kcmmMB?%Mn7!7^UR{n`?YCd}TDQd>`0yS-?fRAkp&mwnXG=re;@!-FZxrNFV zk5GTcMeaNi3WS%JocUO48f0x}KVO?AIe7jJwu}k}mg=$?2Z7*xGbq)}Z!MS|?pp4B z$Z7<1MW1?@cA!cLdl7<~-gk5IvN^N~{BQ;85vAgQ5B|1JPA+a&wY3n%G`9j&dVtPc zT*&TgU}(T}dN3RGXheSue**gkT!nclCLzR&iSHe4H_qe4nLIf) zT~>f5FE^#?+do(!$M|ALB4~&5? z_S-oua`4p!iiLnNg*tZY>e!rk&(9iDlX}ZsGP4LgX`)l(i9u%Gd@JJoDnfqc7G8gs zIE3UCZ+}N0Wp4To@vS1vt}%9H9(rNYV$|PA!3^n;FF5KOqH!!b33DqB$VlPwYsB2l zQO8{b{&k}zQ4;uak8QH;X1KhU2RfFgW%blFFwm5H?_|c>R3}S6#jr#R)K0Gm- z5I?r`Y2~uyrHjhC%kdJt9+j@%$jyIEX+*(O%2s0sI$SuqXrTX;+$1+?I{Lh59R!n+ z4UT|!`0!jwr;TIK@N!dhqD-x>S@}z_bt=5vk{y`Z9h2;E|CkoJ>FqFo;$Vq6YkE6{ zeb!-RZ$XmX0C@!-d3MG~ve#wu5F^EHUSD5t99A4kv0`@jqsTDH%;V&OrCopUCY#q! zP8t_ByqjknlN>Tu3dc2Iq!++=v!*&)S?QY0XgO5rJE(Z)3WSxn6(+564{8KB zwx+9pM|dpc7$l(7W`enx?$LkY0FKk64;9Q3{I*KQgt9#qjz#gdkSnDaJU1Wci8Oy5@p%LYc zcf|*XUHIT|WfHw^QSCP%u2aEvJpTnP*!e-N5khf*_G_7f%%Hp>&_Qr?^e`M#E+Wgb zOqpxYTKH)eFdj>nfLj(s$_3@7gzwOh?kL6?#kisv zM-=0RVw_Nn>WR@oF&cj;M)brOpw%#*>SR>?%UBhMGLXQ%*Nlw9--|J>n?Q4`D3?mEjJd9@1+)Lj2;{L zj5Lk4!z8_xttD}EhuUKWM>&mW0qljv5HN{us?(Lzd&(~7_mqG2ADQ51@MgB0W%<1l zr&fOVEYmcLw7dWo&??KcxbJ(Yg?Nm!;>LuJ1of^1fpAJ4SY4m!IL6{yNpYn7%1Fud za$ejnQt?PgQ+zKFw|>@_t(NV$;GcWdE)PzEiRj$cEgXxl+VRts$3)$6z}KAyVs-@7 zX-Ub)0e&|>ipGD`EJG$Ed9?I9w{|;bj{xs+Kju#d#iqPuX7m>I43Bc4TG_&%PJ^jI zf~`?7c1Pm}Stc1xtJR|?wY*k)xz$F5rLc;Q9zoJC7toQsc#bLyqmoI#=mKCAoii)uo^6o2!^y=^H-xRBFYi z93fG7Ln&KQO|0lj@FclH`Au50O;w$hmCOtEM@^A;r6uq3!84e|wEkb}-o3ezEV~o? zd-W;6oEAHixIh79vAZWxS?KCwRd=hpt6D5n&1gXkCy{v*ge#GW%1jVslTggAHyksT zLXsW!#(ICX+R<9OUTIga4Libigu{x^-}aa2{~h`Yj&triA0S!Pqt#AN6p{D+Jonsl z&-op(g!KCpqgOsbFfBa6rZi61E->RJ_0rKPxGx0)Uc+>3q@Ohc=^j zX?RKS!i(_K)OgeBk$s2Jx(jP)f!1XZS_9v_P{n_3tHZ?MOJ6wW&Ih!Mtwt9E)fP>e zFrmIhkWV%#-&&balr2;02!PJb%fEjy&)NOI-96ls?ybUYDLY!qPPgCh4{VN$^02#q z2%MaD98?w@y4C7~6JH_z{#$08YYY9}TK~I0DM<{E7F1V*8wtHb1A{$?B^$*mvhsCSQTPxO5*7xC$)zncmcKbdCi@V;m+XrpN%Ak&?iy}ILrLu! zjEZyDE0*Yme!F5}uC=h*8Rr@f9mapVoM!;>Y_3VS`exuer90W`ymajd&iN*Pt26$z z4$PG5>MTPlflTS3q633ZG>BRgNuzP*KT8imOspYvPlR$rQ2i!Qo!(EU^8~V1=3{@$ z6ja#5Ed%~m2&lwR7a*6vd9*RvW@Cs0s?E;}KX@aSA<*5N7V1(DA9w0l&DwwJPr%zE zP^Wy5?H~gsD;?(E+n((^Ztk&Dm~(l&xd_4vBjR(08P<2s#6@fWGXDab@p83%xtc=g z($8p8e3^@oK4Gtc_-nNU<$@dp@W_?8<;G}h8Q_F@8~B49Ye&r5fdYmAigYtBArPZA zgttC7Ci!Ywjf=VY^KGX-XH9wIJOMN^dO8nK%c@`{mTse1 zF=xO8C+Yn9ek&L`6>!Ib=U1T4~VEr=dsZezRe*|HxB~O3z+C^FaIuUuU zG0$t7!H(}*pug2(aU0@adbZ;|6pKY*^6~{aVbjVD1Gx_ZVam2~NO}q6n^xc)@THsE z#C~d#Y$V=`bW41GUJCsKNx>a0ccIyGj zh)Thq&1V)$^Ps?>p=PFU#`}ROC83jNt5GkTZy(I_C!0b2@bI!3^+h{TD0!oguu}Zr zT7YqPBI$%KnQB{4+hQ^M^@&q z7*8(nNP{lz^jR5}qvfVaSgG46QM}Sd@Zw-Q5=#U%xpswvQC2Sa!cOwlf@%i;Jenrp z*|r!L3h7swQ1^c%pfU4kRA<92wRoT^&|HL3VSk})Lc0mQC`RcUnmEeADX570-Z+~` zmzlb!Oa(n%z^({9|I&82n*ae*H;5Px;ZAyK=V0IL1dOf3QN|FaO_2#?bP~0_K1V)( zvt&t_M^UEV^(f2yOM9PTdBOwvEq2#rLl)!yZIkZUmUn;MwYu{pq!%v$?D}D+??5lC z2M-^;E=P!AVBQJ$nKwcaxc1;-$&1?k!Bh>(6q116%*f8i(+LS3=W6Zk^hxAR`5ew8 z8;5K#dtO`27fw1 z9QyV5Q9*wsqz*<|AIf!?Ca4pJBM770@&T{A_34K!?|^BG&qsDh7KA!vqj$!y4DZcJz>H2ejnY-xL zU_yd4&fO#U^O8a7NXg;jBa57YhoAg28l@RM264FR3GYU`&pQIdTf2M*A&S{_wpJat z#tFFPS@Nb!jX4;yN}bQm=P2aoP-_ks^cOdX^>xv?aIDNl`dPgIo$1FUOn|N!P*d(1 zgdKlO*MUcCXc_1=3FTYx77EHv-A_8wr?K#V3@(Ye^S$0yCbuXjB>8KDajIUXU>>tFIZeU`6U-gz2D?3&x_qST2b&76I0i};2XynW=yIjyOP z;eEyQ9PihCG-WpKV0`rm&dFT1JoHXWwP}BSiW>A)8VUHq?F+MZ<%zuJ(o3pK574E# zTpbO$YZlQ~fEd1twEAGn>tiVSG)*Q0XTm$&W`$oSZ8Qn0(W3Z59nA2?ma%JL>{%A~ z$>P^|x42Af9~@jL)yP5I_5y~@%G74DvM&?#oQ95v=lOI0xgC`cR^F}FnV+|kH0ggN zs|C&GLCfbpn_5W?$Z_qcgGoLj^-1jL;lqBjKIw4jcdwDQQ8-6`VL55|)e8Zu&LFz2oH{ zMY&J_u&}&gnJ!P{k!tCp-V_E_{cd^S(uIeR;q&=)r5?G(UXTMla{ z7u}VJ39Cb&B@6BJUsLBX5^uB+K-f!zNLB{n(f|m#^flGfVw~fLe zX}GejGN7lQ^2Ynh^G4-f)+3p7%TeT-0P$T%Ff&h%>e%%viVVH&q_C{nz(y()gAuKY zRYv)J5zgYV1q>`C2CyW?i0<^5(-jhXJDR$k2J&-#tw*eK`VuwpKBK@1fpJGd*T4&Y znH;H17O}oeTBwglwCf^w{m_33Qwrn}UP%Bft;MV3`go;@$V`0mv3fq_b>OR$d00y470Ba!%aZ7Ri$}}}HuyHi1n}7EG##o< zoLLFN*=$gWlbR=#`QsopjVq^SJR_n%S6j$w_-AL{6(}yp=@hYL zCs&&fc7O1b)5-Od7f&5wVpf!ocX<`{TVPk6rEx2#Z&x${W|nG3NhBQ^)$u*KOqWR7 zH0XP|Jw1H=s!K~$qE>%nBE;|}OLk%+kQlGt_sSxz83k`Wh+jYOJw!3bm6fFQV(BL# z$Qyj`3W+RS2PZ_)s8zz!0F0iyBTJs=Ph_wtds8n=D*#5!(a+a8SlhyBs8PuBnyW0a z8v40~S{jtHPl;Xy)moywyx7vgLo%Ud+yJYGiUhQ~1nGA~BQxV=4udIQCIL>vg%;d)VfyJSD zn@-m&0Cx2%@g#o$bY^yVTv?8i%+*)8bMGhPe&>f1(R%%t7 zfUY`VXyv_y7qsJfal3Te`0&w|Vp{2{0HGUN0DlM7#6>$Y%~%wZea0Snd!h?1mLBwg0sdk%Q2Q5TGGvK$R7iyFG+6WJ(94`U+T(dBNiLF4Mr&QKar*@(!*F!c4!&6`!6 zYWgYntJ|Sx=XT9%bOzRSn0hi- zOqN``FMK)16$gtBfUAP)T;RnwdRHu&>F=SPK6ihz2tOD8#Z&OsF#ncTN(1Bl#d*W% zCY3$_j;m+)I~A9Yeks7&OBywh2Sw>Bf|Q3Nm7uMJv~)#~2_g_AI$lf!h=dn!NIa?m zo*=mphKaGpDYXk?eeKVa&M}>>Vz5?>i4X5{FPCg|;Mb!l9H)M9cwYB*OLshHH3m%RU_i4;Z0OXnbEbeCT_u-VW5)w_M}v}F>KHf4W+ZrM0rDgqoM8I zZ~9|w`hD5-$++a|W-`1@qVfHSE7JA1rz3x{K%=pEKhMA?ELt*W=_(2BK0Vk=9JEIe zFg3A+saXR*s9|vcbzrY|+#tWrQk0NupiCdpYbq7hV3o zweNRS`)=%TZTm8_eZMe%%1(kto-sXwYGoVzD-%Fl)uv2bcePq(iNyIpHW%T@BMYTJ=;sNMT2UJ z`cHV7HJY`xb6hhfU)cef0tnd1I~6u;r;IfuM-Uyd=wt6lL?7|!R}j5m(NDcsBKj4N zPN~-;bLydAsAz`?71<&3401-8bC6Q+naKK#XPr}TA75G5)El**wo`vfUQmT?(qqg4 z>>JxoI&13Ov*&d07+8eY-kP>w&^`Djk3GMcc?OSskN3O^!#&`zd9Uy7cOH|^K{aq5 z*)!>@g>~VGdapa9&Qk!j(>RFNdwqJ~kW=a{pW8E?i8-PeMEiW*;piHxw0u75bW%S)MhrJ5T7wAz#%oFs~`F zz=N*@r^0F`Um2`QRLB4UIYY_k?EX<@V7}TYc@R(Zn;~B_j>tCe0i&+356TC(y}$SL zY`~NKMrenGQsO(BAByMHvoUEWrOv(mYKG^SL9a@+BdWHenst9uo0V-EhTijq=U47` z@}}?w-D+{kGrVT z(x4YU=K^^Wh?QE99Og(YxL^xNWKv?a@Au$;Evubv=c^@5WElfNtWX0C6m*qiF!vah zuyBP7L~TNFcu;@7d~pts!1)TbgZIk!f3iL&crUL+Da=R-Ah+=2*c#dkuTKx~dXl&487Ut0hq2dpiwFJgef00w{TQag?zi)H zapv5MNr)ftEASF9n0=cSa6`99L>2^GM9b@j1f8^c-A{iG0WpEhyzVCl2lryfRc(p= zY(}vya3yNfGiNVcjTxn!Kz-_qRUDZ?ykV+2>@LsZx3#K|_7%{mKC}pgvsfAl;Rji; zc|ZmXFKb0RcVLuMO(Ph^?H&L4zNn+yJNyXJa7q@|+|?q7F#OMe_~ALAO)?D78Oc^L z|83tm|LuR=*@KJs`MEc?Y<2mC8Bt5 zqS#!595_Kfmq=!sNVb(AM@^7#C1Qt6NXRaX^4e4~Lox4IM86~%S0hroQ4xMsy;he~ zqU>4fudsF3)mS0fNKhN#@d)y0#N@e%$u|+?z6gIZP7^YPX?b7~a4`LVs3y{TOFcbFVD|O;ap$qK~o44-lAsb*s`5IZ(JE7JRE6>FClTb zg6DrcQ&QDZb5 zcQTR@F(xPJ*M{!bh91<0-rr2f;_tEbXx(USCS-m7U+$1qIx`y?sQ37KY94^XVXh%! z9vBH(9U>t+S_(W`G+D8kg*8CWa$gfpmEV6c9)+QR+ipc^#?~^!oz*=PA~bgwmi5JX zja*wjI!oNseR9wd_|MQ@kZ8t({6WSq7rVRJIG+ggUfyb5Ej3@+1(}U(Nahfx#1Gtn zgdYjm4GPgyMN!(|azm^tzlw>mVa_1h^THAb1h3Q4!$i;lNWGE2Gi5!rA#a+5hrfSH zipQ*v2NfbW47}yYt&qcE;H}Tyz*~&Ccf|`v1OvGK2o>5gV-~}+LL@MJc(2^3%rhZ9 zjToaNQ(c}LW3eHZ+aFw-Z>@Xf>ne%7ANKkr^bYTpb1jQ+X!c|wxF+CUlTJXgb^xHN zGHh}0u-Ds*$o}4<6UzR-fhNxgsQrKNHW#UP1&j?s)w|IMH+gsjd&50rU!(MEpF{Y% z;fe&Syhs->RkAnd1hoGVRf~mOjy5E|MD4Qad=^{om4qu`xC(+6G1I@M1pAm^I-fPB zI1oiNrnoQ4$n*pp(7|j*V+z%d#w4mCjY(un7J3RabvN755U*O%kU+JeA%TBvfiYHa zZ895BAFb-Ik5|>#$KMA|dGucZr(DA_0x>ffM<7@xv-qEb$E{;vOZ@k>$%X4&|EtCu zz|jr&0sXscO_cTb7d>6yRYJulrjy?D5#gGH(jBolu7_n!ILUFsA5(KxQW8Zl6kU+pU+#0Yq1Db6 zTU6{tx#{HYs#C_l6Fln|4DmtfvDWp!2K^SdaeO&e0I3spB=X%}iejNmamr;=SC0Zp zyO;*f+paaNN0V^eBJHZP$>w>8P;KV8)I`fs($iO3y5q@!XWzjp(IkHwM1Tl$Ey_ih zYhjdKi`@j^?zaR;D(h!QOpB32Y`RU+jizj6ubfs)aqn;rkY{&&LgI()j*vG?RM6cRUP5| zgrnotz#%w;PN$rlWT2Z#+3@iOLrQkNx=ie>sySUAtEQneO-X;aK{Uj2LPRi?8}r?c zUua|Iawj>%>`gGhBc5;xz_OF-hk@Iu-D0eGW;(3;8@VzP)& z7TpvLsB+ng34gblv995avc5Sp**7sM$|=X%<7sjBho-fmig4UwFsmJqjLi)3$yyr` zQPD<{Ts&ZA6|hSIAD3)_eP)ZU3W201k)31mon(s-2bh08>B3=`OFaff%jIg z&EHlV8yi)fzr8wrz;}23ZPuIG%n&}dz8viJ5{ybss5M+&1`r?%d2f<9U?(6a)+U9k z91^TjwDtvc`(;K08p7$o3A8d^Ew#JxNZ7_#v9_{RqH$PG!uNyN2Z>kDTlKX~J`pU& z6{}aI;oE=EEjEKh?qV;K>wY_wxz;XzX94y}hFx33&*wH?X&7$5TjkJ5(|X?mb6#3^ zSu^~2?+_6Q$|A21^$^KEoUY0=RVUqFH!Osjt&xdRj4`6eW7p=C0psL zu$;KjK^#i}FjwM1tc-@t0ho-pu6sVoJ-}sdaPEI3L5Q#o%QFCq60WH7%)Vk4CvNv6 zvP$NKYb^^4AcRS1#2y^-XnMh-7ZQm>fAk&ro_}vqcd*Sof$!f=xGHqi4hO&_ z%rw1FpyVU3M~=K6Ire&kd(-qn)omXuZl=7hz;huy#*(7)G7oA^b;)zOY_s);=LEPu z9QNE}@UA*CId z_A9CBF76&&0Z`1oL#nxUf?=(T6HZTJ9~_sDUje;xYZ8jM4S8NZLwhx+yf`%lz?$0h zfV4K0C`PWe;JZ#bLScvR#1XiZ0y2MIpi{C2TWvA}`$GMxJ}KyZNj{TnJQ zJ_SVL^cH1+7+X}$JHuE60*_Ou- zij|+u(fHY{P0pVH@KgZ^ZrDKbD;$Yd<*qBCC41l)!rArY?ciz_`96S`S__CU@{EL*nhQJ$Vgmk8F3X^BJ?tZp>s?dFg_8 zT6Q${d}&;FYsMyO9-M<)4bFeBaF8&%-w+*m#d!aH#t?A3<$4z*8hj5UT05A=W6T*# z@;*d0YN8FwWl>2IT(?Eo_9og9MYL^C#JNG_>GK}ojJ4hjwseRCSNZQhH+T%a z%iQ$8zq!FSl;#HAPM>>Mnw#&(KD?s{usbZc;5|ur2Qn#z@{NIs%kF;$Vax?ye<8sO zvM&F1eO)n_@7I7)$;vhypjV1++wI7Cay|wD?ZgWPfF^U=8y6EVc1XUvYd^=2obl-| z&3=By2K43mm`*&+oA>I{0BokU5Cj!iWEd}QV9#Kh(VL{iL?)GDNVy1S!1JFWmXgGf zI1Bxp1r2nRWy0SGE2)2OQ=)GwLe$txK z)+$HjT;}ys2ik&XH8l;RC4aV~igTu+1wN2EeMcVGGH#DYsR{cc)oK1&{${>p@UV}P z@DaSryO{u+^%=NqY+}*oHCVF&@mEDU@@H;D08ltau-TB%#j=06d?^DKWZ_>tUo9R( zu`?3Ww@K=*H(tT+gmpOIA&3-j3-!IjwY8=SONrr!d<{7tp&wGns`rPz5>C0POYZfh zEG%bml27B*FTnryPJVrzKj=C2pg(4*z`jj2nBfXi_$lBKk35k79Kp|H_~(@u?O;2G z;|X^|uBQH}?OcCF0NY~xnytPgID+zzH~^>E=-dw`tN4M}!)ZIypm!d2^OnG$cpA*|1KA>Ct z^FsYk5^ysN#YIqb8m|^f-U6}aJet!G-SD2#))lVr4No9JjetIBgjTvXd#1zL!y+VF zr~13QbEF@?<}0%-4TPrC&xVE!AN3S@9rK;^dlWA zUo{NY$d!)6&uts|wxf+mREX`imdnrpX>`aDt9DI?Ysyd#5xCJII0VL$CX5EKpi_rD zwVkba{<{pF@n%qec?{eNPm?kR`El(5Quwpn zeI?HXMZg~8kth2kd~EiSV1(9CBEmE5TMG~AM}D0R8tBb>g}$`lj@KS%cj`6N_xQ*fYR^3f`eRSxxc&XT85wy8doyz66ly3f)iPsx^nLK!|@vUDb&X>tUAOcU@UU&b{ zAt5(!U8cGFl+5!ZKR=_P`#c$cnM^k95J`WjopX2ey+QWCn0QctktYg^0p}ObykoMa z-m5|IU{0k4fE{@9ixG+!R9hcf98~Ljy@9W?587=Gob(!8WzXr@pTJA;nm%~Vq_K>i zycVL_XAfR;vF+}z{mc^|4tW7tz1KKPkG-PHHy*S*p5mEMS@D-c$Hm({@5hG|nd8 z3rcXPvo?51gVufSJ-xTzZbnHWN0hCy{Q7!40ekK7gq%`B3oyNA*4;%HNCK>W_}k6X z1*{YA;q$~n-4r&dv6{%QsRzvgE9`%-v7w#M$yXlB4&hW1_pdz9+vyD{Ej_c+w+IE! zkY*Fd#dQ5jIuTtBf1KH0f#p`ufeD~u{J!QtAVgYd3(%3lCpQ@)}>6NwhM zzJlv(T0A(?R~c!ysX|@{JM1G0hUnMVR~zz$x6>Ou*A88_zthYbAcyhA^|gO}S{@MG z#4t@1h5r+hTMd13n9OiP8_67B-$%p*i z%(X(?@D{l&N^J&3gn8h{9o0iVVS~$}^3M9yAu_b?(QHv4&mQrl}wXA@+Ysj9VQZ(E(^pSD~v}m_U zW%~P|1hixO552%)Lwq53gzZ1w^y%6|SEuTRi4l9Khay7y_O6mdhW01YvC3555&UFBUuRTRDH}a{9?RZQ6O? zikn zVSbpynP0&KZP4nhjL%&Fp0EXU91dm$${{Gx6S+r$)52U96TgszEFAJhUAz?0ur$9_ zcr_2Gk$TP@sG9j*@w9*NLViW~pzux$zBo=n35W3u!{2HozF!o)=nsmG<2I*zqNm$L z@3>HYtAK@qgIj2~9;bx6V7|9TNYt>W$vf5?VZB1Yby`MVhxba`7A$y|%6j$0e@qRf+*oR3u%!HR#7`L44TMb??cE7Zu1 zwc+DYAMSZx z_i)(lyWRdrZ8LwW({I~?8yt3fKXiM}U{ThaOV{vniZTyWQ4-2m7NQwh@&c3dJ4;>y z=;2q3oQxpL5vWujdp+{X6QY5^DO~-lEDG?aZOPRUf&_7<5SH+USkf1<TMrrjc&F96o|-Z&2@TytaO?C#cQ1KOEeWF)d} z>aUlo*J@X!26sNEFk8>O{@~ezRPvk8z}p{fd(VD-e+VAIp*!G!)oSR4Tsa{4;Voh; z&XzX$Xk&j|pJ3(}XW%mahU&Pt@~wC1o6EpE^R|NEa(r_ssBP-rlnz~?3we}f0nS!M zNHJKqy%$t@qkGsJa+>P`2qZ?npcNmIkc<;#*Rte(ctjYULlEUT-h;)={6iw!wFFCA}%c;=~js@dIr)&o#(?f9!n?iXAe zN^Az{XE0XDaTzb;c>%t&zDR|~f{a|Dd@j>m2Z~3Uc*xj(ceJ!+IZpYtW~WypsPpwF zoOpk@&z~u{+^#4;hp{tmL!^*Sp)S>n+zU{Td(c_unOl;Bi)=VEi@SdZL3vPdr7wj?MyQ#Mm4RTg+lx9!-;LMgY zeym#Z%IgnaJrF|a!K=2n?{F2v%fvngH93DN@&>suggzB=Z{0K6AZ6lk$smMC#HUUq zOGmK$V<~=;+Kh85L+|awAc8!r=>Y+rp+U;;w=!_3ZMAKS3Zb*r4%!xJO;<&0mV!sK zId#Y}^D(Z@(^IcEIDHTe+U--;)sbgqaH{nNr|6WkKOA{hY`Lc(lA7-B+DCARXXAfU z>8aIlpg9umGmoV6%-&`rvB0Yoc*^&P*dadbhRxuyZ=2F>p<}>5t&sh=jg|y6i7vQ6 zF&Q$K({7DNJEo!trgRH`sg{U@k^o<~3?W23|5$O5DQB}0_EvZ?1f)s;C;nf%3o9Y>ofW5T>g43f3Y8X zD({}kyr**SsqA|y|6YyDgR)bDR^eT-)Xc#buf}CS3l0Eb$&fK3Don^{GDLp>Dr~F? zIhUc=2qZ8eueEd~K9cpAaoxI1HjHGe!r@`^ zQK1D04g;TW_M{G_G)$dG%y)pHk>MK;rVMx)rIx;?;^EgQa+n#3xz7@=Hqr3j7Q_2m z0RI5ayZ)lOy;ffu#!f6P9{qpRz|eV(L$_hZv-(EJN*lq%J?wV7F*_oF(gfZ^adCB& zCkIxidacN}I4({$4k?BW=D7N6IDoyQK`zohW{!(WfSN5X;|w-#{9cq@v>=>;vvgmpl@mpvawYHA`qlIw%n5VH1Lm&8pY2@nL|=c_dJ+S{6rMPk z2vc~1`vfc266WJuPmw+;&oESNZkt$5GKqCw5crQ+DjB?QYn8W@_gEvKyPX3sB7S5t zg#UVnbq}bA&2-v|rGxUG2`Tp|?_XY7w zn_GXY%kcM{Rr+=%Y%;{p8>iElq1z5_u77A8c>h1=us=S!sjq*$cI-0oN3spKs`oQc zElg6Tt0Mg=3T?xy-o}z?P-#(5UG|8stETfODMN?&Hjd3?0B~*N~B|Af%YTwEt!NjDB9N;jNHa(0GR;+ znyDC<`uA+DnJs^4C3=BYSe=?zcvFKXcj7j>g_mzQN}MA(pN#4Iu|6}%qu{c8=I1Zg z$v0WLq*(zfUZtizPh0saIMbU3tWGTaQwLsfi5`!97_kVD6maaqjc{Bo+%@L5sQt=n z$8Bq4kpN8NuXM8mzI)x6NOJ`;0|-$*>I-o3;|vlFa|eI*{siLA+Dp_0g-lV*RmI;i z)(omWcVW1}+hnQxU(fS}k9y2z+glh)!`AeYsUBWgZB__&Y%N)$*`{P`p)Ewc;|c3E z{6T$0FdyNI`FYu`JVi|t^i&F40sOw%>hV$`GXRAc-7WJ6M&^j2Uw$^7BG-YoZBu4- zlg6P6V{U(0qs)IJ!|(%BE-(x-Fu!}2ZvF;sG4M?M;w)qEaqx3q$e+9t_?e{Hf;-!V z&pgtTP36x(OCy_u8Mw+k%PfButd!66F3Nsw^Bpf%coWh}Gl>|9YfkJ*7k@E`Afrpf z(~n?pNzGI?So*4g5LbiTs5Lx#UiS4qGJU->oHu`iE~?4mQ@HK)uj?uIqzl(IzXt82 z?7m(!LGK%f<9pi!hlGqj-aZbN-fYZ}Z6?I5nQyD+1;`g4Ulx2x@U_R68LX?jxO2W~ zDG=1levu%}!pvxI$mn9c@e)KUsOb9lz$akfF`(skCKrJ@vf5b1Y?uNzHucXAiFO^y zH@AOUNT`KbrZUo22%jkgr!-8wq&p8EdQvU7I}e8p{Ks|x^84t^m*0H#=(k+VhDR=X zg$J*eo~Pn5WSDpyB%CGZ7hM+2iq|7}G-!f)C4h2tc>kzuuK)O4x}4|m(;$uLMwuTx zUoFsS2m3l=?oS21nl?N=V2x%tm!6AqyV)v@SB|k)0`r43Q6n z$DY=6ttW$HF*x1BJ^QqC?2wWAjbJ=~FWsuNyu4u(u(c6Rfh&H5D+pXi!fEi0Ne4^= zrg66nQ9Gu*F5~&4@9J4}I;-VtFw&?gZr^RHXn(+-c*!$)+8}h@5kp=>1Hykftw2J8 zp+nj&1Hju_UXoJ4!K@5)6)RFBfpB-DeHWQF(7}kHqP$(~xX( zK@FPL<2fzo0SXM-jz<%RJY!HcFUn_QRZ#?UacCNL)D;f-Kpi58RKrjP)e+*9fqH@P z7lLMks?ZX!S%k@&JYNJxWa)p*8Qf6Z8W4V%!k}MsytB(X1nqcUq5HzPO17xRBoiU7 z_nWo~!{~E45^|-P{IKB##x+REhNex=;y9La!7^)EIKR}Q+0mTV<=mE}l11gspRRVF+0OyC43dSf-w{0&6N8Hg!Yn2@te!+{uQl)&-4 zz)jKK-T?`YBwoUS%ORNywyHOrHX^99Ha@C74fF>LloJv0hq*%#UDD$w+p&XCtal$3 zb;pOW|D+5v_hMx~0G?w2nLuX0LBk;O7xVZMbyb079-dv=F$1oDVVfyn`TG;DreWp} zwEWx$#o47D=mmrfcWZyb`-GATHtYb%{#ooNZ-xuRqn~*pgCZacZ`NgxTn~HFcmoeR zGWCk_!Gt{u)Tr5FxS>ZOOgb(T9)mh6N}YD?g_mQlM|;XzKG`spe|(>qYKe)Sc*+ys zg19kymT`LKo0MOFBW?>xt!5gP%WG)<`i^A2LhAf!dQNY6Q^N_H)KRr9k86CF`V|~2 zeS0U>?ae3^w2F-%c2nvUv9-gOhp1t5(@CZmSO-W~*?oN5l{VU)&buF-+7fAwb=i>) z`*0rwUMv^)t=En?3-iXc6Uem_-|mFO{dB8kgh&+?5wh}sXE)HywO7l0HMNE|pz7wU z&WKKDv=x2C%IgZPs%us&cdyG%6kf*5g zvdyo6sH`|oyE#X`_MyUnT{h?Wi*uR{?O>}oDVk?_0Yx*p=vL5QDMWfhGvPk2+piTZ zF^Lihx}rdTPz9^~-Jg`8u@w|BKtu<3_ah#2_~mZDE#=hP`jy|lU-9kx)!WuDl8Jk0 z9UicpJ8QvMDQmGxLiBd zYh8Bx)#^eJ%A@o;;q+P2Rg|*v$BWPwWjb3tl$c(Wesr4BhcSL5Rb##a9k1@KvgL$q{{T&6B(UnA0?By_jEL+e|e1Vs2Xt^koS0$f^X9 z^`6zveV{eZG>rIm&W)vbm)WhER*(wcIH$OOv|viJjdHlyI9ph_RGsp{vM}~~gIKyV z9>l^HF88u=JQ<*)yWfWA;T&$FzvOe8U9H0>G5V zRkamZ9iU;rwKhuIy?(i7a=8Xhi9basSbe|VjO@#l+NxT5wa$ZX0VT_tP|+kf&)5}z z(Ih~+zW?^UBas%8@{VC;G!S^cA#`U`C5KAT8e_`@ z2rB?7fbM0BD%L}M%T3%_HvXJ`YAmfaJ7ZwA~s z``A=FiFt`H4uTvkTA2L!c7io1qashMKY;^v)Z(_%$$;JfNfYws12?2E?{2qSjpf6~=j`4|-oD2*8GM8H&+yPz8o8jUrqmInau z2m9`q4}`i|hUhz<3C8fS7&buoW_)G{Y3GrB?d(QA0{lOSG&be8$cvw4t9m$|ZCHeA-*$#{R_uofoc17?f5^IQAy`dwcY zCWWf9F8pk&ud8gm3@;YtW@)Rg996@Rl(F0U)kCzF-z@2%lBBdqx!g>QO-}%IF02h$ zXbX33Kh(qX`s4wJ^#PH8f#wmEqbQV4;?RrU`=IbVftIk=DZDsnwG)6Jxqe(&Zs4u; zV~qKVaeXg4v)6{B8tx#*jjK^bTKKVu&yD!%k)f}lH}n#h5VUQ}0@`diibV4TFYq|_ zN#IRM;05wk|K3l!d*hRndy{+cwvSQyYRZP)?vbDy`+4!Du!QS>T8_iL+HAX7R2DDX zGN$U{Sc%u&b@(x8)H2_BzVMnC6KxPdg)0l(>Bh|(uPc>py^SuS(hC=v6%5pscC`wn z@OO9D<|;B;EGe8$A`UmmiEY>O_$&{G1IsLIQI$);q@6jNfsd(Ug_7sPX!F1-uw&*3 zby!$9)8`p=o^x}djDUH-+O{CsxM)K_!90BNP~2^e9I9-m5uuo zbXgC!Qa*dn!6OX=SJogN+BrCjY`zk~N_&ky5?&?q0dmbomg}-S|yD?(=vBqF9-;Dizb^1h^CQv?bv#f=?g~ zDEm$ZzkMY`qZq@4)sg-YFfV`2CO>z*z&E)O!b**ck^~eG79EETW<92RWR9H*IoV^m zzqE#SQUPp!Y`6|2WuQyp$Qw-23&(LA% zrxo|{SaIx#r;r>gpc}YKh4yP{&T%;ptxn%^txm6dSk*HX4*#+?KQtPT3*luD^>51u zhIIIUp|%rnx*xoY0dU=Gh^E72a`KGl0*`^n1%J&(4@jwCQn+6u+XDOp$8xO?;2g;6 zJf*~%V{L9t8Y8!;%J!w{o$2Ew(|w$90k1Tf+GaKFAcdKH9|Kiyr;12r%5GX3L@zJp zQyITOnEK7Y`L{}1%dS+a=PFPGkqT_CN=eXv%2>o}+Wsm9(~~Nt*^-i{7k3V$rj362 zM1p;m&dmooEwnP)_v;1Rw-a>e)tP4>4w8~};B$bGbP(1Z_PsB^_0WSGh^5!T;$**nlUyyHz94!~tV%1jA*2 z6l(zr69vgkgEOJ1kvW6VyW+Myz*@Kx;3+Fve@y4I7t5CnC$vwt#U6APoZKT~cOq`y zkI`{;r6E(^kcc;Ac87-SZ*9o^&P-UZvHR~D1}5CyjfCTpZMhHIQ5PB{4m|$Fy`p!a zk!_Cf-p&W>yTAEQt1tW7BmUN=)xPh4WBUm61pt2P;nvuRojMHx*8I9sXkGHKF?m>5 zX?>mBJ2csV^}8@SiG+fmU_ClFjW8r~Y(YTT5)6bhxbbP12x2-Y2Q zjW!74A{n7<7l36(-eATA`n=4(es_0A2UPm{oWuxz;h@ZJhwIcvh)2e=ut5#IU}%97 z;eO|s&Q`GxYB%uRm)~T;Wvw=UE0b|_=^O^+`nnVbfeu0!vj_!+z!NS|e;3mMONc*E z=*O}WrQC(BWKpy-=h-6bOc;-djdEv+NfZ$%r z0hu{?c|NljZS1$zwu7Oy51`?egO5w!pJAzT3Q@DQ);uy8c6*;N9J4}yjv81`wHG9k z+Hqn<<5&QCKkJk?+eq@k(B#Bv_Bi7Kz^C+_!PIbiHy!sTnjXu_AKH-zfvU=JZ{o4q z+^PZ|T+XM`j#r`YqA$t*VDx~m1}<_R0lYnX{~NIlEr@ z^r8n){hV*Iqn6Q&%JSTQvSfE+*sFLUL8Va`Uc>{oBXQ1fMLg%;ey7>2n;gp}<`94Q z;@pmqZ!1Vnj>(bZ+DGVnfl({5nmh}9g#rU?5fN9UOQ2v!jzc16L%vy=q=(%``DWIX zj=&`Eb5OCsjl)b*L9|dJ5L6I|%B2)`67Dc&9ch?*!iqBMGPF5=7|^qpV9xCWU;4a3 zk{~E4MY-kHcmL$y2vZ11h4@-DDZb2Ku9h!X(_vM^iewXzjl}0R`>l)x$;HUKvcCKI z?<192W+?~gzQ zPg-M*t{4St9nhK%4QsMAr~0~H=50C#oBIvheE*Rh@qGUOoFDl7 z^DngXAHM$*zfy3d>LBIWW4-22) zISs@w5mktPzccZJ$K*Vzh~VKNW#8eP?IU`@_Qn~vJ$}PY5o4AtX3dOK_9+@5I+f28 zRxEFi=vLwLa9%suwcLo(T4%0Uk+Y;FR|vOTGzly0eRe`f*-+1dkkcjx{}j&!FxdtB z%ZKKhjMJ;-ue$5KUv<~nqL-URZ4^v)Ft)AOZen}rod*UWmz12= zAf1`_W;D)fNar0E3@4r0ttrg$`S*7rqv&D)fgY<@Gd+@B(gu>ru5m2~Mqd&Dea2h2 z_GU~lD-2LCm%ym5(bqKSOjyHOedZbGhe3e3-ng?3+>;(>c0e@HK#ODbIq2q-`3sA5 ze_>pI<`<2_$zWkJ%5Y<25ccekQt&ug?eF*Z?-8qGIi=8#?-2mXcQ$z~j~CxN&7lVB z%h+srsaXPiW0q$(-|aUl(N)0s(t5?t5|@8P0bq$9+ObGrXkI!|oN zat4W4K?Mn%$)*WKWNv}8zcMTc%;mYC&3&Y49Ar|!q18i?)Z8BAJ4N{tQLmgnjz|c9 zcZs5#(DhLopyjsiSuixMj|{?~+aGD+pEByKg}{Q9vZlKsIo{$C+iX*v_P_5CKVJKn z`4?Cdr^6hPwxOZh=y!=+AD1neo{R+avDr534$E&cC9P%0t@UPUr0O|;P3jQp;YLqwzCMB(8221%*s0ZnHTQ2}_g|TL zSwm&kvn|FR>XnKL zTAvBo23xEiEp2`PR(Y#3%W36~NHNt2J1iapn?BAMua1*{?! zUslqv3j)M97640`xh$7weuD1?YE_D$_g1-STBx$lI_i|&LJwU#`M+Uh+0Hv@rC(Lp ziADoeYoUg!Y`9c2h-bg@Q9NrN#%${lZqY(Ahm>o*BtpxlM-r|C3ctkebd<+jaEzUl zd6q%eZaXS;oK5ud^k81LoPqCuk5({wdcDKq&{`X{#%zvt>0j&SCnbS zBn?WaT-B!>jRT}&%~g0_vkK3D<*V@gds&6Gs%(|TNE(&ewo>to=?@CswtpZ~Z7Ow@ z<}&l=IW1X`%CPNrjvUm4+ne4&)3;<1Y+$hXHNak~jfUdQrLcQ7k2_QFH3A{ka$EjnmneY8kenNgE7VLnsruV9CVXUk(#xs|1klsNaEDk3?&R} zr?fOl?n&q!u8VH2PwbO_p(2QHtp4sUc;_gsaAq_T^Dkj6(yTXKN5llZVS|Sv4zaq0 zy#Vpc1`aWZqo83!jKH6O71GmI6ut;f(=4PJ>NfmH70NU?jm$V!s{Bv%Ld97ybpvRNztE^Y{AQ{{G=!1->}BNjF@7_PWNbqoLR6L^uHd zSl|_TMwzcH+qu5BrZHgCk-QH5b;*!`@){|^)DPakO%Xhk!~ihbWU!Gq)mYss#E}Yi z&BP+t2>wH_Hw>D~^AW6PYdi_+831X-5;Rd8kstlxaudtem*--SDVFUq+jn5N3s<-j z40TeT^6j_{QbR$1`afeB$1pPwdP8*e*j;96k-`>59e}RCT*jBSo|_aUXyn9kTs^@! zZ!^1+jOMiH;682_Tr0+|rZmze9G?r538-$LeR4Ezf77hUiDJ}C)C?--$t8b|xmXsQ zsGXc}T~hHGrD>6*1y%9Pg(LcQ0;!gaz_)k&^_BYd==k%0C+wwY#e=?p9~1I&RDtN? z3Y7D2DF;)QYY}Fionfe1s;iH)3F5SWarv&UG%9X048#OZ&pBj*U#9_{l*qSe7!q)w z6L7e=FD~Ws%A7WTnJfdLz8r1k^6JKlWZFHjfwAMD&{-o_hw3aip+HbdyT_^UdHKSJ zCp>lVvVhxvndNSsmnQpLcpZU%a*ug1mqxRihi?FccGO#j1vtFDLG&OmdAf>(8X1ci zM<`SeypZ{|MZ?j;a^NvVs*zye)N*1GcqQA!<ok?uK32%B@PbP&CwHons;bPuz$AgN|IX8xlV} zhle!wx!8dB2N=^Y7ygXG6DxSVkvf3kVD_+DGNM%3d3)9oah*ge3kpEnNJR<7^-eet z{5h=Qc`^f~YGBeA+(FLww)qIm%93WBqk^k{n8a3`)JexXa=P1Vryex0PIsJda->bT z0)@JMgO3s6@oB`CBW6MUPIBaRKiadWVz8#dsPNdkvuxmK>)4FAaPU>>GMA+(Y~S(m z4bmmP&Bw3EbRr+UZfvuB!3l_qtw-A2*$vcd7!)E6(g{H=xF#%k{d34n!~(r(oV)?Q`KJv=^F6<-+@^9Mx1-q!e!#1V3ThEJAQ z#K6d{12uC=!A=4CR}x~x^Sn%ezdq7hA&6*wfTjt+HN2Yk&*_L+SE9wCD1rqc5dc8e zjO5_umE@}_IC-Q5-2|f7qyX$DE8NS%>v4Z~S)H|I#@rVP`wMepNn>9$wHyS9T#XhK zWPN>YFQntZ&a}kr3@L#IA*{o$*s2LsDN1l7mv(1q$}!ZTs}v{L&N zYd^iYb~IfRT%552ha)e9e)L_@j)1Y9BI3a1KlZszSVio33@lRj@LnifF5WwW<6Epf zek*C-DjHOPg34G0^F6v;<` z=A{cy+OICihy)Ve`EV~(ob*hknh_X{DQ6_-)C=p`=4amhy*XC2=mf%tp5!`b&Vy&p z)y#X=QPECYL^B?hdfiV{BlLuWHAS$UMcZ3bGV6G2%6j&KdRt7LW<;~cbB}e)!B=%W zWgy(^EzFFY$sncgXo>ZIf=U;I+M5wp|7$3HC?QKDGMc9qIV@=xt}z)`dWHApoB{Mi+vcx)9WNp;VI5g`mC*!7aL=&%@H%G-yucB*tr|;@Hrk&~_{; zW);c+MuclkH2+0J74$UYRx3Gp4y+6A2aWKrzjqk-_^2KcZSS%@-Bnc;3TG_RQ

    )Bg;`&-NUCKjtJn!gy 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

    0zjzQTR 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 z�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�o*7&DA}6KAu^rw03#Tq z|0G;iy_;9-bnjDs$FZ3<@t7soefnww+J}KZ zh2#pUE(4EBT;nB#+lPR30$`BipI!PtxvC-uj*A7sy-BOrT6Xz7(7-$09N!7YpSo<> z)^JkUx6Dte{@E5q=aenmlr0@)tXlve?)|1F@Ctvp1TRei$wgwJh2lyq(6bR7kjmjf z<}(KB8Jc)Z9q-HeOI=Zvj0~V$z=xIG7!&dZkmLvlg)*os2nOg4?1}1-BxVWc-~qw0 zk*K6I2|i4%N=h9hohVJ@8!K>1*57{fxrQ4*{S1DtB|hyk3rds)vLnMf#kvh4=_`ms zP*#5~akE2Nhu}bwYacUrs}+Zl$bl*pmvJb7aBav!jz!WBC@Ln~kI44Pyp@!*KL7NE z#9R8nAJ;R=l+Xrf1PETjg@HN;0*f%0(wuuK&+HM9;R!McsB$I8ObIhtG`U_70ZsNH zBGv%6gHeCuFC$^u-l$e{^{JWRb0zevhjeMv4O z4VVMD3>_SleB&wn=vFYx6fqAX4re03{Z%b1aT(FS+pjaSaUB4TP@b*|B8$0xU%!7^ z$XXH-_17C&-=Fe_qa`PYpMO7Zo}mm1BsA-N;6`91V2_0YTv)gzbL|_;fph{TwcjI45okt_C6;PoKFb z(6ftc``=J-Wow&TWp&TMRdC4@ zo29XE83`>K1E~Wk<}%O)+!lZ6oSZi$$CmDw zwisChx=fa7gOF>;m5K>uGDj$-juUPYCoZI1 zmoXl2k!doAAT6LdJ;0keF-MQLGbDUczB&HlwAiy9#21ct5_ECLbws? z!Efc}!<-qy!k&?BPF{cL-ui(2t;jqAS%Y|?+z?@KxWWAJUyScn*)Jl_7pjh1IJxm> zeX>S)Fhan6{%#j?VXXN)^PE1`0IX+wnIHLw}Kthp!DG?qSgpaa)4FLN< z{+94|BQMggLHZDKS9>Ee2*C0~%w+-)mC*OCoP=9f*MIP2UPXV%F`twrVUwUeWQ4eb zoR<^c4AKVnH6RhR)f9gSGWg{IJD|6+XpeBCaD;;+d12)R;^E8aEkDfxh)@U) zKu`<9wdA}kH(AjV@&|oMl+f};h{cUy`(9T1wh+o11n#;Z6h*vHeZROnLfj=?2X4H2 zAWig#Y|FY1RD^$^`0!}8IDq=gP5~k70HGs*q7l}^{&z;`hg#!`Y2q*gFzs<_Ax>mC z__i;NkQM*g7kKW6q+1vpfC*9KgUkw=GO!6#2(nL|fwanF0D<(j+xrdeH1($VIVE)b>wD!k_vBgz%N1452lV5#eR z;q(?R4zquRdK=L~$N?xU?Loh}Lh(bvA;neIqTp1*xgf5|Wx~(dzdw`qOX~E)(0v#$ z@_Rofgx-}LzeGs6zqcLzzhS1(a(AB8Ej|EnYRTMC__SZ>c7UW;p6hGCmT5V&VqlU! z#oJ3C;$)HAiZFvDGCLX|hbwg{S7G6)g#14#G=YDR5g!WfOh|_h^+tFL`9sAKBH}~A zMTA28q!ZG@{ZMh-G{SsIzYq%TlTHYW?2|rCBln@`+W+9-#6LN>^Dho=_$vno|H8qI zKOCH9|COLq{v_zm@()3m{Rdn2Us8LdYP>$pJjaKEt27PqpLDnDF#b?+gxdR1aCc2Z;wPPyZ}Oqy>}lja6x~zPkn%}qIzkjJ zBqYangl7`T6CQGI@;~%p5HHN->qDP`uH)FY<5)6&jm!A8&{qG_&Nw4CIej^o{|||| z_`^uaf3!hl!isQ4$nSXc?63<3*9&w)ITC-8kk>n)fs=appXSG%%=@3?=9jkq%`XW5 z)p3w9@86E|lMei!$)LqABohrRccCziV#rQ}&HH!CaR7*v*Jd!L;U&yN-|^Z1oSTaQ z#2cNkV7p}ug~3hcn9MqmOQD6FREp;DWuRa{=2GN5D%0v@0t5vMlX~6%Ns2-4PbPm1 z=>Vwav%I>KLpZ#MKWLfX9{iEkCO0q zgojiQKp^8anOFSNev|oL@R{c<%pHH2yo@k+UqbaS`$NW}6Zf0ulb7?MTmNRgbe6Q6 zll?~?4X9-7{trs4?|9}n(bj$#J;nXhRR^H!b4+&PbW&#ApJ@wI7n5_=Pu}20NIX0K z588S9wk`j^?&rVBL46r#Pt#xb8&AJDJVI?|ff)TWjryw%LO{m-{{hbi|DJ#EAIUfF z-_}RY6ALNmMuR{bft&Z(_pOWuK@#KrE1`Xl5UVb(J37m-G`PuS50Ei~<~b^M?8Ve9ZO zePyACIki~WM2r8hi5?&L%N&0a;SGwH&x8k`{<;4IOWO>W^UI0T8F50HjDpf4gy%%Y zQ6c<&d{uJJkF)>0}-Q zpa9Lmn8@d$>-dWBamF%kR&KeB(@j$bPVsC1oMKwo#}3h?J)S;vT0no6@rO=ZmaPw+ zwk+EpI&E2YKKT=}?0)hu%ibsdvh08IFU#jIwf3RmzSP=>eEXr+7V<6nQfr@lUux}> z?}u7j@?E~v+J}()Qfr@lY}aJ~SY!?-0d|mcPH(m;Cm^wBaTHXW3oy zf0lzK|7SV*P<9_0uK9mZc3&FqL)m=^x#mOJee$)RwpChPp2ix3Fx_Jo`;&4@ zewet0XS;GgOdR3a;O-YGM|d`=`C;Ndd8Z#HZpq93BITC6^oM_l`=igK#Sas=5O>rs zCT`)`zz-?6@NAj=!^AC=8~2NeTk`5Zq}-A>=RQQ-?{egXUrZc1MmhLl;+AsBryo*| zlnE#QV&ay()ejT5+^f=a+t+^(1i>!sz^`-O@I%D`?r&7w2tf0to+Us5jL(K0brglAW?Y?P#Gf* zAbW;B76G#Ug{i3s%|z})B97eOQ-AJHE}tQQ0cd`wbL4*;6|djvJRyw6-{}Z&0px$D z3joPb|D7)WN4f#(0A7B7HUW?MO$PaeI0A6@rIhX;YUy)-GZ@HyQ2_Le5MltB81%o1 zF7Ur5#JK-o+eN?te{MJX(rsVbiv#2_b4iG=kdRj*O^C67q1`ZW7s@LE7eYmeh!9V| zNiP)qqN9JpFG;3lA0p4p{+;+*_VXVIxPKw+Xu#3`v_Jlb^7>L#!{<0Z1RNr--e+IR zs$S@|h0tON`StikdT|-JWFM-_B$O3Th_(N-`u^18avbxQaC?1;v2yvmP-{9lu5KaQ zzMr-1v;GtK&}(j0i*!jKyE-f`JM!yp%ZaE5k@w! zbSMDi0V{yQfC6AuP|Q#atN}_GT>*LY3Q!Jg8Oj5yfbD+CISBO+EjQ>hn7Fg`h(+rb zY>s`9{UYa>U*sHL{U+z|Pdem&(oOdlS+~Q(Px=l0PIrH$TR-ck(eRUwogdQ9fck&$ z^!ax>{*`XvU+J6Q>B+D3Ut}JQevx_D{k?wtYyATMJN?)CIb--oQg2DO958&!?I!3v z7?*U{9gQ#LXE|uC<8Qj-PQTOjU+D(;KF>}m3IO(h!SgxO<2tlOe{KIS8-2X{%jk>A z8``{G|BsA5Z;<^TqpuOm%ZX-y6L5bDFgYH)IG6z>17A_Wl~=$7_56MFvU9fq{R{5x zXxQ#rf%n?#`c&jTV}K$J+ElLIlQqbdsTynk{&s)nJaSrU zd-bMQnqTIZYIxJAj2EM!=V<*9qsPO`JYVk4+8nZFo@^e+JS$&?ItA%Y8jX_abB20% z@jZRl5lvqO#mZ?Z&vRXjH1o-6Cw}`poUcdf2_ivpx{Z1-)5lR90NZn7E@z_0tG$eT zv7lHj8VcJ&N+(H<@4uilto6Uq_JB%ShI2H{9A*w0TV-b;(rW ziPz`*^?a%oc1_!1dxfYLxduVC0P*G(QI3xk{+70fWP5EU`o>=1n;9k#fGL&JJ6!G8 z$-bWg`+|=x=6qR+&55HfkM!aA_tVX(IZOo*&D80!ay`|3tKn(frPY6WKdI67aN4cC zDD-{6X{H=x!^Fpedunce#5^betsSiWZmV+sYm-Wc%!_%a>-pooul?k$$B%r{wz4E3 zwKhdTTr>Eb2M%QFSiYE7lH7L>Jk?X~x7VUQ z*n^ZsZ_sKPr1k|1y!%Pw-`hYgi~b56=9+5dcC~icG}~vP@zS?i5=D`C?Txc~;5U4x zgVgU%K-m_0;YtrLFcU}5=Pq*gX5rs%dG^{}b$1I;*P)PwHwJ&S44<-EI7+q1&f{I( zB!_Uk-1*hzc6XJ#G2W@w!0w&R{phf#J9DC-wAD9S`;6J0Vp2Wpzf(#q=;LK&ly> z$8y?kQ`4L8R2x_u)zZz7+FVyY=rl#tuE(j}gHQl2`<^>(+H)HQs*}mv$Nl;Z&(`x| zTEp>`){(WjY|nqkc!knh9OVQ{=Z3pTDhm0;2f}{8U4wl#jQmPUe%@JwRt>7g_dR`ql?GVsJ1A`(;XWJ4P#TlpE`L9Nw#wcjr%_zxOhd?qFTr zO4&$G(Yi!Uldi5tXNH%njj!*@D24DKzU-50q`Uwut9!&Q}_4lO2$)8?PNF zj*U~^_E0gYR^+43ST%4CwDm()x^yUl_^e(qdtSr4D{{L#Ydxw{uHf~<5sIdWY$sGb z|9ZA)JVowpzY9YSSdaTdQ3`N7D%LAs3-H+hKIcP@BX6e2$KKblh3@Uz+o{%^i%G{= z!rY(7GE;vVA%CO=w?iVQzny%zog1X6&bWWWPT%w8$>DTy(@E9XNrstC%_H}>-N6wh zLO>oskJpU5Yk?DO>u28IwrM|Ft?PpatW?%AszY$=ge*5jRtQ0GnInEBNtycYwl0vF z%}{E)ZK=an@6}AYI9Tf9w}$2SLo+s(980zosG)ynm^=v-F2p6h%8Zy*_Ef!bEVh~v zd&dLz@=4iBHpuNlj{5_;$?+Aa#XiR6mDe}J#?*!SBBqi4Qty_?PeBj+Y;v-7R7dcjyMr9p=mDHH6JG6y zA@aJQuj=+@hh`Ao>0?mW^q}^8k)9iKb24JUY6o=P9{@BrGvXhwVc5i72i$`s)0cm; zL*}?qCFTG%rMP)f@UpwJ{zx(GsB}|mW zgII2#yX0os^V{sS{$}r_lf%iBiK@`ulFbsH?pCV2a(zv?LQ*2tu)TB&Q7W_4L)4cJbcz)ydxmxoso(p7Gy-|)>I&!R3s1q^(t9#5@%+wJCz zWn8O>=zC|qRd${d(d#R714=&Ka5b01E{vm2j**|w?l@J&^_dh=hbzXoMI4`S6inG?cF%CUJ3iOm^Pbs;Ieq_&oArvNc;otZsoiV*19m7YB0nutu%kWrpS7C zYhPUPme9_udgi>33_QW3b9_zqs)&Z9G=d@AIeSfaZfsnY8P2+_uy1ywOn0x^Nwkv( zk|bNr#nuwbsFT@mYfgT1jo@~G9gH;ylPbfvwaro(dQD`j2RFS8oFT3scliaf=%J~% zdBeND6vgcLxXs*UrJjzmYQTSuCha5l$d6dH`o}>IJ8c-!82CoF*+BJKdEEP;?;`KD zjt;RCZ8u>IX~ey`AIZXKax!`ewEwNJ_vXmV+^7OsCD*I?(xvyG3) z3?AI|Egr;nt~bg1LceWVWzQ1WH(-A|ig^ozrpx#4wc-L^HP;vC6eVL)N8#Fm#+`q7 zEuZjV37(?Lk?+B2wK{oY`RwdcZ3Iw11MYB+GT{5qb>~_q?}iL6t3{U8Tk^8}T90d~ z_GhY5n2+3}9a&@82 zas2-gb{{*h0u6$OFNg&>Ey3iR(~g{T=ITe^>G@lu=|yjl#R4pYgv(WaAJ47vBvQ&d zswR@eN^?#->X)Mr>};?a!Qj<3pmgprzRX+0(IcwJF)ItKMV$8K*AR?KI^*jQlm39o zXgtQu`5m>=s>XkIuHEJQ?~A?aPAc>Bk}*0yvR!&vhRmkNSkt4KpV8rDPJiZL!Wj4{ zhxQoDPjyKp^xN9)8%0qVvf-B)T%osrct6tON#Tmkh6aC;dA|0dV>nJ;HXB z!B50XN!(QKr@l7u&>au5iU8&P*^3$TtnS9KJh~}h`>QSXcVjeODhz@fUlvacMb)ed ztA@)8scn+HtlyfDAD^s1t0~#Nu{)$8X$<>|@gXKY4L`{#5j~2-MR2UWlp`dXvOZ?Y zP25~PoZx@|Y@661-4|pWC@FSYC<+Ab9+^L?uZ%D(@lm0Kz5_LhN+LD zdfwTHtPgPfG*wqYJizqJ>vZx+c((FA!VNi;iy`KPX0pdbps?^n)3_x&x1DVlJ&O0{ zv*5LR!W!d<(q|}MAR+g6IkXJ;zwlNlxx|jcDn@_RyRSBMof-V~)EnE$fb!dLjt)<% zj1^)WD6*nGp4H@g2UCFhz^w0^~8oB@L@96rX=!JHjCS z^HVX%`Q=v$H;l=nyZ6c&vtr_dK(60q4_h5J%+c1lox`xV-TU#uk;lIjL{kz$@nh?r zYk7asQP?Z&dK|YmnVq^pL1~rLJ9s1Gxo3yM27Y|$K?e$coG|1;VP7S*fnBRmp>eT% zg#OyPz1AhP@!N0Pa^w(+k8o{ugE34okqL{kx*sObd-YvxjEcR%q#9n_4Ku9ka@NAm@E+T*M_f(qu@xdFbTh8SEvUz>Wm0&zvh8(^_|11rDo(O+=^29;2l{+3IqfKK5gl`3rsowQ5KrrYVd? z=-NItT}~9a7M$kXi+eE-1FyFFL8^ZV`qQbVdJxTK9+mF2s7^y?|JDHpAI+!AE%akP z#QUgM>|XL?ghcGFzFmd|CEFsmfM{T4G)3UpoQAv_Qsad6LP;jIlI<(2>{8d1R9td4 zpoEC&Z~Sp|EjG+dSkbT1@KP@@H%+pk*2s2A4aYJKYIsy5n(3r|=h|p6sz-l7+-`UC zM7=$&q*!)%;ziLO)t|eYJ*ogJ-@rEWETFBVXh?wV?5pJ^3_xq!S{qw4;3u3}dKS6>G#%Y9m^WDi#n)EYE+26!ha&*V6gC8M zCeqf`9(mi_V)Oeg*JR2sw6o{F|HZAiTvvpvVX|2?g=gNv>j!wn=eQbM0g%j~mXE9R z#`cT8Q!{TE5j$j@%*TIgz)Oc6Q?ONpK8jpK@eu^c_H({aW~_7$G!{_TjGvFI-KqyL z$NRP@j-T`s`{ZniTwn!Q@oYSyJojC!GBT&r2u_s)D z6EF>~;%6M`W@p!~{n%Uy3Q8)I_@raFE=~ZnFB^ZF<4l-;*PQ7=&yk_p zyZQuMAw%Yo=R#ZmHsq0Hm?1gADC%X^P=s_V*4|X6*-ur}f{w?}V>LC*B$cJ8& zF&lQw8|-8Sf4dodtc8dHIf?f*mepKmFkjO+bx5#_vvqcu@f8S5eGohqA0c{ID5#?R zU~j5ARZH`F1xtVbTg5w!IIKiA-ohphhI);34!;iD-Q#nRyd;R9M>yW9u@}8mqvnDF zQ56oL#QVIZ1g8?06ty6%74m=KYMJUFqE|m1WX1SFzcL)M zRE4S7l{T#j07*c$zf^IPOIbtWi+ri#G~QD#kd%ibxX_e9f6m((M9l*2*0_1KcMpX# z8@;>gUzG1>MS-qt%_!r?YGl6Qyq^cx#xI}N=1((34UW5;-M4J&uD2}M3o^N?25b;b z9NFANyxEt0j7GD6J7N)3Y!mfSQ>5uDc&!m#9QP7j;dc;{?=9;Ru&m?epqUd6>5}W( zvpWct`L|E~9b2kPR(g>8Q2b?_=_jsY)}P@(D73$nFri1*Xye6jJR}feVLh zSy)JZ^f`)8tM>G~ji#)Yi4V~hTjH}7L$K9t8MM!1EjNhJ8g=Jjm+~!@H!H zO~pYjhkF1QD7h`rpHhhWc=$g_TYyl-6=f87PRWV_#tPhXsVaMW;K+Z4V;OQiR6F1_ zJO?j1ug0pNPVX{3qOFW@!zdF)EGG1}%^>?X?C_D^l<}?fgg3L=w#Lm=v`1{bKSZw* zg||U}6Ak=}S1E>kplICP-Ot3@Czk0ZAsRz2>t6EAZ`$9E za!g|dIX()&U^MbTSW~3j&R`GTX!@(n6@-0%>^>sm$$QhD^&{dLfw1~pqY*f7(=O$8 zOz_0E%0Fcv%a)E5`6qvs2T1A}p;Wd`O1BVI56izxz80Yoj=qqe68+*6l|qOWtros` zc-Ds$;zreQdH|>NR1~-yC)soTiW1B^-1u?#jQ7q3y+RvxS;3anVLgu@2UdOx7R(QS ztWVOylGf19)HCUeslo-LV&UXuBd6v^ErVJ+u$dvN2rWGw2l{G^hPYQ_5^TMgdJQCqpUC1_aXGp5ofCWVc1KihQ z@WTM6&P>Tt1GqxnU|wG%e;IKtIP|{Dymza1zz3Le9v^qD)%)qs50Kc=g#de)h~?xt z7zS92e!4g@9wYFCl36pBm<09AG0+I8<5j;iG^8KI)6`Ic_8XBW)|nY+>f90N!@nGg(-;>n04l_^lug_u5(-X6V_ipIEk0&v;9Aq|1o5WcSUP)yNrc8<7MT~{ByE*-3p|ir%=)#L3IkV+|a+a4>kIWpm zKqFzo5h(g^EgB!4LyKn9Vf|Fd_`Mi56k`jjVkFj(>nso%j55iP`NqS!>i&j~)l=SU z`AjD+8oD(L`_;2uDK`JGO_4e?#^%Ar7`Cqv=Mi?AlTmWvt7Enfh{eK(Pu@X?Fg-06 z-P9NpxZMXZrX5g2?{40IW@AcK*2`$hltKPv3stUOkzwd+aN%g?Mswz37i&v{DA+W^ zNpS;>04$Epz~E}#@wSc@Uox_SJzelfOnXxcX87z3ayohlbqHC1kF1#z3DUMmX>(s_ z48C6F&8J;AnF(>d(aJXPa3DyV;@Hb=cP6v-jSS2AGMvVEzNs637h%y#1%4@gJi-{v@%U-M`76QBNeTErzHb{YiaE7M5I#4iMG>SDls%G`0^ji5v=_A6Oi1|TtS7GlUIjrr8R-1r-)Bv2!&a zH>uiEDkd2%F5Ly!4X;8$j-eFb#|Gqq$brO8S~N_ zi=>B2GOkk#+sU0BS{YBm>v1_}rF!LhFN-s@N zZgnqf>D(EA`qsP^!>zJ9LFwcBzKv448_O)wI%lwG9yleOnojMcKeZ$6rPq&#QQ}Gs zL--mk)|-8rzf@lBaxurwC@dIHQ}_yaFwO$ClfK^Zyak1Q`KG+h^oGuNQ;q&z(xRr# zn~A3s02gT*DnpQLr(u!v)+a->b|IId_WHG7qHSV-n9*i=k14oEjKRInHHbHXJLSb` zjjnrIHNdsY6UZPsKjiDliiv_qdyJblUk?7(EL-b^# z1?Lujc$QL|n&Gy>dmM^!(lnuNnACCDZyS@*!CQS9ZF`!kWBN$g6!aQo3QJ%3%IBNK zhCv87TxGx>+)qHt;E65^>bXLSQcY?boshJFq+kIe71zy9!jLJ|=j}OJ9SMM1JHYyK?GVv=@;!T)lO9lq64U-VtT{wjqJGXqUoMjWu2zDlTLXPgk-G+e z1X|GLXuha=5T z&oj#q?W#O}btNH_wJwZ^p9Nug!TF@ky_EqV!neP04d`@6B3M>4f?0-D&ivuW=C5ez zRDqC2-@HSOC4|3S@SJPGjZU{WEMw$<9G9k!5U)Ue)Ido0N&}v;3In!AvFfO@{`a3Zar<~7t2Hik$0BBJtY1TJY61$KcZ?~JHmm3 zZ;T&J?BTSct#o=au7a{|z+T`*`4te-&c+GwGIO}VHYzfE_$E4SMrE=4Y2^5(0j&6M zTJPhu@3=thocU^#ttQ9=I@Gp*E)byY;};C=*u)nz0in-qz`%pt>HsRnEbM2LbYu^Y z?4<>l`-7nevE5&*#wsuxnBWrWVH9&2W2KT#TIrMod*Ni~16_pj0R9_1bEEA-ud)0B zfj&<=W)CiSwv3c=AY7iVd$wOaHteov~sW&j?GpQ1D^ji3msX1X@2gt`6hC z2MXzulZg+ok3;brqVd z3`Qg9XM{8an%f2XDh~ocell|(aQQ6qnkQ8>;$09wzMac8=<}mOuKF)b38+CGl?5V^ zYPSs3nMcrnw}AY8JHP^_d={JY3HN?2)~lvd$Ssf>xBOBbragq4oso8OP-G7>ym)<^ z187?MnGpApmv@mQgW*V-z!J*l*deNN~*nJjatA#AU0w!UPZw* zH)spi;oj>()xe;A;K;*}w8JifpPu%8Ygo)PP=OysFNP3OzeS5(l`Esc1H7pT+ThqZ z0&DPgEl4RyxxjMqtZ-&}p^(G&>K4_<`7z9>*nAm}71o)^MF|PzZ%JaPjuS`44kzJex`N| zhu+#Dn9xDt(eOB#zs)L4_Iy4?#j8(&BB9Q#Z;R-IADOg{{`IN#%vI5&Cs=p2s6(Da zMFTX8oVHk7EdKyiDVPY%kolLpTYQ>-nxQXB;}S`(7%l`0ng88-3M&N>O}OWdBk(7n z$~N;8*Y0OR7W{(}GViq9T?xHliP-Z|o)nPdE)ft_K@w2CBZJ32Te&kYx9L(o3pbq= z1S;g~SZ$`UpKUgp%QgcNc+?p@nU$efP1=dcH9AD#K&&Oa7Ca!5+5LJHc``eHz`0XW zm%BlK_y;I%^Y3#3`QpV70Mvq%C~D?^*vji91{k?nXgWq9ek(KpB!0S8VO4pgSg z3WVpkd^?BmZOT3oPK;_yEJZx#v4E{SlTHO}GLwNW%PPQGlYi8d(5G{)Mu|Q?TKJIw z74MbLbhs(4IwkXBnaAEf>@{V7I(f%0+ERovuFQ{ws7inhNTyCyI3NWjr|;{UUM&OV zq8vEvt~;Y^Vf-*#7?0P59ei(x>%$sKu5sSXXP+A}%Yrr@wfan-0*tx=;NtdzSY5j` zbC0*!-whu>dBZ3XDE`!VET(E7m=AsL)@}ra)2I>Sy23*Lq;q8zf~Q7y0;eG`b}lD0a(=zcm1+CqO+t{grZ!;Npb%J6HRdm4=~8Ka z=ne!16u?=SO4RoS4~qK^TQ&7bR4nV{kg=V&ZitU*ha!6@p``y}+nxOw8dqtE+=*+E~rOCZx%ABQ{y*7t29)@1vs(0Fnrj3PN1BpuR zI(enSlN3f_R;_$-XMo2e3CY_pIYtdQ{ZQMke{LQ|{fta*(sQPN_*-#u)39tS?Qg0r z{^u^wp{!Xf4ob3bgqW;pOwLyd1^aT? zsdw4(u*6Trna0Dh1X)#=(BaiveY(3MKro!Y zWgf!k81c;j)Ohfy>C;`tqmnQf(#{C5f+^#-#e#+tLtAitV8&{Ap;=n~v0pS2hxsfc zVI^&hhrxSItr(G$4fh5(LJ$kY_cc~keRaIzuY?fbSbpz+jX-*yXS6t3q>)u=gL*S) zu;^Hmy8upK=xU$2fESuNv7IF$Jn}O)A!JDrrA_zOFnmC>Vh0j2$f4ajd9NmW+lB#v zG!C%;&T?1V8`C~S70hs*D!;Un%6UV4_inw#yhkAZCWj9{n>OF$p}~(`y=>h!2q-J+ z5*!B*>7a{$Gw>zi${4Lzj4Q=kmqSrlt*KK#yBP4FLR2(iZ<&j(&>*C^`jbu zc)%<(tc)px+or_N6IhUV@ z`|@H|8!wOwDy$Y_ilucDO7ACEhz6zjV2a>8joWM@6y0xmH4aEM9CnziNF^U$G4F%K zc5!Qeu2&FM2ib*u7C?ekamiqT7tP%d46IPy4r(~@*+I~8JO|OHbjGY1r*2cST&!V~`B^7CL%= zOsxQLH#{2AQlr^~Sb~B>U&s9dh^FkGrhKNUt*upW6;1*voC{JbTP_}2sA`6H zqS1&~T#mvbC->3*X!GKvT4lvQ>Pe_n(<^o}f^E%d6vOB|f{$#S zFAY9hs)a^~<9&6Sz>aK))%7O>4KvHN$@A?>qb7+H^`rePgR%tC#-sXnBY@0*PZw1< zBJuYOyB|5qTvE;qs(Tk++r#L*d-8i7K#0=WW0AMnqSJ-nm1#n}${}g&%*4D2RxbHv zZDo+KhF*3*CxCy4$cduZ z=R-e6XCGe}?zkQaL3dJi+#Rrg0Jj&nY3?G-@cJ1Ra9?#xpuc6!TD*3}%K=2J#SaNV zP6fY9U{t=fTl@n?Dr%KPW%#fUK#PMDb`8IP}37VL({H8{4znwnKmRRO3*_=fFfSoeFb9dD?iqPGI6${qsg1T=DNbsEf z3(x~4Dg3fK8n;2ri`GIH{VVfaT#ww+{u$|@wKhIFbZI)8lNv^U@z*?PddvN}`*q^> zp=Lf5coQ_xnF;dB_9LF)PM9WZ{dt8yQrID(9$lhR;(f+S|8Rh~he;t==KCk7_#}0~ zOGCLU(P7HaJlJLQJ>BM-XTFBZMsp{MGBmdCujm`~b0>H4w)J#1gy6*su96O6=L-!j zsTrDBdmS}V=gx?Kpx%24lnwOeDWf18piNaL{XU{X_YPMeWqjbE1C2y~~p>i*ePI*=ra2IkV6>$>uYV+NSR z8X9%IQa!vFjK33Ry>UruaOGcm6oRi3*g(8SYuT6={aK=a1bn-hCqPXaeZYtHQWEN* zm$r3YA7S8@>~N#p$@c?n8f~p1gUHX8G7l zHY>DUfo?*7e`d;B(dn#r%mAve6F*go5Gk{Bd!nhUcW};HonvjApE=VQYe*mYe0rtL zWn|xxs^`c}d*gAtG%r>b^my%naKUVAx$W~YQyuZfK96I#CtAvfoyt){Ikhm%r z^dvY1upo%Ol(%(=%XvYT*e*%VeTM))`iU-1VdK7k#wPFVq-#V;Q>J$LiXWgw(@Bq$ zOH(z+>3Gy=?;rp$nox5UNz0H(cm<@Bbu5fExaIz!l)K z!5F{l@R33bm9;Egm9Dg?sugsD0hGc9@p1$c*bTw0D-gFAgmdi6XPKQWp+MT3A6TaP zPL{2IWW!0)KYp0>9Fc=>nN_7FQ4>XZ1zqny{3Kh)9^WLM&hzhgw#))B z_jLy5Y%ak{Jz=@^qL(VVSP)I#KD6$IUV-I-XMoBz^{+aE^DmRij2iRQ@G-GeQ(kv~ z$t543TcQ~06$>C0PZcypN|8{eoDP?yP8W@T*;y}D8O}w&8VV&uQXW$yMM-KKp0>lG z*h@yiHf2HmX43FLK>Iu!h=6af>W>bP+<(YT(AWsbLZ*w;^w!wS6{co)!$n~5 z(D077X?3GUxScK*!r^%$GQttP_bqvXnhBT(FWDg7QJx7<87#IH%ls5^%Uj9>q7S5h z!yygGuD1_D#%R9cCRW*SffKz340-9?`n43^g3QUXsLFk2 zI56E$$$Wk>_lkYjU%WO*nb?yO1k;I+6z`7SXfE0|Mr)pGlN~Ri9d~J2Zd)NkXDzw z7{q>>1@d8sFZ6C^*avEM|J{4e;nkw@+rtLhFv^Dy>J4wD88+udTt5i4yL%CTnY|?~ zDe^;S4zuCJ{*=g;bKu};K0uZ)CF>bZfvA{OA|Tg2i-iYadh00NviFaN9-oh#6oi?p zCegehn#9)W&)rN=kJ(L32*|RZO!G;jcZUN#3K4-SDp%Ukzkhy?4qWa6(~lHV9Jcv0 z>k7V$8rw@O_6-{6eMyrPhWxpIvzUfDE6u;M3RGwlKD|ao?S-Ty01UtGMw#6je#TNR z7FaA@LN_A28EeDAnL6d=o!m6RYL1hZT;*4%R(p6y-Us4eORkb50@u`i_WIQGFvSL2 zRvUC`S#%H&7ss@QT@p7Mc}~E%0aquzqDa(Wd=^<63Ih@M3CAp*#iYYC%{oR%Vd@FByL1>D0Vw? zm;_>A{7xlN# zl@90Znl_8(Z5Kw)4k|8xp+os?6`@}4H4+Vcrf5S26+pEHMe%R%#&aMr|a6m>; z`bn;8EaWEE$*<-hAw{XM(w`qE9yIF5(YEkvhuj5?m^lpjp-(iqD>Qj8LUo8^|a?ZrFH%) zBw-RPo+cN1V|qJiBGY6Xe$}z(8D~Cih3jp@b-q>K+jSL73i(!l>StElYuLY7mv&7J zW&Pqehce&SZV<23Gqc;``g@H!&aa7^t^G>#v`az|3_FAI$P0K4E4LVtJFnB9Y3czBAuM{2`onIRuzz*hiQ&O$e%71u3PfkEb?qB#6P46q z7TL_kV(iYikYpffFCfEVOe(@!aBFR+t0NDt;`O73yrJkkuF8t7%y+u`+)bv*s@&N6 z!oOG`FTksR_q-RXu#YD391LPu3b}l=N$RqyXb;1ofi>R>y25OW{IhSQpT(jplEB#b zniDb)X z1NA^W$UijbJ;GWG=$wx5yG&*NWt!6S%aJB7FtA<>gpfCoNUVY|Q+nfI&Cg1Cm5p(p zBCgbba=m}On$=wlGY07WHN>}Y0+Qi({VWTAv>$Hz89tq0Z#q$R z{Pn*d(8EsAzoezX(5pNG!1L_4oO8bx$*T*hfW0Pfy@VmFVlv2Osgzl*ISvLT_#sQR zGUtQ4nAq5+$l4o|to89v^4GX5V#>eDeGdSCOYXSe9QF?^A{lueY0l&`_W_>o+3qZK zT(^4pm$TxaMc8~QfqX#v8t95J`|{tE#m&P44+24vZ!8qdn8$hJg`WzjpCZJthc_>?WXMyg6A8W+Y)A-h{_m;zN_)>VS;)tOv?jS+wQN0+E+Ax z3MbGTX58@NktE}Q*W#x%_|)(66`^I^Kpos6lHIoVmtZx*Em(`P_7h{&f>k)|VB~r_ zB?S}h_X?~O{@1==BR?Sdh)A{Mx4IJV^VMmVX_CQh2L=HWg#4&xcS0aMk^KyZ5e}xU z%Wk6@BP^us{h;E~oRN7z$;b4oDf*Bg~JdBc1IB^(4m>c-dVZ`gZDjY=5i zieGSi0gwRTWjn1OTDMSk`trm;LQ^%#)l1;Fp6GTjm;yoi*GdBd()JJ>_*!M(D4$&Z zkihHq77)|Up~Vg6eN5=Jn^f!OF2o*+kVOL;M-)@0Ki}AWa6eNhb?3?xg>Ex{W?!@P zJ5CGByhftucY!phf34XthgYIqBAPSu6x_YU{z^;#pQn!e4^aJY@BiDiasIn&L*)PI z+N6a2zepUc<-gRQDE@i>n2~>_&)V@%;|~7`>`aX#cBC{bSAl#3$xw3o64WsR%=V3XuNq zO>@70`BK&?xtrZH#P}20ANAjv|0#x|0rDL-{+HO!aJ>BA_R5c84V!3xvr#w_`ww>c zJBj#bw(zSMRW-!k8EX9TI`p5F$hdzWw%BhiFT4K)_rK$9|1QS(ukol1cdd%0u@w~) zGLl{f#Rjh1x{S>z2%hxr$tajg$AO3#D-kgw83R<_b}tIfZ+Q-RbkjvI$;G~QFn@}i~VhJ`g>8j ztjY4T7RqLg_D433F1wLTg7G1wQhFN44Cj`;;I8ejK}zTHP4Ochh&>W6)V!=RrR;99 z*TbSzst|BWlGyaVYLk)RD5-yAmsGG4Mt{a0F~HpyQ zWZ$$!IWBOvwA_@H`Uch8nvUDZ9mpzTx{n|HQ$h*8yNYeOUpA|R47 z6HfUR^iCg!-PDe!x_^DgvU}v3y9+KMB0aK&;aC8Y>?L;1dt9{+)bzb=H*1RdtdS@z z_Z&bL!(+@?p&?xqMkU`njwqZOBol#q1Zxi?bHHwJDRZ1EZ&pkipH5XHPE!i-E0#g) zHCDoWcs0Z&Uk?-^+2m6fT{P6My;-_wFhtp6wO!s`HS06L$$!Nm$4#xzbf0w3+(*d& z376XRme4!WyQ$S(Drqtz_7zUax-g(0VL7)(UGz#q7eLf($D}&wq`F$-!klZQ#;?ot zO*7RzDB+f z^+o7zP?yU<4SyFk$}Xkz0o(zh7cRne5d*pJ!oWlaeOW^{=*C9z@S_9IY6ad zuB|4Nyp3bgU2Ll~Ez96}nYA0Y=5>QJ>FDPDU@8m}&VPi|bO13P$~4f1iJY|M);;+i zXkNM~MxaZ%B)jLnK)nHpi4~RJNlM?I)&@X+3H_H> zBd@mxr0!l(DEC~GOkv7I5%lAwXnEv4EqsGX6P!N+Ck|(kMDzc!b=ErD!^#@HpcG*$ z^M;wR3x6|nuKwuzwU2hQYZsQrk~OlQSqqe}N6+SAUI#=YskjbQ+INXy{Hicr$T&;< zwx1Dj-n&R`*_LULw{r-U}#^AC?4)HC}s6w~#X>v1dYFzDKM zvDoFulcF|D?_(Q`txQG!wgy`JS>d{-oV|4N!1!`ngtxJ&fVmDEBPX3VEyu)rhyqt1 zpnsugev>Tlna0MDF-hk{AG87hwsP60ION^1(}uVNBY&AD zYfu_W0U5a8-9-nby$O+g`D)H_-zv%o^v*G_OuxkKN{~?OzHwZ)%htTcxZ~9n6*V5D zswR=)^Qv&jivVl&Zq<)TkXu*ANg+3K4QEw56vwdwP`Wr1w=GKC!q0P^o3$fiTDL2T zP%C6P_;YT_^jZ@Z*97J|^}_4%(SId|1V#OFOw}IKC4aq`?9`ms2Ga2Wkr&sqfARd3 z%bjiR0}rk|^pgBjtvNTaAUyXgpTeSAAIAd4f%`cYc_nJP2?Yc_TuD7Uax{#|{ z$1jb9Fv*-);KtC5L7_6I@0)jppFsVRpT;88aEJASP@Wmi5cp|v5&RS0u{xDmM$m{eYe$0 znO6@P=|t0KPMsU_s643HI=v79w=2 z9N47bA8_`o4B6VTW$+c z9-8$Ljv&4~m~@J3Pul$qe@?%2G}M2z9r^1K5{vRUw6Ksji_4t|(7Kf-fB6!7T`)+%uSGmfX2v_7?dOW5KCgl)8#ecgtMzb4CY3R1;0C zt){Qe;0DpPr*CdEBHy=nrtya~Z(RFXHwP6W79_So4_s!Jk_j>2t7ZNP{U$D_oyRJaFc#S5ItqY?)1zU>)UTehpI za3Lp}kc&!mo;>kSExiA=&H~m+!d}D1XwgbqkzMCZB0V zU|Rw^w5goQq>r&zsUB6FB1vcMg~tt54paPAKWAup8l4B2L!QXmlF?bMZ^_Aa4~$$xNL9lt4) zV&FXk7C!jz^JcaUy)ov%#|hJE{PdrDTr939M20y$Vn8{CAb*^S1`kuAI3kU}NnViV z0gH|-q49w0XFPHlr(f4xZJ9)w^=jlf9V8M<=jVMYL4%gmYfMn(S0E|38AoXchnJvXKvtqmizT&MC*VH;cUlC4 zrIhQaS#_rl17^DfoCnl8La;1>!>!hp<#PPFur)ZRuFDP$;2%(*VVbhueeU^34w+J; zt(37i-JtlZDPp1+i(bd#%k(ZD<0b0pKF1|z-hqGiIDd^sE|nUO7O1WRzmddVE4X%E&9^3AXw zepnh7{0>`5@&uk{UjC~Kl{O-Yrjw>121mtD3jV&yxQ%axDuJ=FM)O)8YpHnWUy8lF zI=1w4GkE#k6{@#vmev-93ujP<5|HD=;cZz7exkkUrR(|G_ z72MbS=nNUl%UGW-SoF#2-@HIxNZ3Likoqx)=%IDm1jPKU{U$wK)wFu?%=LRtu}iRV zx;%mgy9}KggW6Y@Bv_$IiHu(7tTIA$+qJm}1`IBKCVV&uUi!GulfRc9y%H>c#NYk^ zXn!5GU|GDk5gjhp!aB5Kt~f;TtlXMOGDsM@xJ>&My3E#CISBVe_yQU2_BrMz zpy&jOr4U2J4s_s-ywOJ!_A!(|eTw_P=rwbVWu!o1_f7u#0;%hgfkvccHn#8bvb=8_ z{N2JhP09^D99{BJjy&in6W~LCcFdwNH7Q#0H6pOlKq@vw`BP4YVcmNtri89j&IRqn z8gz}OX2D$SWdpu3TrnX$WCx}6bz7@#yxK8ks1ZThQ1Xqio+5xlhKPqO$~juuThE6V z*dgTK4oQ!=OA6_4?vi`~tD7%`jbD)$9e=IjDUrrQ=b5y0nIJ|N0xQdZ^)s5Y{<#UL z;fWmv?XgwIyF#uUUj}@f!4<{c*Dkh$CC^Xl1NWuxZb2F6_p3-(Cu`6@--c)3;;cZ> z_KxjwgHQVO&h+_2*{!$VqKzyj?VllihVG+o!BFC zhcZ$kA0QJ11`yoYLQ^7tvi!3$Myffwj}zH;@Uh?=?;5-Qm9I-A%j^cyDo*z}EX>BF z_+#@a6poJG!0^uW$->x9Bt_P#+&|nRJk`VxrkJ%=co1Y%Bqm_sb5#cN!|>Mk?%Z<( zqP-#8`{WR7I%s-|$Oe-0%G8R(NXKC4^Y?4GG|R-6M7U%ozX(NtGvuR3js}JWlkIEu z#GqHMwU=L&H{v1bR;{Y$HOu8uEMHXhNmA_g+RgxV>piG}{ML7QkGJzf|HW3jAaWt& zeF_vRN$Pcg6qANE@vwIkVeFXc6eJ>#w{3=d)`)wxAwO<8%}RGrG&eIcqy48LyK5k5 zS1a8$`7`@rla&pB*+D-5_YC<8=w4+B*NR5ZNL&6f5z#<$vIRMa?NpL zdfTClE|VWq*O1tQ3CmFs>{X?6(RnGYfA&bPg&nH(CH0L^f2ryH8mCIxThR-Nrm;pw zOpz<7+JFTt;NWG#J(N}7;c7J41d-T{C(adua zo|NL!N&z|(Ejrk+f78TAU;<>q1KAxtXfOo>sV;yBD$h3@xFVlk;+)^ywiYg>rFO1= zbg;&a?m*Ba@6oqNj3e+Zzq$HiibqxxUD8K5W$mvQmMHOiwDHdt=@vgynXC$TuRLgH zaNB0rTZ@JryK48{=Egndhj=TpOGRKS_44|Y&?~Xo1ighTfA-3UzlB?R0NBGo*ZkMw zy)*gzR83=S)d>*%aX&oLh%ve392=$p`Du~(YI|FT*Sr!1uqm#1CQbpR=VM?`XV=Er z@Q>K_x$&W^qp^TS{stH;yW?v|mrjtploH0Ia}}eCoJ03Ur(QwVH!Td()FzxJ%=t2!l2e<8@d?7ta}VG~`Tq5?HWVZ)bg_Kh*LNL#*Qg`o<(k7WQ{v4XAh%1p*` z-Y`Lamy@V!X5g3Me=Ose`di&SPRjnR4Oj}kMseHlXxX6Q6fB_gJ}mZbD<&G-_|DHQ zoK(xPUI&aG#|+~3xP@n2Re9|+_N{(Pm?BLw^S=0{f7y*sN}j&Hp6B&Qh`b#w_@&#P zB|NDc)vhgG;?2(D!3_EKEQ=kp;jsu*9e6^^Lm)C`!ghZkZhy#4(%m5`9kOB{s``aY z{)3bR(uH@}ubF8RCP>=JEv(BJuG(>du|SA-9zM0_SOkKQB7{2ON72(+&7px>!J#OM zGofD~e_EhHjs*B~@X55A)5_57lSlNDAhGlglIdJ+qI^-R&P z=Y-U+;NBH2W)b&mT1BzIesDjm$?N-KhxIykSs%&EM$(~FvMpVNVU};#&lmD;MQhOy z363Ksc3tDoEDkUHBN!|U5mQeekBe#oj<$m!e`0K_0i?9OwGX!*sthSV+#NQOD5jIA zXx(up5VIp5oliZt@LW4J{D>1(C^{nU)j)dH4-Sqk^#VI>BEs(7B@meNA#eIN>GM${ z+rwnpW|TCLBROc$I3)>d1boo*+^3cf#w!@57LIo8J|_KYM|})T`2A@9=ikj>22fmN ze^&O4A|3Tnsuh>~jfm26TZ7PRmq^2sCZm3g{5`)hZV*}~4tt(cm%(n2i}So@eIc@N z%K2NF^T`rY){??4I&O!aLHYz-xAW-g_N;=iMwujQ+yu)JMHuogw_(MqhjZI_y)8=R zkvRH4`@}vw&aiLc(WVij8$TbW*+CCL-E%>&b{oqN=b-hVzN47RRd}t& zb=$-tBOcwFm}GH%L&Du`TjXcQomz_k5<|Q0UqN6}}1_Z&tv?QhK30W6w;8@s$eObq9p z`LyAsKw^l_CxkzF<#+@MYPJyqkrg2*{Ln@IaYpLhIJ_LR2x>fFwfv+Ec50!-7&Mhw z<)06PxpVWkd!`g_`vd8^k23cyotI3-5*U9I~{`sB3u4p5k-UWYM zzUP6egT{VUY`9{~pi{MsD97HWZt;`*{?s2n78 z{I}VmufNaj>s;7*@R^>5M`#%pFB5;9Ui5eKOAljyAt4o{pPa;aDKbfwyTa%uI*JH8 zl2cJTm3ByR-k!lm+&GM>dd4wSYEjG#xi^1J?04I#)J%f2Jae)QuGkk)^qf6c3u z2raBf(-4P#4&-`w#oW-L@6llp`$!S~#sNU&dQZ3oiMjv-0uu_`G^l=7-^cf4p_V8Y z`DurWtukb7#{97flZf>pI z=?~2mJ`(ijT&(6s^9)-NwAh(X8n-d>5yamSWWHi8p+!_5LFfR6%fb%uHgS)uYfKKZ^tXQ&x?9^}X6dkXJoJqlX$2sGqfB=9Ks$ zEK?yW2yXj=JnhbS5|`S@5*mO0)(ehhd23YI$g75sV9AL`od7BzF{(1=@A~rysZ5;p z&}aG{yVya12jp)2^N~^=M{1x*vn4&o|8=57A79GJds6O$U2-%b8NAKhc^vH)8I7pk z+`JY(O#}2<6VEJq=8oQ5)uGEK)}C$|8*(I#QcuO z;k4W{uDgo@zd#o#c+?zePr*Ybc>pP=OuhR65~@F6Q1mAUyv)Til&zGvL&+po*skmg zS|_}A&h#w`h^_D!D0p0Q*%xja1-O`>pfn(=s@yn?86Rd1S@ zFdG0cHL#Z-GxDA!P02PUw=xlt^R8RQ`x%7&Pel#U3rXPChXwk77=7bwY$i~stXfQ7 zj3HdYs=eMS59@SxB*daLxsyklk_S9i@M-R_Nh>T;C)%m`Qqz_p)AvMoqGDnC#RGBD zng@MZHsx|s3LK>sv0r#D6LGE?g*LWzWh{Q&2j530`intKyC!vYgI9enGb;zOkvEEU ztjX0ZQ!-}aiw)akn@aat2 zii}$)^Z=t&%J3-Lw@|wh_uWR4#D^u#AWp5+6%nz$U2%6jwxj6M;>`a`_7Rt!WAR}SM7Z5kpWdyA zbNkBnm8fD%a^I(pXFy>ungG-EyHScDPy-A)dd=Q{wo)5rDy(!8wPRG%&5t!}4fc=6 zTMyVO%>+>cJr+!deGX7|$!R{s6MQujU)oqK1W{PlTOFW6Ivd;i@o+dHD^VOx^NS0k zd}?(xH$TKus6VPChrJeOknu0;PiS9MYK7@7GF81cZv%ebRqunmBM`?Hdj0Saii|@g zEQ~*YLu&y%ho+uxv2PH3ZT)f=-ux^>COTuV4rXV42E-of@4}yw*Y8BkFpghY=O;Zj zhIG50QgSoH1pVXxI?xY&YJ%}3+Z1m+)UO<7ukdgWO;-Gc#lOIQg;&-!z5(`3r|~(j zlS@0|SZ~p5TUJF2F;(XxZXnNDv;C63;pvor8)&%#;5z}7AN8^yVZoeA&KmYy`Cf%) zgxfyQL0lc9I#Bs6ir_`-;BmuKr9D8{h#P{kol7gg1 zVS?RQ!NQYl9Y>5|0|*n~vgmL|Ez=WOw2qc%D!DZ1hDVU;daooq>>d_6J~64ZWHbZ^_ke- z2Zu~0^%6+km)@CZlO$}OKU82E+`@9geSK}D5SDU_0?#xs3RYO^&T&0^8^1;caCiG_ zhqye|uUYO8y~&gG`e+S_McCtiANF1Q)BerV6sY9yW+J`%*mZOj-ZwDP_vV?fN(yJ@ z2t@=Map#b#Y}z*#{+Yd3GPfv3-C)2FI*z;JHpL{9eO6px{gsy5=HrID!458qQEMKI ztrYKu)!^xKPi=jVrSjSg%4w3Jot-0(2Z*I?n&;Bndj$UWNRn;8m9p%A%Dw{La(WEM z*p~v#A{a6ybtwvMA`+G8lB12nDzFpjOI_m5bFk<)0L+0MAJb^sZ#sxVQ=28$#NP*m zv2)4@o8Acj=dX|=eIcE)$h)BnzqR^Ken~P@s7A(X;>&O%Sbz5tDVi?x+)b4}&@pH( zswEOs>QrhBHPGAnE%T~>-K2ojXP%tYp&)2x>?V=Jb{ycNwu9Bnqqn_Zim5*Xfpw=m zchnTx-;r!{rj?uybL(8_wfDvVrua2C4r^Y&BsU8rX8<4AB~7$l2V#4s_!?EDE*pj&sdz~nKD69rTSdZ)1dGezR5g);lceL-=qW(L+~^) zL2hxBthp1r($^z3FkWY8p%~};n#ZOQVMv>k=I7h4#W4KNud`iHCANCTOUy$|p^4S6 z(8kFFR;mHi${cv3IWZO$ZEp9qbxnN8QUqVjO|U3)@>17W(`c0+AY5_1It!$c5)z#% z+>lh`^3>*RS5z;57EZL#JiqTKr0j|osN4-V^Wn#V4~7_Di%xDVw@U#*6Zj(fjx!-Y zdR1gS;nnWQBN_67LObu|!+?9Go-Sa(DA@#4%#hIVFOaNvYat2K=u1v8~# z*-u?ArVI$N3IfvzO4=LZEe`VtnrQPWCdpW-j(m^EVRLAIc(M~f6~_uCu{&bp+l1iU zm*3A8(F$L^7K#Xmbj*^GoW{2ep_(Zt;~*juu!g4Z^Bo4MM-JEqggu@TBuCJr2S6sg z0U|K7xhQ?o6_cPs5HqURXooCn1rdrI<56J3Cy{mhVrilk9TU8f{S)!-mLr1XbJq^Y zWWb)RRPXnH4Jyv^Rai_oNcc9|PF}mkhRic5bNL;Y%n69g z)s`&BZ{KRxlFfT>+vGUo$RH=@h8-uB>*`9WB4p4`rDXxl6f@A+CI2(u{ zd<|G}3{pSn38j}L1-YG&fOsC!2>S9MSyKq%64?Znm?=6E)4E}Zud90FRwFdqJf zK1N6*6?9^pd|cO10S?(&3xDdy*i@*Fi&drt3IPsX%p>@rifGU`zJp3boX@e7dd zi_$hPa1#?$QN4%OFvyXAWsTep=W5JUnknodKcpSk!axXFA_+2B>v0m6Mv;_r|LF<@ z5d$Q+<0x^t$4N`7r3->)D!xeY+U_335RI^bPd_goI2bcU9UJTp&#rCeOi3#CgI2|! z;Rep$o6?sc(Uq3V5Y6aC$c$Mr4$!2G!G;tDfKvoUaFC1vey$aNv|(o7{1Mna{X8Zx z$tD^u0T!WboVcQkE1iCUfu8g>*2sW-`Zwqz{*V#~L`8}ES{FMsKrc4LcJTkdIPB@mV0bZ(# zIUlgF&*W&_qy3dr{O-Ea8Qi%?D?NUmn`>>i1~tI1=}p+t>v@jDW9M{LM#}*x){-W9 z>`aI_HZE$n6L3cXAeH4EY>kPA4VZjv&Ik#f$MA-r2gWad)`jFK8O5B+0g4XH_2*8X zSA7OaG7fm9gjKS1*$Utv4rtA^t=Jglw8hiH9RYpH@v~wMR9XxWOeyNA2D95Abrm@t zC}f8RqLWkA2lYD$>p3T{qsl`DQE2(n2%8@G z)Zd6riqkuPtZnVvzgH6l@jw>FU0dI%g@w>b$Y|KU-%J1y4EGHnn2l?3*G+L}lsCaAUpDW568w^NMw&;dVn1DN>Dc?_O=Jn_EHD2@Z_ZhzZ)&OukwRmyWBFTjH&Hw=OlDd;NNQvsFeQ$ z(vhzVj19=_WBiy+#8%J{+CE2=I~}i#IWr^9_{hp{`WQ5LE`L0ch%3rCO7nXPxm`IN zH7cBcZV%2(=2sYNvzfa(Lu!t;v{+QT=kw_@<5$S3$eWRHAa?_3g0ew{P^?U64*^)Z z0W*?;Ys-wx8nT^wZgW*gQ8R*2_-Zp)gDw0plKUoi{^{G-NFv6xQ$Yu@Xau;hP-XRW zCthN%oNbRqj*BVEmYQk@Z&ewHjuY^Or6*p0AU-6S;C0W4QrwtE`-cE>ws z?$|-yj%)f7N-;c1GMuEP#{6;nm}?Yhn{KA=g-Q-{fMqBjr6eo&2*86kqJ)$R;y0~- z!wFqVOQb|c-~v3R3H|_K&o*G>EEBDOtD-870Y*eEz3Q#26`%YLRkslenXbkM!ffZhQD*vv!26dk5J0$_{H- z3+Te9n;B)X1Xv2yOe~Qg5ot8Vz}B;WS$7}0CXBuDC)xozGc?x~UeL^RIjFkZ;YW~< z)0vGO=Kg!Yypvh%L2bAaW7v=e%HoX&Gbgi$qQ)JNuDy4N5RmeZMS!nTv`Q(5wzM1U zRG6Q3j5iD#+uoBy8&;9fT*}Ys9XX`ZA9Puu>WyGgRhR4#>7;YlvM0ZqTKY79K{e3Y zB-l3DDE~%ny_eoIsM{6><2=ZfxM)9sSrb_4{W9ME84%F`Q|Q`y7ym4GqeWHBpQ{XI zBn2b1ESY68<{EWF-LAq({06>oswW2BbB9Ze@nu9LoFN>B^Vq zkw*cajX5vkNB!sSYEdRW8^Cpcg^MI6$Wt{V{qY(I+y6>w;P>#si=h@wx~fD;vECFq zx_yL}8M-L(`W$=Ef=f!RY^QaC*Z@LJ#811zAPdo zBjd>_T(BbYQC{j-qotD=|d6o-@d)3nsLZcgz&W_K|h2w;!@&dnw# z#Hz#NYZ^0KTOvml%Auu3ifcO3C7{<+eHu-vr%0om@!}5xrbi? z-YDyyXt&g9k-dP{mcGuB1vu7iB`JGVA0q~cV2_{3`^ga zmDuZZ(azYiz(+5C+Z!Ow7w3Hx{ilt0z1qt1c2tG$FW3Fe^z(l(0QL_u@cVzBLj4bw z!2DZg8I$`jRKaC_GQ-!5%kVl=-~7yEJ!>;s#@sb$-NyI(gI+Su@RN3aU|jNN?SgrS z-mmV(=+5Ndr%T0Mbu8b@`Q4tZfhoVbhuFAQsCyaMqt}#w`&e1}*6sQ|ITth18~M0a zH*=fZI2f|#8zgygw&_QJ_&j$tM|Jo|_Ik%61fllZ$9)B34*18PgI9iC0D z35Xn#Ph*P;ALGqXiiw_b&oYZ^oPx~}iG-eu&2vgRQ}7K^O08c`4GBsJUzH9x$Um(1 z-k&AQOueyx+#|bulel6j=W|1_vLSbT8@CE7uX>BJhAiWH2fL1{sL)`wVXajA7`)k` zp!`I=^`Hv!T)r*vue$&0&ohj&;e)RCJ~A3Lo_>9^y!>lO3isCT{!un-66Vv)y%SRf`T~i+rUqaH82+iZjNF> zKhccu#2Jw>#4k}*3m0GY&rV&!HIT0qCX#qWh(O={MR1SbKB|wig~|Y=m!m@NA#Z_d zpjU2{j5^2?YPZ)Qee^!KCHg>CkWrnLb!vwBVaRCIiTJCLE2+j- zRNJZo2avwTpZk;7migIiZr=&_SFafPwb&Tux6Y}z&iPN~N_8wYKS=(pk+~DmX>CR} zIOe;4PFG%X^f0uN`%j&VKgS=GJ^+XPb~xdGh|zYvbSA#DV$BJx#{UMUNJemCoupu{%^6hLaN zR}>ORjzE|7_vR)B;?;)HLx8+}CPN8-87d((G&Xw0K+98Z^PVZ21kZSdau9$*Fx8^I z4u?c#WIr5ns9^<&;FejHy?e%VTyf#WOqvL?h~w!cCVDkmE>E2X~W@&V?? z<ZWZ^DRmT5|9CGmaR4_Q>hR zw=lAE51Ba-p)?j2C=#MlnI7hH=)UTnZW^)1%%kv;WQ;RQgtg0_ryGjTwtouVLxGo= z>v@}bQtf+LsEgGwS#I0dX@=6mhzM6{>o29tMvUX1EGU^N-q|X}R3K7uSZeecXO~`X zB?7b(V78Bgf$b^Rtg$$?9RDAGYwy;cD$GTV{-9onN?Uq46A}mzG#pgCQ`B%!vDG%n zuisC=9@hK5-~KN4zFJ*)B!@A_9COULL)0L!6<#$JHZrgNJM-{7_V{7-5wzXwCHr_Y z-UUxdb;;t-`sBUi-5Z*iifo+CWP7x_!%4h9(Kb2-6}prqKCbxj^Gb|=`S$Qp9HZ(J z1&V(F?Y3|E@kGj}x3uW4X;;eE?3JyT)6dJx*zh)3Y@7I5ns3d`m*UmCwK)N_=x+WM zK1!HNvVyCttgDkzb~?WPG{KGtW&~4z($^;(7L7?OqQ@uh}Xw&-aly zoPG5XK3|_EZxjBqxYXO1{H46UlXdtqHLR1@rJFjtCc7&Z`8l0`I{VpIez@S~zCpFq zJ>y;I?nA>wwfQrdx|(9zsBpL`6(sU^qb%G{17pIh53Kb@0v zoygaH%Ff6tw{3TS@R#uyyKY}TYZZEFympW7dYLZ6=S3Wig8lvDvYs9fp5WJQym%cs z{G#Q+FtkndW-ZZM>Sa$;_B0#u7f-3AFxI1Iz80d+ulEs+H~49Ng!Qv=wCE?X-#@R& zT=EN!MnPf5^YwbFu4`2ua5swPMV1u&>3FtI2i%@98U;mv;~#ep9Q^e1%9XfnHlNRz zIBr$KU*AVKst%t+JnDcFq4Pkh>P8I0t-0P*_1o8_}+(NqOW z7e`Z!@BUkIId7YzvI5GM#-WvlcST8Z%0AE24UW!PetbD>EJ(wr%X@o!dbWZTk}jV( z?|b{ER-!iFv9sJ{Np1&D-Hl&Ygq8c(;4K!}?pCIM>F$;vbHk(F%QHUgoL$A_xt_=A z^gZ9l{G{Tf@Gi#!KI4)-m-i@$ksrKe@@f4%Z6f?qcJ-=$*?zrx_H-6yGc}%Z9MjMI z<;;qsS)QKPFCO;~lVo?UFJVWIYx9QIysehOd~4zOM!NXTi;NdaKCU!APdA^**LZUG zj;8T{x*LDS(d+X#nk`=F%d7Z$L3z8re^`r;xc2Skt|QLd$AO=7>^^UBRCynZS+)PT zJl$U}#rE>jeHL4~ik2nCqxAwOc^cfBcARHj^bVi9&C&_ac*&}}bLOw-1z%eQpU2(C z?j*Tnvf1P>&o86*b%4Zea;!t^Zd{GgrfJrHsgX3tQoOy_ue@v*#>?dX9^o#VFSbwO z<3=aX-fs1o6R}#nhLHQrA8Gq+j2=eK6(Qe-E#E^0Z8D zke`>QefJT;dVHzR(Zu(%C9HRuwYC>1LemXN%9YZCk^6UA@2H#E;+Zxj2nxAD&~* zcKfyS>>pQ^eV-+Pcz!L(`8c}dpMiAF7X{tK9B;FBxifdn8hthUd~VD`_nh$A`5oNu z4cl}w+18)SH~tk^_UhxwuBIcyK366RUo1%9o|x$$59{OU{(14gx>xIUXCIz_KMcMu z-aqow;<5@y?`Gb8-A5mj;;l-6y8G}_TH!0o!4pj<@)^R8ksOxJW%Nl8FCq%Ysf2QJ zW1oqCbl$1;x|TEpR37O3BRX1tUmv4uJ2tDK&Pb{QYPYwsuIsCv&Nu zvN^5WuasBwr-eGO%jng*UlRNCX+HY+Qg>!6l-%UB8~C>;vl*&=$CK-S6RJ%S->D*P z!KbVNyB52G+pglp9bFkZLk_OLJ`t7C7_P^9eMZu595wM=y1&T4i5D<&P43}#CKp>z z)KLj?U&$+di{8R+H{BWY`A(no@;0ho(d45MhSA|&K~Cf5wb_)H<7Pokx=+<+K`-{$ zIfkUZZg>~b+3m7eyg#>po7Zlqa2LNXoX&Y)bZfWB%gs}2tiNu4If`edlZ0VoK5<5Z@kI-6;;w$q;Kn&YBm3I+r@Df-Oexdc)wV0-vU0_?%K)fz8R&(?e+bz zt41H=ah_L`+>Vd=iqU68o@e&U_(S@9dHYNhErVxvcMj(=GNMs`j?m=he~7Go`>f~l zC>WEf+HOb7@DR^$)9dqf*Pgt?^*Ok2=Du{gjeC85es4bxGPC$J*^Je4*NpM;X|$kE z(cW85=lNknTd>}d__*fF)7UAp%k&y{lNGhb{^=rj)%?@mzUFxNf5Q7SySs(2SIA^JL9lP-~ow&-3&A zIzK%n=TX-s^L7{9X2W{vkTD^(79x~;{CJsk+x>WbolMm6>3MX|j+;32V2$^dXf)rttI^0BzpQtK@x1%|S~cU%;UEdMi^j;pw`MD4Wg7p?ao5NNvsYMU_I9o2->XA=)7IB&(TT&&`h5~IkUe{+3a-^ z^l|S0EY4f^cv@babJ%|a{d{U|oJFyAh$%iY06Ob+m2fy!vp+=>0Hx#p6wIjEt|F6C zQy=Po38|$e6vDU8Ta_h;mOU{5>g&5gXgEc)KQ$8o#hd>1=rdc6kL%r&tv_VF=tZ(7 zciy_4Zx)y|0M1$8Kf1X3)J)W$k_mw7{!0Z+t2X+SQn&+K0B}GGfVZS0ao&-b-;XD8 z=aMZ(`|BOH1VGv|{eA+xPkkDyBZ1u_F~^dBVP0P2(9SwqWGPa)gGzSt?s-CsY(XKb zSecDOdpl!MvvO7Hpn`l7Ju`(oFx0HwJHf8aBt+Kz7{CleKEKXiKcFzzP6-Dmy2@S? zbQ_ciCx(-y)xaY_Id+RQ0Lkut%Z;#NOBx9m$;?G1FTHzq^6uF*w6i-c(iEx8K}vsr zpZw&N`DtI6@2<)nP?Ax^83yj4SF-mD%SDnij6{M#+DPVj-iq95(=a<;*GNf*+T%78 zX6mBr!d`k?N8}7czFtm9f7Yp|2X|lNOraaNSHQtyvK@;JRO}<{#1nLR7be*xOho0~ z_4woy-tkG;Wz(=?E86N`l@cBA|F0i^W6PgwMLyi;oiC8g7S!gQEAs_~++laVuq7Mr zzs!xW6BTRI8A$yYJ9(X$hM1kbGBwzr*X!@%0dqkq6iE^VSgonbz5*o(mdp#FCUz$} z1i}Z|EbK^NyS?V9kQ;Vqh{V?`h#Vuy2}qKm()t9E`=EyB5}O@$aF~5PeZr36n?xL_giL~e8$ahs zJ;pBZyRS&vk8PD2;XT*ud_miPd`a7^AAh92=YgHQEzv!`1ta^yLwjx4z62NhsL%Z<2vUT~r4k5ahSjwe~l%9iRab^cvz#>#RG6bV`w3`JB zJ^_&ByLR&FxBYAKrh0dXw{zq7(g;u z2$&0Kqqt_zeo1mFO^OnK_CY!^2|G67ZMN$7xO|L#m7m!CXZ)sNl^Sqor!W!IP{K5< z_%|j1Qawft*ZO(^6mm*#kVw0kFJ#5Ez;vk3IvkPY{jr$ zz>ErlAj&W<#9aS9`fO~xY0e&S=AyLmFt|2Ssqf@7&^?QaVWe_@1j4`^zlB&3Ov{}c z7}AF}Z+0Ltw7d*N)Bo#!jSp0q6r{jPrOEL3>TNEwxJamv1zC7?^BIG}6t8_BOytPA z!BK;V4gw1D(I`bP()$F`z*3?H;C;GYjF(9zF?7S&@{X+r9Piimk`8#J$E6%_E1M3_ z5qiujq%s$^`I2{kOk-QW?uR+a&ja>m=YH?#_qpe%uoGwR&MGEzjcu#`y5uMC&NNmp zD9V@mT4t*$DY6|a*@Csebw{}?xetO6ka9M&Glvw+aiT`>;_6~7N~}~(!J=USi;XY> z-l_8(OrMInc7dQE?sbcXVK#7+jVmf6Cznl>R1?) z6!LvPXAwzk$Zga~7w(^o3+4Hd5^l@Vq`0yWR1hX`Ws#x0mQ^maZfZ9n#D?dTrh#?W z-26q&60$}pyUc|}5HywMH6Mx`U}4})!3JQ{*}%|uobB=dXRT+$ny#{G7&C|6gOH(y z+wE1(6Eeqtvf0rX-a!!;id?3FS0>V*d(rr}O?7og>dz%W z^ygBF`~C2XTis*7^zkMB4(J_f#53r8<0jRz*64;~>PI^Li3IvUpAV?5Mj z-&W%B{ZhlbuWz=f&$i-$OT#>|DI+Z`h^#|dD967yc&}uD3lk%hK7CE@vpkipjo1>a zV%yx|BO4zz!$Lp=ETzjpO4v$pu3ZkGF{tWevrCb1C`xraz4!C+i!lyr^F35t$L$`U z0?8_WR-_Ax#FCpKUP-?Q|SsUjA^IVb4s$d;SR}*K^+QO;@sxSLryk#VNGY zQ;Po3I+Rrdu`7_0cVg3_Y4Ks1!U*iGNk9h6Fs*(hjG7F`2(RBF1&lX_mjv8MeX2L$50d5F-egy zk1Vpzv-=p91+yJ>jj$vXx01S|&qAI-SZEA%0g&s@bwKLM%t^!*jH$Uqq~_oH_} zjx9V~F~1)-P5=buz!YFTZc1W3ZsCA`^WSUpq~dJLaC3I=aEuDG@k%&&W!hJXXJ1dZ zfgeGl@c|3a_^@IRTmU=&elHhEaM95ewC7=si;HYV1w$kKyWwNaQ#B#;?{<+cY{?lq zjAwS6_WarZ8ckr&@K!*o=Nkvv@*m6I5k=9C^fQ9fS0L*jMlO z`sT>&IiT%VDzkS~<)16EVWGimziK>`9MQbvGh29(3nU1}FXevA1c>49Y%M)(uEm-h zV-WZCGMx}x>UDrLULz&FFTnkLZ0vqMdj36r@QMMC3e8dSXuzyAMR#&~@P5759i%oM zk)~r8VuozBC~NQiH&fL-k}NYA{8LnJZVz`l3^6NZ*Pjb zE@}dtNEa*@K=NHb|2kU~ZU!e)r>xHPF5Di!23|B7_6z&vvO`SPd&uZ>l5ZYxC#N4g z`o`Ikmpwm-gtLj{E=qXqsgUPw>U)TfXYTE|E||h1#~`!WsHsCN80p%7+@b~Dh%VoQ zyl!Eg@10~F5IN@a)+pvlwh!^MM1lmQU>;JY^dJq9OlPD3ir$SlEUyRF9cdubh!ir{ z>ok~;#;~*SR-#C+QyuGgc}@CtI$-lJXY4skHpG!3fBfYs-}|`DI>UM!j#r{W9g zA0UXhhlE*#k$54IdJ0=Z^GnB7&J#n8F$0M}ECQXhlA2#JlGL}QLkh_vdb4Ms9IE-d zYEqBniGwW*34&2;q*!D&Na4GcT9TN=eXNL>MAyH<#=e{lC((;4tq z?}t7=(mX}xi|`klfAX;(%|-90A}^85)BbUd(Z74@bgLK*nAJFEQErsyd*t%ZMGmi@90Kv(v@)L z;P<>^;D7YaemF5}`}rR3_ea-ZD;E7T9s^etTkgw$Y_r3XJi{4=hN3KCWm}r zc3#haJSbRZTUXH9kjlR1szxBklXo`@K@wkd9D@)TgSrHglIY~Igcf{nA44Q=PS71^ zIOeD$r~q->%#Fqd>z;o0KumGaKNUZf~Z zPU2KW*jy4L*Le4-^WdrSJ~b&4TGveKPe*FCW8#JC? zqp5QHfgwX)R6KIxZqO7UlP_6$HC>x=h~!Qzqj*LPOj7G>hE$Q_Ja?l!b0G`7gq3l` z?ktukr@nePt`izv--WUm2*yG1)`_lnq4G6Pj9qMBX15|;9%^+XP+wepUAd9D#L^0X zTzl~ef)sYSp1W!yj~lYw#G-4fb#`#1*&?Tcc!&89Y25XvyYL{zyIGN zueeIT%nuBwC+80DUTaBD(2HBj6GPU?`+Bv0{?;ET@t5Y&sTe+w^`DoE|HJ1c|HS0S zJ{#sGpM>#0pFa)n>CU_7&t7{CY-##`c1a?n1lmO3oOb(kQ`Z;wo?C%oPCaGL9oe`f zCNofE;JX5*uoE~Cu9} zA$XbqdADgZr@-y85`inP_E>R3!J66NTVGNQI)moV14KEE6Bude?edrszyZ;tke%X(iK zJuj032i0rkQIpVXr}V1l&veBmew_Qnuo94j5tJ`&SyMV~=2$RHPisn5z6**8u&Bx0 zI~cBXZ*u}SmJr2+4E#=cZfnjl!Ox_kJ`mhx4_-# zNxFr;zfd4o-(O@m3c>gNee;L!HT{Qs-XB~<=dUsb#kpWE>Okqyv@FI zmLFciJEnPl{8LXU@+Hyv7jVP7vtjI7aS!9{>`B*gA`&C=Hlvb%Ik@F>r1qlMV-*XC zx;juS=7|z9iRuKB{25dlqe@Z=!k#5L`T&BQRuWA{9YYCPTp7rGZz~a?K{JtVYe|p{ zA$28oYiJ#5OAEkoPzZsX4;rw=Mqiz!YZad=N2tB~d(~i&m)CO8Z6iHirt~Vn2FxT1 zbUYW8br0GMbUY7#e>A}!528ODcJin*DEc#IeeUyHH>i>q0}_sprCpSN3bL=kee5 zsIbhx`Ma)vERbv{$U21VGqfQuXJAFVYyxi7zHRUuZfiFp>}f9ZGQim@R8XMwNF!Cx zLunvrjS9q&(_xX?kY8;i8bb6s)v;VLFNn;7l}Crj)L&G8`OYb?ul>FSzXQQMekc3j z>qYu@Lm^j4zYbS}yWQ9M;9h86YiJxts@E;(pj&*$^&Ut5?!`wfA^padUv1$x4mn7Y z^_DH(RtVU<;yx0oZ%cEjV;Dk^IzoD+wWeV__T~wUg5;XgLdM7yftns)Z=kRzGZ#n9 zCu*@-s+1#tRlB&op62n`J-F1FrR9Cj6o=?_pNvS=i_0L>UH_ezaM#KuSpjJhW;6cf-f~Tx;Se%I?RdS7<3MX zbgeMQ(`gzzh&clX|Gs`4zX?XM%4#I9ROjIK*Rw}u7N8=}9F#jmus1yhw#exoQjP>; zNEruz_8|mqnT>>^)#Eyja&f;mANm?7PHk8+Bn$^5L)bbm&#(5Nd&5$X*NYx6((8+_ z|38k`9)?_``tLEyhB1n>hDTNMpJQZB>;E-I&yj2#BWkTcY>!mVnA&G8~J$r@MulL>;5Fitk)p%V!K@74^%RgaI*>tzIbeqKiZGNE}Nhdm^iXK!jB$;|$Le*SQs>+3qsXbmU*eLnYWL8u++T2M^~9Fl8S zY5#$k+rn~m47t8?{eFZ*ddxFoD`SpiO<`n?L8Ts&R&2}k_kFC6|GD1BjacJsE;P5nzujl*9vUb>(2vDuzzsEmF&kKGUWLGFB+%D zko&=>QrI?v1ud>&u4)$*gwaAG6w&>>UazrYIc?KD!laoOibBHfP*@gH#6i*u9Jt!u zi=5c8`4Zf99je~BQSRB&yx;_XpE{}Q5qgMwy|DtS9ada?uiJsc{MVXYevdDWL^@aO z^k?kx_hVX%cGZuT{aCBnG*HYz-?gAfxPFvJsO2d|+$B+t5^`M-kTC_iUbJLJ2nk);H~vm;*4k(xNIh%tf%h#0WQ0w)$uobtq6?NEIJl+S8t}_9+4V*Y|U4Lv#r6w)nnidxuWxp`>044|MR&mxzhqt zlw@xdGUAmrfZnx8)<3{0=1))%3W`uCiU5|R z#Us=D2h$~(S`QtAchmkNU+aA_S=vAby{Y0_Z~Eo`4~#^AarTcV<&T~>)_UH$TpaCs z=Q^eN>5x5+TKNeH=YDzQ0c04feCtLs3vK3Ml~Slxf!pl%x;JlBC{E+)=WAppwoZSG zsM?pt-i3^~Sl;$$UIhJbr*mDulX|}d5?-~A5LO}uts`{5`5kY`PkoAa>>lcRMUmbA z)Vm(@`-_8rr0X^KbI%?7{H|Uid39(jGpe$PO39o%Tu3p-zM`DpbBxD3jOqn;Q0|gw z^BLZ2XPzi)F0xCgbiE!zB>Oq^ot_60S5y%Y@eB)Dqm$%;gOmpw@jiz}=Q9XIW9j^6 zHh-IF-EAwN)cjZ1Ay_MV-3vv+Wj&9}&yRmU;X4L@eAh1rU&@M>x$zSp22Fd#tNaOu zoKD|!iBumqwEnGgJJiZCAeCbm8Fvv$iwYxz(mbxkvm3R|Cl%(|EnX~7S(qV{K$QAe zG1~@R#}_eeTZ1Zdrq?Vf@_n$%0xXydRr3NO)u%u1A|ts4F$riny*Zxw;4VnZww3aN-Y(@Kzf;_4bu^~{C+Jaa0m!)nk6iOy?fqw81#sHJ_Ti?pkgM;`d! zI>5hU@!-a}OQY;jv&kQvIGg;5A?Y_>dcEiI&)RwL8}fJUeAjf8;ekv&jQB$DZxRW* znaWLIWHZ!ek)x!}(K9SFoj(!+DbWWAV42l_r~u64-Hr%`K$%}CHs1AjePD!vvHI}u zin&;MsN??!%*gn>yrwQTE4Sc!{ZT0DJ?V@W99<(v==vMCQ7b;hQnE0~nGX$8ea$eN z>pTPsj$vydkZD1Mm3TITNBwZD>xWx~mYNsNi@v@*efSQHM}6e{%M*1@@>4%}aO%H* z+QN@l@p}$>PtZ61Qel$E{Qc1@HVm1@yMyb7fI*}X&k0eJV9XU(R)}P_)|wK?lyNCN z)E2qdd$rNp2z&xs_%o8m;;=h~H50)>g}WA?VN z#eoT3$73nl^j=#Ji`=)PP>gvQH$8endai& zz-zSr?A|r5%|!33+VsAZ-p9qGzNYr=>+Eq&bAbO_4on`gOxJKX2#Yb@O6FozrwDW& zPnaz;hZe@kPe?XKy4I%ie4+C=7f#QbZ#!5_4|c?LzJ>00cCbZ0)ZG%}i3st3-#P!6 zIqq|iNb6Rq?rL}&jZ#ed_?-RnTSdNetLjlRbpB|+>=dv(~x?f0Ef8w=#fN*!X8QhdXO~E@P9DU}tp&?mNPm zAsv4OB%@J{o`fEcK3};xgRY@5rgCMEH>)twJ`Ii2dG)Q)@z%6|a`~Qn{(65v@xR{E ze#|CX$5t#PB7N?CYh6u>`J$>`vzMjl`{tNNLr(Avegt+~vum5ToRcbKxPaU%IhQ0=y{i!?mukY7Q zk1LDtyPx2@M&G3a&I|hH6eLDxf72m_$yloxk`|^>N^Oufjxz*t=7EwNMd<>hL zjLZchpmW#ADbkQAgM#3Rtx_IIMeUZ`Ao}atXSi~dv^DQ#YW_6ZrDN3Bg3}P)-<2mM z!g%xP%REGaAuRIoSP&cTe2)~dF}kj7712-U7TAc5R_QgQQ5wc$V?<;de{5b0ih4ZJ zd4>C>$91XkMC;(>`6v@WDE=0_j<$v4=YyQmchsDAw|!|VI8 zKM%UnPupU_zD>3tGL&Bj5-1nxYt zg&f9lQZ&fDSRne`4WriVy`9NDKYRDxTzf$Y5|J&lKHlln91eXyi?8DymH+A>4-H6< z!5?qbkM2;?hyQ^OV`V&i%bF{6^tZ;NJ!gv_-BRawuk2UYGIOGuwXjd2WW zf@+B)sXQVLiqv~MAuPhLyJ zci#D@FX_h<_8NiP@A>81SKl)vm<@u&=-4BRqt7-%NT7|Pe^&&S?kCcH4mOghE}pqC zn#@7T$wL=@(fuMu?+@qtd+@;z`%^cD2S@GKCE)xtE4ZNI>O$IJD8!7ahK)Wl1kz7> zFY4ELrae=3lr3!K-;t2|b1wRR!~S#nI6nWr-~X)xW-B5xSD^gQeF?gqSTTY$N@ZsXiG!2xs^&Q;?V1MSnbesmsMd zG&gy8e|H}>1&v=STZJ)y=mdQpH4V?^(k;@%BB|MIoHK}P$CbH9q^JWd^-oYCT#e^q z+7G5okst@R%~z0^uS0FEp2jx+ znxV`E(HvYFI#E)WGiefnt@n^vPJl9vSB^bs#|X8i)>wONT8%9|H`gS(o?M8)FZ0i7 ze{x%S(be7G)i~|-a)d{t1{u;Z0r$A&4}3f=|LA3tUmx_Ne>Kj_zjY)2U-czYEt`Bi zqd7r}#WMmaje4J^57E`5%It*W0dJXOw`qb9_XD|p$|yoYUJ(eD(8yT2t-0vy-SRe@ zRc~rPw1fa^fi1ml0KH}MJ95D<$ZG!e7>yI zD}^Ce5_w%LyCT>Z%}i9X`hfcAi7exBzQM|wg7BJ!$~h65%Qs*1L+bx6CCQI&pmo_l`ZxJg z{}^;XUlGqqYZ;B9)7z5%;`4%54l_1DcK;f91ZxwgDkg z2o3@KvC9(UM!Ayqudgp(h5z9xW-6=Dw}(r|h6j#@MSkbSBR>4o=h^eg^G`qS;71vITW z{wYo%kZ2f*t_UPS2wF0?pE*{M?UiqcE5Y12&3t)1`K466%+B1l6^MLJTVq8rIl7Qh z+On*V&$il?4&Y@bP&+;7Z=>p+mja#A|@y;fpy@T{EeE ze9k|8PS8E{rTY(ue;fARpSmrJw>~T6lHJ+Li5-l^BoH-OQb~(dOKhkNtFPN0UQSf9 zFWQ<18f6D}WDfWcpXeIIP(H=lc&m2>lrcUMD6X($Ya$#fogr-pR@pf3k37{$-04#dW=;lG|9B z2}P2x+um~?XT-SA3UDD(IB4^|dvByWngni}Ioj(Jf;G8tg)lO7ZXP1FI$7-k$C51_ zWzC#;@LkzL=Z#mLH}?Hvab)TI2>tRczK34_%KLuzUZ4NY!@u+O`*&{rog4nt?~MPf zcl>%O^A(Nqe@UoF((4+h-DSwP(}G2wLlWf+`|2W*W4cjGyXBmNJ`7sp5Rp0uN6z|; z5Q|X>1&hHUk}<5rbEv&Pz|pKTQTEU@5D3qPT62*|v{cxObkKt$gQ3<;i6CgM%o2kv zm~GkE&KOA6*G>CcF}lt*ID_B>t5{ua_0s2;S|{3Re|;Z{KJOMe8u0UPFG{u|-<}@b zQ})QKNzBh)#g~2mWWiGh+B1=Hs`F<0)gM~x;!EhqQTFiZ)M6xAulKo7Gk4JJ^xo{x zA{mW(e92%d9=b|HdwhA+RM~Gmweo)JPkJu;Ir*nIL}SRHZ9U@GA0FM~b^5Ifd}C4f z(|a{&f8~oJ$_35TiXa)0h*1*d7ay_^CA^rS+VK#;x39#T^n^pD3=^v|~h0Eo>Lr4nsO4 zCAafQda;G|?8ADu6p!~1X3SLBt>ZehyShQgfALz+Yp+vDiEaQ-{k*E?XI_Wco_GHr zaJe6^e*UFc%`4>)NzmMWyHb_*xceph+Ki71u>`?$x66;V?#)ZACB2c=1J_X*UA4Dn zf#S=WjM$NcZS z=v?PdkK~X4nwP_x9oBTe_J^2D|2q%*f1Zv2w>C_UUY#A04%O4eUiS_|bzAQ>=h( zs`I^}j(j&VB>FnC=F9hoANISiWkr7Z=ilCHgZ=4m9`fCMsENngi_RTXdbdQee;Fd_ z7$cTZVL3gP7K}`!(0&ui1Y@&0ns0SK_87*tl9tvw-EroH^~Y*Ctv#JHRt zyNbT=Jz>2E;m60(Wx9{Cd(^uB)6e|Z1NnVs!*?G4>v=BwyrcY&zNZzHe}o(`S;Zt< ztRm~YP%OvEb&CaYaREPGNUD4CBcAXiJvh?Hf(h)?f?y=x4l&8Ubj}V+UHj*&dQF9N zP`h(xZ64Wh>f@4{Og+!6~nZ_C<2irVJ~KQ!qTD&3TbI!iX?jh)>>LDH7R& zsPrw2n2SY52+?^LtaaY6e}KJ%-3>!9RNcnfv=cwYNTo_FC<)wz2rz_o>J3n~%Xd zUlS*^XJuL;N!p-4@1_njL0p1_=(+I+{O#?`mO$KDbqzq&>?VzcSky<>nNGe`HbzE- zmArFZL)SjpgtY(J&$&4nRHRmnRIg8x(dde??%T5aKJ*nH?oZ=Ue}8ZP)JO06ug6N? zTbusrng7uberx;*UxJj&d1Vn>q#jQ_9ZT>ZeW2$=*nSQi@wncZR)61>we$+*fy^Ql zU6_5}y~|&1K=YmLsW4mIj@O$$5779Qa?O`}{)np42wVd;7KFWis9?|!dkl7&dep$~ ztYr7cKDhJ$T|a%)e|3KPSF0RNi)`r>jS))bQD}Ty>Ry%_hn3hkQJ$hjm^|vK35|^# zjpR+|5JaRdmd@9Ze>lgB6tUKBP{hdPJw>S1+?f5;PfPRqlw?;M7j<7(&^&<5N0#pY z_)w_lcah4_f9sJ0-+k0j7T@Pc{M4l$y4%pFpFTWEKm7PRf0wCHE1ZA&afcd==2FA; zlJ}k(%`vVUC0Xt+CR8CJ^XUHE12#> zO{mmo0M$#~lj(qTX>`qq%;t8hTv+mm_S|#u5JJ?*&myHDt};c9jlr}LD3>lo-D8F1 z*Y{G|KhM`5f4Ybu*en|aR|gbxNpvh7$X!rkx0c2X1M%>9vAk$qt*;LnLw#^#LDu^Y z>p_QU^|?m;PwncbcA>|pq=kilJug4C!J&spg_1XRAJ@+8u z9k_16oOHqe;6p#=iVL!Ls=Q<{^uNCsSxD6NYRmlKf2!0a%3Qol!$UIjMU{lXZ{$Pm3;1x{hkb@7ck2T z@b6g#+LPX&0f=OuNBx&xKLe9Ne-0j7jiRlTq1V&kn*pVLGays#X$X*Nd{DW~_GaMRb*)P4 ze?O@a3hf>4`P*IB_a?f|X!m;k8OdI+|LFnNxk8}W_}6pws|5^LnU8zC?ARZlG}Cqb z!TUCh!-`7h(`i|PVrbmuH3dm*+qjZYGJo(iH#n40U@MNO*95i};-U61YCmnABi?mW zqtv~yAyU@L)%lbVA`+M5TBZlAy$pi;e<)%R5{>>F;mC5<%k>s1;^A0&IC?u~D*JRG zbsTK4?DYS%_iasz>&lw%C*u5vo)xhp_MTo6hY}R$7HmV*zlYTjTdD_0$aXs+D{m_C&svjHOya!xBUIRFQBwNvjgws-A1LR zjAz1Yd%xS0H~_d-@b~YcZ)?xoS!|S<%gl~HZcWuXaAvz;j}2j>-%kUAXbg(llJTdE z*l&=eNfOzXG48`+TcRbrNluGt=Z+fp{AO_YW+WR1*CW7BTK8dicJ|61D!`KYVX1nZ}_= z_YKG}XNRyf2-}%dJhC3cMNo^8Xb7R|n~rc;kOYRqEC#BLD+w7@f0)zJ!!98)#>u6z zd|%j~_aAJHPhubW8+fzZkY#y-;N&bcZ0*qAALrG&rasj>?vRSuB!Xewo354!8E2|R zToZ!9OHEt4gu89c;U?~r1NTkl0Q#(JBuN4@vD-LL(ZI6^F;|St9Lih_Y=h^UXoo>w zh4F%i^jL11`U5D(e?7r;eRGI6dU}@Bfmt(D>O>Db;`J&HBxbb@={eDJ;4L!tv=Oh9 zhiyV8_#Q$Pls`APY`2{}Q-7837^!dZ;a&RDmUDl8x5sj&x!^bMS#L+T?o)eEtHUtC zeO8gic{s&Km7eVPEYm##Z%R&Lyfj}Fjl$Su)b9e9_7yFfe=xNL`U~*5MbXw(v>LEr z6gu40c|=G64Mv!b@e*p=3TfjWk;Bjq!+@EemP^zK3?s^=-lPB7DK7a3eY=d)lJ`Ya zC$DOyttB;$`%L4Ny4W^qgjZ~s`VE8lk9s1snuz*@^R*>xT^F-S8s~6Es!-El#_)(4 z?L6S%mm}j7f4VTa+`OlJ`L(*DCXNs${Ko=Y)lH!_2h zxMPJqX7!KpaYi$3YqzO4!?;ErT_kl-o=upzGe+zhLI0dUaJuz0*m{rHPGhLe(VoXk z@CXRwWxD(Q)VIBmyjd+SX&xiFLBId7b!uNFvz} z-K3_%NKO5%asEx$VZ_FFr^H)9c<@1e^RwO^Y%O6R77*I={?=}_Un>KKd+~{=Ua+ydTTcTG{>3das1(zp1gB|I&Fp&`sojWUlp zrf)hkhi;*Thag6fj;CHy>tGyFFZsVXpDtL&eER>_L0Rh{11&Hn(!M0Y_A!qA_Mx5q z$(s5T|H4N{xwNrg$8%Hq91a$}Aja4e8cAlte{g1ka$f`CQ;(ZXlJr#RFE2z*b1LD( z)J@ON5>qD$uEG5p_?TY^!c)H(GfCsGj}q`OE+e(vY0UvGT{oc}0AiT^s0Vw$SStGp z-vhZh({65$7HKeD$q8mwPav@eH12tPHg-d7Oq!z4)3ba2>=!<&e>?Y zf5jerrA-CK>JtquF<%K(UkOxj54at-SskL+M;Uiq#-o$|P90otbQ5T-71-3a9OFCf z&q?08s~wX-3>O;dR^Oao?I0HkRYs z8gbXMH_(XMIg>oe|qa#7pI#WqP&oM}R!4=Kh+t5Faw z)K|2(g-Heda5RZC2m9N%eHJs<3``jZ#+K_+InFyQaQnwNoc3`Z>dL(dykDm6e%m=d?8ygau$SXDHCd$#86&37!Maa)g*R+s|>mbspOMLyPTfcy%H<*z*p29{9-HN=(~Y&beCVx;@%}b#`WwOJ9lAi$2EQDIYgc( zu!XKhk9D+9MxE<;kKvL(GR{IaML%Teqx{uNR16(xNM9S_QNq#gId0Sde{GyaU1mP) zLv)xRLe=1@v|~wZYS8luPfWVCb>i3-1$^OfZ3=Oh3~izXt|iZ(IL5Cq(FR)AFs>Bv zCQZK%a*V&g?B9yN@M(O7ExSy=5?|r*sUS|`E6BdZ{is><2Ty(R$d>n#;P_nnW^5Td z#N44|_9XYLPkd^dCpPbAe|~o7aTL-xJJKFr#!IN;c(lddUSWD}udvshqy2BkPVH{R z-Ufc^pT{pr?HUd-i53kodxU##joM2q7#WvwN~${$9P9B|e!=zj|h%wn#FQ_N5cFSr@Y&1(!a6%c{68=CF|Ge~TDLUz6`UOL~aY zBKPOL$BS6tsa;~Yw?)KQkZ-md_M7cSv*YDtJg<}n{g4-Js??jEN&~n{bY=GH1Wae! zSsR4Ob(l$C2E&44)IS^t-0#nzyO_*kKn5bJv1gy=uOBRmZB#6_>BYqP? z%f-`G$-c1v=ucOPf1_giY8rdgxFYeUA@RmWyPh_hFpU5j>%1c#b(RoeAL38!Y{Zch z8y~%EKc;qkC%(w&SG}{-xHQ|7c6h~jBxuKEFHYl6;(9(!^U>D&Xy3PwkCvXr^VEkG zZT+ISkGf(|)*gVblf>-R0+r%g1g620hPDGewFmpuse?pIzE@sV^^q=Ik)vGi? zn9ax68AVKjKpnRdv)kgcI@vOn3Qh+QNgu~nVAdEnpW5J)qg{}W-wZI@9Z}b|U^cqA zXRJ?->HY-Ytsey=R7-wP0&UuvRVXm>C~AvVFl*2xY0w~QK*7{n(|DkRg7CBdiXYg{2t0e zuH9$K3~lQ%^e6838rukM=ES2wze8_?!;1w1_u&n*!yhTknp(mMY`N$nHcc<}*sXVW z-~#T4IQSXx3dwKP5Q4a2bxlsA628xkkN${B9lTPDe+IC%L^OiXoB$VfouCb2#chWJ zrbAO4Xem+TnVbi<>rn5j!R;Dxz}0yr-G`UBmS8;Tk=%z*zsJx$`yRtS-oznh_W8Fn z@V(}6{__?ydU5IdEBzl&>0kGI^|()yuIXeuH)_?9;jHTejAgrx8#LhEI$`Nt$Ya)V zXDuR3e~#~GRLsHVNwevS1|+jajhLLl8y!b~A?nPgI1*(?`N)z`CF`qA5(1Dz)pk>@|GPC4(Iw7VzC>xaMpp%~t{*Yk@N- zwV2JJQzq?LZzcUM+9p3HBa^(^wQ=$^rEF&UNw}d+wNAuLp`NH$lIJ;H&#Zc~{z0pW z&Bbn`b=2lC$-io$-ST;PrR9`%lsuG~5%KC)SD5d2ET`eHt=XM9ZE0{BZaX`@e;M`I z){XRD)Y}qotS@+f6Zn>%Hy_K}fE#t@6@&T27}!H?`y3fRyx~Kzel$w9Zv@*-&4w`x z@{?NVPL@IWp_XS)6X#)W5><3}q>T!(qT1H%peLO%G5shgQL|}IS?GoJg89P^3$$sP zMSGg-IE{KknYY8fs6WMv-fpz6e;3%YvJ>-$Zbp+``1SDhJJ}!gAH{0B{-nLW<^U>M z39kLLhibbrf{@{PRoZFdEv*DHh5~;04%ZT<{Dj`CASIw2?e3`maM{Hoc{$j$|}*iXul}?Yc+Z>5;6o)c&N4?VhGv3A1{9# zaBYJvBF9-2(HDGdCNvZcoB)Xmu$8fz&VKmjqrEWD;_?Y!*BIynEF6WInb_jtRX`v8 zCR?rmpzTLt1K|02C<`I|;{j49Td6!7kijCL1+@x9e?TLw?*`Zwras*! zmIdpG7I@2rqR#sDUvm$o@DPgOE0Qy)c2W7i_q|z(G@Q z*9?sv3t}LH7>H&nogJ2k=Lxk&Kr9O*%z5h=%-GzqsoBXVuuH_ivNfH!z-O(5DYozo zLSt^aTxo3Uys5=d*LpP}Vo0WV&GY&!28U1Z%M_xnd90C`e|^_CM?ksK!f(A09wY*3 zO{KA83F~4R%rbzh2lM{O?BkNyW9B*r9>-v>V$#$4)DFy@k?6Cg_D1W(VnAt<=rkd8 zFpNV%G`FdHNvxide@;Ae#PS4kSG8n9YczMG1 z^=w#{S=R)9-pTx7j^sCc_WBjaSH=Qv{s^Z-6X?X)&RPt7?opzLVG}*)(8FH#8IVn4 z>%@yGjIeI~4)!bY2E9cBJ9p~2&Y=v=&v|x|e>(Dkl+ST2fL8A`1BZ2R_FBiF%JFY1 zjaLo#xs@L8Q#LYp`k)cAbqtj_#%=x)nRzZ>#{^=OkCC=DrP+`=gV(zz?T>(S<%iTm z(*nNNAIG8?*}J}oL7$qIU|_TwX5L7c+Z3kxEKCa=Q!%I32s##9yM2qX0dod*3z~yY ze^a$a(6!jw>9ckBkY?<3Oz-Z~UCUy?X3bvTVjVWae${DA*s4DQKs~FwjjfiLbG~96 z!XAx*^`$=Sdc1Ejg1Un3$D&cj%2&KrqW2DZ)|lCtJsWJ#!mK0AKOds#Os*& zam-n-vCAh0-EARoSJnsymc_I*J&I$_)AZeLOB|W*TNX3YbR~|tFVkz`ZcB+we}A$p zR+s5Cji^cX(@q6CNahu!P=s> zz%OXXHZ8-#Lw%vPuvS3)AP&slY#n3pS_|5ZG6R_P+`a`JQ!#}zf)=)ihGS|$DDK`t z-^dw65FiZrtkLi+=2E&z!d*Nvf9J@H#W4qg^)tiW7CM0Sn_3p5CdK;kIOeuYuXlD^ zLS_2GvY4KxWBYnCy+L0QG#<5@mNdF zy*Tz_s{X*a)TX<{+HDdG@k?WfUo|-{KhZNY&s1}VbGZ=C4nzz^%`4-We?*)nyl)Zk z^ttRSk2ZrAiDm!T;fW4%)o|QK0?sh8J3sKG}9olN#MWJFc|MU7=06fnSUkVmg zAKNsav}hvQ*v_BM6Ep$Vf5g7hyjQV~wHab4=%FjDkkn!T9J{pcE*jy?pE|o{VCq4L zm=*(@@|CFqXFZ)_zeaHk(2t3nZ<(AE-84_k6W}Yb_-;K9Lv?CWsDx9L7r)QbfsM0k z*33MvExajTF&kJTp^CjSE&RHOzR;CZe7lse{_a(bF*eDK7Ikg z@GLOo{C!QwaBkim)-jIe8GIT;PxJZ??_0olo{i+aj&oW+fyI@!@7O}FIncYRD@JA+ z8eADB5cU%~+n1w{`a96B;%y$LX*pU6nIX2bRSYiTHLfe@HJu@J5TxrIGBeAd;a^-k z89O`ZpOq&-EUH)*e}KM%N5mE!cckM9>(HOC3F=MtlqQB~%0oOb@}^E1%hn89G@rD? z9qMYL@0v6Qdyex;+E+#by5m_PRB)|{&yQ)?w(cC~tOG3x`w8jv>gl{RlOJUF@N{Ia zTOW^edt>fEw9QDxdEXkr!+E)%HIo+ieNSXGpuy@|8`?)5e`F9N#ye8ahl#Em$cYgl&^mpG`t$_9oU4pQu_2d zrBAO@`t*8-F=I%-e@n+G=Gi11`>AH*diafgjBDcV8+~q1 zPmc5+@~<{_N9-6&-BwmHlQ^KtGIcfyN4=@dQu;EXNIStbW%rG?Y*~yPX%j5V8|{-U zyLviizDnNVCgHNK_^t+D8)ZU}UeJ_2X6DKoQ6hOCXiXD&A8E17-8Wh$`R-2I(R7jb zf5V|&0xY*y*|!U=rS$tYF$MB|qYbg#-8b5XEXNyd9LFL~-#aZZjIzlk72WMnDUnFpt^9pneFsAWN?h*fpIn?+HW1*w{V|2Km zlK{_V<$ay6;##_qX#(B-*aEB(&C~5Qe*sowB~8`AvDgf}z`^-5)Wag4TMt-g+W^CK zd!b5!ntf|etItMp$0wn#dm9nrU}oG5roDYWV9o&daQY*6ObObds6RGPdk99rrXxmy zbzVuI8^D}j-Q@G|90Rv{PxlGZ;R)Knu`qfAHkJ3nM%iFkIZy6&NpE-cuFmO>!CT+n>l4DAz)I zj}y87%<+5A27>{RIT#8|IHoh`;k_>4F(EG0W+-nCH6MIIo^jKEz{w7D6aOxu=E4X_ zfaP%nc>zPkeSSlhQ(*aAJa67%`E4wx7VXRNi*l#}uE6s7Fyg8ekZ=Nm9=w1B({n7z*qkJSQbDSgt_=U-6vf z|GYk3D_4x|7+^bk@98&he|n>-XqOY?>Bcxo`*VopO7-q_-+y`hJCN<>rTtiwAD3() z-w`Ks*-q$>tjl)wFs^)0))(-;u&=k0@`H^$O%cSE?S^tFoal8rPDcq@Nc~7sy&qsb zjT!i;H%5Z_ru%XH`c}T0yr1pmh_pUw`P_um@lemi^RcvCn|E^Ae|x@CUvw|k^O}w6 zlHP<=FQq<1g!PR+E1xOHuZR8djOiXHA^w&1s`>l&5h-0-E`r}ZOY_Nd&PJ*?M8Wd6 z1iWB8LLc=uZC~kZqlD~mTv}*%#XOuJqW!o_5GSkzUXb3CbaH$vcyArX zEu82Jtw1*+2Da1NfB9_ttM+z2d-X@@{>YF@mo#}q=b>~H=N&3fArm}GZ2?qpN_OPA ze1cX1u7n;r@5!!=vFc+yU94d{Q|a$I#dF{~p5sy<&o`g(sIHM5&UxVl$Gy#AhxpM1 z$bshJcgj^fCv9Oo6D@%@hp*@_iXkE~&NxT^S>|Ft)TEIBe`!W(uJ~U>UTWdb=dA{=Q%oz3OoAIMFPoJ5JJ(d0_wn(QhU>}p=To#?fBTZVf6wP8i!Y5~ck=i@>|wb4vl}iZ z@t5W#`Qk*2;quRTvI?KR&%@>9E|`QOSbxji=fAHf+x1hYRk#%2 zhMRS?7xU%6|GZnocR?tEJ3m^kSHpOHHylql@%q~`T2B63xOk3M>)~?!eH5+6lhvIc z&7;*fe}A)DO_pnlHwRYfpSzdIDh{LNx8c)zvigZku@HYK_qo!2KKI83^z1(lg_e1rbx8I|e$?9nyCEtQ@Jf1ASKM%)ateNutIf}!z z6hDfi`DQ)&o`mCdfVnOt2kXWBulwaB!M6K3e-7j4`Ed7bG>`n*8|7#iPkz3!TutV~ zb@(#*o&@1~au+`j{mHjwl&pr&dntFxWHbxccZ+a&x3BpjWf8qzd3^HZOz5A7n|Qt2 ztlvr(E@elb7ZQ7S^duGLE=k*{tSD#6;W|x@*Sq=TTeu$1L;s9mwMYq`hKq2%`*zf~ ze>1B1=?Yb6xQsifglDAd^%c_Y?s<}|!u8~+GuZ!290c>L1y~2)KQ1`t4c8wOJR{$s z!YM&of-{2A)2EEDH1sH%kK^596#aTtKIAoA#H+=hXXP3FdDh{hD?-5ToYld<+NyLo z55;Qu99%TX(`q<7lYtMe8e9RCXY50pM!emKg%e>@gm=3%_P zTmL-5|9toyPre;4zF%O|dN`U-zRQ2_=EGgIS$}&9x0CS&!_^z6rKGDUIj6WtfA=Tz z`Si!gv@5Nb=Sa=XaMP-x5%V@WJuwJbks9e;;o)xV%fL z-!9V{pn4n^PbY1L3z*Lp+n*1g-z3aWZ&vf+^R=bXMaLk6zwX23aycObN-a`ef}2S zg)H8MGv4Ygywxn;>KX5wTDzFVyLiUCatrTL7Vpvt@0(h?oW;3(f6Do`)~;mnuAK3% z+|(r1Eaue{=7oFp#-XERjveKMzj~ijZz_E*du-;;_*cunSpIz0(9gdc`uCN>;dhIS ze3p#-?eLP%f`I%L2*{Q8zw#|Y)GQ(ASWx(_HY#QbIR}N}Exb!vyi4a`_FJt~&Jt3- z9eMIu=#amH4(ctuf2&!%tG|Uj`AlrczsClNJ-^ZNx$H5VyMUnE#1yiSqVOIm$~iS( zDVB3;;T9SBEE)MTG%6mX+#;ipC8KaV8WpmDqHqN$4lR_g-Xf%!CFC3^@^6iFi;z;5 zkaNU1RHRb6MMybINcl|2?`c#eOUOBRD8Hpr)hr?BD592rf2X-VLzBXLG|AsrOTVLE zx$JSCI|Hp^@wR?Zv(Q9+k0zyj@fPO!Eaqo0Qof0IA&Yn645Dshu4XY;Z^tGz3pUg% zu#vm1!An`(&++0m=H)Er<=F-u1AcH}8$VMFl>Hss!Zw+Ja`2`T@rceG*_SQM{-#Z9_e&Ej1><6X_)G}x5P z(RL0N1x4NeZW5C{sB>px%B9=Hl(L|sbOkzYVV%!ne|?S^x3Df`u|5ZiTUe`Etk3b` z7S_cq)~B#=U%iEODT{UKcEl-VfkEjC802r^UCH8ojsdr6b~TInIS7>VH}&ObC{VhF z0!sO|ahW|Z&xgPItJ^8%tZ`p{Kkn7sZPR%<3joUR0ibvb>p~XmGXN-7ZkwUXSx8WR zj|8`_e|XASkWhXP3FVvGsFcOK^mlfn%US49evb~faIR!=uKW(}l(V3rd<7bQ6?e*+ z$WVTd3=(;MqvdniBRF>fK(}>pB?~7i?{T7_mhlU~iOC+|=P;rcsuh&-%O)F2ra6^z1xVDKQc;w`uO0{OdE_&tua3bz zk3y!DGcYL>%Eeq>DXKRKQ8R^{p-G`qe=O%KN-0;qNlGzO${C=jg+f(Tl~VP#x|A}d zl+KrJ`CLg+%D;NxxaU#Mlv2I`u3|N>{4&Pxc~ml`R4$;akW-4kyae6zsAfv3UVvAw zoG;}Hw<+?chFZ!MkhzWfFO2zfY{^xtrJR~C|LXD~mu;$QZ1>af|9>Ue@Z@6 zO8x@Da>a77_{-RmZNT~7g7ZFK$rXxs=83;v%dz{0e?AuNuY+UO zX$fUbc)gme{oq2q-+TOj;CXiLL$v3W#v=Ih-Q&^ZDOydAF$#{s z34(BpuB_qw=WhuPhV!T4Y855YX=(2-_Hi99I-scB=dbaS`usDS%if*sD!0*U=udvD zRQck4?vhVBno~~sf8sxGsNp52->chsnYMRnJ3SA_Ki?ukd^tO(^v562q}%#mlrPf3 z>~zOtfrUEyYD%xUKQBanf^ef~dm-y=0e|Wr`y^v)psVZNBk*2PCyTvT;3(SOrL*?8 zH}AS5Ui-tPKbc?F>U8qmQ=r%8nR_AIs{IBmH&C_o((!qUIh*ZLN9N&xn zU|PT1GrgECQZ>OhfG^7TkH+R9?_c|fJLfFk<+>8}1!{dy>V zeh7pY4DRQXAIs=NHhaiV^PYqOddvQV`40`UA4VxqSRhPXcC=jH9+X(VjGYXPFK@d1 z?+1w(fBnaoFaLfBCd2Vx|B08FTV8$n^6zo@@+BPq*B|Kb`^R7Zei(-@fBmPVdf1cw U`$1OYKmX%@0T|SQfh($ delta 1254574 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

    WMHNiThVe^P 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

    L4loP7~WT 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�}{TMI2;%wgy}R37e$euV?Qe#wGfr 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

    BOizX*@dN*{n8e32w5>mZ1Qz7R9grD4auDf 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

  • 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

    B`) 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

      Q#Kf0@buH%V5!2_zeZBl&Y#m4EYz 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�OdlF1pVml5 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%0AJ_I6q90EhimWy4dlZD}6;+BOO`}*A6 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%0A4Nj8*UG~c)5)WNx( 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

      ; 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 z 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

      eERwc58qb#D0h14J%o2F>_rE7Y2m!+Yd(%Y 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 aFDmsd6Z_{It;WCp<9`AD&P!tH`6d9MT+bK) diff --git a/examples/server/webui/dist/index.html b/examples/server/webui/dist/index.html index e042d5cc..0b2aaa30 100644 --- a/examples/server/webui/dist/index.html +++ b/examples/server/webui/dist/index.html @@ -7,8 +7,8 @@ content="width=device-width, initial-scale=1, maximum-scale=1" /> - 🦙 llama.cpp - chat - - +`;let C0;const ou=Uv?new Uint8Array(new SharedArrayBuffer(1)):null,jv=()=>{C0||(C0=new Worker(URL.createObjectURL(new Blob([cC],{type:"text/javascript"}))))};Zt.getConfig().pyIntepreterEnabled&&jv();const fC=(e,t)=>{jv();const n=Math.random()*1e8,r={};return ou&&(ou[0]=0),{donePromise:new Promise(s=>{C0.onmessage=c=>{const{error:f,stdOutAndErr:d,running:m}=c.data;if(n===c.data.id)if(m){t();return}else s(f?f.toString():d.join(` +`))},C0.postMessage({id:n,python:e,context:r,interruptBuffer:ou})}),interrupt:()=>{console.log("Interrupting..."),console.trace(),ou&&(ou[0]=2)}}};function dC(){const{canvasData:e,setCanvasData:t}=_a(),[n,r]=Y.useState((e==null?void 0:e.content)??""),[a,l]=Y.useState(!1),[s,c]=Y.useState(""),[f,d]=Y.useState(),[m,g]=Y.useState(!1),w=async b=>{f==null||f(),l(!0),c("Loading Pyodide...");const{donePromise:_,interrupt:T}=fC(b,()=>{c("Running..."),g(Uv)});d(()=>T);const D=await _;c(D),l(!1),g(!1)};return Y.useEffect(()=>{r((e==null?void 0:e.content)??""),w((e==null?void 0:e.content)??"")},[e==null?void 0:e.content]),(e==null?void 0:e.type)!==G0.PY_INTERPRETER?null:j.jsx("div",{className:"card bg-base-200 w-full h-full shadow-xl",children:j.jsxs("div",{className:"card-body",children:[j.jsxs("div",{className:"flex justify-between items-center mb-4",children:[j.jsx("span",{className:"text-lg font-bold",children:"Python Interpreter"}),j.jsx(d7,{className:"bg-base-100",onClick:()=>t(null)})]}),j.jsxs("div",{className:"grid grid-rows-3 gap-4 h-full",children:[j.jsx("textarea",{className:"textarea textarea-bordered w-full h-full font-mono",value:n,onChange:b=>r(b.target.value)}),j.jsxs("div",{className:"font-mono flex flex-col row-span-2",children:[j.jsxs("div",{className:"flex items-center mb-2",children:[j.jsxs("button",{className:"btn btn-sm bg-base-100",onClick:()=>w(n),disabled:a,children:[j.jsx(r7,{className:"h-6 w-6"})," Run"]}),m&&j.jsxs("button",{className:"btn btn-sm bg-base-100 ml-2",onClick:()=>f==null?void 0:f(),children:[j.jsx(l7,{className:"h-6 w-6"})," Stop"]}),j.jsx("span",{className:"grow text-right text-xs",children:j.jsx(d0,{href:"https://github.com/ggerganov/llama.cpp/issues/11762",children:"Report a bug"})})]}),j.jsx("textarea",{className:"textarea textarea-bordered h-full dark-color",value:s,readOnly:!0})]})]})]})})}const hC=e=>{const[t,n]=Y.useState(null);return Y.useEffect(()=>{const r=a=>{var l;if(((l=a.data)==null?void 0:l.command)==="setText"){const s=a.data;e.setValue(s==null?void 0:s.text),s!=null&&s.context&&s.context.length>0&&n({type:"context",content:s.context}),e.focus()}};return window.addEventListener("message",r),()=>window.removeEventListener("message",r)},[e]),Y.useEffect(()=>{const r=a=>{a.key==="Escape"&&window.parent.postMessage({command:"escapePressed"},"*")};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[]),{extraContext:t,clearExtraContext:()=>n(null)}},pC="(min-width: 1024px)",o0=e=>{if(!e)return;if(!window.matchMedia(pC).matches){e.style.height="",e.style.maxHeight="";return}const n=window.getComputedStyle(e).maxHeight;e.style.maxHeight="none",e.style.height="auto",e.style.height=`${e.scrollHeight}px`,e.style.maxHeight=n};function mC(e){const[t,n]=Y.useState(e),r=Y.useRef(null);Y.useEffect(()=>{const l=r.current;l&&(typeof t=="string"&&t.length>0?(l.value=t,setTimeout(()=>o0(l),0),n("")):setTimeout(()=>o0(l),0))},[r,t]);const a=Y.useCallback(l=>{o0(l.currentTarget)},[]);return{value:()=>{var l;return((l=r.current)==null?void 0:l.value)??""},setValue:l=>{const s=r.current;s&&(s.value=l,setTimeout(()=>o0(s),0))},focus:()=>{r.current&&r.current.focus()},ref:r,onInput:a}}const lh={content(){const e=new URL(window.location.href);return e.searchParams.get("m")??e.searchParams.get("q")??""},shouldSend(){return new URL(window.location.href).searchParams.has("q")},clear(){A3(["m","q"])}};function gC(e,t){const n=Zt.filterByLeafNodeId(e,t,!0),r=[],a=new Map;for(const s of e)a.set(s.id,s);const l=s=>{let c=a.get(s);for(;c&&c.children.length!==0;)c=a.get(c.children.at(-1)??-1);return(c==null?void 0:c.id)??-1};for(const s of n){const c=a.get(s.parent??-1);if(!c)continue;const f=c.children;s.type!=="root"&&r.push({msg:s,siblingLeafNodeIds:f.map(l),siblingCurrIdx:f.indexOf(s.id)})}return r}const Xa=C3((e,t=80)=>{const n=document.getElementById("main-scroll");if(!n)return;const r=n.scrollHeight-n.scrollTop-n.clientHeight;(!e||r<50)&&setTimeout(()=>n.scrollTo({top:n.scrollHeight}),t)},80);function Oy(){const{viewingChat:e,sendMessage:t,isGenerating:n,stopGenerating:r,pendingMessages:a,canvasData:l,replaceMessageAndGenerate:s,continueMessageAndGenerate:c}=_a(),f=mC(lh.content()),{extraContext:d,clearExtraContext:m}=hC(f),g=d?[d]:void 0,[w,b]=Y.useState(-1),_=Y.useMemo(()=>e?gC(e.messages,w):[],[w,e]),T=(e==null?void 0:e.conv.id)??null,D=a[T??""];Y.useEffect(()=>{b(-1),Xa(!1,1)},[T]);const R=Oe=>{Oe&&b(Oe),Xa(!0)},U=async()=>{var C;const Oe=f.value();if(Oe.trim().length===0||n(T??""))return;f.setValue(""),Xa(!1),b(-1);const V=((C=_.at(-1))==null?void 0:C.msg.id)??null;await t(T,V,Oe,g,R)||f.setValue(Oe),m()},F=async(Oe,V)=>{e&&(b(Oe.id),Xa(!1),await s(e.conv.id,Oe.parent,V,Oe.extra,R),b(-1),Xa(!1))},oe=async Oe=>{e&&(b(Oe.parent),Xa(!1),await s(e.conv.id,Oe.parent,null,Oe.extra,R),b(-1),Xa(!1))},ie=async(Oe,V)=>{!e||!c||(b(Oe.id),Xa(!1),await c(e.conv.id,Oe.id,V,R),b(-1),Xa(!1))},K=!!l;Y.useEffect(()=>{lh.shouldSend()?U():f.focus(),lh.clear()},[f.ref]);const we=D&&!_.some(Oe=>Oe.msg.id===D.id)?[{msg:D,siblingLeafNodeIds:[],siblingCurrIdx:0,isPending:!0}]:[];return j.jsxs("div",{className:Yr({"grid lg:gap-8 grow transition-[300ms]":!0,"grid-cols-[1fr_0fr] lg:grid-cols-[1fr_1fr]":K,"grid-cols-[1fr_0fr]":!K}),children:[j.jsxs("div",{className:Yr({"flex flex-col w-full max-w-[900px] mx-auto":!0,"hidden lg:flex":K,flex:!K}),children:[j.jsxs("div",{id:"messages-list",className:"grow",children:[j.jsx("div",{className:"mt-auto flex justify-center",children:e?"":"Send a message to start"}),[..._,...we].map(Oe=>{const V=Oe.msg,C=(D==null?void 0:D.id)===V.id;return j.jsx(uC,{msg:C?D:V,siblingLeafNodeIds:Oe.siblingLeafNodeIds,siblingCurrIdx:Oe.siblingCurrIdx,onRegenerateMessage:oe,onEditMessage:F,onChangeSibling:b,isPending:C||Oe.isPending,onContinueMessage:ie},V.id)})]}),j.jsxs("div",{className:"flex flex-row items-end pt-8 pb-6 sticky bottom-0 bg-base-100",children:[j.jsx("textarea",{className:"textarea textarea-bordered w-full resize-vertical lg:resize-none lg:max-h-48 lg:overflow-y-auto",placeholder:"Type a message (Shift+Enter to add a new line)",ref:f.ref,onInput:f.onInput,onKeyDown:Oe=>{Oe.nativeEvent.isComposing||Oe.keyCode===229||Oe.key==="Enter"&&!Oe.shiftKey&&(Oe.preventDefault(),U())},id:"msg-input",dir:"auto",rows:2}),n(T??"")?j.jsx("button",{className:"btn btn-neutral ml-2",onClick:()=>r(T??""),children:"Stop"}):j.jsx("button",{className:"btn btn-primary ml-2",onClick:U,children:"Send"})]})]}),j.jsx("div",{className:"w-full sticky top-[7em] h-[calc(100vh-9em)]",children:(l==null?void 0:l.type)===G0.PY_INTERPRETER&&j.jsx(dC,{})})]})}const yC=["temperature","top_k","top_p","min_p","max_tokens"],vC=["dynatemp_range","dynatemp_exponent","typical_p","xtc_probability","xtc_threshold","top_n_sigma"],bC=["repeat_last_n","repeat_penalty","presence_penalty","frequency_penalty","dry_multiplier","dry_base","dry_allowed_length","dry_penalty_last_n"],Sl="w-4 h-4 mr-1 inline";function wC({currentConfig:e,onLoadPreset:t}){const[n,r]=Y.useState(()=>Zt.getPresets()),[a,l]=Y.useState(""),[s,c]=Y.useState(null),{showConfirm:f,showAlert:d}=Xh(),m=async()=>{if(!a.trim()){await d("Please enter a preset name");return}const b=n.find(_=>_.name===a.trim());if(b)await f(`Preset "${a}" already exists. Do you want to overwrite it?`)&&(Zt.updatePreset(b.id,e),r(Zt.getPresets()),l(""),await d("Preset updated successfully"));else{const _=Zt.savePreset(a.trim(),e);r([...n,_]),l(""),await d("Preset saved successfully")}},g=async b=>{await f(`Load preset "${b.name}"? Current settings will be replaced.`)&&(t(b.config),c(b.id))},w=async b=>{await f(`Delete preset "${b.name}"?`)&&(Zt.deletePreset(b.id),r(n.filter(_=>_.id!==b.id)),s===b.id&&c(null))};return j.jsxs("div",{className:"space-y-4",children:[j.jsxs("div",{className:"form-control",children:[j.jsx("label",{className:"label",children:j.jsx("span",{className:"label-text",children:"Save current settings as preset"})}),j.jsxs("div",{className:"join",children:[j.jsx("input",{type:"text",placeholder:"Enter preset name",className:"input input-bordered join-item flex-1",value:a,onChange:b=>l(b.target.value),onKeyPress:b=>{b.key==="Enter"&&m()}}),j.jsx("button",{className:"btn btn-primary join-item",onClick:m,children:"Save Preset"})]})]}),j.jsxs("div",{className:"form-control",children:[j.jsx("label",{className:"label",children:j.jsx("span",{className:"label-text",children:"Saved presets"})}),n.length===0?j.jsx("div",{className:"alert",children:j.jsx("span",{children:"No presets saved yet"})}):j.jsx("div",{className:"space-y-2 max-h-64 overflow-y-auto",children:n.map(b=>j.jsx("div",{className:Yr({"card bg-base-200 p-3":!0,"ring-2 ring-primary":s===b.id}),children:j.jsxs("div",{className:"flex items-center justify-between",children:[j.jsxs("div",{children:[j.jsx("h4",{className:"font-semibold",children:b.name}),j.jsxs("p",{className:"text-sm opacity-70",children:["Created: ",new Date(b.createdAt).toLocaleString()]})]}),j.jsxs("div",{className:"flex gap-2",children:[j.jsx("button",{className:"btn btn-sm btn-primary",onClick:()=>g(b),children:"Load"}),j.jsx("button",{className:"btn btn-sm btn-error",onClick:()=>w(b),children:j.jsx(Zh,{className:"w-4 h-4"})})]})]})},b.id))})]})]})}const xC=(e,t)=>[{title:j.jsxs(j.Fragment,{children:[j.jsx(V6,{className:Sl}),"General"]}),fields:[{type:0,label:"API Key",key:"apiKey"},{type:1,label:"System Message (will be disabled if left empty)",key:"systemMessage"},...yC.map(n=>({type:0,label:n,key:n}))]},{title:j.jsxs(j.Fragment,{children:[j.jsx(X6,{className:Sl}),"Samplers"]}),fields:[{type:0,label:"Samplers queue",key:"samplers"},...vC.map(n=>({type:0,label:n,key:n}))]},{title:j.jsxs(j.Fragment,{children:[j.jsx(Q6,{className:Sl}),"Penalties"]}),fields:bC.map(n=>({type:0,label:n,key:n}))},{title:j.jsxs(j.Fragment,{children:[j.jsx(U6,{className:Sl}),"Reasoning"]}),fields:[{type:2,label:"Expand thought process by default when generating messages",key:"showThoughtInProgress"},{type:2,label:"Exclude thought process when sending requests to API (Recommended for DeepSeek-R1)",key:"excludeThoughtOnReq"}]},{title:j.jsxs(j.Fragment,{children:[j.jsx(a7,{className:Sl}),"Advanced"]}),fields:[{type:3,key:"custom",component:()=>{const n=async()=>{const a=await(await fetch("/demo-conversation.json")).json();Zt.remove(a.id);for(const l of a.messages)Zt.appendMsg(a.id,l)};return j.jsx("button",{className:"btn",onClick:n,children:"(debug) Import demo conversation"})}},{type:3,key:"custom",component:()=>{const n=async()=>{const r=await Zt.exportDB(),a=document.createElement("a");document.body.appendChild(a),a.href=URL.createObjectURL(r),document.body.appendChild(a),a.download="llamawebui_dump.json",a.click(),document.body.removeChild(a)};return j.jsx("button",{className:"btn",onClick:n,children:"Export conversation database"})}},{type:3,key:"custom",component:()=>{const n=async r=>{if(console.log(r),!r.target.files)throw oa.error("Target.files cant be null"),new Error("e.target.files cant be null");if(r.target.files.length!=1)throw oa.error("Number of selected files for DB import must be 1 but was "+r.target.files.length+"."),new Error("Number of selected files for DB import must be 1 but was "+r.target.files.length+".");const a=r.target.files[0];try{if(!a)throw new Error("No DB found to import.");console.log("Importing DB "+a.name),await Zt.importDB(a),oa.success("Import complete"),window.location.reload()}catch(l){console.error(""+l),oa.error(""+l)}};return j.jsxs("div",{children:[j.jsxs("label",{htmlFor:"db-import",className:"btn",role:"button",tabIndex:0,children:[" ","Reset and import conversation database"," "]}),j.jsx("input",{id:"db-import",type:"file",accept:".json",className:"file-upload",onInput:n,hidden:!0})]})}},{type:2,label:"Show tokens per second",key:"showTokensPerSecond"},{type:1,label:j.jsxs(j.Fragment,{children:["Custom JSON config (For more info, refer to"," ",j.jsx(d0,{href:"https://github.com/ikawrakow/ik_llama.cpp/tree/main/examples/server/README.md",children:"server documentation"}),")"]}),key:"custom"}]},{title:j.jsxs(j.Fragment,{children:[j.jsx(L6,{className:Sl}),"Experimental"]}),fields:[{type:3,key:"custom",component:()=>j.jsx(j.Fragment,{children:j.jsxs("p",{className:"mb-8",children:["Experimental features are not guaranteed to work correctly.",j.jsx("br",{}),j.jsx("br",{}),"If you encounter any problems, create a"," ",j.jsx(d0,{href:"https://github.com/ikawrakow/ik_llama.cpp/issues/new?template=019-bug-misc.yml",children:"Bug (misc.)"})," ","report on Github. Please also specify ",j.jsx("b",{children:"webui/experimental"})," on the report title and include screenshots.",j.jsx("br",{}),j.jsx("br",{}),"Some features may require packages downloaded from CDN, so they need internet connection."]})})},{type:2,label:j.jsxs(j.Fragment,{children:[j.jsx("b",{children:"Enable Python interpreter"}),j.jsx("br",{}),j.jsxs("small",{className:"text-xs",children:["This feature uses"," ",j.jsx(d0,{href:"https://pyodide.org",children:"pyodide"}),', downloaded from CDN. To use this feature, ask the LLM to generate Python code inside a Markdown code block. You will see a "Run" button on the code block, near the "Copy" button.']})]}),key:"pyIntepreterEnabled"}]},{title:j.jsxs(j.Fragment,{children:[j.jsx(B6,{className:Sl}),"Presets"]}),fields:[{type:3,key:"custom",component:()=>j.jsx(wC,{currentConfig:e,onLoadPreset:t})}]}];function kC({show:e,onClose:t}){const{config:n,saveConfig:r}=_a(),[a,l]=Y.useState(0),[s,c]=Y.useState(JSON.parse(JSON.stringify(n))),f=xC(s,c),d=()=>{window.confirm("Are you sure you want to reset all settings?")&&c(Do)},m=()=>{const w=JSON.parse(JSON.stringify(s));for(const b in w){const _=w[b],T=dh(Do[b]),D=fh(Do[b]),R=hh(Do[b]);if(D){if(!fh(_)){alert(`Value for ${b} must be string`);return}}else if(R){const U=_.toString().trim(),F=Number(U);if(isNaN(F)||!hh(F)||U.length===0){alert(`Value for ${b} must be numeric`);return}w[b]=F}else if(T){if(!dh(_)){alert(`Value for ${b} must be boolean`);return}}else console.error(`Unknown default type for key ${b}`)}r(w),t()},g=w=>b=>{c({...s,[w]:b})};return j.jsx("dialog",{className:Yr({modal:!0,"modal-open":e}),children:j.jsxs("div",{className:"modal-box w-11/12 max-w-3xl",children:[j.jsx("h3",{className:"text-lg font-bold mb-6",children:"Settings"}),j.jsxs("div",{className:"flex flex-col md:flex-row h-[calc(90vh-12rem)]",children:[j.jsx("div",{className:"hidden md:flex flex-col items-stretch pr-4 mr-4 border-r-2 border-base-200",children:f.map((w,b)=>j.jsx("div",{className:Yr({"btn btn-ghost justify-start font-normal w-44 mb-1":!0,"btn-active":a===b}),onClick:()=>l(b),dir:"auto",children:w.title},b))}),j.jsx("div",{className:"md:hidden flex flex-row gap-2 mb-4",children:j.jsxs("details",{className:"dropdown",children:[j.jsx("summary",{className:"btn bt-sm w-full m-1",children:f[a].title}),j.jsx("ul",{className:"menu dropdown-content bg-base-100 rounded-box z-[1] w-52 p-2 shadow",children:f.map((w,b)=>j.jsx("div",{className:Yr({"btn btn-ghost justify-start font-normal":!0,"btn-active":a===b}),onClick:()=>l(b),dir:"auto",children:w.title},b))})]})}),j.jsxs("div",{className:"grow overflow-y-auto px-4",children:[f[a].fields.map((w,b)=>{const _=`${a}-${b}`;if(w.type===0)return j.jsx(SC,{configKey:w.key,value:s[w.key],onChange:g(w.key),label:w.label},_);if(w.type===1)return j.jsx(EC,{configKey:w.key,value:s[w.key].toString(),onChange:g(w.key),label:w.label},_);if(w.type===2)return j.jsx(_C,{configKey:w.key,value:!!s[w.key],onChange:g(w.key),label:w.label},_);if(w.type===3)return j.jsx("div",{className:"mb-2",children:typeof w.component=="string"?w.component:w.component({value:s[w.key],onChange:g(w.key)})},_)}),j.jsx("p",{className:"opacity-40 mb-6 text-sm mt-8",children:"Settings are saved in browser's localStorage"})]})]}),j.jsxs("div",{className:"modal-action",children:[j.jsx("button",{className:"btn",onClick:d,children:"Reset to default"}),j.jsx("button",{className:"btn",onClick:t,children:"Close"}),j.jsx("button",{className:"btn btn-primary",onClick:m,children:"Save"})]})]})})}function EC({configKey:e,value:t,onChange:n,label:r}){return j.jsxs("label",{className:"form-control mb-2",children:[j.jsx("div",{className:"label inline",children:r||e}),j.jsx("textarea",{className:"textarea textarea-bordered h-24",placeholder:`Default: ${Do[e]||"none"}`,value:t,onChange:a=>n(a.target.value)})]})}function SC({configKey:e,value:t,onChange:n,label:r}){const a=R3[e];return j.jsxs(j.Fragment,{children:[a&&j.jsxs("div",{className:"block md:hidden mb-1",children:[j.jsx("b",{children:r||e}),j.jsx("br",{}),j.jsx("p",{className:"text-xs whitespace-normal",children:a})]}),j.jsxs("label",{className:"input input-bordered join-item grow flex items-center gap-2 mb-2",children:[j.jsxs("div",{className:"dropdown dropdown-hover",children:[j.jsx("div",{tabIndex:0,role:"button",className:"font-bold hidden md:block",children:r||e}),a&&j.jsx("div",{className:"dropdown-content menu bg-base-100 rounded-box z-10 w-64 p-2 shadow mt-4 whitespace-normal break-words",children:a})]}),j.jsx("input",{type:"text",className:"grow",placeholder:`Default: ${Do[e]||"none"}`,value:t,onChange:l=>n(l.target.value)})]})]})}function _C({configKey:e,value:t,onChange:n,label:r}){return j.jsxs("div",{className:"flex flex-row items-center mb-2",children:[j.jsx("input",{type:"checkbox",className:"toggle",checked:t,onChange:a=>n(a.target.checked)}),j.jsx("span",{className:"ml-4",children:r||e})]})}function NC(){return j.jsx(R6,{children:j.jsx(u3,{children:j.jsx("div",{className:"flex flex-row drawer lg:drawer-open",children:j.jsx(M6,{children:j.jsx(Fb,{children:j.jsxs(l0,{element:j.jsx(TC,{}),children:[j.jsx(l0,{path:"/chat/:convId",element:j.jsx(Oy,{})}),j.jsx(l0,{path:"*",element:j.jsx(Oy,{})})]})})})})})})}function TC(){const{showSettings:e,setShowSettings:t}=_a();return j.jsxs(j.Fragment,{children:[j.jsx(m7,{}),j.jsxs("div",{className:"drawer-content grow flex flex-col h-screen mx-auto px-4 overflow-auto bg-base-100",id:"main-scroll",children:[j.jsx(f7,{}),j.jsx(zb,{})]}),j.jsx(kC,{show:e,onClose:()=>t(!1)})]})}K5.createRoot(document.getElementById("root")).render(j.jsx(Y.StrictMode,{children:j.jsx(NC,{})})); +

      diff --git a/examples/server/webui/index.html b/examples/server/webui/index.html index 471f46b3..47fb9557 100644 --- a/examples/server/webui/index.html +++ b/examples/server/webui/index.html @@ -7,7 +7,7 @@ content="width=device-width, initial-scale=1, maximum-scale=1" /> - 🦙 llama.cpp - chat + 🦙 ik_llama.cpp - chat
      diff --git a/examples/server/webui/package-lock.json b/examples/server/webui/package-lock.json index b2e3cf94..ed229881 100644 --- a/examples/server/webui/package-lock.json +++ b/examples/server/webui/package-lock.json @@ -16,11 +16,13 @@ "autoprefixer": "^10.4.20", "daisyui": "^5.0.12", "dexie": "^4.0.11", + "dexie-export-import": "^4.0.11", "highlight.js": "^11.10.0", "katex": "^0.16.15", "postcss": "^8.4.49", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-hot-toast": "^2.5.2", "react-markdown": "^9.0.3", "react-router": "^7.1.5", "rehype-highlight": "^7.0.2", @@ -2444,6 +2446,15 @@ "integrity": "sha512-SOKO002EqlvBYYKQSew3iymBoN2EQ4BDw/3yprjh7kAfFzjBYkaMNa/pZvcA7HSWlcKSQb9XhPe3wKyQ0x4A8A==", "license": "Apache-2.0" }, + "node_modules/dexie-export-import": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/dexie-export-import/-/dexie-export-import-4.1.4.tgz", + "integrity": "sha512-3bw171qUuOTWSYLXI7C/0M6p1X65Rho3tu1IvD9By8jn0+3t3dLSkDlZ1BC6MbABl3kRlhtGigzC+SF+qcS5Og==", + "license": "Apache-2.0", + "peerDependencies": { + "dexie": "^2.0.4 || ^3.0.0 || ^4.0.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.91", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.91.tgz", @@ -2917,6 +2928,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz", + "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4938,6 +4958,23 @@ "react": "^18.3.1" } }, + "node_modules/react-hot-toast": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.5.2.tgz", + "integrity": "sha512-Tun3BbCxzmXXM7C+NI4qiv6lT0uwGh4oAfeJyNOjYUejTsm35mK9iCaYLGv8cBz9L5YxZLx/2ii7zsIwPtPUdw==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-markdown": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.3.tgz", diff --git a/examples/server/webui/package.json b/examples/server/webui/package.json index 6ac06b1a..48f60f58 100644 --- a/examples/server/webui/package.json +++ b/examples/server/webui/package.json @@ -19,11 +19,13 @@ "autoprefixer": "^10.4.20", "daisyui": "^5.0.12", "dexie": "^4.0.11", + "dexie-export-import": "^4.0.11", "highlight.js": "^11.10.0", "katex": "^0.16.15", "postcss": "^8.4.49", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-hot-toast": "^2.5.2", "react-markdown": "^9.0.3", "react-router": "^7.1.5", "rehype-highlight": "^7.0.2", diff --git a/examples/server/webui/src/App.tsx b/examples/server/webui/src/App.tsx index cc4659e1..a1e19a70 100644 --- a/examples/server/webui/src/App.tsx +++ b/examples/server/webui/src/App.tsx @@ -4,21 +4,24 @@ import Sidebar from './components/Sidebar'; import { AppContextProvider, useAppContext } from './utils/app.context'; import ChatScreen from './components/ChatScreen'; import SettingDialog from './components/SettingDialog'; +import { ModalProvider } from './components/ModalProvider'; function App() { return ( - -
      - - - }> - } /> - } /> - - - -
      -
      + + +
      + + + }> + } /> + } /> + + + +
      +
      +
      ); } @@ -28,7 +31,7 @@ function AppLayout() { <>
      diff --git a/examples/server/webui/src/components/ChatMessage.tsx b/examples/server/webui/src/components/ChatMessage.tsx index 40ea7471..a60fd241 100644 --- a/examples/server/webui/src/components/ChatMessage.tsx +++ b/examples/server/webui/src/components/ChatMessage.tsx @@ -20,6 +20,7 @@ export default function ChatMessage({ onEditMessage, onChangeSibling, isPending, + onContinueMessage, }: { msg: Message | PendingMessage; siblingLeafNodeIds: Message['id'][]; @@ -27,6 +28,7 @@ export default function ChatMessage({ id?: string; onRegenerateMessage(msg: Message): void; onEditMessage(msg: Message, content: string): void; + onContinueMessage(msg: Message, content: string): void; onChangeSibling(sibling: Message['id']): void; isPending?: boolean; }) { @@ -112,7 +114,11 @@ export default function ChatMessage({ onClick={() => { if (msg.content !== null) { setEditingContent(null); - onEditMessage(msg as Message, editingContent); + if (msg.role === 'user') { + onEditMessage(msg as Message, editingContent); + } else { + onContinueMessage(msg as Message, editingContent); + } } }} > @@ -283,6 +289,15 @@ export default function ChatMessage({ 🔄 Regenerate )} + {!isPending && ( + + )} )} { + if (!viewingChat || !continueMessageAndGenerate) return; + setCurrNodeId(msg.id); + scrollToBottom(false); + await continueMessageAndGenerate( + viewingChat.conv.id, + msg.id, + content, + onChunk + ); + setCurrNodeId(-1); + scrollToBottom(false); + }; + const hasCanvas = !!canvasData; useEffect(() => { @@ -204,7 +219,7 @@ export default function ChatScreen() { // 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 + pendingMsg && !messages.some((m) => m.msg.id === pendingMsg.id) // Only show if pendingMsg is not an existing message being continued ? [ { msg: pendingMsg, @@ -236,17 +251,35 @@ export default function ChatScreen() { {/* placeholder to shift the message to the bottom */} {viewingChat ? '' : 'Send a message to start'}
      - {[...messages, ...pendingMsgDisplay].map((msg) => ( - - ))} + {[...messages, ...pendingMsgDisplay].map((msgDisplay) => { + const actualMsgObject = msgDisplay.msg; + // Check if the current message from the list is the one actively being generated/continued + const isThisMessageTheActivePendingOne = + pendingMsg?.id === actualMsgObject.id; + + return ( + + ); + })} {/* chat input */} diff --git a/examples/server/webui/src/components/Header.tsx b/examples/server/webui/src/components/Header.tsx index 84fea191..601fb960 100644 --- a/examples/server/webui/src/components/Header.tsx +++ b/examples/server/webui/src/components/Header.tsx @@ -5,6 +5,14 @@ import { classNames } from '../utils/misc'; import daisyuiThemes from 'daisyui/theme/object'; import { THEMES } from '../Config'; import { useNavigate } from 'react-router'; +import toast from 'react-hot-toast'; +import { useModals } from './ModalProvider'; +import { + ArrowUpTrayIcon, + ArrowDownTrayIcon, + PencilIcon, + TrashIcon, +} from '@heroicons/react/24/outline'; export default function Header() { const navigate = useNavigate(); @@ -24,9 +32,11 @@ export default function Header() { ); }, [selectedTheme]); + const {showPrompt } = useModals(); const { isGenerating, viewingChat } = useAppContext(); const isCurrConvGenerating = isGenerating(viewingChat?.conv.id ?? ''); + // remove conversation const removeConversation = () => { if (isCurrConvGenerating || !viewingChat) return; const convId = viewingChat?.conv.id; @@ -35,6 +45,37 @@ export default function Header() { navigate('/'); } }; + + // rename conversation + async function renameConversation() { + if (isGenerating(viewingChat?.conv.id ?? '')) { + toast.error( + 'Cannot rename conversation while generating' + ); + return; + } + const newName = await showPrompt( + 'Enter new name for the conversation', + viewingChat?.conv.name + ); + if (newName && newName.trim().length > 0) { + StorageUtils.updateConversationName(viewingChat?.conv.id ?? '', newName); + } + //const importedConv = await StorageUtils.updateConversationName(); + //if (importedConv) { + //console.log('Successfully imported:', importedConv.name); + // Refresh UI or navigate to conversation + //} + }; + + // at the top of your file, alongside ConversationExport: + async function importConversation() { + const importedConv = await StorageUtils.importConversationFromFile(); + if (importedConv) { + console.log('Successfully imported:', importedConv.name); + // Refresh UI or navigate to conversation + } + }; const downloadConversation = () => { if (isCurrConvGenerating || !viewingChat) return; @@ -99,12 +140,45 @@ export default function Header() { tabIndex={0} className="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow" > -
      -
    1. - Delete -
    2. + {/* Always show Upload when viewingChat is false */} + {!viewingChat && ( +
    3. + + + Upload + +
    4. + )} + + {/* Show all three when viewingChat is true */} + {viewingChat && ( + <> +
    5. + + + Upload + +
    6. +
    7. + + + Rename + +
    8. +
    9. + + + Download + +
    10. +
    11. + + + Delete + +
    12. + + )} )} diff --git a/examples/server/webui/src/components/ModalProvider.tsx b/examples/server/webui/src/components/ModalProvider.tsx new file mode 100644 index 00000000..f2ebf8e0 --- /dev/null +++ b/examples/server/webui/src/components/ModalProvider.tsx @@ -0,0 +1,151 @@ +import React, { createContext, useState, useContext } from 'react'; + +type ModalContextType = { + showConfirm: (message: string) => Promise; + showPrompt: ( + message: string, + defaultValue?: string + ) => Promise; + showAlert: (message: string) => Promise; +}; +const ModalContext = createContext(null!); + +interface ModalState { + isOpen: boolean; + message: string; + defaultValue?: string; + resolve: ((value: T) => void) | null; +} + +export function ModalProvider({ children }: { children: React.ReactNode }) { + const [confirmState, setConfirmState] = useState>({ + isOpen: false, + message: '', + resolve: null, + }); + const [promptState, setPromptState] = useState< + ModalState + >({ isOpen: false, message: '', resolve: null }); + const [alertState, setAlertState] = useState>({ + isOpen: false, + message: '', + resolve: null, + }); + const inputRef = React.useRef(null); + + const showConfirm = (message: string): Promise => { + return new Promise((resolve) => { + setConfirmState({ isOpen: true, message, resolve }); + }); + }; + + const showPrompt = ( + message: string, + defaultValue?: string + ): Promise => { + return new Promise((resolve) => { + setPromptState({ isOpen: true, message, defaultValue, resolve }); + }); + }; + + const showAlert = (message: string): Promise => { + return new Promise((resolve) => { + setAlertState({ isOpen: true, message, resolve }); + }); + }; + + const handleConfirm = (result: boolean) => { + confirmState.resolve?.(result); + setConfirmState({ isOpen: false, message: '', resolve: null }); + }; + + const handlePrompt = (result?: string) => { + promptState.resolve?.(result); + setPromptState({ isOpen: false, message: '', resolve: null }); + }; + + const handleAlertClose = () => { + alertState.resolve?.(); + setAlertState({ isOpen: false, message: '', resolve: null }); + }; + + return ( + + {children} + + {/* Confirm Modal */} + {confirmState.isOpen && ( + +
      +

      {confirmState.message}

      +
      + + +
      +
      +
      + )} + + {/* Prompt Modal */} + {promptState.isOpen && ( + +
      +

      {promptState.message}

      + { + if (e.key === 'Enter') { + handlePrompt((e.target as HTMLInputElement).value); + } + }} + /> +
      + + +
      +
      +
      + )} + + {/* Alert Modal */} + {alertState.isOpen && ( + +
      +

      {alertState.message}

      +
      + +
      +
      +
      + )} +
      + ); +} + +export function useModals() { + const context = useContext(ModalContext); + if (!context) throw new Error('useModals must be used within ModalProvider'); + return context; +} diff --git a/examples/server/webui/src/components/SettingDialog.tsx b/examples/server/webui/src/components/SettingDialog.tsx index cd091a55..004b51ab 100644 --- a/examples/server/webui/src/components/SettingDialog.tsx +++ b/examples/server/webui/src/components/SettingDialog.tsx @@ -3,16 +3,21 @@ import { useAppContext } from '../utils/app.context'; import { CONFIG_DEFAULT, CONFIG_INFO } from '../Config'; import { isDev } from '../Config'; import StorageUtils from '../utils/storage'; +import { useModals } from './ModalProvider'; import { classNames, isBoolean, isNumeric, isString } from '../utils/misc'; import { BeakerIcon, + BookmarkIcon, ChatBubbleOvalLeftEllipsisIcon, Cog6ToothIcon, FunnelIcon, HandRaisedIcon, SquaresPlusIcon, + TrashIcon, } from '@heroicons/react/24/outline'; import { OpenInNewTab } from '../utils/common'; +import { SettingsPreset } from '../utils/types'; +import toast from 'react-hot-toast' type SettKey = keyof typeof CONFIG_DEFAULT; @@ -74,7 +79,155 @@ interface SettingSection { const ICON_CLASSNAME = 'w-4 h-4 mr-1 inline'; -const SETTING_SECTIONS: SettingSection[] = [ +// Presets Component +function PresetsManager({ + currentConfig, + onLoadPreset, +}: { + currentConfig: typeof CONFIG_DEFAULT; + onLoadPreset: (config: typeof CONFIG_DEFAULT) => void; +}) { + const [presets, setPresets] = useState(() => + StorageUtils.getPresets() + ); + const [presetName, setPresetName] = useState(''); + const [selectedPresetId, setSelectedPresetId] = useState(null); + const { showConfirm, showAlert } = useModals(); + + const handleSavePreset = async () => { + if (!presetName.trim()) { + await showAlert('Please enter a preset name'); + return; + } + + // Check if preset name already exists + const existingPreset = presets.find((p) => p.name === presetName.trim()); + if (existingPreset) { + if ( + await showConfirm( + `Preset "${presetName}" already exists. Do you want to overwrite it?` + ) + ) { + StorageUtils.updatePreset(existingPreset.id, currentConfig); + setPresets(StorageUtils.getPresets()); + setPresetName(''); + await showAlert('Preset updated successfully'); + } + } else { + const newPreset = StorageUtils.savePreset( + presetName.trim(), + currentConfig + ); + setPresets([...presets, newPreset]); + setPresetName(''); + await showAlert('Preset saved successfully'); + } + }; + + const handleLoadPreset = async (preset: SettingsPreset) => { + if ( + await showConfirm( + `Load preset "${preset.name}"? Current settings will be replaced.` + ) + ) { + onLoadPreset(preset.config as typeof CONFIG_DEFAULT); + setSelectedPresetId(preset.id); + } + }; + + const handleDeletePreset = async (preset: SettingsPreset) => { + if (await showConfirm(`Delete preset "${preset.name}"?`)) { + StorageUtils.deletePreset(preset.id); + setPresets(presets.filter((p) => p.id !== preset.id)); + if (selectedPresetId === preset.id) { + setSelectedPresetId(null); + } + } + }; + + return ( +
      + {/* Save current settings as preset */} +
      + +
      + setPresetName(e.target.value)} + onKeyPress={(e) => { + if (e.key === 'Enter') { + handleSavePreset(); + } + }} + /> + +
      +
      + + {/* List of saved presets */} +
      + + {presets.length === 0 ? ( +
      + No presets saved yet +
      + ) : ( +
      + {presets.map((preset) => ( +
      +
      +
      +

      {preset.name}

      +

      + Created: {new Date(preset.createdAt).toLocaleString()} +

      +
      +
      + + +
      +
      +
      + ))} +
      + )} +
      +
      + ); +} + +const SETTING_SECTIONS = ( + localConfig: typeof CONFIG_DEFAULT, + setLocalConfig: (config: typeof CONFIG_DEFAULT) => void +): SettingSection[] => [ { title: ( <> @@ -187,6 +340,85 @@ const SETTING_SECTIONS: SettingSection[] = [ ); }, }, + { + type: SettingInputType.CUSTOM, + key: 'custom', // dummy key, won't be used + component: () => { + const exportDB = async () => { + const blob = await StorageUtils.exportDB(); + const a = document.createElement('a'); + document.body.appendChild(a); + a.href = URL.createObjectURL(blob); + document.body.appendChild(a); + a.download = `llamawebui_dump.json`; + a.click(); + document.body.removeChild(a); + }; + return ( + + ); + }, + }, + { + type: SettingInputType.CUSTOM, + key: 'custom', // dummy key, won't be used + component: () => { + const importDB = async (e: React.ChangeEvent) => { + console.log(e); + if (!e.target.files) { + toast.error('Target.files cant be null'); + throw new Error('e.target.files cant be null'); + } + if (e.target.files.length != 1) + { + toast.error( + 'Number of selected files for DB import must be 1 but was ' + + e.target.files.length + + '.'); + throw new Error( + 'Number of selected files for DB import must be 1 but was ' + + e.target.files.length + + '.' + ); + } + const file = e.target.files[0]; + try { + if (!file) throw new Error('No DB found to import.'); + console.log('Importing DB ' + file.name); + await StorageUtils.importDB(file); + toast.success('Import complete') + window.location.reload(); + } catch (error) { + console.error('' + error); + toast.error('' + error); + } + }; + return ( +
      + + +
      + ); + }, + }, + { type: SettingInputType.CHECKBOX, label: 'Show tokens per second', @@ -257,6 +489,26 @@ const SETTING_SECTIONS: SettingSection[] = [ }, ], }, + { + title: ( + <> + + Presets + + ), + fields: [ + { + type: SettingInputType.CUSTOM, + key: 'custom', // dummy key for presets + component: () => ( + + ), + }, + ], + }, ]; export default function SettingDialog({ @@ -274,6 +526,12 @@ export default function SettingDialog({ JSON.parse(JSON.stringify(config)) ); + // Generate sections with access to local state + const SETTING_SECTIONS_GENERATED = SETTING_SECTIONS( + localConfig, + setLocalConfig + ); + const resetConfig = () => { if (window.confirm('Are you sure you want to reset all settings?')) { setLocalConfig(CONFIG_DEFAULT); @@ -332,7 +590,7 @@ export default function SettingDialog({
      {/* Left panel, showing sections - Desktop version */}
      - {SETTING_SECTIONS.map((section, idx) => ( + {SETTING_SECTIONS_GENERATED.map((section, idx) => (
      - {SETTING_SECTIONS[sectionIdx].title} + {SETTING_SECTIONS_GENERATED[sectionIdx].title}
    13. - Download -
  • v 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%0Acn6~q3_x1Op9=oKgykT!?Qm!3 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 z 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%0D<-#Z3vlE~=n--iW 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%0D(XFtMC72ELbK2)b-E^yq?in>H%qD z1m&`{3r!)kM_*n5@X5U8#61EjYg^>8euaN=5?)6z2UQ%nKXI`CeVyK@vwFa{p5J2u zNV;biF7`$cfuRS&XZ&lN@s`-RBNvhg;Z&RD#3=F51F`RkhTIg^aX^M1f}VX}LuiyZ z+xYMdd!B6+rGOCb@!>Y#5 zTZh(s-!uN-OYV-f|IFs0zw*wEMyY>hEO%1vNwXB0OW>l{E0$TLb(S58&kIS8ABS4%`8^f9*M~$SVyG&&^6FFV+4^h$$)mf z)_2PM>63`jOZNJqhgshf92zq}DrlZS5p-q>64S)eH^1$BLcaO)JVE!9pP7FqR=)XM z-;?Z{05ez0+CqOoE;^K)FvS7?SZ ztu(Y9!4ZGv7&8Tfi7eVfSbk`_1J{`G3$m!$0hkqip@sF(BhUjA9E=?Xpbmq`1fIre z)J=iI=pnH&b%jV%5TngXffRoNhyke$BQ|k>&~q&3KGhml7w&rkC~Kcq&J*weYhPuW z7-@*LkMupUKKZ&gPY`|bucnFRZ$6`M{K+@aJi+;se>Y96ee)T8>rcK}j`Uyx7$bf( z=aI%Hh+_oV+5}_leAZqz_Ie~d*jj3#c{JzeXtMcB!fgIhKjZS>@R@(cV?mqQT284u z1KNX)6z|xWWb-s6kqJR8H=n+WkzF{j|MZVl{=tJpP~5;6fqNP)?=dmESvRC(>>B$I42TU># zO<4++hJaXB?0fxR%Xr}F&bF%YOty$C(qRi=V?>PDu8H4so`XJMTN zrzp@r>n5t%+H9*DmsPQ6E3pZb&-(p$JjT}M`KKJ?O0hz!9)waHxg;_HCOl3*X_>8Q z(Fm@8LwnDnADN@HmDs1LwgU#?P9rFz5!FBNh#3DS(%;UvJgB~SI3ujt+>W~*1Z=)$ zas~Q3o`EPSzH)yKthF7G*ncKFDYI2X|A0@y<|5HF0gyXzWOEA}chHNe`LjRYBjcO> zpD;aWD^fB|W?Z>DhMQeDh#wE-%y@N_XB+jvYS_B+?JH#jvKyNv5SgsW-v7>Hv<(`z zX8nYPWi&!B)W7Re{V_<1d8_)#TmO2TTTg8U^q{o@Tlas>6fFM{@4KX-&5yo^Oje;u z_jfe3e)Av(J)7g*51*e#nX}^n4qg;edXVd9?*k~a`48j2!W9GgE1dT4>Z>%gQ9iWk zz>%y9Pg%hvLO_hX?PLKQu=$nD^XQcQKf@AbrT+!iMf2#)PlL7RGhSLooBvUJo+GTS zXD_ii9?E||X!sp}Kl`0mMhV&IC!h3Skc`=)2LztlyZrrqww6-TknWE<{+Grun|J=@ zSow?(O?w!zhen8PnjmL{fn6jY8Pb(v_sP=qBR~G__+f3)8u!Z97a(eHnzCphZfUEZ zy4kuDUVpc5o+lu+o!Q|LxP;M5V={>|_r-@7O`v};nb0x6`3!fn10yTzd2GA{)ZKmL zRwidd*(JW&0p2M2(JTK4`Rv;O2Y3h8EbX(t_S&Jx+-Kf&J&VoL3X`LMe&0-?W17HV z@`KOh8Z7ob1;8!)p_c)BhTmu0_Z0tlud(MJ@2xNV%$~^?{_`As;Xlvu7yk2{^*z%g zV2gi!J2p-0v&UfVkG%QKbQa_T*Y-V&z4C=iKX5?)z#Y;2W^Mn%aSRTC-~*SNCcCHb z18$yY0HDmCW5k~2@3S}0fc$u0vgaS~zwjD+PQLKp=P&&C`3wJjo*5nhxNICNl(h>2 z{GsXng9m_^!JSIhF8l+o|F%E)!1dqu%O8KZ^xJ;;g%iH*|H8c(4;@hdd)`n1lix&R z2LUUad5rJIuE&_c&)+f1$~;HH`bo8zJp2p(%w%H!7yRl6Jp2tGv-Moxn`LutP z?bX1-*g?qPDf+_qSnJFb!B5>kVKt4_{Tr6y?EiwrpL*v%=%@v(?&VLq6bx@k{6QC_ ze&K)6M5C8fU?^B@>j&26d2Il{$i{bONTrqoqPkherPY0^T+6v*G1Nh^+0{gDV;1vu~rgz4eeWzfm@`S(vs5Q$k*!|{&uzr6Qflpw;>OV0& zROXio_Uyay$ilOWAf=FFeoNAk;gf;n$M;S8ZKw13PS45(%+4kP@B%Q$(i~7IFv(x) zH5q;(qmN9%afCKYpP9cJ!~yS94ucfHJ8N&q{3NOx$VQeHzwMGR`~Jk@;%ESJtp0?u zb_A@R7yIssz~?WzsWE?}&y#hoNx_@l|N39+-%r0`*4{5(*%vR_V(q)L_bG)H`)@Li zW#&#Sjf8Lg(#TBm*FepHN#XFT{YuN|Brv$2^gd8<|Nnz8{sym((J^LpRQ?KYQihKP zk`XKzJxu@%R_^qp-!%ZeAN2Y3-o4?ijNi;rwEezZP# zj&S_;>tDWW{iWV7e?*`5v-k%}{e?&12Or{Zd*si!``7p(z}mqx`ky}I2ZNZh|DSfP z8T@zLFt{&XgxP<)eamq`Y5}5OJ~;z8vb4$0_tX!ce)uT+j30~j=NC@^o{Wweg*Sji z)^3H_!=8SOvy7cLA`zG)gSQymo$=)vz&GRD?|2yh9rm$j7J!pi!@pla2-BR zK6pDmkwc|u&I(q1MIPd-TY#pxg9hGVXx|flRlrp^W_;79ydVWiaR)2-K9L`Fa(DwH zxzCiMfQruQkrQ4X(g@3m682{WtH}|*Pto*Bsk?toj&1??kc&ykofP)py{BupfYDH} zC;;#}6=|f`@vr)I30yZTa4YVR-w&tAo*5q5wRpkX7e9-H?^ARhVq$agF;LIHzGsgo zrIup8xPvvrIeev2c#BE${kD&BrWALJB;WTwR?pGqZb`Oc{rY~q`p_x}ChPspcYW<` zk3WCyPgHged-!kv+okQUr{TZ;m!W&+!+g*G%YXa7|IbT%8~%^WDa-%+kEd(d%>QAW z{QUTTd8b?NvI0NP*v{*e5SVRQw6(ou`(HIpFLP^%ce zbM}EBBON%>i9R8_A*_K&muQaCafVj$T>46+D9V@tdkNOXAV;2g&NzQ{Qlw!C_z^BFRu5-J)zQ(81E?7LVO+<16(!{GK z5KsC0QQd|9Aupl>UyAEWw)sV}*k;w4gcukHCsNOg5vV?`xmngo ze(U+Iv1ps*c(~NU^0hxS+eD8PdmUYQ4+yF8=AxBg_Ish@uUEKVFU8CGt8&Keb(@Fp<92@!X0puF z?c=_(2A+FdA_P%@_+=thi^dkOdhcCK1r=@deh$a60fu5O+U9Ip@Ah5a=Iv7uq3R#R z8CeuQCkbAw;5iRNech}#226GS);yhz&gqsk`P*Au#!XwGGAzz3sZt6$iPZ&mn_z#q z`P=KIphU}i^HLmE`_oqBvnhYiupyeQHmnzmOO;@Q<6SA&Pa_Zyb?ok<KWEqkk(9_8ioel2%ulkIJJ0Qkne3_V>d>tSX1OZQ&Qo?K4xxL99TIdIP9 zG1GtmvIT76Af5q`-9nUl<(#|6aT%72MRZYJWhb{>~WOCqr`Ica~@g>N#N?UG3$RK-ycWzB=));n9EU<;TX_yW18YEMkYt z=xQwAlC*ZWTMO>0`&gJhj3ekg*^?+V;c6SE;1bJczAkeKDBav;fc9H%DQT=L_+qe zEv2D>g|Sm&?IC~Y$*h@|2I$YB*;j*3`0MGs*_UO9{8`x2HPnK0;&H~@QZc?w$wEek zyy_O3R-`9xx*QRv^mwns0ncTnBoP62Tx_=(U#;a$v+*ITY-4+9+IRdoT}w+h-sTNj zr}AM8YVq{cBD$UHx8(JQLe-a>X40(-aZR_6x zB*&;}(AC!Cfk-Hy@%rRAMVsavm|OR1ZRfz=R&G!Vb+p>v_RriT+lq+eEYtE(Qa=-? zRGz(f8*+agmv2|^vH-Mu=BmfL6*eqHfP6Geey7KYyTI!JOF*>0qakR=IK+DgSX|jZ z1Lb-s>exL*hH3R&xeX(0y>VHo!4^K{Ded=t>GL*V~V4P z(%z&;WTI3zD=^+3_)J}V(G`E|d*!Q8*0EJ;nQ>~S<@5f3sA8Ot(^}5^Hpb6FM7~$a zgctVb7kDBi)LgBW24IA%r$vkkg55LHI=e;bMN%8(2|GdDm3zxYcG}LCb#AMzr}?M) zx=o#9H0RiFR*C|(LU*g$M^@k}sMhG6VAtyqQ65MmtD?P?NSjwhmC7hp_GX86uL#S| z7TMlbhuvv^E?wuiJY1WpJiml}JiCetxbrm0kNe_G?oO$klM3gLcT8cB_L1g?*SAuZ zt2iTibkk_4^NP*47&khycW)Q8!Yv6-yVpK>Q*?uketojt_SIe8y?g22_09gV z9XXfVE#CMo2Kjy{g389FJ*<|efm^}V)k}B#2Td1$$X{(`&noF=d!eVIM)vzgnp$6= zXK)GaYS}jp{ z0XO@9oxttgSFnAYrm!oYXL4>Hc7g2)$@hcByRCQM-5vXOm&W$u?Q82m{8!$8q~UapP_EQ} zHkIuC>Sk}IrTpMj`rd+=h<$>S`*FHnZ}He(#f7&E>M5aQ}nOa(+ z#msBFw?~Lv_C4`wH9h<~668$CM!(sA5PFoJo>yR0Yb9QxsL?ihe39;&Q#JCXctKEG zXI@3IFDvv(*0eB;!Ezia7N9w72)#&m?@fVzsU9$OGJOsA)%H#Z?9Dn7)TxNp zLVA;4sCt$9;@YUkDR*w;i&M8)P}@WppEp=@+r#rkrNth2hrOpYT}uaRl-oRis0b3e zmt`d7D%)mD{7B|aZn|z;kpZ1nJQ?sd*f{FyUCrW{Tvhwsy+w2?h(4UL-IesAr|Bu% zJob-R3Er#1GF5u*E$1FRhatJ$GQ3MBshV>ar-@~0va~!1%C3JLv)AHQ;}{B{29xyM zIV`G5>I1oZ2qN>*v&oE?VhRI)C^x|!ZG0itrbdoZ5sjm$uddJ4L2d2$cAb%p-i?~5 z=hgPml#jr4NAY&Es-k?v<;7gY_m$Inl+*gU?850e_T{~~*XNQWoqQgP%Ov~r!p$G# z`Z`HZO72h+*L+f!T$Hzz-`)?}=H(km7$dLiy{h)w_0h1rfLJTjA{DoPv&O6%%6nax zwvy$n~}Rw=JBxJwr9T<_I7vo zuU)s>XUbu{Ig!VE=U#)2IQo%)PqHu}k6|Pm`7Ys9Mrhb*MP?Y~NJwuvHyTtDnO5(^+O7>(o$20N)jiVPqi$eh)@w;8?xT@wYd(X2WK4HR8Z`T|+BeO?&+J-@ zx|p5RN4JaCU&L;;02k~X_17Xho-k=p7E`r}X<*jnfK-J(%HYp$rMo9f74H&?mU zu-BSUdpK9~ZRq0w&tN`66DHk|&CyZ9g`H@Lt!ge*?xiy*t5<5C2IJnzqEhd=?a3;s zz=TF+faBfh-6KwloW&bwZ_TV73TYYDA~r^6Qp#(aBh$dr+NpDo0Z%GPRG z?Aq`aqUEN;aBu0=xS$r?r*^5Iu4MM1u8Ew2Wanb+Co5gU(#lGt-AC{6V)B#;>6r8cpSQfnw>u?h(+wIMNoyP|UTQA=~+T#_)7m-spXUldw z(elb`a0t;fh9l=1*X(@Q^LA@>M3RHIIqNb{xTC18JqJB!dk9TcaFP+AvkCg4^4~!Y zrZOG*P3&+7Jb(+?DWdwEO5^Het+ZMNu)W+Dz}tw~b(rl%v2FGsE!Hz7y9sq&ms!RA zDNEUZYJa*R&r*r-NG3IsQ<&K&H1169-3%mz$}q*-EV>L7jK^E9qBCty!rc(0M|a^L z?X?Ovc8V{lc!>k)>>QWP+TyQn?3S(U@3zj9Gi+yjRHApGHm0dZVKS6aaTqpJjqrVw z>0mQi)H36+v&fSNd45WhNQr>=P&Bbz@V(T3dLqAT!~7Y%tt`DfM`NT$ny9z>EudXr zwii`abBqnH+%2Bo9_CM&O0j%bbL#kBFdQAO(?Q0I(P`)EcdkZPwOiDZyd#H;HcZcY zQ&-`b@{OhLo#S$I*hH_ZFD~m-w_Q>M--%CZ;VB1uJ5E+d$IA~A-mTl-&+7fL=pToF z-C>rVt)0K(61@kmAMbMMqOEz_Ncw_5j;k66K`G<`_2Z?{INfEn-}9HH@lxaUnp2L# zv9D^yxXxSQCGTn8bOF~c<%^Va^7P)7rt$XTW7|kqfAH%e33xG`7mHaItT7RiG_Wty z!e1|UlQ#8obE~!OD>P3{?%m?)=2aDcNe;&0bt}`9h8-ukI~@C zNPTY-ytH@EM8&=>XZOA=LX>G8=3*`0-+k}Y7UC^GzaR7fpB7D@v2{Rmh!@g-_4XFE z(`j79GxSL@396#i#!F4*ai^b`YYxb(GrvFkI0|-EfX~EHPISE)&ZjqUxAnSxwYL)} z_k5N%^mrPAQnMaYqTkN9*}GVxw9YOP;IeD3+^5*y)|cn@Ze8s(^%shEA7)wE9~Mt; zCj&!1J;2zYUWsqKbh}CKi_GDFBF?=GU-VrqDw!e*+$-Bmw?5anqg@310cw3F49RMd zmAiS;pK>vl%3^&+!t%89>>!IRExbHF4LuEj&5m&=e-yn*9XhLf41u4kF<-{#(bT_HYn8im{< zSzgD_=A5J^DN*4V=juQ#ZdYub#45bPFtpX-GVk$Y)xnLu-<@CY!=`mQ&g7t_)eqZaaYL$QejPEbKbP8 zNYI^eb1ZlStGx8Z#yZ(@VD&PR%vPX}qous@+g8Xc-dqyXG;|ohRBjIs ztEY2}{Dm@e0|?%}Vo#oB^vw#bjUf)#!_^m!)v|b^9y;-+Ilp>cxyIMj4t($2k6iz( z9|F;wsVHr&TTt?U)*fWs7nk0$;`mqyYirq)pug>?J8TE92@_ta@ivQBTrh9eep+vB zNtDFpO*4#zaDB`S+8c{9yRNToy&?D4V_#j$3*Sxy zHQX(7=Ldd-{Wy*JDM}uOUp~?*K4EbeOy!{T)_fAYJeRyOUtd#Nq{8!o*2i#Oxff;F zBIS6!=FeTQ;f&r)0^EXSz;!ym+fMaJUb@5Ofjk#~57(E5rKXmT!{s{CsgI-=r>__1 zs^_fgcF?^&UdTUDtX{Yr9Bl8S3Hl)z* z*EbZ>pd;Y%p9&R zByMsgoJd~M?&AyIg=YM&8*Ql_F7Bx~w6EZQscD*Cw;uMptMUeYpd)VUdo;SPo11$H zWBWi7bX3}tQ#fe70jt;gP?mf@I@_tq(A4nm>!ii2@+HGJnXRMxyrd%guV}i$sp9=Cm*O?TzqccL`6+=d%jceJ_p!*(IeFkK0G)RO8eyj_NQt z*V`slf@L&R*T>%10&TC7cyi}-zY=zTd>s$g=2E>ZQQdC(Q@^ps=RM~aeBJQEqM&!P zJiIRFT=3mjcIDSQS+QxquHYyHVtDSv!dg6>vu`b5T+}Y_#pMu6i>DbphUR3X8d@%i z6rA;WsZaCS;^ntpN_pl!;@(*GoATKEq_Ul~q-M@7FrOY=ElJaL?ljY>E9bd?Ehll= zJl%mdxl@$So_`Ogcd>ebA?dpL@CYQ5)0LmQvU?MQSDv2^=CXCw$0aebxR+pbOCShi)y3B=9lF5g;gzT>_UPS0!S(gP23JL%8ftzFqx z2*c*C)kfP)h~K8~dEZ21o2M#&J9{!>``v}-)ydU5Khm*WRCEk3;c@%k-%e*SUOY=T zH?L+ldBN&#HdBO#YP!;kv0Xf&jw;&~V&%2CZ022MJndGvyY8!d4(n7?f#VTz)N~@iwQEc$X(K?!-fX2R&SX9;CKl z$O|HQuC(;!mzGZLJ@wCv-dPPG(;TJI`lp>A-gDzl{jNZS>@G|0-~i2(maC1hd`;9? zR${5H{Owx+t1S%Cxv&;JK0JpDLfwPbqag6eKdym6+hs%g@d(`O>oP6m$Ms%qz1rTX zz4aFPJiqL+fT$wi4~x}*&GPE9y++RZv?-Ip5&E_birs5nc$0B;Cv)$eL)`Nvh*Z1| zU$7LqA^dNo8$0~qiCI~b2x7GMZO&;QNM<}e4k5Lt<;CbpI(`!Ot-O1GP2KKxLTuli*rB6)J<6+DLqj#^N{67c%foBg^v9J~TuEHGb2S{Y z(=jAn$SIQh0uNP5_SeM87R_5aiQ@gr#ha!Pq@#>I;ifP6_aXM1r9qF%F@5Trb0-wS z?fewpi=YeA-9bKFWa?iQbHeYeG&3blenvcU&i>LRtJSN2csN{s7drQnx^s2k!S%U# zX4}oQHP=9DH&i+H9g3X%BCr5D#Q|?+L2nLw6^zzX3HIGY+*^=t3Hmr!2ojaD1$THA73roY1XH6Dr%ogOPeM#Iva4`IrO z>dTo0uUw>ozq~JN-W#fEy(K%fSZ(AvEL=es&+C`B?^>BZ>--7cDSvu+dX84E`M{Uw z=vwh=oR?W~UcSce{zeDus@&?BiVwBaa#37JDo>w(YS})v3%={PRl@Ir{^kmca}gis zd5;2BkOO)GOK#p84~2W*=WLS%>-{~95@gWVns9s&3!4rmEAM)D9j;E9yV29h!(ys# zbK6$%?Clqe4ey6(;Uzfe;$^4KyUK^Jlh{_Nu%0eC#QR1qZ>PnPRR0fM=dH6X5TMt4 zac5zFiJVGuhL;>Va?Y8nx4z$A?@B8-Qy?@vgD8+@o^$SBAHpkQ_&MS^&ake2e=G`( zI&%Fnd!;FJH{9v(jVk(}&>91%arfgdqV2ZIcG?}p1o;u728KUBQ(J@c!pUd$K?u`E z0_aM%=M9;pZ!UN~L_M_!>hsQe0=;y;zXE4}@Pf&K$uq*zfS_Qwtfve0eSg87i#DuN z=4p$#qTU1;2r&WCnc~*W%8#0fq+qs80B*_a*kw_cvhEU>NA1;})_A}JEl{TE8%iK9 z>f^X4CDsF|AoIzip<_y?XZ-Uug?(pbzuZSJvWMt>E8oYFtB#pcYWMiBT(`9>52QSQ zim@zL-4VS<)nn>cd@aB3FE57@lAk`xldMcH=u(NPv{+d#uia}sI}f7ouQHsFhYFD>fM zatAat=yF0)k)Z8$o{Rwn#0!%bS_A{Pgy@UFD9Ri3ondg-oTyweDo3!Qc#cltHi|tc zy~gnIv(mcJW`NNtq6kn=F+};Pfn%jlPwG%#Wyr;fw;965vRHCgON$ik__?$mEH_J$ z|I#B5CbV70s`?bn81$;IbF&YB!k-19$c*UvCc5TI6Om(#LHeDVFNiuSUQ14!AB}25 z+$z&6WqufBS944dPe5GZHcNFOtbSFR_2wG+W%`giYl zurldX?4e1%*RJQ1QfeWo%=$gk=UC(x#3T^HZdI z?CHLjB$Guh+n#)+MUm!LL#Rpus@?VwkaXjgjzq5Z!c4$S3pe9M5K)??}y&sE$U*?m* zijc*UX~b`_$KBOKB+PCuD^AE3V?U~^8I1AjY}m96aVXo9YuT6)1<(^jCJz}@Rpc~Ny6%AQbGN4~ z(K9g2@tO65$y=L``gO$sA(4leKJl}*XeBICMClXs!LlJ=e@PiDzXyPx?Hj=)u=96= zElX5C-dcj+Z)p4hm57<-y_y*Y#siDI1E5k*2{ae?$FA~!cL2f6c~U4`k8&!^YUVuh zg-LLWnQv`bUagssid@Qg47gd|d*Vfe<<0j2uOa01xPLFdr3p)3qg(&(a}1z5L(-hH zLuj;qDYF}%g=1{S{K&F@2Mbz}V#LzSgtDfJ&)~2Q$pOW-=diN+T8P&@?;UpX&>H?F zOPbc-_KLKBPES0y1ycYKhhT7ATa)g{qtPW7Ol>Nhl-#;O2xM1XMJ$&Gj4)KZT~8wl zRS7(iIj??VK6^V$bvUDnCyN@yATRUO!n8xxkstDm!_na-KD@)BJaDR(iu=)DH35$! zOsRS!{NXd9q=(MXFsO_~2z_33a&V$Tsy1M<5dwLC0$zB3nU~YRL%*6ax{iDqUgGb; zXmJnYlcHI8-ewC?fwT9|^vDaTkifh;MH5Q#dwC)qP98=41T`443iPJR$4Gjrrk*HV zRLFdz&N`AVsBJipo*5G;C<>jG7Y-0 zli`GWqi%LiDV)VJsH*{^sd>T8`X;DC!&Mr7i*qg(WSI~wUR7YN5S|( z#&#v^E!Z*wEAdcHdP7*25fF@23S@@h!U&Ro$eGAyECmF!G}@0@aDg(scveJHpvGgY z<+g=W#(f6`Fo%TGyVnKr08JSNO;lT$&ma$q@`GMYr;v5{ugE&YP?;s4h+0ZFE;G8|!YA zO2yV+`fXAq&p`hxXLVcNOvZEAUEA2ap3x%<*Vo4N2`Zd0UU9&#!%lowRRJr1{XPPJ zog!%fB8WWsTF7FzI4jZ9R z;gb~M43Jd|u{-U#n?>*`4Ac-QG zGf&QbMI42>);Hk~+*1N(lPFP-$a|bRo2Fj}u+$h`yL>NnhF`}167eTE08w1(G>81h zif?+B{RBc^;r*OrbZn(xNy6-$Vwk}CiZ?|Dzmoxqfe+w5eTH{`(~0p@3!QyH4;DGi z-$I$4Nzaf?*}zli&ME@JGQzeB)fT)w#Heydz58m?!u$QGCdl)6rsI4>5XQRK=Xo$y zq-~iTcf#LLwVM!109@VXiOQ1 z8snts!$H>cR1uSZ8&7I0e*0#^!Bl<&+T~rFJ7@`HIxk&-;u*oJ13Ds7o*UelC;Gj) z*dsWjdpb0%-ei!}vAADwMOO zPtj7-x`ir#!JvMRZ_~k5l01;V1Ct2NHS}d)vX6if=c)zn`A8iKg8G)!tX46v=tZ_w z0%1v5nGa&kQA?IZDXR^JYv(U#RkVpeg>&CovkRLE;UUTcPzV#g4c^AtYo3 zET&D_74XE2Vu*&bYEH!nEflT7U=JMNxXZ9RvQB5^9lFFDs~I4-8Y4@59i*-L!S3KfqtL3Hi&u;XI-3arX4cy zoSFSD=Y)n{XkrQ*v@-oN;6}{FPPb&@t*E+!`Lnu&Hv?|Z8HK-RM*T|^#BYCiB@&N^ z@Vc}0QH1YNh^|2h#vo)1PI3u9)V@-GdpEbwOv@>QE;?CV71$HnS+oGrc(wh=0$yGA z$+L0UCZd!fA>688r4hfIrfnt|yf+i+G|PCw8Mk(bHmdR4V#P8XfJMdx{c5qKllPcl3%@30HXJlm#y;D?L9WoGdB0~qiFHuWl1l`0R*jw3~)@>yur434! zZ8=JCY){OYna<_4tJJTKwMOvJOlvYLr%6M;oI5PE>x2YkR z6{ZRb7_?;Z62tT{eh=^&PUZni&;eDeh;Q(dy+128-Wh8OKTyo_q8%FccI|3sF981$ z`eIxJ28|j10Nh8-7xi?^%<3ZBUDU>s3B2)17)fHDzwL564oUddmURG~Fk1Xvb&q+b zq?WC%srpJSMez}>=Ki98lpvD=a-3f>gB1nAY}wTZ&uOg^xNnE^b5&8OE3ZKu_LFSJ~Jaje7XB~LWtlvT=?2c z&2HbC4yv^dhOYU^>fVY(m+x4yUYxiKXHz2AO!ctVd0Uq`^*WCt0MAsWrn?&Z$6z>j z^_CH<78$&1P3DV#n)M1tMnTFcc)2k1Q;5R!_^I+lDJX}|!OTAk#3djBZcD&KEDM%7|6Zb?#5&gasN^dgnU?C1&bG}Sv1<%sc zM{WUiff2v{wQ>_mO8W$_YnZ()`Jq$F9o_G_Tl=mnj8wvZx9!0)w0R36CQ!BXGU*Uc z+^RxqRuqoMs>RA?%;HkP&8xgvDom2I_54@31&x(;S^>6OcvT{Fyy+g+7~|z=W^gyd zge9(*1g1u~ZuG`upxsHejvAWIF0~T!PxYG$k$x>jSACnr7`88eZV1y`KpHjvQKzkA z3?sHkem*OIMJGInn1xW?1tT*zW2UD!zbk>wIv0X=Jc6rU3DJT>lI&&_T|~C*)UyTu zvJW=Lz{r_ti6_-3oS)_ykeFH*?F$2l@U^)MtUl~Rz!>Jn@j?Ibgs7fnZ>r~53qtkR9f;7^P!?naGv z=`v4n%I&&F8s(|*CELs`u7x^23E}VqSWr?K0ZE;Zq+o`vJ@f%N|LUUvPt&_xLQHUb zRgpRjeo6qR<12OEEjmF#O(Lx6wDlfIWUzxXzh>aa(J-62R-cBp~pMWTA9=8q%wNE3*nHGW-hEaq&iWQ z&1lYk{0s^;K9fX^E9POJ*ryub9*^fG>~DpC=yDaa1=DbWt}pfzv6(do=<)I6eaZH& zo;M9rYV`=G$j)?7Y+GWcq#bG>^worOI>}f62o5l7`~hd?sVJM9Y^TN1v(h<-b5Rxh zvD^|aibk$ngD~(Ue=m}oc_)wgx5~#NFU-;2?9afg!X@+-Mtq&if8%I0BU!DmdzgoR zQdzx3>*J3agOUfy{%@yyCm?n@)XqjoH=409&~Vk%T#=p{{&Y;ZO@s6Zz{5N{7|9ZC zvjGd)jNP_~QqtHy%-;TY#sOy;0w?`aU|E%a{0s`e8^5ldX4ulD}Nm_%Ufgk!gbf#WolYLmDZ$`{0UCglf3F zKyku;Q5OK;+<4O_4WkPfgZawEh}>b8-Utul3W;Sad#5~sX#0cgwL;|@AM+ZSsq|c{ z4nFjrk8O!u9v!f=Kx3o~T#)fIokyKp)f#74lJF-GT7p&e$GDyIP6)IiT!Phq45w%| zrOlVv?%a<8lF|C+&`H@exr<7gM2{NeYo1fMQm{Eho$J+Y{1}u zHYSr{YvtMIj$r*s)p&pva`a#ECfS^b1yaNW9Op?3ZmAJ$=g2A_VuS|3k?axiGm6j* zWGSkA%B}NKYc;uH$;~x*lWI?Yv%WxnV_Bmw8lwrteL9-_8AFLNEdxN{L@AY3e81;Q zd*~K>|EQLhVq@xUTp2C?>OZ&OYe7WjjL&v1YHt^+Az;mIRK*T|usi6IY_QQCt>K)a z0r7Ciby93ozy=R447h-x{Su%fmBKwpaKf3%8S^r-#!~eI%|MOq!{bQ}u|Dg5p-?iE~0Oyj-BaZ&q0PsJ+#y@I?{gC%7 zNimv0e~1k;_($FN=XeNfLzjwX%%$S^yZtW=`wyUx8F5R}l~go2`Y+%AK@R*UwZl%3 z2T$sMKsAQpdgBkehVtEiNBoL83B^Bp)0X~Q+h0BgiQj@l!e&lFfnm7sj~>Oy|G@UP z?A=zKN-$LZ!Seql6aGM}EYWCabr>t2K4#>|xn=DE*0HYCHE!}SZXA%&5qbvjY|)N}dnYq&BH zX1N~8O~I?O5K4$YPtdrX=*gIhEk-+AS^YGhbIAtBkL<%WoG#2VFhWwR>7*rHk;Q~H z&J{oBMGStTbj4W)3my$cWIM2e_NA^D_hM{Nwd}b!5;4$!e4|Z6zjL-Pn2%}W3fDd@ zRfCB=P!}-suXpK~kGV&zR)@T4#F!9l0309o5M{~XsrQIAn|T_Oca@rjh_dfAa~gW? zq}+W$wunpm6YQwEw`V_M?=)XG;u=$eR3Q+sz-lud3UCl2HgcrKdE7ExGwQMX|D z-cZUJY4^E*gnHK_n88kteVD6+^OF2oEu2oZmg8%R$GwxcN=JF# zB^YWW(r}eL-tim9_EMEkXy`J@m!mx@(k+nzO+@5>`0H8BzA=8cH`Y%rdF!>Re#${i zR^*9_b|S#+Kr#_R<57EFB*YVC_-(Fm?<2A#_o$!Wk!gvmi@|A}9H(B7*14-O2ifnO zxfNV#zb)+1&*EuI*DqPc0x)Ho(2FzULot=L^b=s&4p{%okyG((z zRuLNKD(DeJDJ=W)qmt%k!&*Sj_1=pF?G3tgn39d>r=2|$)h*l#8|D41P^+=`zPfn| zx~aoC@Vlot!F)Kt9`|DHJE1PLr`h5mgbSO0_SkAy>`%al0oyyC<({M|G)Gh->cHRL z6j2(8%4lW5QjA_ZwTFl)-b=nC&?{ST%~@eA#ZX^FI#z}oqm_W5i9NmZapf|^ex5X* zf8jJ}6rz<204%+HU#y{v;H+A*=iR55aUuv9c>kD;0@MmB(4t+l$X}Ow$%AUb6ohPl zfM4TvtbDfGmb7Z2(6S?B@^?c8(AEO2q6u)I8iM@#&!e#yCQfCt3sg>Sy>u)!*{|Z0 zJ1&g(J3}g(OAdS-80WsDpG=0MFC3+r`z9M!Y%#n>+l9J>a=0>Qc|`+UPnVTUJ%#MT z2#;(e+YD};+OEjyr)hKVUVL#a32#h)ex(p#s6$z#cffyNGi)CawXsrYAqO2==-zsI zeS=aghx!tv;VuU$9PhC3;RviGLv^?T!(zDv7x2|?8sjZfN+-+b@!afWzAiCXcg4E@ z>uyx?FEjAXXYC9h(YFN4;KJg zhdAi?bU@RBIemaDnmgX{d`&K}b1cr38FzwDOyc4hmkW6X7d+y=TdKu=H9-cbD7rAk zVCJk}N>}_k;)4=HvL9g-K=^EV)0H{?hKn8kEvmg_8_H^kjq^+cst_>W_7Vo;qT|iBgE;2_3WdjC~xP_+UD=N$lvm5*Gs^pxepr(6e$kU9l&Z{w7=@<iKL?fkplMi`WT&S$K0=`Q!Ak<5xI$Um#k*A-eQt#TRYpI<#b#*EqswK4m! z{xYTt*3Xe>;B`B_l0Y4vEL3_nvJB;8bj^wyWZgZ`@DdYq%*Ts&K04+WpNcw84~I1^ zki!(j*bSmMJymBh=o&Y;yozC7*kn@WW0)pn2z&Qd(t-% zXfJupQN)07HQ$+kK_3S=+9sTmEc7!K3*cdPGc!nOSNDzw;&pUra#&f|RL+Pj<1rhS zyFE$Lto0MOrZQ_)V)SO>1X-@*V{1^F9~p*83YjnAWNsnhZKV&Zb0bqgdXk%uPbGSi zr;B&8S=HJj8ikRc=*idOwdLYogOKhe=*ss|QXYLzf7zCQafw5K%h2rcwjtCeghYz3+mA*_g4py)JoUannrxg_bb z$rs?U0J5NhXEag+g^&9Jj4iudL)&VCRNDf-#DTR8h<;a{Igmm@%42hmvzLeN;Y1)L z>Ug7IR>O0DstX}O`TD)m`+~U?=e8g$T#DwX_Miji;S#4jY;uo7392<+N1Ezqu;-RV zVa7d~O-TP&hOO<&Bb)NUkfn`;fC;W&{SyQGI$paDla{eNw?F0xL7aiO*1|6)p6kWR3!W>X)Lm5VQoW}m=6wW zd=7SQ{w?oSu*JNZBy=elScLWm>-r>s#8o&}?YvPEgItp{n4HMH4BZU7C4W5;BhQUq zVenIbpJkJ8VwE1ID+#IV51yNXdV|6NJWS}Bo@OR8)v43?EX?KkZX$N58uLuyh*LMFDD=yIYI0d;>1DJ z-=T^%JY}>R4W_=5))^Xy;-)y?{ri5A_^GWL9X?>4LbO1mX+^X8q@#N4C>wPcl?PlpsqGJ0BSJ3Sl>E>tww+>`G5p;56HYsOj zhks6xTmIFDZuZpje(a2*8`evL5MYWq(K1NmzumZDg@x8dvBF*MeZibkC?^H39B5%J z7+B@g+_Nn9+B*O_3C6Z<&L$5_#&HCH+-0;UY)q=D`x26kk1H#r%!dZs4P}tPk;5_Q?+DCExkg#zBv{R!FX`>C_vGbjT z(`}K!oE%7XoOzej#X))K8+9dRX#+FG`hX)lvKc>jH3%v>);ac@R2+%kkAPl(z3v59 zI$2n~C6Jw=et1(L)K9(_8D?no3tLqvn$f{>@&F!F{Y*7_a%6;xHD<=xB) zkY+kIPju@be;s-hfJIP!mdMM0nXS~-MsoYw<{nmbTPC=OeQPN%^u63I$YCck_tcfZ z+>OcZs;{{M)Tw_j}CQY!m$)fRz^6|#5Exx~8 zjE3^P=~Y~;2ab>Sc~{>yqZR4m+~)=ss60Y0^L&*6T^V`Sok6uWuWbf@&)>G(M)BsU zAFD|G1@Ty%&mI=*6$mS#u(9`raEzWiSS}qr2xAA{*5w?u-wYvKcd81-d?duWVE-tr z*DzdPrADiU>7va+3(@v#5hPbjLwEDf+=A?9hucmbMEQXLW8LN;z~6aYhG5y1b!T`n zZ&d&O#KOaPu&8zvdrO^vw5)D+Wr5pRO~=zA1Z~drBM0qh6f%xuw!;D0x9+}^j=bm3 z3^PXZjX)-00w8ohYMjx5;a_9|$2zZldR@HNkaAd+zf)+ru5gENPgd{8=>1RMdB<_j zBhc4=h7W~@e4#T&z3qNd3j1?^ly;*KptMIYJ42buJ|{>>49(SlnXZ&E-30AVcS=m@ zeBGiR`g~aWWd%LbF*w-|Ja13eghQ#exOp^ipW>k_)gp)-P}^e=u#(=YXTAnZEmJXs z%}y{;HV6pA6L4$vr8Wduppyb3K;U zqIns-H?YcC{5s&ufbuW!s6Pca;K)MP9j5$Tb~fdA5rp<|0RcWlf?_&T;;hF-wfWya^#`s4=5jvL(zE z@98n~Y3-7KX9VFC!o~cS+nV2x6Wc}OoB<0RBb6Msl!0BkN{!ooygZO7buIH+Gz{&) zWXg`soS~%MjHM<=XYh@1UYvEzx1>gW@Xsj%Ify;22%Tm46VGZqHCU9Lok!`NEz!#h zLus$nH>)WE<;5vPVEzhRjsaEUhV?pQ4TxdUHWdMXJiG4jyu1j%<~ISDdrhjJ)U4u~ zhH=7P67Qd<4nPtP0qbL>L-CDOD=qdLr}vKb({c@EloU^ZHg3tr007JUh^W5v=Yg&3 zseloM^E0S!ue0jF{R#_ZahTIl9InZ>4<=!33f7Bp_Vj6NCA%m$_Pmt@o{r#g`Tfij z%v}?I7qF5n6bgsUm^(#>&~OnE@J3vhNOfMjhn{5utP+ebghx>yGLPbCHZV3(fdAoC zi_$PcASimqjY{}#nrv_Ria}r|)zI$&J?20)%Hs^g_6Nh%aN3vrct2v%aSN&sO2vF3 zrr)lphn?26q!7hM6J9BWHNcm%6G4AV%geC>@qGm_=C&%FRl<0?9#7-4Q)mq zQgAZY-?`?VTX4mG?J{P59};I6f5SW9zv11gpY8Sa4;vJoiXc0`@rRZg2)EZ!8ff-@ zP3yBx511w*M*ZJt1MY;{8Kmu!vKIzqH?X6T9rLDyo&_| z2Gi3)t*N1dJ2uUf7^f!b^J4xAv~K2q5KMB#M9TxVg?{Luz(b6} zocKooLAH*V1pq>s9o+*tqadjXsdebUPS9=pCB6V$Yorrr%BfBlyO9LT4&lV6l1bXD ztHEY&Cf3VG13QH%BHWJ$gEWsu$Q-``WcedE@n(-CHIE;2;Jqx_EME8Gx`n|4- z6s@lSI>#MG-8<0AME0c1ITO$9S2b{CI_T|Cy4&6kq=px#7ABh0Fmn7AbWSz%5M}!F z5ZOBm6-H214qN^WCJc#~=oUF#EnrMeK$wA`__KUA3Sh+#(7F#oel!fe3rR#=QV`;c zPk3gWvy#Ii*7(ASftl0uobj`N3QE;M+43!1=3a-1uW&4$?5sK#M|!fNPuWL}4QMOD z^A9u`8N-5p4^N}Hds=mi-iwA6z*deXlo*bP_2_Itn3;;$y9{bC!~^9BM2cZ^)|F8Y+9_}y$8 zX-RIZH8}D&Iut9Hc8uD3FbST+aME8aqZ2PPOoFjFw`Mb>{#>BOAJ{US2EJ5%ge#** ze*_%!DlV#ML!5vb&G zlYEN$n12flp}ACID{dN9zOCo%QB**ykfUU{Ep-74k+PklVqP7%mY0A4BPvpC^l00a zxWNMqN%n3?GFihxCYidF%DwLxrP=W{xa8VJN7W>LnzAPxbe6S}Yn}#rocuw&AD1iN zTD%L_zw79V$*2!?+MDaBf5to0dYyrUg1#3)=v@S=fS{AG_-1A((bWTvag(7xm@~mu z_-SGEMBf8LXv^lBUX$6e5KVchRm0NWv-)Spsvi@G#*)~)4OckbL?dfyAApNRpIM&p za5T6n@zQq~m5cyE?-da|iGMnKr2g#$JJ$b}xbcxe1L)mA9!W*R6Kkm5~PAQeIwK8N_Ff8sp4Y=@pbiDY~<4 zsr4q=w!ANX46qku_sFyC75&zlQNhgUBq^uX2(- zS=UfN(B&H*e;q!4rWDY3fXD$7>q;hhD1Y`)#1t+Q{5((;9=)AehFgH&WOzSQ60lM& zPsE&sV67i1h(T8iUQQtEfYGHCs4%6qbr+;KEQA_{X+0r4t*Vg-0+l!}NI@?p9-JH` zrYyR7vv>7tVh2`2Q5?WUY&UJkq|-owuDQ%pL@$I|e`IDPIF7m^H0IZYySa~|o^qCY zjlm3KA{8}mo{f1V#rlCAEz{2h2|3W1S(9+W(b+Vo&Ez0eNbaU+R->P zVNd9Ve`_+v0N77&_|K3nFt7W9k$CmR8}kK< zThsmVCVq;Gj}}7>m?MDv3nEUFI-Ji>8P2`ai z0+JzqBsqs?x^x{G>d}bA?+QY9`-IwybJ}Nee}S}0&pzU{y=)5;6xV&?D%1fYa4%bW zRq^1mxo*7>WfcqasD1qyJJy7G7Klwn@&S=z6qLf5U!^4JYzR9qpM!>fG)&k-|i??L^ zZiVL7Pn{=gn*D@SW^u@mGrnq_Da92MJv<;-p)bXJc2_!}rip6a8*g~WBmO8FEId9M z=@ZZcT6J@35acISxcY+`xh?vYhKG*Ze_eijepp@f)ax=sZ!`sJ!`VW;9ShSHp#?FX zbZ)+a{?vW~?~s}^@)#InnrbW23<~`P{%YCJ*mlq*U?1OiL9E7+=wC4|u+Ku_d=8jN zh^y^O)=#FKm34CgZiBdfdOTqcq7Zsq27b_`YDW>>C604}S(9g#30Sou;68Q1fBAQu zemH-qQOcaQkoIrL4ElDk_KkbsFe9=!;iNyWAzyr5fB z>pMS~o9;rDSH>RJqhrO$f6AiL4U{Nm!qbhV;r%*lyKAzqiOlla`Z(;)y*>Mr8JjDY z(0fhSZl-WMz-XX87kxP!RP{MtumsM^g&`kdW;HC6rzV4q0+388hH zG0?~MJx~JQjpAbV;ody0=Xje~wNlZ-`t(}~pV>Ja&@s3Id|7toe{R1XBAt48seMnw zb_i}WV+nSBuf?K$AJ%KnAJ(?)8;RtNANykxC)%<d?_zEajndus$~}6|i$#Zz_B1-LLaBW^;k1&O zCqRPic#;t$Wfaotf4(e`a1K=t3%Md2k5pl=?X!F7Wu(LO!m1RL&7Wvz^{nHnRr46< zbb;Qw8yKm;P7|O{rgVoJ%5T?MjlD2@<6HQ8J7cpZ_msz!Z;V|a=O)S(Ieb8z;^LGX zo-qh5vrqgirS#kJATPVqSstIPZc~j)mKB2I`gtA>$t_!xf6fu`Qi*-d_W~HtVe&jU zPgAgWW}?5>{vv(6OvYER3$07moa^wNi*Lp`4af1_TY?_GA0L~$T-$g55}$g?ej+Ho z+g8){yZSbVAS~mRB&)#N&!{Su7Bt731f%@iqOey?_|kcHt#0UUUp_7C>^h30o;QK5 z-ybSH1-p{rf6A0~i~OZbbGHkdd)0D@;g03IzNw}AJoYO4xglw{w|UB*ne5bxH{t-M z-uc5#y(xw|j|6p!eV}jA@ybRonWI8BIL+L69$WF*4(SxAYA}BV!lK4o>{98tq*+p@8gV$_#?feyFp*a&U1xPt|aj^JB54L zOUlQ2e=f%lJpl4PH|+RO5p%yCxQB5z-FOMyYj4~U3&+bKT)0rcnsaZXJ9&%75aqiz zOQxki-ss44v#UL~v#*-r3KKqH@8|f?C{IE+3Z7Xg^e>p!GB5Nyy_kblVc6d4WAkxo zeQam;!GqlU!M`mne`5AAT@P=L8}@8$2XiR(fB10pik;fa<$Cke!X3?HM)A%u;8cmn z3NJr|9n~2x?v(JA0`>=Hiuf`;-f+*&{Kq@!R08k!V*hNfJe^(EL`y>9{p>Bh%?^(` z=fY8Z)7K(g`=wA00XVHHFu3tSks-cZ-O}K0;5{!6E#})i$gsdz@##URmcTXW+UTP9 ze~zo_-Rs;eTys~My?4CwoO?1xEloz47z5Srj+Me}qck|KyO^?jSuNkbS*KpHL=T1S zb7$UIIcv?&u+sIpPs&W^RkFS_JHI|(VRyG$FFuyp5;ty0*iWE2pBM6I6`xb59Wu`! z`c)E5xjE#ME+W+ENy=Wi#K3R4k@ZU6e|4`W>JOh#w7hGYOhTLWogM4Xwn;OtuB%Jv z1s||D`&MHv~Ikvw4B{ZdYmozYCPK=*BaW zlkDN6Yt|0ki?KCcrSp$qT9!c}7vtZn2<6h*+~+vyRU=1h@u-*= z>&M}dpVxJ!9v+{5#-85avr(~UF!KUuWfzj5`p?%VS4{h1lg)RhkwkL?|Y2Di~(w0RjfA_lyaZ252Ge z3Z`jXbLEaF>0%F#Ql!3Eh<+kfVr?J8;$t7g^Rxs4xt4FUcj07NDLdXxD}#f=Sc*4E zsi{(XdpQBIxOz1(tpE_le_F>m#d|h4y!L5D*5mS^s%OLbyG3_TbmJFvvfIrUse4Z3 z`fE@s%vrN)#+}=m!9kf!34tJ%E zSf-lWanu<*15ks<$HxgQkvOZc-8Jg)=$)I&HoCZ&;wNq&fsfd|e}0_n^RaJ|gykQK zUQ-IHCLg{eZ+PyP0#I%#Yw^+@=#;`Tic2X0QTlpJ_wDw6O?&C7j00BWbKX?GWAA0C zS=+gEv&VN{>C)q4f6!lt#++v{ACuTg>*jgLkleB9lwexP50Pad1uUN1l%_OK>7Lg< zmNUhN$PTWx9lOi{e@{5fIA~{m{HA(33bUy>A*YZpQ(}+0;SUdb9jVB3f{Kj~!|`F+ zN0}@){xKPvaA@LJ&mqz4D%ut%hLrHQlFDmh6sMR3_wah~1f%UuA0o|rXhRCaEc1}3 zWtCN&d3s;v*?FmYnBfPnhPdAyI!OvD*=5JeJ&#<&yRLOIfAaUT-08>d_=e*yvSps4 z)dhQQpGcP=3WKB$(PY;kLZ6-Fb*NF$gDyefB($v;;BwvX4+iYpH4&Na_MsdxZ6^4# zUl9n#S(Y>rt@b4(em)U=1p^4-;Uu=oK0D^O7)OD}9S2vW8|uuuO<#B})Z=kv!iv1* zRn>FpC?Dzqe;!%obG6HTq0&t##!@w~I=_GI0y($Untl|rDy}l649x=@d(&~+bIdNy4S-P?$y)!F8F*W(n2jC#y!jm^IVxD z7wyt0oLcs=N>(IK)1f+&DLcoxl-1aC%G(MoJ*Tl?Nc8E(MDwiZ?V#?Y`z-Bx4R-=Rci? z_Aw5JO1T^bF{esG9WMrDT>N*_3q3;oyF)vfTx`!RqJ3#7O;COMwhcAW+=Yk@0%oUP ztDd@Ff7^wV$NfpJ;+Rrp&u;D0{-mmsi~x{Z8oz5vMDc^L9%u#@e8N~L9BpinZ0(sOwXOEb^!qV$*E|B z;=<3NP8Z{Ss&cEM9v8!l{AXlSB6quMJAGWT_HM?PD!(p+`bbjo!4`y!gdfk>V=$JJ z5_gv)1Ega2+%JY6PUSu=5N77&BNq#Lf1aM)`+eet=esDbpDQHu9S-SdbZFMGney3j zC+glBRDIye6MCJRtcdrDWfv-lVcg1zWIQ(BMP;ck)l6EO`CUa|Y~^8wv&@E9cQwB|>pyGn>HR^xDD<#Mb9YCT;e z<9^F?M(wR}FrO=blX%aTJgB|%Hz-C`h}VxkQs+qBiR0}l8Ag$Sqf3JMwkACDAbdLC zcE|C3TpRV;N4wMThNoFg@Vp81Lr zZRnWYJ{Fo!-Cx{dv5gutoO!`nbhse*>E4y;^t@#&Rb~@Rkup-F%Zitk`6N5x$h87j zRr20?sz<{Cc~LRTwH1QrH(oOx zjZKbM?eJty^@{_FpJ>z3&9r5=yQksUg*WEauM5v#_~G=@eCLD(a@50VsLp$4=xr$V zA4==a(Nu6;(XL3sl={>(U04S02F6?sv}eEMO0!ez>W%_Fu3Yz8o=#05i#mG-L!B*Q zoYWg}^@ea`!UC54Dc?r$nUC#DkV$(_NSvB@)f}=S$<@qB`WS~N* zjQ1CLY1Lg*!@bxGmS2zs^~>o_+jYaFB$!m)>leEUaqvjXIj%Z%e?>9KebeU@ZE&9_ z;9MLm;c3NV%75tyPOzG;Vr(5bJ#`|Ct+`|(BXMZn-0AEFO@L)%K$-cWe=it(jnmaZOUUyWO^Eva_ z1{>`dB6X53rNX>3KPI$a=8#|Ywt6%7WmoJMnL8>WGw|}se`ogcmG-EevOaU_^5Vw2 zw7IN%P>u&JI{tjBrrD>BNxGqopA2uj25+yZ_4PD9()E7ys&=tYI!N<{@i{nq;dRxR zpvwr}f7ti^dX(PG{sgt#Tm+TC-S-KDyON!+EX$;K;kuj;)VVX33&kB?ZAiVrXUSCh zFj8j_?u5hbe|>z|)ra!LIE{A`>rs2^Gq5_( z;TTNabfnm10DK=;H~9)!oVw0&*Vf~h+xPRsbOy^YPf40g3EIgYzR3Gl0itxYrPuW$ z1`N>L-q(Z|^*EjG+9%|uo17Sjt9Ni_yE+<_5!WLte>fi}9`rp$v!>I%8fuqN5r3ql zB{QiV{`ozjI)Lr=r@ucU{Qi_r0iyl$yE)$a`}0B#AOigD{|JjU2vayux&+>|Bm#>E zERk4%9Vj&@o;(2>7CKGg4AV*GNy@=~QuZW&LY`LzLLQ>hYaOWfVhr>*?hWydjRw44 z;;NZ9e>`g9j<*cFK*_Xhbz*4g(%U<{e@Fvy&FRER$HCosa7H%q3{O6yjP|%vvrt9* z)oeOwPJ=Uao`~W@QU+M|`Y10GO)mI2p0l_7(Gt_UQu1+1QCYT%nWj{EFO(c*GJFI| z&u4Y{ij^t9nB_ZAxaRWq##)7G?!dWIb)3&0e+|?SU9Tm(Q;ASS^D$HB@OJSitRbE( zl`Ls-SeByl)~=+|ME&!7FJ=gU*jHClCX*nXFmS<+{KsE)Qpb*h#52K%|NSZBpBth> zo^2MaN4|_bQ9kb0>i9W+By#7je1SgH6+CX*p$ajzrzyG;FMVUEghTReXC1HVnSz$k ze*>)cz?Cg-h!vwz?$@UzpA9#eJdJ(hqZ0Pf$)V9L4Ok z*?HHURep}&>1EYlsU}!0rBn{zN9NM3Put7`6sljC~QOJNK5*NtkAewR=GayWGFJkZUetv zexOb#>G%~{eIff)_ zOkc956N3Fra;xlTOF|NuFn|)Ctm71>+-trQ%>cHYhmhn7#L@ZOCzMQPFK~qPRyC95 z2C9W^ren87k^wR|Ic(eYy5KZ+Y*qzs%4L_4kMU zil1=_ec=tnJ3wis?m#;NOE+ zcDJw3=<~RT=SP!V9(QInIe}%6&IlXUC z*Qx!C@|~dbT;iZ%UTX{F=bcwq@1TDN`^e97&aUcVfoxD5&%)n1}Nl&k^lep$@S>L zu+~d#hr7MtWXzpb(dh}O(XUnqe|<^S{SX!||Ee@lXJINTD)z1rD72WKXfPF~_^d=+(^a4{hegPD zhuEO5MkC2kJH+Vq(5sAeH+=nAP$}DYyT4i7zA?r!56=}pWob_y(W+lw(3V*4z@NkP zNPIyuCYZBSqMu7`93w41$`;={tg|T5`}i#0S1~4yazLNde{nO@?~$`y@&p19a^i=0>$RksYeTx~(I@2~K6bPycT7JC^6X_iaE$X! zm=wAP$I@|5e{3cd#i@OZwBO%hT1j%7D5A%RD$pII&`$8|xq{pKnIa&GQ=3rTFN3ib z7xz70Yv-Pwm0jobFQZg~;(c=UDrc03Vj}JW8dYcPxvO8CdcaSsC1*J7a2I%7eRaUu zan^n9&e+2`Sbw9YKLeizUr zbiG4tYI|K-`()Y)?4^7Vd@huOS=(4U51xLGb_#WRwbM>}m5=ge_YQX#_35UyLe4Gs z=Czp0?)9)FKSHgy_t@wz*F_XIw}l&?hxocrmQXSk`d(0TZTNnx2LaxJ+f637NQ~Y0 z;@0Epe^j}J_^Wc;1xko?)wISrY{}T3u~J<18@!a@@Optlt_|GW7QR3=8(#%e$+d18 zC_3O{#0T!Kw+YNm=(G@w+uXIMWpD#ZcgZQFvGp#&wE#u4uzjS6y|1ke`F5sG`|!E#}-CX716lQtL)%jSH4r~ zOO(Ilf-!lGdcV^qadqq98nG;3^&|=pl@FcAV-<|($;suCJNzM9J-Rxr-7}1Thc4)(r<`d#j^uNJ?7SMo!r^nasCA!(3L8be zq<2}pBzj_to?m=$$9Y}4X!>5F@Ajcnn_3@G!~5Ae#b(o2PC7I`P5g?AHMcFU2ZTTU zu$T8vd)zJfv^KFc*g*}N^3pkvMLQSTf8!GuRUme!hCA<#AfL~1Vd6NjQl?s23N$az zqDMcxI;CeEVfZ+)ujY8V4%NA^9qxK*nqqeigL_dHAKKiJ#ESDLC1> z=RmoONs}%a6ZG8ka2q~{G(Hr=v5)77j`|XhY=j$57LS>AO%#jHh}p&WvOZ7ue@YX| z$Lj2vK)GpwL=P+xcxc3$p>)ot7!R#Kh355fmTuPDv|aXTD3Og0dfK?z!&$W|Gh7NHGJ=f?ytFLB2{e}i+JzVFp7 zi-!B7q!0M=rXMwZpx49o5Q=V|Fbg23_g#6%YJI=ltvtWN4|DjCW@*N}L;AQr7w;o= zN$Y+5N5oG;-7K_I@TI=L9TKzR;p314>-4c>){449^eu!Z?nuB+%7vwN}4@6{hmeZ z?eI~pqc9#${Vk;@=xuy-l!_?jDiK`15yzCzWRBaj4b>COF~80}mRh5}*YZ)M z(_6QHoXEj&z@9cdt;FS&q30O7$`GbbK~-)zn#S!|Cc6gtr$__ZfBWT|&GPV`<;`JJ z7z2=Yb8w)~H}gOpt!tqP-f2x}{3Kv4>dPq=hj2E`Oo-l}Jv!f3BRDK4ne!e3Z*~El z+FC7V!K8h#SWeXkZ+v+Ibff9;VNI6QEChE{M~Mwy18@@!E$tsI1BRHj9y3X)_XqB= zAnviSaN~W-Ro}Nf1xvS)dpSPDYJU+mji>7IXx!4+ z?)`HcwEIVJS=wha;Nzi_gcZthI-lJ6$cS#Tirf%;ucyM4fBNY;TC`Tmg zZ1gmb_4x6vl39NHn2#)hA85gnP6szOYw_e@^eT=|1ez>3=_l!{zBMcK(0#f#mVDHV%Gn(b`y;Qa-K!b=q9{Ju zUS{@(e|^eu+&Ge+7IwRx@wyz3M?SmWZsS@KnPp_1+R=Qfqfk^W4*`u5G>ZTLPcyNh~n9oOwo+tey& zdw-B;N>rW|tHbXG0Cf4bcI@^$08GChYHHiyuJ1=JK#Ksd0Gt4@X0#$dUy*Mu_ZBY}(IToC7H~lT5cv7& zU>Pic2e{In^y$)%6&1r4PJDpevgfavZ-X4o86eLh;fiwxq z5&!S6fv2DVj3u(>JiwX)h$Wg8Edrb&NDuSPo84s^eSJc5RhF#Pe_qqg-bF6M zaPuRa^3YnXNY%syEpnF#+v}gWtMW>( ztWNgQpM3JL3g@q{>MiGN-)gtqvZY@?ZpYWwiUR!gh3w(&`GVGzvBg{GGs3D?O(9K| ztSy4q%2%+QPuoAee|O)@LLEBm$h<$g>;> zv)i102UGScM&7l;$A`UES*jI3Z|wI0rF+gV-pMr zD!B+rGa{hDF5qqCg91&*-J`^uId8-ILf~%uDx~6(0Am9$3qS~v03;e%eq&L#pI+rj z&;Sk>V?v>}Xj}X*+um&ZCYR}I)j4YixYH}Ef+UU5qW$Cye*yo_1pue?{^wYE{>__h z-%G3gySEx=*C7qEY<)jy5rLTD365mks9L3|q8CO`6#VZTpi)pIsCf$R5mjiiILUd3 z(e_oH!K;9+_%nEaGz*hlhWIKW&rL>4v(g?|?0s&lTm2_&##uKLofj3Yk znETR1D^y^~f1=g$2%xK(oKka6v5JvpiO9nUd0GH`YeUHijMT1|05&avQV;`p2jI!2 z(cATw27pz2fk69-w+$;`9?SEFAvtTU8@8v(?|!UXTw1Hf*<~L6gO^p_ZCLTG3%_yh z5{>)8qjY<318D1`teXsd)lXMP36G@8ETcotYmY)*LVa z2xI_1M5=!4moiL~1On}a)^y#lLf-cI4-Wt0yDeIs&L9Z_8DeZ9eMu!yPB$=VKAHp< z5@Y<|YYYMbC8!|gx4gOlkgXEYpj8dB4Dz4ae_d~NJ^xcX|Kvi1U><{*SAE>(8X=nY zm~?GceeApH$ef>^!NN2ZRZcZ z_I@#Oi$g*DS3G%0+-jXCfd$v%d8$M}stz=@iU$c0=2%R$cm$gEd+tvOatH`UfP`KP zf6xI0)dgWo-Oi6EbO(jD;kC7$-vHXr`K8~Q>0w0`pjB$y5&=+Z}z&3G%w!@ze;feTR4~!vSXx&VVi_bDqB*T3j9L{6whqu; z@`PL`$kwU`UI9|ni568t>;K1lRT0wm#$*8oCyE~=h3F3;Y5=~hGn~+3tT}BjXp6;P zdj`t^^KQb9>r`N#q|-?fu^Z5ZvuiE=nbTKXregNg-8s)snml~inzgPf1#4h zYrt>)J&PVJ`2s!^4DbX1hM3x?fG464AlcSqfuHsKA3X2sfeAw#A_~W{^qB>;@|r5Yd85hrv!U+mFWV`$b&O;y@D{?SDFe4 zLK5sR62K6U{Hun(BXJ!KG-T5qf7!a3WK{#V<-9a$)ep!1v5lQ91c420h$KLMa=#&1 zDuE>djATH|5E2Cb$*(UT0m1gUBL04EqE%n~V8M^ye%B3D*rvWbArVBmD3-miU?fw| z0ZDG3A)HE(I01wke+nh!&NGDC_ky)SQBQE|#bp9#Aca6Q!-q0W0My@le^P*ryOiNS z{?J$a&4-Ok%1ipgAAj&a`qr3l4cK@l{;AmnY3`jcD()c^Ev`xlr%f0tB1&QvhuYGF z;)F$jHAjZlS%Fr#VcDi7mL)u$m9vHf2rhDQB%At^MI=(zmw#V&|3@ z$g}1YvfjA+K%m3fzJPMt$)zUBQy8bK=871rCP>8y4li{YRH;mTgzH5hgD+QT%NJx} z9s;jXsCTksyl-A^5)~eaX#uI<@?b;+Z5)XH@|?f*;zy@_wLl*Ke{!8Kf0qMm`G-UP z`Fmx3Yq=f#*Z?AnHKty{UL%Vnj75M6AXsyGeli=`vEUsV#2ZUEi?9@we>B}?cR~|^ zP@j9PD8gwkAoyT>8lTjaG*H0^U`<9OE!62pg87yV)p-3~+xn(Lz^>$Zf4rPK|fUyk0Nr|PjQ^a&MNQ&TAUp)E_%AwZ) zvJ67EI!zRtIfCC@@wnn_h`#^eGR)Wzne5g_HhPC z7(g-aA+%)BMGW*T84xoQr__MJvJkWkJP`$MIalF`1xN_M-kd5cuzt;#&?{J@63Yo7bKc(u$OOXf>0zohT#AF!2*sB3aV_4pAcJMl-jn!!| zRYaU(T=55un&4+r|_F^49Nn*I%Ye^_v=G7(&drR;V=?AS|;butfTc zljcYPt%h(~I~w25o(X87tZ;wG22w$ez!LD2Cc# zRoi+$c3K2*bNLgA(D7f3}Np2=Lc$io0PE-s%Akpf{W)@*1f( z>JS0aUpyIrO2B7pGm5XAHJ7H6fhPUsgMVZ3SFiuX;BQYvU(!|&aI1eY=v&KvG$-D2 zFsHZIzxY&!1(cXBU1;+eTE2ue84znw{Gi##y#glmu`#+RReq65>?l6Zh~%tT9ueV$ zfA7lL7+XAwK)3*MCTEPIK_;C@Ha>wM^7xPcF{|4`L_m=1qv4@WnhdM(<5WG7YIhg; zJmteMkgF#0;c(FaZTy#b1>pVN2Q%c&sexO(qHjD}@xQokr`P#E`S{g>b;$H94HZnr82sRS^7cne)?H8wp`iQJgGQ6Y0XMi0YKU^ZlvurzVjm zFA--ns*(Pd=SG6%o0rMNnp=CA!0+_{o~Q-@^cEM|+ry5CwQv6ul1(4|sUub_e^1}O zp$jUl{c5wXW^*er`CE?+O@bO${%}Sx`Tq}YoI-cf5Nr^G zfF(lU?iP?j2pq{?3HiILXQapa&*F#F`>PWU7E`B}lt6 zvHtY$zWD2IUd$VD`r>cD#q(mo$^GG_zkK0mU;fsSzuYMN;qvKU9<-**e_vg?#rcL| z`Ii6CDsdV5f-Qm&feKvw$nGw+=OMD~3EvrD!_++TJ^lT^^}WpnC$^^{a3_)o_|9W& z%aHcExP+BRkO(WXD0kaO)WHU1<4NZbmKFj8X=oWczEKQ#2;v052#~eeEm)XV zH@kH&js9w*ltE(ngKdBLf8QTW+y0(xd_r3^?-$QF@RzTLzkSDVFHB!ju?4y2vD(!* zDm)0Jv9F%wIg(0P25*5VO?qz^PgVm@XLen2}J=@kW%1WpKwer}@*EEajZM2uw- zX#qTD6No?r@JZBGZGWkI>*HLBg9Hf5$pYhXDbqfKSf)UUQyV-Sf3Zn@5fJ~%X~}Oq zKDQhiHa;a{U~TajfTuX2Egs>Y>lWyb{Xey-(--vf?aP1lv^HLae)v}R8z-u@YEYYe z2g2L{r_cv0W}ugv5CTk%c?C%C!-{UDDb*Q(%}>*8+*TAJuNvT8rNp2&f65>@)wl_N z>zisxNK7Zqhd)|If0b}A<^+dS-DLshl`Ytl@+@coNI>3nv2pwDAKf>Q5MTMCm-Gb^ zu+=e6uX68;Szljo{ft!ocaL+kOPj-=y0!U~SgTd@lD*>ZerR*VZSR$VlXR7iQ#1+E zqj{P!Ag>OnKEkU9o3|a<9Q6CA<4rNBQy$WL6JVTxPVhJUe}?#-1`=aR*disGCY$gG zG&}?sT7oNn=~b{(iKe3kU+lUu09MlStrhT`>VsfB;}d>W&ISP+()qQOmjZhe3>0^RhrcjN7<$8Q`F z0*qike{HxKo)r-K5F5-ESKD=2P-AhJHa(rK>YQ(J1@*;>{?ShV)*=75?ILh_`I`J| zok_%e@jk#SnusC;3w9v<;j*O$A)Z7RIOA78c}=>l8}x?wi|>kzbpesB)^4xU#l~yD zI!fZG6E*@cAYg6&S_JXimny*@jl0z`7yRMef18FV@t3bzU(G0p-+sjpSMdID1^3d@ zc?=wYw|tl+2ttI!NOfYSN?CeRChe|&>y~wn*zI*ogz=jl4h=k;_#=W4B2n`&z>>6J za&z{ADB%_0^kYtzyj>HeMzHaQ`ET4AyDcwFvc=s${crAH{fS5m{#-x%#q1wn{MEqT zf4_Se*Bq8uv?cAw51#PV4d+b<{A!4w$L5a5TbzZoHCq~Z41Z!rxv8^o17H2{eNJun zIQgS@`=?%|{ok1T+OhSFBzCg{ZFWrjf3O4m$hYfBe&n{9c2vb5@>zaL_Ih-Z+a+@NE6;1r%e? zOB>n&+r1&C!P1ab7+*~hif{01`&jQz_^JdxQ6MI)Gg&68^F#(AgcFkCb~Cd-`Sha2 zHv!y_4*aKI_OqTztKgLX&pi6;=fqxl@y~VAA6~*saLS=fj1#IG9ui_QKpQRafA!m7 zl$N&n+F1G@J$Ob{AQC7}0&=C^0R*u@IONKNOfcsdPMRoU)SAmakN@_X#M`WC-yRgG zlqwY}-_M~4EGUr%LZY!g-Cq>yV0{$=hMUkA<&9UsVe^A0Zhlz8tsngVun&3L{vS&0 zircxS1dj91`v1hLl6st2f}cJZfBtW4BbVKAJdObWYrnZvd=rSa{noJcdmSbJ8xI@y zO5f|Eto@&2@rUzx29fav$%tQPS z&n*o_#YjV7??@$5CHbm|1i>HvOFA?WvHjYXs>qXer(BD{WChcWFA*Thf8QL~wDPw< zxb?Udk*;^oaDv-=Alas)eh$`TQq=hGoct4y{1%Vv7vKNW{*-xQ{p7`e$Cmo{doCaF z-3RnP_5sU8kqNK!IMlxDn>^>+OZz^KOt&PuG!ga60Vsl>95=-LUpa1t(v2sQ_to&q zUpp_S>JRpS+!Alx3d&$df8CCU|AGeu?5JHYvXf~6XaQs6w?2p@g1>qTiQ(4c{pCkr zd@O%#`s(uE-ut&c|KLNtY1@!?2^v626!>uN(u8$uJPxISGHFr|==_!`W`XgRBbT={KbU*dUEX*4zU@B7~SoHLnZlDU#A3#5VW>guZM zs$UgZIm(xdgZL#+fAx*|%CA%HHa9Y{W$I0P5z6~D*$~hl>tAxf^0gj?qU+8;HF%s+ z`yibJ{mxtw2m9&L&?hw>#}&1GRDs{D`FD)4YWyS~jd7o7a{0wefA~Whx>s@cjW?=X zoU1+G5|S+R#@1^=pr`>@nL~vpY#ex6OsLSLO1cEURaGVYe?2#)wfIOKGSD@~J`oEu z5h$1PjTXcv6**>ey6}t*orLfCGFzE_TN}QsFQqUTpx-tpG!@(ejJS3NZBt)Nxn){m zDyZ_7AcUc*gn(k4z*sj0R}(Y3;{LN&L$X3Dut;*tb<@0QGuWH%=%e-hK#8) zL6|lOX4d*&GuuPS56CAz`n6vyc-zmlueKT2AGon4VGsA*+ zHy%@8Z9-1>PlxxGb0)-@$#6o|IG7y9x^|2^lc!js{{6P;GO-O_ZUnxf`svKqeb>+e zg|@ulf2j@xTx;UH7Rq0{mcN3Q(Ad`oyyN^ClYjUfvf5tRH@3^y8h8CVuJ+?I?s~5! z`o{_glDDpr8B}F7BZK6ZjZIAQ;p#!D>7qorOb`#z=+AIt%5Vw7X^kJF=g)jH0X`t_ z8&t(x^UI!@wl8o2_Z5dZdorrqBlC~f5iO6qTP|(TgNwh-E{hbfCVASz!aL<_khQbq78ha?paT#^u8e{KfP&?Or2K&6fi0`D75@jfA5zKR!fA9R`~ z%#wDGreL=3v)1D|K>N)ga=?{jo~r~2rd5kRgfh&Sf#1DkcxA z)7&e@{P`GlTv)y!Vr|XGdu#e3qMF`n`h`fpn+7!wV%F%K+TV*h9d!!+Z{~dee{BPP z+16Ai{7Yxm^2w3nWT_g*()hos8cSHNjR6G!M?kp0Ic7u*d|eb%E=xxfTkwM%_YEe= zq0OYwmc8i^B=h||o=`TJ>QC;X?L$RgFjkmE+zqV)5(;CQE7t%yHbF2(MpizBu|@@> z6rU$nex{sODbT!B4v3I%{5Uh7%mvA(+JC;YN-*99rBmamYKNc0kndgGe^ug}@AV%) z=fc~Ey#`}Y^TRjRPg5N6Y~~NPIsB5*!AO@EBGsC_!X7+#({m$3$J}&{Fkn% z*S_#x%QMjrTk12P(s*Z9F=sxr76`KZVuhjw z-{bq?RY&r!C+c^9;fDIIN_tb#;61+Z&JeP-)fH{3TpKWMskjdLXZA>4(qJ6aQYVRF z=;3u5!PsHmSws0XAI~5YhBga{7Yt5QSyHOwGeTPXaD$aWm)rS!Uw_7R!hKGkYY~(q zEsc$Wh>cz`N@pdfdk6siyxO|`DY;Yo;}r(|F(0Ah)qY+TX4a2Q>;GvhB#qAU#o>*E zs_jPHFF?rJo=j#W7~dKnBEQ)xtm6Z8)}39ZBVty`r|yHtUP?MpTn+S9)&9`&+ouJ5 z(=QBr(tmFJ@!9NJK7Xgl3i;1M|9X;>o@)H-PQ!owUwG(+{(Q@ow=YqX?iX(NZTmE_ zg*PVn@KSt1I{C|1p@uS%$WWLs_i6<0j4IbRQ#Padjc6FCl8l3IIrICg7!Xc$;_5`k z7fT|xv$JMuys!hgo#uQ(DdN4k4PD8IkeCKz#JH~;sJ`0auW6@{sw)F-T#T_g$_jws>SQ=C9;J3_?!`4P>E(%GF5~ecWdJ#-8z*H1cGFGIfXc zr&i-L6|Looi}LH$%mMNgpTGJ3E#u?UuYUfP{n4K}MStO*rya_Oa7fy7K}bVW;=+~E zL53V-z;@O_%-oi%!e^pL&BnIAImG24@&Z;YVv?7W^l--<1;i)2Gp-TIx#^FM>Av%p z&-2Sge)$FF*DKUGdcXbRRF`H1S_!@+G2-Z>@Jyyu5ya86mq1;Ny!K^tyzxEB4~F9H zcX`L-zJIYV-?>Nor1@JVM}1#oo0@o*FEpLR@42pHuXWA{(x;=#o~DUWjWv)lrNXuK z*B}v^zw`GYwd8WWl&Ld=jh1HBGjn_GQf;}&m&`9*jTF4b>!_N4y2w9m%sQvh_)Yfi@FI66>vBv6}X`@4m=U4`MzYbinQdDZs&ex**?b?|eE_;@TC>m@4-R zL(=$3l>58?zkH9|F35rsg;)}o=|(54bK=yPQ&M_?`rY?mynjv5S8srnI#r6BB6q1Q zToSmME?m-n$nV%k`y_t(QJwaEH-5oHB7eSX23msh=+2@1!Uz3{jrhTLY2SF>*&qAj zn%{Ll{B2XAPe&3X{*kHQ$5GEt%M(@Mmo9%&2z9`HvOm#-*F*d7@bj=7PNhUX&^3{;qtdTiC^eEY9Yjf@uF!QEk0(F=&DyWw;a17bQC|j4 z{>MM?i~s7gC;tgg{fd{>I_-BnOn<|7xewTc;MaZ#X8iI)EdIpKe`9KpcYbi;zh(a~ z9YOxYE2ACtJvYzU?T#OXoAgrdW9+w%HPm(!`c*9Z1qt%|f8uvt&x*3~)fhC)OCD(( zARoik_j+Frcf=oOMmo^tV(>lw(|N3$64oCb@SH}ilyynme{T@(@M zACsN0dHCVAZ#;AI-zWcG;ZOflIdMb&@X~Ns%Q@d=4i=roc$r{^{>;x_ZM*-_Lr95+Y#6%z%1{21#@b~@Id<3zb9+wG7NX|B-qXQKV@7d{cS+|zlZ7rEfW*=urBK-yMNJSwE$T}mS46tRbT>XX+J}u!K2*t3l9EXj;12FDivva zwhdloUwej;_G<9B-ecSXS(2^<3ABUq>&Sh{-+0{9-}Odg^ZsCT8@fZqP2Ep^^sm%4 zf5w05jd1SJj;@Q?nsgLno&02p&&ssTzf`2M*m@+;hHfW+< zwC8i6L+r+%B3#)t^8B#DwOPAy3w9;x*0?r-<0!4CWZ!n-{=K&T@QZ!Nt-fRBU;M+q z><}DJFrd7ezd)8uyqL{|eA+7fj+Z;Zpyn5E19bvnLVvNJXPMcI8a;;7s; z8e1$NkI}4s6JIfNL4OVZL@G6NfweWhF|8`Ub_f?*fg=c|5m{JtzjTRs>-a#;C>UJ^CB=B1=_}i;Iy#8W zkw~UZf?QwE%Rl8A8MQy9;lie9aO+j!HF-d9|30q6{qKEq@_){;uKoV#$Nq}7{eh+Z zmCHNt9}t{2Wu`iuGcwNdUj4`PavrKD8!71df*V{ zg3qYdDLbNy&l(Y!bN}8)l`CD0=Y}enCO$&1Kc15y=S27?khsULtA>W{c1$+H^4|9Q z^KE}&PFt_ZU4Ksg)P;Yw*Kv#uM*UqAU_ifPsr#@i(jtVEFB!^D;1|2W!aOG+(Qh(v zh14||A5B>>3b_T!wV?A{x-T#Z=r7&R7i=#&-*(oXS45~4^4*HVhJn%ykr2qj9g!g= z_~{od+)0z+_&Vs9XoG2kR_C(`f_XC)!(6L+UA*zj{eQpt_#0cM4f{WR{9k$!mU5*F z#=WE4_9gnhP-hNqZ(l#7w1~({2=uLylsD_?d;h2cLyWB{@Qd>dZm0Aci*UHA+yyxp z(xS2`W{Wnyq}Ha157&CcKz+W+NhO;&3zy<6pYcZy;QwFP3ioHt}AZAvO zFkPs6e}6)&LK0CdNRSH#9Rv2AovF$N(FSco5=Rp%xBQ%xD)FF}7ryCtQqBj#|0vr9$uS6lLv>1c2JJ7|D!rz4QhNJ!8P>PSipOp{&_4QO=eBLK|OAy z!I#gQ-k&a6N!Qjz{8`&wDvnLmd(QzH3Ja3u7k`q5HuQ=RDkwRm2Gs_PzW7rUzGG#W zA19e5Oq-@)v`>hML_HTyHABBlMBzE7!-rzc8l0i75z+9s}>hXJN8PAfp?~3f> zg6Se8-{aphQc2uJV?ONH_-ok~y<^2FGu~J(%(q5dOoK!H@^4HfKmGFmBSyW_p98AD z>wiJOTKdFdg{`AMzGG`a{GgCetw2$bxvh!hNFlLtKddQ6!f-%>yrdupnoGuOO>oEd z&lZTp_LON;rF1gNi9557pave1uBK}T2Fmpq37x4dO~kXq6YXxlSOO#S!+?Q`r$jOb z#JI-|p^-Wq#K6RTM#IOoJw)X%I>@)Y|9{4_f3L~DSAF|;=D%_@B6t5QA5WPE>vTi# z{fSFp6+mcfD%o0D5>ZiFi>Tv6Ra}T4I*gX+=VzYmX!U$coNvxXyMg9*5{JO&hKO9p zoDPk;N!LrbCeY8yP3EW1I7kc-s(Yzw{veJ17-RkAA>#P02Ipoqe*9nlsXy?9Jb(Iy zOaJA=N_rrwz2+wd^GgkJ@kAvqk!D`X&RQphejN^U^#5s{f^2~sH0>maBgc6&{LqBQ zXa$1Lj7*?!np=KoLF%Oqj;(;FG%biE@EXS^pzbHiK=@v7ZyP!^6>44B1*<& z`r;EU9Un{>EC?`zKRXU6!N|V68Gj^Rm_$uj?BOb|br)p=qfw$PcWRex%(*ZmI# zCGMO^Y1TL{UjRt@0ck<5h~Fa|%(}i#8U5=2S3cD59O{m~|MvgP-IqOP2dQa7R7REh zl=6;QWdk#SotdhXD{DNFY{Dwl(iHyfIQ#_@?U}?H#>u>x8i-p!oFeYa&|hBXQP%k* zKWhx>hWYRNm`tS31m-F(JAWDkJi$C2O-FumF~;Q)u+fJ@h)9AhaINMe{%8wet#(Vk z-!o?To=g<}w%wV_)k@VL~VO^~z=Fhx)aTMS1Z* zw~t+o|B3Gd2v+HKl~&a2w$A?^|0SN@$eQ1A{svcD?;E}`_1&MV!8tza>FQ*R$qn1=?D#ohuvfTM@?9c-dj81Eyn7;`EL0->no z^-`G~SeG;xn78^9w|{c??;ND29>TA@FpNp_-bB`T@)y>adB?9TB9;dbyz5C$SKykO z;2Kf6O=V#rW)t#_1)^h8bBz0SDrJm$`=rU!<_hz)5Aa7GJ$dKR?|qL` z0%MYx`}9zDNWeqvA<7-i&I+T6vl9WCB;6mJr~bw%RKINau79V!*X)n{t8;@c)y=m$ zH_wXLNyoYiKFnsUoH1aQ26oR1lLb}f!VeOQijXz+Duhl&;~xmX3Sm;9-)&XXSJmU1 zner{;n)v+br?${^3KHw;)R+>iJrb-5#@M;RAnevYK+I2&AtN%eh|etsv8gGH8H7_J zo4o$9;w#v`{eMHG-Y>6pp?>89{#w6ZG$3)4dyaefy<2^zRt&1c+_Wr0Av2GRi#zE^ z^EpU(;L@E|5G{4fsT||q8?9WW$??K~G17ennIM%woO5lbvtRg--#H%Ux16un*>_E( z+Ae^E8!#JJnjGvb|E+5>cT?vXLOgPOIoF>m(b5F%b$@!3((v+uMu`e-i9Enju-}E0 zmY#|W6|$z!TJj|%66rGoTKhwDBL$W9;)SC!&(!e zuaPV{gXDV)T>Yj7s27<~@yQmP@=9n#@LV$$CEyYY!oZZFI##b@cL#Oe2`5-IL!fMa z%i$Vl$$#gV*J0LnNAZJ8|HIz+CpfIGs&f{0UpRHF$yN>GuquwfFjw?QzA(x)#%h8& zR_%w@8p9ucAvA)tIW+inr^c%$8H2BUtZzRTV7!r6JR@0QSeR3SJSL&*rO5;&)-B_W z?@Q^QB$Pv4mQ$<^q)Q%XP@cWq=V9k#7BJDXMStmHKAx^V*Cg+*$vSw!>>L^I{44Tg zdV3jrwLLDvh$`y=X{Kve&D8)|CHS1GI{t%rTg|{aN|2zuePH~@@{1|vJ=F1^C#0M( z!2>wB`*)qAUw%tnx;^)w`0`M1Or?H>h1Sa3!vN+VuSJ(!DIp7wjD5YU7@4Twxh1_X z?0*47f^4Tlt9_2vX*{uWSrR8z<>Xk|nbdc0{Pe|EKRFF{RiF+*sd+{`(WcImQ}w?1 zombGGNcSD5;!S^l@QBoU);|0{ZHAc$Q1%hbB}fOEF4>aG$p;m&Z@)s#fPy&@v&r5! zsNxeMN@Zbzwso#iX?HO%RTsO@T$K}o<9`%kL_SKQcN1%Jy?*L4oM7H55y^xq>qeeo zU7`j1f0ecZG5}AK5a%V>CnZPg`&H}1V~r*Ju9Z;l4N^{i%?0wC410gi{o%*A@2v01 z#zt#wHU9deT@Zfdh4wvZz4Q%%*E9AQV4Wmf1408|5kvjX|9Q0xF`akCx35j_u78S( zs8Gjvjqa}vUTF(m=HBmosrIek>ZhU6#Iqzt89_zPNfsZ!eIuDTV15+D{C)1`O$>zT zpkm7j!k~Sx^TiD&@NaxnlULXH<=nb1h!tQQHm=-1@K5Z} z=*j^_f9F@c?XP)U$R}1)&&VK3rx1oq`UC@NUk=)hi`Hv5ni|Tbo4%Or4vN-u1ul){ zuenW`+dflFJ~DRj&Q+uAZC@q{6|ugLbISPP2rAFbKV>M6S$nB`N}sn`oqq?3YxSAa zN;Q50N7VUhGwWT~=f_w2weS7b(_it$?^-E;jk{os+1iIcd%Lcj(kgk*#bC);xMxyP zc=AFII{9*@PE>uShQwNI;gSXJ7lyUTqe9%9$OoW`7bvzuAEuVNUF#(rke?RcyXd35 z=&9SbUg1oW$wc?vkOf{>D}N^+-}9S1RVrS;Y1>ydY52gEce(3x+AMo1W`FCsq`e}dg*@#m}YJVrB@UC^))G^T01aoRJw+HFm zfvBKvFm8BTF-DXVn81hAMUJ%_5RZhkdAc!2ltWJ@V$29BM7!E2}FyI4jS6cS^T|MvCw(sAD@&wvuTd`d#tdD(=vdS&G|ay?DR94ALr9N%%zH{IHL?W+^9MoB?57(XXc?Ws&q zXHOi$%sQ3@{OP>0QDm>CbuC$?9t5mPdv;PP*hKFXZGOow1d@~W6B{jT!T0Jp{s{a8 z^WpYPjZKpB0oQ%UWSyOM-<^K&*wYg{pIalmg`8o2aIHr%r+<+S!Er&a@e4<-smql8 z;+-$Mxv90Jeb;KmT#%pqfQ(h&u>z#~>z~$Z`t}RG>nf7Heh8^3u9oaf3>gi#HT`PL z@r+REheUKNG5CNAh+~n!(~6xwlYJI}Z-bbT^lN{N_c9J??3gcM!oj7Rup3&`y(}Ve zcWIf{bWX$FyMI0lv2vmGXd`qoja>3^5wFgtogXazuE}Di-?_RIlJd^9BF1_j+dPV# zrrsLB82ACgFGQ7>sSpPAlx+97^HO!^NniFF-mO%YZSU!kf%|6;Aj ze4K+?kJaku6I2514UW_a(3~xk7VYC@%)BLtNC?^D$tI7IdJN zY_8jiAAu=6FY(-w{0L->=ZEieI>7ULb6(%yJb$k%0rAzKb!Z>^bL)UDoek)UJ`{Yy zvw#KIn7>J5MH0L|748ajMFK@4l#7mZ#(3SwJn2u&3#_kehJ+Se$IZDmpbxzN=z=Sp z4Nytj&^*sjVhTj!`w#UwX0~b_5-Bo;2>0Fmh<;D2uJO_V6Ke@*F&Sd}J=U!^+du}m z34h$+_?W=!bsXjn{-}KydnE~#&c7cNkd<>x)SsQ-`|zy8F<;euX+Ew|Kx<%XLb9U{v5|U z#`)6=yncr~gau3@(3Ca@XkjLrUDFHeEPs&%=VL069|jG5>-j_avYI}Gq2mJQmo@X7 z4Iq2rHZ4|N74?0HiU3tAaWQz9{IU=5R$bX^-pAXkh() z!G8qP_mTEspp~Ov&kc>GzO0uONK?47{gN=3&K;(O1fbJ}L{ZknDe6q;W*s(<#eX4T zCsboE=--#lWa4}W)Ur#-l|m#@!byXUpz*SOn$g>BCncc!mt+wG5E z)0ZPgYJ~DoXroJ^2lA;`av!;YDZC~AdAww zkU)X#- z)^TNQ5LyZzijMuXgr}8YX^|;q32KkWqNnF2_+smD3ewVIW-C4q6TSv2I+IFELn2Zo zu`Tb|6;o`6ec&U2P)`r@HJ^jP`}nN{QI_CdOA={w>ZZIhl%9LqcU!-dONxvS%cxc zX$n;-mku-IoXZj#&X^YdNRhl1I5L8Go709U%6zOiM?Ks@hB+>kk zU-+8i-r&t&W%&=*g6mL_en1rjCDK_dK^$UA^eppIZU|Y@hJP1;+%eN4E-9>WZ1Vu; zmBh>FsGth>ap-^b!TZf#x|sYXLMX@KT=z3g&PtVNkDs-mzaA*4*wyVouqb zSNhV<*sX+dSqe`5HOb>p+)9EKGj0cmrn*Gl$*$IlIli zt{Ih%*JtnRq2n-MxfjhH7O))WRi`CkSNx6+@|hLdPfhWIxH17*L`z`vnjfl2%pEN0 z>q(@aC@wbV#XeqxurszVK~I03BmaWvQPn(yADZ8h|9?Ltd=p(8g34CWl2a@({u#K82N>|(zyaj z(lX^yek&=I;K0-#F@QV@=MDtC!==B53DQHuHGg#^lp7Rj(=~`Bm=7s(+m0O;QhHZe zRj&B~pT){jfW-0fta?HKIKI8(Fv=;8Pn4x_>+4ofJqfL^A03D3&2^-2Twk|o^(0k& z{p>i5H`kHAd41i*)65-|GePvANS!tG913I3l7BsZ2Y*2H7|NHvLkEi~?WqY>a*A~RmwJLKU>?qu z7Qf`J)N+)epl6|UGGdlkh3<+n>1bzpviB=5<$9W-Oe=xy#gz|0ut=vkuSHn`%u7=1 zTUP7Du(_uc3d9v0QQZz%HrR6t<7|)bEB}5^0C&IgOx{D=BHoKDbAj24cHAp>2!Glb zs8{{D<1!ARG)6A7WVo7#R;@Q_j=I@1c_-P&foH@H7`6WXM?8kQx%#qWd@VM_zJy4N z=f0Rbz(kL&>vJ7-+FZf$AJ9Hh0o)ORFnvcL1ot1)Yu4w-5#~k^0sr^HF+k<`6 zkBK5V%64`wAw+qNb_M-MJVWR*ZGY?>lJgO0_!n&_qjJ;vAN@&D7L6ST0He1kTX5Zx zAePS8e7+R&&FAknB@}y+f#fXS`y=d|mriI;O|uGlRq2&SOK=aUSDLvp6zG2JWH3fs z6Mz4?hO`Y2sI$J>l5DO>5Lu00%Igop#aMyo&0GI`ox68lft>PUfO_9qLx20vexEf? zKi+ds&{mPl>p!BQ`@@3_N|f<_&F3qncf2?xw_qMgIo0!fIRm1j{A29z?b4h0dprKG zp10@p!>DO^Pu`Fi$S&M3K--m$eP)Yq5XFb6MMu|8V`_Sopy|qJDuff5|lu zK>C?y*3U-06CHoXS5;5YimP*F3Vea|;%Jjhsxqy4(E$T(!im#d$A7*%S5SCw5a4PoD*tjeufS;AOQU^RH%`q!W$=<(nJbwS~Htj1s7ESy5IBeS2$8poXK2FNA zcICME?$|*HiXa+}e}5iSFZ9`nx?NG0h`Dast?PE6*Xol6VQGe+am&a zZxSHiscXp?wy&Bsiuc@=zajZ_p;5eYfwv+moO6F+Ts(u6|_4rsnO=wPdv% z7}R|V?n)rvn0eEFL@2i1qD?vbZaZ=uMt<5V?8|rCUETM=?={n^pPk*6sK<(XHE7u* zLa@E0P5YAZtADemq<;2STh8&>KW(wkv+uU7es1-Pjy%L?x4-C;V!yTVn=aIB+P`VS zB|iJRZHE1xeYdsietfqr%TkujzS9B27$IKK)6qABI%^*CYYFM01UC=O?8kNtI)J{a z3Vj|3F+Us?eCfPCeFAJ~S;@L4c!@6CYq+K`W+02N^M3=@|9hWX;#!)GBa{QJE>D0P zO7q6uCc&|!jc6~8w?&s*?P*uXBRl;Ns^xMWU&n>ly~9s-JTPv@T-$b*=;BWb$)v{N=g_#{t>?Jbwb3(1t)X zFvgGo`2dsSCreJ49JRrhQwgzxGxo%->k|TgM}O#sd0;O3tu>r!!oUb2QRECp0&9#1 z=q|+dc?fGs_W0Mq=drvwrvvQTf5&?n)^YmvUWxB@uzf7Z9oq?k?_sdS?=%`6*b2PP zAi{H9!a|W5p06c&VgHtbRAA(=l!RhG)|sR2LtI0WlgX5xql;@=TCw3!AxL-I7Fk44|MSTD@jrW-8$d& zhZfNM{{?>eNBt_1j`h68e{X-U`-AZ)Z2)%teX#;I$oHl|@VUhA+BWp5=dXu2RY)O;x#KKoDe6@K3p3gqts>7A&*J$HuvTT0Tw@x(R1hxq#$`Hdqu-^g*D9)I4? zKY&r+*TwUCoF>QfdR~^IS=WIeF7|V#h-%jN-`?x~?YUIp@BfmI>+$HK;oE=KKMFXG z9@1+i@H&H7;@^5)eQdu$derTjehI{zH1~Dt@0v(byw{7ua|h$aW-YI3d63|EP2|&e zKjGIr(=m?Qz~r1&-A+JK%Y!jE3V++X&HR`cL?tg=Z;f13zxnxr-{bY`?`Sqry87R= zr6Irm^M7RYjz7}+yX18U55K{SA_>t=DQ2m+vkP z@a7Dt3l@F{gT`QC{Vkef^!WN6s-xrgI^y6e=wO`+{1z~-tBJs9T?tc+vwv#?G${#S zX(}K((%)Cui5vn+9PG?YkO_`I#Lv>`9QixMI`EMs3+&_^^BD9JJG%h`YXQ;;a2NJM z+k%HRbhQ{Jj1bV)__4RX(3aqh2@wpx8AI@!${-3t6>~v!h=$*vb2yZW_7L)V1KK71 z=)RhP5;HJ2^N+Ku@t3DI-GB8lS8ncpkZ_Z(=iT((?lqYSJu=e6#$d+G&~Ne4PvMZB z;XuwL^3Ka%HznOjCA~wr?hUliNYBtEua$T|v%@|bJcNmH(dmEtUv|ayxVrt<|8l$D zx3}uN{V)IR|N7r|#p(9H?N-V5|9l@EvqSZ7_G-3W{2#&UR0i8?wtxHg`dWFb4%>gr zZmUC?;;|ArUas@Uy%|Gr+8+u`7U-E=+;S2jUl zprbKB4Z48nvxed2|50$1908;hd@hfPMi{4$L)e!6*D+wUi7o)Ygl zOsae+KC<@dweMXH`;Wn`8tk5_zaqgy zzt*kMXFp?+EqR_5sT0P&6Hr-Xa@bjpCc}mQT7B-GN!R@3{eNkzA}`VD*#5?!uSSFJ zYta8l!&TI}uQ#{k5=QQMYU$(rH9W6_>eAkeAkCwX;hhotJPBfHjHX%ZR`zeZO=tI- zdi~aGVx87hJL{`+s|x$3o%Qe4nG8M$hp}vZ zZs*6MJjNn2T7Rokc~(6UhwjiVtX4R+Z`WbE=}s<}j$ah5#2k(LQE*@8 zwkfS4`-_QNSJQ-FeBmCHIKg<5}+<$vM(^BgPbN8cq?!4raWQFZ; zrk9`=SIM{y)6G~Pw?8kp(dhQ*-=g_()w#1zHqZHH5R1L*r5kPqLHIn0@paW1S$$aQ zYwL4lu5Qov$4yl0Tb!Kx-s=4Eu}s=UniBhbkJ~E|!5D@EZHfE)hu8@Uv!r#>_G4HU zdw3=O41dhml-xeYv^PxVR;y258O-RKET^r7jMkm$E_Fz$%{8fDOIkxBsepw#E2*WX zQuoQ-lw{a(s|oE@Y84ga(vki_@<`fR0kZ+v14w#>uJx=_zIYVIq15~F>6Sj$>9Y^o zacY*9TRpO;X+2Kuc7G(a{;JTgf%am9wp@M~>wlrX?zw~KzQ<3xbGr;?#t{-j~=bV;-x)2c9oa42z%Pi*lYc6E|WG~I{PT?==qM% zR(~62-MYeNZ9n8g?dYPB(S-@y>m!9%kF8QKK75?ojV<}4o8nm zI-9w((YYcU)@LU#@%yuGnOoszy4^YMuIS#5%l@-B^OU=_)~93ok;nsatY=|AgDM_q zX3PgvOCw!wwAt9=D{n%ywsh|8`Ni>hG=Eahp>>{9%h>ck&E+zi%|HD8q}$?y;ihc8 zJbC3WKQPj+LyN69$WA?)S#qs9gvWe7<`V|{aK$PkKacolMiz1JV)shvUS_YHf=?%x z-qS5wp$g8?`r==2dFO1rddECSSLaFC(Tyq3;b9eFxk$T~fHs@W&)^=%W_}G%WPkoJ zdbhb6b@qiBE#!;w$<)85Npd@y)6}wd)+wX@b++6l`8=BH193eUDjnT>>~8dft6ch* zp|wtw=ASr#2n zrrp1M_O$_-NLxP1DR{t>PS>BBXB;ET>5bW{oSm;`lotUVKA+FeYH4^YaIC>$IdR-| zv?y=q28kzgf>sD_w_I$Z+)R?mr!}p*?SK~4Ze`X!xewFwkS+$J`zu`z%uU}a-FQ0O-L0dp%Ah4g zugLsCOjF<1X%Vh`Vb~(|bz2j~jb^JayG6jBpCGdZUw;+)!yu&C?AP(s zm2TXfbVKoJkFDu`7ch9Q7mTYX#Xqy<` z(L1j{x+2@mPMfjEr;2)=qtovNtse8ukJ(h$ZX&+eEVxgY{-I~~@L=BNUTlP0UtL$d z)P%_I4mBznEWLGn-G3$%+ssos(bmQNd0O3i5#3Bi)5&24Vk(b@G?S^lIJU%nvn*fP zed(1QMmN=KIJ?j%u@>>2ZhK34gwyTpcSk&YEm-F&I?u=UBDcxP?f8edy4>t(X_v`u zA7rO%Iq+idwdNw9$=;yHpgM$WcKL{+U|@?=u>16k7V{>9g@02ljK{Wndh){NTQ2i> z$z6F`^!6$5le-&3YD{^$x+blU;UPURX?G73;YZu^M>SeU^mynzP9u7nd#BmunC9X7 z;O*1kd6cd`zdV-@dn@*Xc7IR6(DeN|UOwj|Z_+XEiGN)@&Yv6GjYJZsP_2dfcX#Nalt7JI3O|IMaYP9V4s(IEg)Tt-C^E)3dJ~@q?^48Ow z#pf}3thnCd_Q!=Py96FS4==?Wc0a9#ij0O=n;PeZ``Mdzi;WgMubbQ2YqtXVg1x@b zw&uE=-&bB5_Ri7bNOo#fByOC7Z{E()dcIQggLXgCn17X`UAS}KyxvadVbvSY+2(!| zV9Z92-Mz+ZZM%Hhpr?2b=TQUmwPwb4llumrk-?BJ(9FJdajI8PjqV zyOza+*2nEhBzYFqf{|`#yr#qF-Nq`F^NiLbn6mtYPfusJ`6Tr>?yT|pS|71Dcno&+8F(|xK9RicVP4< zokjO0FGXkFJ8N?*<8D$-I@`z-&hlwpd#hITN*4LV*3<3WapJ4c^G&?y^TVpUzj(px zWn5O{^d24Jtjum!=ywm>!;|51dR2n<< zDceT(FuAhvVd0#e0~tC!dg)E8au<%D60}zPHFo=kn9EPG8(8KGOl<*~b|J6ig^2&N zpu{>94^z0g1bx6}J#Bq-A@|q4_DlwyIhU8I73$_vZo8a#$_Q-CJod@dn_}F|1;VSD=(X&2v_&K71v;0`PMIy)9 z$BVU}m5bjFkAqp{_WPNxx!ow=UA9SZaPw$>P>aiH<$R=kl^5qz-~PDK!+D>?<9~Ta z3(LHF$lb>?^gloj^yl&r%K37&@A$Emcf{QoKd+tYnrg$`9S;~kn+F!&t2}vCgZMOF zx7PhN&?Ga;laUWP)~k1W`u%bgvDFBau=^CB zjLs631*cuRKR8??b5%k-yA39zjDO_wo7m6twM}pN+Ruxg;Z&JhSkM;ha-p>f^<0^( zdUkiijnh8P`tv;4Mn-YYqj_Z~>GQL+s#4tuSsM#^^<3G%IJ=-^Rykf@qv}UA1D2NEapmVCf-AKw()J1t=e&BKK8C&gn9|yQ9n*CI~*T6;(z#21Y1`I zu|2%JlJzcLZib`R2QlDy-^_}vb%)`a4ZES2Se4p1>&Vm=nqyY&(^G%yx_*CLC%en4 zPlEM8ms*q*pN@!zAL6n!Ce@-prT2BmDE2mu5ze+8N7=APZnBMWyTv#rw~uSgQ~yLSm&IeHvJ+FFb0WLHJ)%FWE}-5hP$N9AXS zp<7)?!_TGI^!+$Fe?*hBYNdg@8jsnicx>jK(K;Lk>1%6+lfLbdaDSiACY#&kd7f#Z z=3P|3rP#QP9}j0`h8N!JPObUyl+ymuP9g0&FD>eNopYFLZIz8*GM^q<7VoCfYI&Mz z)6eJgF~1F&w(*mKoUDiKYinmW;Ulh3hx>s$C~t1!$5r>!IY>dn_PKRCF}?KS?a^55 zTd#B%`S(|~xbRm&pMRPe+k;uT32cp25gYj*#iyNrT+XY8qu~Ww9~&R|o@U3zM|r;%+GsYY_R*~CH>Z+-JUF-o#W}bv7)_K-1M=m;`z-N z!FcRgVz%{$-r=-O_RueB+=l=Uj-)G6njb@hwycUS{H#hDPJP+|b7q7)}GH57;o6^pB){P3$&n=70$V~gtB3U)m zDGMcFxGRTIla$k#{c4+uczf~EPSH;&W=C~R<6cTeyWS3!X2F7U2KeUFMRthqMWFaT zhgahjo`2&$NcvsHw=d^Lu}z7f0ihRyIai$J$X^=oWYn6qHI;0KQ?tPRz+v+9&!-=K zbDmaM6=aP0GP_i43sXPSc9Iz<+g|ui;mYCBx}2eM+=hei$#6qq$KQxnM~6g}G=936 zuX(63!Jd0!13g~@!>2h@HV9^lYj2hMks_PcEXZ*_%RKJJXbCWSQhCXr7$sV0cW3$A-KAumG+BLVnI^P+RuDO&oO=n2@ z_kUxM-Oy~#n-%vwx5|<V6ECKn8tB|aoTd(@AVKu069W&MXBj`dIDW{Z9FnlBc<=RPk9p45k2ItDg zCKPFjG%Ge(Mreayy%tw%u7Gxk{lj<6l9pGBh&dV7@2KWu^q!9AoU+w$=HWZJIw9#$7_hF~|CIxGb z)68%pFEdCeh4#Mkz+CBEq>VL^tApwTxJB8t^Yb;2?ciWJ$lbnU2uvGL`WLDh1< z1~i^>qJtUXyyKA=R62>i-hU+(+9M;&Epsun(iKF)b$6*ambbi5$jRAlXs z8d*o!GOs*ZC^Dl$r1d_>ebV%PqKo?DP)Re?$ubiGdz67pJu}1f{eK#97hbL%fSMPe z4CHsdE<8ofYFMEFMkNUqw<8g%Y%v=BLpgnwX8}uWIoX}MZM&AqCX{F?-#BpfO7y(1 z4Vx;*ID~oFa$Oqj%^Ge$oGn=vg>)b9lwu|-61{L1Tu^o>l4Q*;N8+x99{7>hYud!M zIo$v(-?-Us*2rf;cz?6*WHq{9T=GZC?@x5ygH9a-{%hIq348gbtY~b0k_;cB3B!gI zB&t^i!Z}5+36OLQy;iA8zh6KxTRJGfsvphfw%8hj;K0Q@!TN-GF8!}#D&g~W8ky3} z7}ZoDp|ytf4|RL;D}Nz!cCF5(OSKW;&m%=l zT2l_6+gUQ>qQBtDrD8+z8l!!q-aMx;E=E!jO;K4cM-=dvRJDyMwxG6QgAi)XR`C1_3mJ&WSD#b)?NWg$ZDfr9 zdV*fP&A25Iz<&}22DvhFD8JWtP?l99OF~qf5+Pet+*nosS%DpVRTpeZ%!=1kYsoPYeAnhhCn*Y9&oOpC)lv;^~~ zfD*$|hd7}{q3ni}8tE++r1*Z#1vAKgiGVc%pPWh3n{Rvb)l#&OY!S>!iQHc20Ho8R-M-y$&BpFVgEwDF% z)LZy6=zo_4>5hK9Hsm7P5{|vb);y~Akg+kKXM<&>>6ZjXp^kOQUyGfiid$by3Ciw zAF=!ZDL~f0NNZrguAEOgER*_5tx6-cLeC`AlCKrjhk1VwDdT5gA3f^So%9H_gG6}? z%qD^2Qc5dxJ`ycQi4$ZrL4j}ei(73c*^JEJyk{c~jWPkUl+*(~1}jJ#iKNkt4;&$8 zY9|H&Y^ta@&mcKTk?-VEL_P6SJJr?c=3y%Gthj z%$f_*fXRRDikTL}TI19KLxxk0(6aB<8LScbJ%?phA-R|SzRFn(Vl!`n;NCf)tLk)s z^#{zqbfhBSqSQ3sWOV!TCRZAjw+7gcx62%dx_GmMX&x`di!D|?NqaEtv^q-o`XCS6 z*L~$wtg)6lP~x!KNXQCEzQK~*3mDOV>)`*kpZR}-1^IHpy;VSyJ_O&reUi8EHOH{P ze53)4DusbM#wcLK!;l&Esz!C&ta5kz9X9Sj`;m0@=0Y1H{8-trhHB}ND#A4a)!>WJ z6dF%SjJnE#6)Cyt4=;y10C(Ma1Yt;{DA8>in+aC3( zAW~#uYVpTP=DP{Y(u}Y^Z^{t;XAVd`#G!x9fI*XZYVxS*b+S;BJ-9hb%anCH#bBts z!k^m~D8LeFZP+rb#&r(XmS2kHmlmsoazbp}30s|bm%UFX5k8W5eQsg;GogAoNMo|RReCU>WbN#fnZj{XHq{MTYCL~U(Vut#ObU;90-&{kI~93JI+M)JMTen-_K#`{M+q!p z-T}G@wFF|Bi^IVN&QztNjX6k_zS=%grwqKB7PHL;QFNDnWN#LixVn(B_Zo~ zh$bVob3Ez95&p2S#l`>@fTDOhdA@&~)Qf?P=e$*?+*f@1%G;EZ~g$swV)O(ao+vp2~sqdToWY5iQe0yq!W&AkleX)q7Tzw69>c zmK?|QpIyIg1_6A_9;3+Fp0`D8Twwm5`LYk|C{Kti1F9n40`Y*+(y{H(5bl5aM_Y&o zHn?OuVP^85E3X2P4;0dz_9~=Bc^L$LO%UtO4KdRY8%_>;7)iP3Nvbd1zI9hTjCQZ& z87-LWW*g^RN;h8vU==p0P7eY;etxEK(5VUR=wO()zPv1V|oL;*p2~y&(uuf-}QJ>_+g?%%- z_5qqxun>-&F3Stvs2Z7Vg#lSHGoTXE%K&qd`wmqxQCQ)FTI_m_#)~gx+&!J>)E{~z zg-RqeS;I|AKKSU+iTz#nQI?Hh0_4S^+7WFKl&>PRMq_)AoD3&rIVlf_6{Q`UOrkI~ z_^bqXUM@0gXm{o?0&9Pal>efLDJA-eBBNZgdGw=8xw#GVfZ^~{LP!+}HAQV8z{^=P zm=}FCn^-?`i;uHNJD4LL=J5?Yj2b~q+5$k&BG4zRR?RReEvGP7LkKT6XfAT6M7Ulf zpf9=$t_>!$W!IixO~|Ue!aL-}Q{JlbENYcOq_akLJ1mPDSWJJ|t-wx683GKjnv!BG zZUHsgp4``h7C<{(T zx=~bsdy7h>iP!}L8ZUu5OOg}jtd6M1R*zadrn`{zTR2^3TVXQHGl`RIFuw8c@k(ze zPQ6fHd6;u?adt2SFG*?npSzx*lD#kWPGM^xb&2P*MWTN)Q@})v-zNQjeuS8l-Hz}` zu>qEfKq&_EtOe{2*nt&UDccH-W>Mc0M?bh+KV2dS6iQ~qT(uwF0Zv#a%&L2Bav;pY zVnu~VAC$9I2wgk0yx1rC1~J*j#MU9HG1NrCk<7l^fkzIqZUrojnLsJZ^GJZZ*3YF~ z<@3V1U*dn)UCfwC8^FA7k1ivax*!O~&kwp|Im*9~#Xqq`vdgB-sAcliUlv;xCDn%L zm+<>KZ2b7FESpEvPw&_k_y*kC!r}H8&tbnK^B5U@^-|SC+>gFm64;-`fxRxr5yU#B zF5jFu1NGacz^{+>B#v#7=)y+J4tJUkg}}Owaa4bc``Hdk9=}RxssVi^lB0*+5i{QR zF@959;n7qj_&AreX?tpH91(qb#d5*R^2k6Z^n1umviQ~&VhFfY@TT3QhgA#VvKZa3 zGLL=SrMz|Ig=y-mTF}~6P}{f+n#Yz&JLwGIuAq2T6yCxT?SNL4mW&&CMuDAcK65PAAkf z4gC&{IWe7`X3=7jO2bvOu7nTT6{Q=#hqzpV;I%H zMWOqOH;!AdM!ng+PP6U_AnqN2iZv3q|v zvKYXV^1&OJ#BN^%ZUFwHh^$Dap^Q8%Tl*FFgq) z)zfoP1%geeV83E-i`;LpwT8I*xiO_B1W5?0V3GUMVv;AK18}RP$cW!BJZ}w{Zd@6n{FHEZc*Rof*?MNx zQDrAH=x5j*-@dn6E~u<9SN-M#@<~qCax+{Z2@@dg#>x@HiJwEOV3VxW=ZV_gF&s<@ zAGXmem~7Hsjzh5e6%>%+>+GoVr%q<|+ewPUBGQSCuL$-#os*q~!IQ%(&zgV2fOg*W2L4{6j0%Cv4Zp>kzv>e4gRyb(}2*pGaQ)y_za5= z2NHv#;Bxe6EAE&oV`Fj+&=@Mg)BE8Fr2l?>?>p9I9AWRS@QuYy`(m4o0B$mhPa1k# ziy($m8#?*mG-i!HY7?^9_osiLZd+}yzgGh{2g9ZJOnO)H2qP!J&Iu*zdcy`TqEAAk z1XiZ-I__6q1CbM|cPsri;(s#i`9Vr2-q4ZyQ@Aj_Pb?bj)SG3}Qk-bLQnzZ!S!j=_HShp}hM@zqiLWR}0%u^4rf(pEv zSJ9g)?-rgX$=C_e9p%Xj7rsL$)|9Bac&w3Sj4K~Y0XDIv5JaZS6^mW~5&IfEnKSDy zE37c}mFOkesub>BUnGW_vU`X7R{+GSBDJ0TRAQNa;h4qLG&z4H0X`s|iwNWW(tekC zNWkDWegXnrlWLzvTiNkR9DbaGlvQypa<`J13V>8rSwHr~5EfB`JKS45VhtTBzWbJT zaD-BouhmNMGmxaC|+5u3Jyz1u9;u91~6}EncpT zP+|*jmEWB|@Hu~g`H#JAroV=>Te|Ut^E^R^OkG3qN7w9*?cWp$BE58#6D+~K#Ic}s z%7Hwn>ZXIk)~GeSP~@DdG$|Ly-pgl9z*^#$%a39&ahxa%a4!lhpR@ZD1)#S(O%`t` zSEskl4mrhPKiLLLI)Hy19_r&KE&PxF>ArhDxJFEkqSAjEoe)E_2joTh0`oJ0qoSKc z<*@HIPpjRA1H}c)=BD{>maZYs=YzbBEZL*ZO$pY3p2<}+eUW|%opK4&>#0l^`E)nt zPXs(7hSy~GB}rxV`Bgd_m-j%TZWgtd^GxcGGfH$c2r;r9{OP#Dr<|0FB zYcFzvj&cH>r_Bv^(_O_g0oh5uz`^9NRPE>vCP078k@9eHm1E;4rwAKZVKA>6f2tf6rITw6eeV(Z0jf11zYE$>{*f2AWFPt zl5v00=g`36>3@acZg@H0>}^RM&O0>=QG`UDX9FPJ)s%SCWq@F|OceQev*sclj;c3U zoROHnSa+lmA7Z3y`!da$ZbP}aAEP0?cn-O^2gQ1VA}ja2jvfJ;CtdX5{lTakz~;3> zVE&?sci|9)rZ>;v7o%@Yp|+4v)_OHIW~5N1Cr(lVPsprLLyX1OTZ6u_zNNR zbt`B?<*#5{%mBY_4{8}a$$1;FmSs+eJVSUb|5EA{DS59b_&w=S~NH+9i6mQ4ZnX& z-=FKKoA!>@jcRo5xndQAF3w$LcLb}z+o@&Zm1J6Wr-S;>C2UJ6921)((2PvM@k?Aj zwe}U`V!YNUF%9I`ceK;%DP-odk>QPchknSL+WAuQb%3( z(_}NnRA0_D=I2oWAE-3DhbWXp9GoF)r}Y4?J&oy5mTNs)K8ahkVf2i#PwW#iDpsq8 zlK4iH4D31e)zQ|ki|$$jop9sM>#k4`Ip;B&m=aZpoVTa9CKzc;dAWaAU(M2(IpJlt zJzLx1S2iLJVDy)topq?;Oa~x1_*c-BIP7RWGZHsd?-&D}o_K$Ue{JK;zLMZ`x&7_f zQP3A*)*k9U%y{IUMKoLH`HX^i%AsS0GYLlZ4F{=61*z|dwDEGBBFJEDfr&}rd$}VD zn!Bk>rJ6N+p+yUKQ)GY8J*kp6&+_6VGy0XHh4*f{4i|jIHFuS%id!BI8j#=l^{A;= zDp&pbx54-zqvKs$kZ;H`keQ^D{i`t!T=o9NB6Pge{93oQbOtS1_qByX&BC&&WA3He zvoTbo3djU)^LWZr-wrfMYa)$gLIblOsUFK!8i_G`H}V9cXN7;F6}T&sb1r)<_b9MY zw%Ay4X;z0rv9#x$nb8Ywwx4D4iF{6t6p6Lh!4LlHS}iK3vZF=sXazFugbaIdxX%Dz zSR^;jKxSC+!r@n$K@@1w?VE@LUO{Ybr(D3iugnI!wen*6IRg-b*vJp{W`Q9J|BWjf z*!REcO<+@D`1OBDjIbJxCCk`Lc+cRBJrH!Z9B3-a^Y{vR?BY+;8A7y4u`dVLbd~V@ zN4~(KK1sXyvSL@`-&y8|MX&SO*ez*|nV8lJvCM>BtWKI%qG`xzdhtF*?GX|F>p`}>tZ0)%r^2<&&dv)qL_IZELxNniF0dys8xR(iB&$qr% z!6m31SjJ~CWv#ft0vf~?4-0{3cW_KD1PPp2_GIyy4i(=?T(OxB5D)x%jDJj>seh|f zFQVK}L2F;2i~H{}&*WqUQZETA6jUD zD2v324;kU`02?KyO)kbUvC?Q*B84uYGf0!V@Ik~|!A^IWLbKiNdab&sAh@orV#~jpAR0;d;aTYQsP^-0^>BtWXTyNkv_Kun40^gBZUx=akyrA|v<# zJ+?H$_$&MOjH$4Lx!ycVo!ZSjP|xat-);%7UQScHEe zb4VCR*G3r&pW}v!2dGtT04if!w-M9~YxWM9)CSM(eKBKupt)l`I-rYe5Tj`zAMiV4 zoJ%6u03w-;kZ5}dusc$tqewIIp~&`rG4bW8p;{}7DB!M;hO=HU`eKc(lrZr3KK{Y! zd@MqCq9IIDM@4qro)^=*YI+#g5{!SC0rOSY!};es4sYvWX4X+ zObDzRkf5-?J$A@pm*6k9A%#v~1CN#%S*t6T>98UZ(4DO1wuEYm-f!`+IT3%CWJ(BR zj?|;Atcco4J0>1|FGtos>fP1xe@MPW%wzc^D(Y4&?&b|%>_)SZ#uBGdztZ1!iBdso2HKTCGwN8-f^tDPww7E6N}GeB4d(XfaLiw0f-S2-ew7v6SZ9;V5 z%D3L#oqFiMklo)t(a8O|e0WXeBqMzVz^b2=jQdinEsLV=%;SYJ3Re6^->cu{zCq;P zKmN165*dh;XwFbq)Zc>-zxw9M*R)xjs^57mKxn{#?rReS?kyeHmqdg1aNuI%3ZyEW zf5|URW(_MHtk`|AMJs>79%C45>u+v%=CA_a67*dqeDwZ_8N_7~)%;XbloSEjnqBPo zLHNa~U}mWOfw)9RA9vO3d#Dz;A@-A0vNe$pSXZ0b#Hy;)d%--qCf#|&;{ekOEh1}^ zK=sYp&G9!G;cb!&|nGdsn~rZG04D$ya}cxy9Z5ly84HPH;S)OVn0MvW^WT zR}3PLFU(htz+Va{#D^bE+hKZ!z+S$e&_P1gnVR29p3_0gkqk)gOAt6YuN#|KQ&+#K zClDS&2dx&OlXifqR8lSAnO`#c(ny*i0<{K1LZ0NRds2eyn{uJ;*qOrnI^CRE`pkv= zyrmUuB3s7~cHDp2b{GkNE@!RguIA(os;C5`(f!e!G^f|+r|Iq3GURT#qAAkai)f{T zqlYKC-FK3|flJ+hQEk}Hv8Q>qixFZdRGc<0Y5$wcaQfLC6tU^O4yBqlOXH0${kUX3 zj$n2`GDR{j*k6h@NrU>O>DN?IwZT!jg*yDBVp7l;=0BH`!1j-FDgH4T*xJcVrA3S*{&Vr-?*1R-`wygL+khrwa*QU>AF9FN z{vQ6%!NOXdq-Ys)sW|>VNB(-+{@!DH+>&%96-|!*i!c5!D*HeBgPkA`p49(9T@1rj zf8N$qEVG5`vvU%Eihtv;>c6@DYl_5I!69QaC!xSF-1#pE`5$oImVb9fRdnH$WgGwNG&Nmp~+ zhCc0fKnZScQ_MCrxC+Z5y%GSs4}q1y3kv+f01&lK*(PvdFP;j^CFg4uj9SgTHN2vA z)a-k5brm0f;LL}T2kCF?a~7*^27kpIwch+CGFI%?!iY4*H~mF$sjxNSat(S{$l8}g z#kggVULP=HyP8=RY-_qxZF>!H9H`3iZTgjlqA@6e#Kkolab}G|*(-c!g(cUuUD#iX zJ_!UrR6ya9iS&EH*I8c#bv3`eTTX4#7vCxxA0sP&Jz~%!v0!9+#%~C&<&>(wSVYkhm!QuOVtM3 z|nVh`zEKvik_l(&e0zs z@IB&?Bxd=Vy)rd$AC`Spt`}DBcfMDD zizT({!(|(;tpU_-E`mS*<^y-s7Po}q?#XG6yH<7moFu2&b=R*wdN zCr&pwEhNu&057Iy+g;z+xw{>_wGBdlWVIhH&dPM)_h?^Bau5`s4Bj(FO-tXzN+*k$ z*so#$4sd)=YIvlUGXDVmjeeUm(v^NA3Dkz1da z2+n-~+^_jEkWgdAv|V>{TrFV)nSgTPIaTa|iZdYNt3N=0*bJvh(1q?R$b!+RLPr&J zTwVdvP?{%A~tWBE{~*bmCO4^k6X=#Mu*Ez_pXqpPB{ z!#3wAnavj{h9PY!Z1^}_9#nOIpGP01ty{dATb28^i|G;r8dnEQoVUS|$3k25?is<7 z?SiI30&{&y9A&t%9pUPvqQ8&44YG3`K@2f~yzaw+#bTw$)eJxgN9-TdT?7+*G^%i| z=)*#?{uT7$1^csFOBW+cNsGt`v?zE@Ql6yNaeP9f;Zo#~w99JB49?1bKe~ZqQUh%8 zNL`g|U+}uLgm*wajr*-)s*={?aDgC_T06>tiSQ6+m zs0c>p(h>Ua0+8n_KIzSW0?TT`Cuq7fM_ZTWmv?l107e%yo#TMp=*ySvi{}6X;i`Jl zhMpSj^wfn@(u89)S-~tF>@*nmQw=_mF_(N5F@AMcR(Xs_)A+H@ZkIe1fCL~o%iHe{ zV^w zVaf{ofXt9ZNtqFYMeeU|krl?IgGW#N&S+C*FzI>##tyH?1(WBMDc-J5fGbsmlAWY z#qACg9vmjIHgHGD!Sv% z2E#}Yu3a#m9z2tblLl2LDK$X|trAE43TNK2;uH~HCFw1HF637y0TF}7x$g%OKV<_3DpLi<2pN!YF(2rWte{ zhyJdj7chHHmlA;7N*Hp^K55_CT))KrRR&?uXq+ngcCBfBKKFt~Jj?@^^x>bgp zXzk_)3P3!_<3$1isr6}oYte)TpU?=M`Br&^@{JEVk0c-8WB5^y*n8pfl5-VJkfwh= z?RUnOqV{X>*6o|B#KTH;7~Ju^Fzz;)KJhWA`D-|T+X-AnAu%k~WX{Mf{+LQYAYd$T z26D0;yZ7vdOI5hmwWREl5R5_xqa>P7ALYTECO z89uj>1&I}I_9M9=(lk-F$#;~5ZB{EIEIpj{a`RSO{qm5kj#=b3zT?$}D!K+UTcqc_ZM~vSlkLFUV##x`Lv9Jjg2UW@-|yhD$A0 z(zPR%-fp=ck|ti}FxF_tgPTSC(kw`pig>x{S+EpFAFg z2^1OcZedp``3+Rsznox7^ogB;JE-`&2VQJ7c2N-Z&CBAnO1!;|k@mTflyzayFY zNKp;*=e};LJ4JV?$*LVXFMQ-wBeNW9a89fz&k%XEown} z>)?$pkPP0j{chZJ1p9!YF0fR^pM>7ncedw)IyE&uHrcc9B%Pva+i&5<3(J5b4qXmC z7?DLj3F^5%c=74Ffw;UtSrgbAJpAg}_2me^9UvqNv)H=*9m^an^CIG}DjjWqTYY1f zVJ{wy3!-H*+wTOEyeM?Ay1!%9h7{?U#S+Rd#+ue7Tu{sO0!^I+*)8x$Azf$*; zxp2O{cQ0%1g`NIF3qC=XX~E%2nhm)PV3Y zJ_x$U(Iig4pn-m|ynJ)GpBW2n2=Xo6-uFD6mOv_Yl#lD0{f3T|j|K>TRHv=|R@^A8 z)EMwu)R(3P?l8ovb7tY>(=CQq7tepMj|`f1;Px9~Zk8)v2U=Y0!m4tw?Q)+?X_J&%MX&GE&$dLaY=rmWlr zZ;`3AAS*Hr(juf?Zcw&oJiKtdBCXZ3joy#tcy|msm(Q{%wn;v-^kE>0OfhV~l@6HW zAv8U{y;0pnXo)bnc7zyT;qbcTZuufp^W4}NEvyh8v%Vze48tIx_j`u5@n@1zFkTJWF&(sU)Miu)?cBhg(#4Us3x2K)_I zd)!#;Gp;=#H=sqvi&(Oy$hjLq!G8BacK?H|L}Z@w_PGBp`66 zKLZ}Yg@Pl0S}IgJaRpHrS_ck4DVwZAgYfJaZYRUh1zv0^6-q;hVqe9S@iLuS3~fC5 zI6H%cdKx{iXJ9jFzy5?)I>rD5WUIgfb2DRgBF?frx$9 zaxE22^B5lPF-DYvI|3)bwYDXsaGX0>o)4{mVmSvgBjPPrBDluEa|o1a3PPwi7xl4s zQB(98e!evaXu}hXnvEAB!;^j(q!NVhk0{tyi*Wu+afeu+@A571x^ zcQ7|LgubCVIS};1gFdzUZ3$0_|Hxl|xjeamcpAdWP5NE%+I)sGy4K9*ntZ#LCY_IH zl)LUYa=r+uzJccrwSU&vE)U&sNn;~6{AW)wPVELCFviLOG=?4J`)caVzeG8nNwdQ9 zipm_EscSwfQrp+7EVe4MJoecFq!Y5a?&rDD_xo29i?%wE(AAb@Eab=Z-EY``e8q8a zbQBX=j7%zMBYHB_peFs+y`~KGQsjBJLCNNguPKee!c=cg3Axhx;OTHC?z&$<2AtEB zx?Y?a#dwqB!4QyM13KxjxYJn9fCwNBerMRed~XHa`|oGjlfJBkeW-Ac@o()BTX7g? zbx}K1Au658#E6FNkUT=cNvmjoe>1*b2fn7GYjkh~d@P&`1H3%QY=wCGjRyW+z zm|A87D%)rZd|MfBWJ5uxFSK-LxtI)rJCJoOr;_O~7G6`I5J-xDmSA=&Pqt6WVJ#+a zvysL%#W;nRrvt*pFj$OIQ{HI$>z{RU^5wM8+;Z`Y`$i)UQoUl`d;K_aU5I`t#JMFTbUC^oEB?im{-$r z;%F<3qeZS{EX%heaSO-yk6NWSiXF-t{R?B zxp6KhPo63fCY*79XeC$QiZ6a6E)9LC9Xx2J-L*O#sOR_5B3IPsThHHjtlM7j-7?L} zW5PsmvvEnRFr96n68^j`b=`j^ELN~D-^->q|ZoW91C{S@F+QI+xPhz)3`#zM&65_OvxBW;UNM|1hEMs z!Wt@isrG$|rNuKZ%r9DbSWwLIJKu4!bVsC*-fj}y8; zm}wNQzflc;tquE*G)*i}<=GC=#X!^d6cWB7e&9gL-}9J-xShY>JL2OuGi_PWSk03f zt}@LjViJ%iSi{S&76T0N$k(U0gfcUEYe(OthO^1MSylx-1DDh-1F3d#4FK^NadhK+ z=)*ZIG9Dao*4`{?w7xomEhyX2)lJ#xJDl1L?YD)0pMwEF1{fg1Qciq*cvdi>v{YhfXqezzO?#Y{ze3dV3 zyqcqb3AE%p@o@w$ctg?-X(0GjzmR%YK3M*^;m*MTt$Faoo7E}MD` zjN+TbDTh>XJ9{b*-p7TO&g*C+uCvRTJwY4k9iGG((B(8e5Vj*}lPFg{axMNXGUoFh zzGn8317dkai7cymsixHgf8V}Au{t4ttMq`8x%@oT!Rj#l!V4>vd_)mfqd}gQbZoaJ z;j5z(>r7>5^`DubNSTs8=tPU*R1n{oUU@wc2RW6gXc>>oN;hSG3<4{UXD>JOUBJMC z1N#dZSo{h=B5Z0j|y%{s^X8jP>n{W1&e}h5`^a{Nmyx%#{rKXV61LnAYq(yLt zV=u{Zz34`!i<8;x>j37m;YPU5^V>#iu0j`p&2LGkU*yBar%X&@9nQquyBSFXZdKf* zA=kDLjXAMH^<6*aY+9-=<|fCEhECH2Ul;_MI5!t{x;w&Dbz%?%GQMm-f{!!0K7X8= zf+=CajR<1MCm!=y>s|?5gyCd=e43v7YUqBGP%w?rPURGY>&Sg1Px-mkOP&zzpROG?$$HOdsJ(ddtLR(#WfYSST3v_#>YH zE?0%pEyv=FL8q1rM3XuwK($Zq=PefSQ>VNqQ&nX)1g7Zz>XbCAcefgUOm~?t+r0Yw zR)`O}r$u+)`4S9g&yK{Zybm&2cD(kDkPv)B&10c23Tq8is*As(bQT8r^;o|{Pv;EG z%%rND;}WRVfhGnnM$<<}V!57olg(!cxg04V9xJB^9LTX z2Q!}gWFVFNHGl7T7cu#N-9+I`-4GQwbb5mx9S|9OV~@{_Vacv|HD}~|9$qj>&`g-u z6CZCOYNjF1hBvcWsRg?68R7oL%4clbSqyAY$Aq_E%~VD9lhyTc|f;HOSERL z#pVzsMv?~4NRDi?v6&VV4SEK8hEeo79jt%*dkfA4eD^QeN9lHdxLR9Mt59F8M`+*I zo><>Zv%7|9-bWl774}VQnRz|J8)1>6=;%U_XzweVZtp`GFr7ZpbC7}yj= zt;}0ra5#?m4S{QarD52RO{5+!*0+^{;Zl`ThQ=E&bhssPFGV zO0dBi$efw{L^5AAS0`j3nL5Z5okZHaje?gmXeC&kcCB5Dj~IuvbD^NC+-}zi&uhfj zxbMsTI#47F!Wg$F+ds-l_#bD_ovsD!**q2lmY#jM31W4B^Q>9?MSynXLj8``>J9hX z20YFwJv74!22OU#ldST4mdC4{lkO1$rqEKVLnhzOGY)I!iWataW@KCAZLWaKtGfF; zQV;cr)&?18B1a4BI~cxSi*U4y3wXBDUZU*sZKxW=PPz=>3BR2P?fu0&S=RO;n9(Si z)14I~wYy}0U?k9BPwE;q((5v0r7?xm4T!_6-Lp=ZfX$yHUDv~i2r4;8N$>Y;o8Bx7 zDsp*P3K=AT_yB6M9rmrw`88kHhD~H4)kju+fqhs}p0=%Pq6;3sw9kbtr!-&s{Gg6YOamxWyDsWcn#+!S&&UFEDi#d-l( zhPXXK@;dSojgiA_>Dww;Ms%N_twR!aQJfDbw=2_)i(bq4$R^pVFVT`uOn%Zq^-#ud zkB3r!I#p9fADP{cgB?OHe7`;a@HC_ipK+_+@XgG@T`S+#Ry6J{h_i=%6z8$_j9Ukf zwLCfFh{CUuva!h8^LW%Yn>^431NG4%QDMst0?zPeX^3mP^*^&ShUTYr!zMrE20|`z zzuBPURIb~t%;M|EOxA6DirQLI8d^S;Nq38X{gt>Wc4I0$6vj-I?Z}fsR~F^t7FSTA z@3cnqj0=)`KFWD{p7%bGqVj!jX%OH9MAQSSEFyBbY1f4x|Ng4w?dCf`zise|R~$;p zElCf0LA$;zu5VtKuVQ3C4GN2Hz8jVHmBfz+VQ(gqq#2#$uW_RQRzo@w&aX+|!0$uK zza>2<^1*P5>br02w$FxtJ-si&^D?FW z8s_pIoitz0{ccrqz21!5RqF1A#`9a_V{(lMS7EUuJsN$O&MY`Sni-h#vX7;Yry^|_>`g9ts*fDr>=5T`H;HhW z-y1w!9%P%Ww1|3t@k<&utg`%KwsfFDhTBZXKzYaaV8RPavCo6%c6d_}r~GY~yh|f9%cD(z^v@oGvv`dGOl?PgsJNsvzX9$BfXmcI zdLL#^fsEsS)RNk0aop-=->aUFhJ+k&$K1Rnyi}~6C&if#yU*gczzv&>^yS0UArq!U zhjXgcR|s1^PScX}DMD+-6-rj)?qw=4;A$@?_(eB@ z{E}2PAt*$SyaIbNM>y$gn(oecI?8|ywY6O_TfI@L`G&l?^=jUUubG-w5tUrn7fh;i zCCh3U=#TD-x@}te^Q`i~iYYbRrIRae2S`@h%qb&Va--N0Aq-5rl=7u%ABPXrRQ2!Y z5mVEDa2}!uU5UHKax#LBF-?t~B$DGwrcs6RvJlGqczA%mkU>5MF5cBkiEiTZa8lkU zM4TcwTWZ791onVd=fi3}}&IbuTrv7O~SMnXiQ!wEn^5dZ2qCAi86j1SdfQV6$ zoBQy=R8HY{$Hg$~1E~^Y-&wfC^UAZ8^~17%vg5fI%ZhEn6>WCx!jxdquMa(1AN6mk z^sEz4aibvpT*XXMa^YBEk%Q#lB7wj*Q^C%g+_ooO?<9_U{^b=BH7r%?#e5PkI$Pm&Z&1A&GsG~+UH&_AryY_2!5xq zRUd0?ecpH%#TN$EsGR5T*RZk{MklH95|b$LqPHxzm>s#BaMR3lL(HA)3PKiq1N>-iR>ae0$k23Hi=+_Af<&TG}1wrTbj0^lss2|(c@Ie zHtXjqYqU9bvb%EqonHnU6?*Ny7!=O7sFtQyPb88O-l<_e6hUrY0^4gTYDbU^N0~$f zAuWBI?^wNQK;2d36G2sG9xAf5UPdkn@x7(vJ1p=0Gg2pXmC|UD?_;A#V1!?tYZJ82 zDh+6=5#u%ZmbKS9PQ`TgVvDqYz$&NIb|Uo-NnCP2I93-DguYc8^tiV2V++w-EaKLo zM&%V7%F9un7xD579Xm1xajejqVS%1|xckP$&8NlA>)IWqh}%5k6~CAz%>7)6ye@R! z0Ik4$(GSu%!h5;&hE{)zu;~pps^-i}o0(8!!�%U!r0Vxn$m;Ry9C>#=jrmRU-Qn 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