Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub (part 6)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +25 -0
- backend/llama.cpp/LICENSE +21 -0
- backend/llama.cpp/Makefile +9 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-apir.h +15 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-backend.cpp +58 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer-type.cpp +110 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer.cpp +173 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-device.cpp +192 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-impl.h +36 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward.gen.h +53 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.cpp +99 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.h +23 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.cpp +179 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.h +86 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.cpp +545 -0
- backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.h +115 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/CMakeLists.txt +236 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/cmake/host-toolchain.cmake.in +15 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp +0 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt +35 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/acc.comp +37 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add.comp +69 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add1.comp +28 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add_id.comp +42 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/arange.comp +20 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argmax.comp +60 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort.comp +86 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort_large.comp +114 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp +61 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/concat.comp +41 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp +53 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_dw.comp +105 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +480 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp +431 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv_transpose_1d.comp +98 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy.comp +25 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp +51 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp +320 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_transpose.comp +67 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_equal.comp +31 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_experts.comp +51 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum.comp +83 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass1.comp +60 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass2.comp +66 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_f32.comp +20 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl +692 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl +1376 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_head.glsl +13 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_m.comp +42 -0
- backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_s.comp +35 -0
.gitattributes
CHANGED
|
@@ -36,3 +36,28 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 36 |
backend/llama.cpp/conversion/__pycache__/base.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
|
| 37 |
backend/llama.cpp/docs/android/imported-into-android-studio.jpg filter=lfs diff=lfs merge=lfs -text
|
| 38 |
backend/llama.cpp/docs/development/llama-star/idea-arch.key filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
backend/llama.cpp/conversion/__pycache__/base.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
|
| 37 |
backend/llama.cpp/docs/android/imported-into-android-studio.jpg filter=lfs diff=lfs merge=lfs -text
|
| 38 |
backend/llama.cpp/docs/development/llama-star/idea-arch.key filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
backend/llama.cpp/gguf-py/gguf/__pycache__/constants.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
backend/llama.cpp/gguf-py/gguf/__pycache__/gguf_writer.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
backend/llama.cpp/gguf-py/gguf/__pycache__/quants.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
backend/llama.cpp/media/llama0-banner.png filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
backend/llama.cpp/media/llama0-logo.png filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
backend/llama.cpp/media/matmul.png filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
backend/llama.cpp/models/ggml-vocab-aquila.gguf filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
backend/llama.cpp/models/ggml-vocab-baichuan.gguf filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
backend/llama.cpp/models/ggml-vocab-bert-bge.gguf filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
backend/llama.cpp/models/ggml-vocab-command-r.gguf filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
backend/llama.cpp/models/ggml-vocab-deepseek-coder.gguf filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
backend/llama.cpp/models/ggml-vocab-deepseek-llm.gguf filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
backend/llama.cpp/models/ggml-vocab-falcon.gguf filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
backend/llama.cpp/models/ggml-vocab-gemma-4.gguf filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
backend/llama.cpp/models/ggml-vocab-gpt-2.gguf filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
backend/llama.cpp/models/ggml-vocab-gpt-neox.gguf filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
backend/llama.cpp/models/ggml-vocab-llama-bpe.gguf filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
backend/llama.cpp/models/ggml-vocab-llama-spm.gguf filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
backend/llama.cpp/models/ggml-vocab-mpt.gguf filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
backend/llama.cpp/models/ggml-vocab-nomic-bert-moe.gguf filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
backend/llama.cpp/models/ggml-vocab-phi-3.gguf filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
backend/llama.cpp/models/ggml-vocab-qwen2.gguf filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
backend/llama.cpp/models/ggml-vocab-qwen35.gguf filter=lfs diff=lfs merge=lfs -text
|
| 62 |
+
backend/llama.cpp/models/ggml-vocab-refact.gguf filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
backend/llama.cpp/models/ggml-vocab-starcoder.gguf filter=lfs diff=lfs merge=lfs -text
|
backend/llama.cpp/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2023-2026 The ggml authors
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
backend/llama.cpp/Makefile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
define newline
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
endef
|
| 5 |
+
|
| 6 |
+
$(error Build system changed:$(newline)\
|
| 7 |
+
The Makefile build has been replaced by CMake.$(newline)$(newline)\
|
| 8 |
+
For build instructions see:$(newline)\
|
| 9 |
+
https://github.com/ggml-org/llama.cpp/blob/master/docs/build.md$(newline)${newline})
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-apir.h
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "backend/shared/apir_backend.h"
|
| 2 |
+
#include "ggml-alloc.h"
|
| 3 |
+
#include "ggml-impl.h"
|
| 4 |
+
#include "ggml.h"
|
| 5 |
+
#include "virtgpu-shm.h"
|
| 6 |
+
#include "virtgpu-utils.h"
|
| 7 |
+
|
| 8 |
+
struct apir_buffer_context_t {
|
| 9 |
+
apir_buffer_host_handle_t host_handle;
|
| 10 |
+
|
| 11 |
+
struct virtgpu_shmem shmem;
|
| 12 |
+
apir_buffer_type_host_handle_t buft_host_handle;
|
| 13 |
+
};
|
| 14 |
+
|
| 15 |
+
#include "virtgpu-forward.gen.h"
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-backend.cpp
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "virtgpu-forward-impl.h"
|
| 2 |
+
|
| 3 |
+
static long long current_time_ms() {
|
| 4 |
+
timespec ts;
|
| 5 |
+
clock_gettime(CLOCK_REALTIME, &ts); // Use CLOCK_MONOTONIC for elapsed time
|
| 6 |
+
return (long long) ts.tv_sec * 1000000000LL + ts.tv_nsec;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
ggml_status apir_backend_graph_compute(virtgpu * gpu, ggml_cgraph * cgraph) {
|
| 10 |
+
apir_encoder * encoder;
|
| 11 |
+
apir_decoder * decoder;
|
| 12 |
+
ApirForwardReturnCode ret;
|
| 13 |
+
|
| 14 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BACKEND_GRAPH_COMPUTE);
|
| 15 |
+
|
| 16 |
+
std::vector<uint8_t> cgraph_data;
|
| 17 |
+
size_t cgraph_size = apir_serialize_ggml_cgraph(cgraph, cgraph_data);
|
| 18 |
+
|
| 19 |
+
virtgpu_shmem temp_shmem; // Local storage for large buffers
|
| 20 |
+
virtgpu_shmem * shmem = &temp_shmem;
|
| 21 |
+
bool using_shared_shmem = false;
|
| 22 |
+
|
| 23 |
+
if (cgraph_size <= gpu->data_shmem.mmap_size) {
|
| 24 |
+
// Lock mutex before using shared data_shmem buffer
|
| 25 |
+
if (mtx_lock(&gpu->data_shmem_mutex) != thrd_success) {
|
| 26 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Failed to lock data_shmem mutex", __func__);
|
| 27 |
+
}
|
| 28 |
+
using_shared_shmem = true;
|
| 29 |
+
shmem = &gpu->data_shmem;
|
| 30 |
+
} else if (virtgpu_shmem_create(gpu, cgraph_size, shmem)) {
|
| 31 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate the guest-host shared buffer", __func__);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
apir_encode_virtgpu_shmem_res_id(encoder, shmem->res_id);
|
| 35 |
+
|
| 36 |
+
apir_encode_size_t(encoder, &cgraph_size);
|
| 37 |
+
|
| 38 |
+
char * shmem_data = (char *) shmem->mmap_ptr;
|
| 39 |
+
apir_encoder secondary_enc = apir_new_encoder(shmem_data, cgraph_size);
|
| 40 |
+
|
| 41 |
+
apir_encode_cgraph_data(&secondary_enc, cgraph_data);
|
| 42 |
+
|
| 43 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 44 |
+
|
| 45 |
+
ggml_status status = GGML_STATUS_ABORTED;
|
| 46 |
+
apir_decode_ggml_status(decoder, &status);
|
| 47 |
+
|
| 48 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 49 |
+
|
| 50 |
+
// Unlock mutex before cleanup
|
| 51 |
+
if (using_shared_shmem) {
|
| 52 |
+
mtx_unlock(&gpu->data_shmem_mutex);
|
| 53 |
+
} else {
|
| 54 |
+
virtgpu_shmem_destroy(gpu, shmem);
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
return status;
|
| 58 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer-type.cpp
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "virtgpu-forward-impl.h"
|
| 2 |
+
|
| 3 |
+
char * apir_buffer_type_get_name(virtgpu * gpu, apir_buffer_type_host_handle_t host_handle) {
|
| 4 |
+
apir_encoder * encoder;
|
| 5 |
+
apir_decoder * decoder;
|
| 6 |
+
ApirForwardReturnCode ret;
|
| 7 |
+
|
| 8 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_NAME);
|
| 9 |
+
|
| 10 |
+
apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
|
| 11 |
+
|
| 12 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 13 |
+
|
| 14 |
+
const size_t string_size = apir_decode_array_size_unchecked(decoder);
|
| 15 |
+
char * string = (char *) apir_decoder_alloc_array(sizeof(char), string_size);
|
| 16 |
+
if (!string) {
|
| 17 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: Could not allocate the device name buffer\n", __func__);
|
| 18 |
+
apir_decoder_set_fatal(decoder);
|
| 19 |
+
}
|
| 20 |
+
apir_decode_char_array(decoder, string, string_size);
|
| 21 |
+
|
| 22 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 23 |
+
|
| 24 |
+
return string;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
size_t apir_buffer_type_get_alignment(virtgpu * gpu, apir_buffer_type_host_handle_t host_handle) {
|
| 28 |
+
apir_encoder * encoder;
|
| 29 |
+
apir_decoder * decoder;
|
| 30 |
+
ApirForwardReturnCode ret;
|
| 31 |
+
|
| 32 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_ALIGNMENT);
|
| 33 |
+
|
| 34 |
+
apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
|
| 35 |
+
|
| 36 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 37 |
+
|
| 38 |
+
size_t alignment;
|
| 39 |
+
apir_decode_size_t(decoder, &alignment);
|
| 40 |
+
|
| 41 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 42 |
+
|
| 43 |
+
return alignment;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
size_t apir_buffer_type_get_max_size(virtgpu * gpu, apir_buffer_type_host_handle_t host_handle) {
|
| 47 |
+
apir_encoder * encoder;
|
| 48 |
+
apir_decoder * decoder;
|
| 49 |
+
ApirForwardReturnCode ret;
|
| 50 |
+
|
| 51 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_MAX_SIZE);
|
| 52 |
+
|
| 53 |
+
apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
|
| 54 |
+
|
| 55 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 56 |
+
|
| 57 |
+
size_t max_size;
|
| 58 |
+
apir_decode_size_t(decoder, &max_size);
|
| 59 |
+
|
| 60 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 61 |
+
|
| 62 |
+
return max_size;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
apir_buffer_context_t apir_buffer_type_alloc_buffer(virtgpu * gpu,
|
| 66 |
+
apir_buffer_type_host_handle_t host_handle,
|
| 67 |
+
size_t size) {
|
| 68 |
+
apir_encoder * encoder;
|
| 69 |
+
apir_decoder * decoder;
|
| 70 |
+
ApirForwardReturnCode ret;
|
| 71 |
+
|
| 72 |
+
apir_buffer_context_t buffer_context;
|
| 73 |
+
|
| 74 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_ALLOC_BUFFER);
|
| 75 |
+
|
| 76 |
+
apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
|
| 77 |
+
|
| 78 |
+
apir_encode_size_t(encoder, &size);
|
| 79 |
+
|
| 80 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 81 |
+
|
| 82 |
+
apir_decode_apir_buffer_host_handle_t(decoder, &buffer_context.host_handle);
|
| 83 |
+
|
| 84 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 85 |
+
|
| 86 |
+
return buffer_context;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
size_t apir_buffer_type_get_alloc_size(virtgpu * gpu,
|
| 90 |
+
apir_buffer_type_host_handle_t host_handle,
|
| 91 |
+
const ggml_tensor * op) {
|
| 92 |
+
apir_encoder * encoder;
|
| 93 |
+
apir_decoder * decoder;
|
| 94 |
+
ApirForwardReturnCode ret;
|
| 95 |
+
|
| 96 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_ALLOC_SIZE);
|
| 97 |
+
|
| 98 |
+
apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
|
| 99 |
+
|
| 100 |
+
apir_encode_ggml_tensor_inline(encoder, op);
|
| 101 |
+
|
| 102 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 103 |
+
|
| 104 |
+
size_t alloc_size;
|
| 105 |
+
apir_decode_size_t(decoder, &alloc_size);
|
| 106 |
+
|
| 107 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 108 |
+
|
| 109 |
+
return alloc_size;
|
| 110 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer.cpp
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "virtgpu-forward-impl.h"
|
| 2 |
+
|
| 3 |
+
void * apir_buffer_get_base(virtgpu * gpu, apir_buffer_context_t * buffer_context) {
|
| 4 |
+
apir_encoder * encoder;
|
| 5 |
+
apir_decoder * decoder;
|
| 6 |
+
ApirForwardReturnCode ret;
|
| 7 |
+
|
| 8 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_GET_BASE);
|
| 9 |
+
|
| 10 |
+
apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
|
| 11 |
+
|
| 12 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 13 |
+
|
| 14 |
+
uintptr_t base;
|
| 15 |
+
apir_decode_uintptr_t(decoder, &base);
|
| 16 |
+
|
| 17 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 18 |
+
|
| 19 |
+
return (void *) base;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
void apir_buffer_set_tensor(virtgpu * gpu,
|
| 23 |
+
apir_buffer_context_t * buffer_context,
|
| 24 |
+
ggml_tensor * tensor,
|
| 25 |
+
const void * data,
|
| 26 |
+
size_t offset,
|
| 27 |
+
size_t size) {
|
| 28 |
+
apir_encoder * encoder;
|
| 29 |
+
apir_decoder * decoder;
|
| 30 |
+
ApirForwardReturnCode ret;
|
| 31 |
+
|
| 32 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_SET_TENSOR);
|
| 33 |
+
|
| 34 |
+
apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
|
| 35 |
+
apir_encode_ggml_tensor(encoder, tensor);
|
| 36 |
+
|
| 37 |
+
virtgpu_shmem temp_shmem; // Local storage for large buffers
|
| 38 |
+
virtgpu_shmem * shmem = &temp_shmem;
|
| 39 |
+
bool using_shared_shmem = false;
|
| 40 |
+
|
| 41 |
+
if (size <= gpu->data_shmem.mmap_size) {
|
| 42 |
+
// Lock mutex before using shared data_shmem buffer
|
| 43 |
+
if (mtx_lock(&gpu->data_shmem_mutex) != thrd_success) {
|
| 44 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Failed to lock data_shmem mutex", __func__);
|
| 45 |
+
}
|
| 46 |
+
using_shared_shmem = true;
|
| 47 |
+
shmem = &gpu->data_shmem;
|
| 48 |
+
|
| 49 |
+
} else if (virtgpu_shmem_create(gpu, size, shmem)) {
|
| 50 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate the guest-host shared buffer", __func__);
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
memcpy(shmem->mmap_ptr, data, size);
|
| 54 |
+
apir_encode_virtgpu_shmem_res_id(encoder, shmem->res_id);
|
| 55 |
+
|
| 56 |
+
apir_encode_size_t(encoder, &offset);
|
| 57 |
+
apir_encode_size_t(encoder, &size);
|
| 58 |
+
|
| 59 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 60 |
+
|
| 61 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 62 |
+
|
| 63 |
+
// Unlock mutex before cleanup
|
| 64 |
+
if (using_shared_shmem) {
|
| 65 |
+
mtx_unlock(&gpu->data_shmem_mutex);
|
| 66 |
+
} else {
|
| 67 |
+
virtgpu_shmem_destroy(gpu, shmem);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
return;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
void apir_buffer_get_tensor(virtgpu * gpu,
|
| 74 |
+
apir_buffer_context_t * buffer_context,
|
| 75 |
+
const ggml_tensor * tensor,
|
| 76 |
+
void * data,
|
| 77 |
+
size_t offset,
|
| 78 |
+
size_t size) {
|
| 79 |
+
apir_encoder * encoder;
|
| 80 |
+
apir_decoder * decoder;
|
| 81 |
+
ApirForwardReturnCode ret;
|
| 82 |
+
|
| 83 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_GET_TENSOR);
|
| 84 |
+
|
| 85 |
+
apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
|
| 86 |
+
apir_encode_ggml_tensor(encoder, tensor);
|
| 87 |
+
|
| 88 |
+
virtgpu_shmem temp_shmem; // Local storage for large buffers
|
| 89 |
+
virtgpu_shmem * shmem = &temp_shmem;
|
| 90 |
+
bool using_shared_shmem = false;
|
| 91 |
+
|
| 92 |
+
if (size <= gpu->data_shmem.mmap_size) {
|
| 93 |
+
// Lock mutex before using shared data_shmem buffer
|
| 94 |
+
if (mtx_lock(&gpu->data_shmem_mutex) != thrd_success) {
|
| 95 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Failed to lock data_shmem mutex", __func__);
|
| 96 |
+
}
|
| 97 |
+
using_shared_shmem = true;
|
| 98 |
+
shmem = &gpu->data_shmem;
|
| 99 |
+
|
| 100 |
+
} else if (virtgpu_shmem_create(gpu, size, shmem)) {
|
| 101 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate the guest-host shared buffer", __func__);
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
apir_encode_virtgpu_shmem_res_id(encoder, shmem->res_id);
|
| 105 |
+
apir_encode_size_t(encoder, &offset);
|
| 106 |
+
apir_encode_size_t(encoder, &size);
|
| 107 |
+
|
| 108 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 109 |
+
|
| 110 |
+
memcpy(data, shmem->mmap_ptr, size);
|
| 111 |
+
|
| 112 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 113 |
+
|
| 114 |
+
// Unlock mutex before cleanup
|
| 115 |
+
if (using_shared_shmem) {
|
| 116 |
+
mtx_unlock(&gpu->data_shmem_mutex);
|
| 117 |
+
} else {
|
| 118 |
+
virtgpu_shmem_destroy(gpu, shmem);
|
| 119 |
+
}
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
bool apir_buffer_cpy_tensor(virtgpu * gpu,
|
| 123 |
+
apir_buffer_context_t * buffer_context,
|
| 124 |
+
const ggml_tensor * src,
|
| 125 |
+
const ggml_tensor * dst) {
|
| 126 |
+
apir_encoder * encoder;
|
| 127 |
+
apir_decoder * decoder;
|
| 128 |
+
ApirForwardReturnCode ret;
|
| 129 |
+
|
| 130 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_CPY_TENSOR);
|
| 131 |
+
|
| 132 |
+
apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
|
| 133 |
+
apir_encode_ggml_tensor(encoder, src);
|
| 134 |
+
apir_encode_ggml_tensor(encoder, dst);
|
| 135 |
+
|
| 136 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 137 |
+
|
| 138 |
+
bool ret_val;
|
| 139 |
+
apir_decode_bool_t(decoder, &ret_val);
|
| 140 |
+
|
| 141 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 142 |
+
|
| 143 |
+
return ret_val;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
void apir_buffer_clear(virtgpu * gpu, apir_buffer_context_t * buffer_context, uint8_t value) {
|
| 147 |
+
apir_encoder * encoder;
|
| 148 |
+
apir_decoder * decoder;
|
| 149 |
+
ApirForwardReturnCode ret;
|
| 150 |
+
|
| 151 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_CLEAR);
|
| 152 |
+
|
| 153 |
+
apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
|
| 154 |
+
apir_encode_uint8_t(encoder, &value);
|
| 155 |
+
|
| 156 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 157 |
+
|
| 158 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
void apir_buffer_free_buffer(virtgpu * gpu, apir_buffer_context_t * buffer_context) {
|
| 162 |
+
apir_encoder * encoder;
|
| 163 |
+
apir_decoder * decoder;
|
| 164 |
+
ApirForwardReturnCode ret;
|
| 165 |
+
|
| 166 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_FREE_BUFFER);
|
| 167 |
+
|
| 168 |
+
apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
|
| 169 |
+
|
| 170 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 171 |
+
|
| 172 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 173 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-device.cpp
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "virtgpu-forward-impl.h"
|
| 2 |
+
#include "virtgpu-shm.h"
|
| 3 |
+
|
| 4 |
+
int apir_device_get_count(virtgpu * gpu) {
|
| 5 |
+
apir_encoder * encoder;
|
| 6 |
+
apir_decoder * decoder;
|
| 7 |
+
ApirForwardReturnCode ret;
|
| 8 |
+
|
| 9 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_COUNT);
|
| 10 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 11 |
+
|
| 12 |
+
int32_t dev_count = -1;
|
| 13 |
+
apir_decode_int32_t(decoder, &dev_count);
|
| 14 |
+
|
| 15 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 16 |
+
|
| 17 |
+
return dev_count;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
char * apir_device_get_name(virtgpu * gpu) {
|
| 21 |
+
apir_encoder * encoder;
|
| 22 |
+
apir_decoder * decoder;
|
| 23 |
+
ApirForwardReturnCode ret;
|
| 24 |
+
|
| 25 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_NAME);
|
| 26 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 27 |
+
|
| 28 |
+
const size_t string_size = apir_decode_array_size_unchecked(decoder);
|
| 29 |
+
char * string = (char *) apir_decoder_alloc_array(sizeof(char), string_size);
|
| 30 |
+
if (!string) {
|
| 31 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: Could not allocate the device name buffer\n", __func__);
|
| 32 |
+
return NULL;
|
| 33 |
+
}
|
| 34 |
+
apir_decode_char_array(decoder, string, string_size);
|
| 35 |
+
|
| 36 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 37 |
+
|
| 38 |
+
return string;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
char * apir_device_get_description(virtgpu * gpu) {
|
| 42 |
+
apir_encoder * encoder;
|
| 43 |
+
apir_decoder * decoder;
|
| 44 |
+
ApirForwardReturnCode ret;
|
| 45 |
+
|
| 46 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_DESCRIPTION);
|
| 47 |
+
|
| 48 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 49 |
+
|
| 50 |
+
const size_t string_size = apir_decode_array_size_unchecked(decoder);
|
| 51 |
+
char * string = (char *) apir_decoder_alloc_array(sizeof(char), string_size);
|
| 52 |
+
if (!string) {
|
| 53 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: Could not allocate the device description buffer\n", __func__);
|
| 54 |
+
|
| 55 |
+
return NULL;
|
| 56 |
+
}
|
| 57 |
+
apir_decode_char_array(decoder, string, string_size);
|
| 58 |
+
|
| 59 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 60 |
+
|
| 61 |
+
return string;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
uint32_t apir_device_get_type(virtgpu * gpu) {
|
| 65 |
+
static uint32_t dev_type = 255;
|
| 66 |
+
if (dev_type != 255) {
|
| 67 |
+
return dev_type;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
apir_encoder * encoder;
|
| 71 |
+
apir_decoder * decoder;
|
| 72 |
+
ApirForwardReturnCode ret;
|
| 73 |
+
|
| 74 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_TYPE);
|
| 75 |
+
|
| 76 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 77 |
+
|
| 78 |
+
apir_decode_uint32_t(decoder, &dev_type);
|
| 79 |
+
|
| 80 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 81 |
+
|
| 82 |
+
return dev_type;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
void apir_device_get_memory(virtgpu * gpu, size_t * free, size_t * total) {
|
| 86 |
+
static size_t dev_free = 0;
|
| 87 |
+
static size_t dev_total = 0;
|
| 88 |
+
apir_encoder * encoder;
|
| 89 |
+
apir_decoder * decoder;
|
| 90 |
+
ApirForwardReturnCode ret;
|
| 91 |
+
|
| 92 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_MEMORY);
|
| 93 |
+
|
| 94 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 95 |
+
|
| 96 |
+
apir_decode_size_t(decoder, &dev_free);
|
| 97 |
+
apir_decode_size_t(decoder, &dev_total);
|
| 98 |
+
|
| 99 |
+
*free = dev_free;
|
| 100 |
+
*total = dev_total;
|
| 101 |
+
|
| 102 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 103 |
+
|
| 104 |
+
return;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
bool apir_device_supports_op(virtgpu * gpu, const ggml_tensor * op) {
|
| 108 |
+
apir_encoder * encoder;
|
| 109 |
+
apir_decoder * decoder;
|
| 110 |
+
ApirForwardReturnCode ret;
|
| 111 |
+
|
| 112 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_SUPPORTS_OP);
|
| 113 |
+
|
| 114 |
+
apir_encode_ggml_tensor_inline(encoder, op);
|
| 115 |
+
|
| 116 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 117 |
+
|
| 118 |
+
bool supports_op;
|
| 119 |
+
apir_decode_bool_t(decoder, &supports_op);
|
| 120 |
+
|
| 121 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 122 |
+
|
| 123 |
+
return supports_op;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
apir_buffer_type_host_handle_t apir_device_get_buffer_type(virtgpu * gpu) {
|
| 127 |
+
apir_encoder * encoder;
|
| 128 |
+
apir_decoder * decoder;
|
| 129 |
+
ApirForwardReturnCode ret;
|
| 130 |
+
|
| 131 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_BUFFER_TYPE);
|
| 132 |
+
|
| 133 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 134 |
+
|
| 135 |
+
apir_buffer_type_host_handle_t buft_handle;
|
| 136 |
+
apir_decode_apir_buffer_type_host_handle_t(decoder, &buft_handle);
|
| 137 |
+
|
| 138 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 139 |
+
|
| 140 |
+
return buft_handle;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
void apir_device_get_props(virtgpu * gpu,
|
| 144 |
+
bool * async,
|
| 145 |
+
bool * host_buffer,
|
| 146 |
+
bool * buffer_from_host_ptr,
|
| 147 |
+
bool * events) {
|
| 148 |
+
apir_encoder * encoder;
|
| 149 |
+
apir_decoder * decoder;
|
| 150 |
+
ApirForwardReturnCode ret;
|
| 151 |
+
|
| 152 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_PROPS);
|
| 153 |
+
|
| 154 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 155 |
+
|
| 156 |
+
apir_decode_bool_t(decoder, async);
|
| 157 |
+
apir_decode_bool_t(decoder, host_buffer);
|
| 158 |
+
apir_decode_bool_t(decoder, buffer_from_host_ptr);
|
| 159 |
+
apir_decode_bool_t(decoder, events);
|
| 160 |
+
|
| 161 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 162 |
+
|
| 163 |
+
return;
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
apir_buffer_context_t apir_device_buffer_from_ptr(virtgpu * gpu, size_t size, size_t max_tensor_size) {
|
| 167 |
+
apir_encoder * encoder;
|
| 168 |
+
apir_decoder * decoder;
|
| 169 |
+
ApirForwardReturnCode ret;
|
| 170 |
+
|
| 171 |
+
apir_buffer_context_t buffer_context;
|
| 172 |
+
|
| 173 |
+
REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_BUFFER_FROM_PTR);
|
| 174 |
+
|
| 175 |
+
if (virtgpu_shmem_create(gpu, size, &buffer_context.shmem)) {
|
| 176 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate %ldb of guest-host shared buffer", __func__, size);
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
apir_encode_virtgpu_shmem_res_id(encoder, buffer_context.shmem.res_id);
|
| 180 |
+
|
| 181 |
+
apir_encode_size_t(encoder, &size);
|
| 182 |
+
apir_encode_size_t(encoder, &max_tensor_size);
|
| 183 |
+
|
| 184 |
+
REMOTE_CALL(gpu, encoder, decoder, ret);
|
| 185 |
+
|
| 186 |
+
apir_decode_apir_buffer_host_handle_t(decoder, &buffer_context.host_handle);
|
| 187 |
+
buffer_context.buft_host_handle = apir_decode_apir_buffer_type_host_handle(decoder);
|
| 188 |
+
|
| 189 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 190 |
+
|
| 191 |
+
return buffer_context;
|
| 192 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-impl.h
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
// clang-format off
|
| 4 |
+
#include "virtgpu.h"
|
| 5 |
+
#include "ggml-remoting.h"
|
| 6 |
+
#include "backend/shared/apir_backend.h"
|
| 7 |
+
#include "backend/shared/apir_cs_ggml.h"
|
| 8 |
+
#include "ggml-backend-impl.h"
|
| 9 |
+
// clang-format on
|
| 10 |
+
|
| 11 |
+
#define REMOTE_CALL_PREPARE(gpu_dev_name, encoder_name, apir_command_type__) \
|
| 12 |
+
int32_t REMOTE_CALL_PREPARE_forward_flag = (int32_t) apir_command_type__; \
|
| 13 |
+
const char * REMOTE_CALL_PREPARE_command_name = apir_dispatch_command_name(apir_command_type__); \
|
| 14 |
+
do { \
|
| 15 |
+
encoder_name = remote_call_prepare(gpu_dev_name, APIR_COMMAND_TYPE_FORWARD, REMOTE_CALL_PREPARE_forward_flag); \
|
| 16 |
+
if (!encoder_name) { \
|
| 17 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to prepare the remote call encoder", __func__); \
|
| 18 |
+
} \
|
| 19 |
+
} while (0)
|
| 20 |
+
|
| 21 |
+
#define REMOTE_CALL(gpu_dev_name, encoder_name, decoder_name, ret_name) \
|
| 22 |
+
do { \
|
| 23 |
+
ret_name = (ApirForwardReturnCode) remote_call(gpu_dev_name, encoder_name, &decoder_name, 0, NULL); \
|
| 24 |
+
if (!decoder_name) { \
|
| 25 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to kick the remote call", __func__); \
|
| 26 |
+
} \
|
| 27 |
+
if (ret_name < APIR_FORWARD_BASE_INDEX) { \
|
| 28 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to forward the API call: %s: code %d", __func__, \
|
| 29 |
+
apir_forward_error(ret_name), ret_name); \
|
| 30 |
+
} \
|
| 31 |
+
ret_name = (ApirForwardReturnCode) (ret_name - APIR_FORWARD_BASE_INDEX); \
|
| 32 |
+
if (ret_name != 0) { \
|
| 33 |
+
GGML_ABORT(GGML_VIRTGPU "backend function '%s' failed (return code: %d)", \
|
| 34 |
+
REMOTE_CALL_PREPARE_command_name, ret_name); \
|
| 35 |
+
} \
|
| 36 |
+
} while (0)
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward.gen.h
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
/* device */
|
| 4 |
+
void apir_device_get_device_count(struct virtgpu * gpu);
|
| 5 |
+
int apir_device_get_count(struct virtgpu * gpu);
|
| 6 |
+
char * apir_device_get_name(struct virtgpu * gpu);
|
| 7 |
+
char * apir_device_get_description(struct virtgpu * gpu);
|
| 8 |
+
uint32_t apir_device_get_type(struct virtgpu * gpu);
|
| 9 |
+
void apir_device_get_memory(struct virtgpu * gpu, size_t * free, size_t * total);
|
| 10 |
+
bool apir_device_supports_op(struct virtgpu * gpu, const ggml_tensor * op);
|
| 11 |
+
apir_buffer_type_host_handle_t apir_device_get_buffer_type(struct virtgpu * gpu);
|
| 12 |
+
void apir_device_get_props(struct virtgpu * gpu,
|
| 13 |
+
bool * async,
|
| 14 |
+
bool * host_buffer,
|
| 15 |
+
bool * buffer_from_host_ptr,
|
| 16 |
+
bool * events);
|
| 17 |
+
apir_buffer_context_t apir_device_buffer_from_ptr(struct virtgpu * gpu, size_t size, size_t max_tensor_size);
|
| 18 |
+
|
| 19 |
+
/* buffer-type */
|
| 20 |
+
char * apir_buffer_type_get_name(struct virtgpu * gpu, apir_buffer_type_host_handle_t host_handle);
|
| 21 |
+
size_t apir_buffer_type_get_alignment(struct virtgpu * gpu, apir_buffer_type_host_handle_t host_handle);
|
| 22 |
+
size_t apir_buffer_type_get_max_size(struct virtgpu * gpu, apir_buffer_type_host_handle_t host_handle);
|
| 23 |
+
/* apir_buffer_type_is_host is deprecated. */
|
| 24 |
+
apir_buffer_context_t apir_buffer_type_alloc_buffer(struct virtgpu * gpu,
|
| 25 |
+
apir_buffer_type_host_handle_t host_handle,
|
| 26 |
+
size_t size);
|
| 27 |
+
size_t apir_buffer_type_get_alloc_size(struct virtgpu * gpu,
|
| 28 |
+
apir_buffer_type_host_handle_t host_handle,
|
| 29 |
+
const ggml_tensor * op);
|
| 30 |
+
|
| 31 |
+
/* buffer */
|
| 32 |
+
void * apir_buffer_get_base(struct virtgpu * gpu, apir_buffer_context_t * buffer_context);
|
| 33 |
+
void apir_buffer_set_tensor(struct virtgpu * gpu,
|
| 34 |
+
apir_buffer_context_t * buffer_context,
|
| 35 |
+
ggml_tensor * tensor,
|
| 36 |
+
const void * data,
|
| 37 |
+
size_t offset,
|
| 38 |
+
size_t size);
|
| 39 |
+
void apir_buffer_get_tensor(struct virtgpu * gpu,
|
| 40 |
+
apir_buffer_context_t * buffer_context,
|
| 41 |
+
const ggml_tensor * tensor,
|
| 42 |
+
void * data,
|
| 43 |
+
size_t offset,
|
| 44 |
+
size_t size);
|
| 45 |
+
bool apir_buffer_cpy_tensor(struct virtgpu * gpu,
|
| 46 |
+
apir_buffer_context_t * buffer_context,
|
| 47 |
+
const ggml_tensor * src,
|
| 48 |
+
const ggml_tensor * dst);
|
| 49 |
+
void apir_buffer_clear(struct virtgpu * gpu, apir_buffer_context_t * buffer_context, uint8_t value);
|
| 50 |
+
void apir_buffer_free_buffer(struct virtgpu * gpu, apir_buffer_context_t * buffer_context);
|
| 51 |
+
|
| 52 |
+
/* backend */
|
| 53 |
+
ggml_status apir_backend_graph_compute(struct virtgpu * gpu, ggml_cgraph * cgraph);
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.cpp
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "virtgpu-shm.h"
|
| 2 |
+
|
| 3 |
+
#include "virtgpu.h"
|
| 4 |
+
#include "ggml-remoting.h"
|
| 5 |
+
|
| 6 |
+
#include <assert.h>
|
| 7 |
+
|
| 8 |
+
static uint32_t virtgpu_ioctl_resource_create_blob(virtgpu * gpu,
|
| 9 |
+
uint32_t blob_mem,
|
| 10 |
+
uint32_t blob_flags,
|
| 11 |
+
size_t blob_size,
|
| 12 |
+
uint64_t blob_id,
|
| 13 |
+
uint32_t * res_id) {
|
| 14 |
+
#ifdef SIMULATE_BO_SIZE_FIX
|
| 15 |
+
blob_size = align64(blob_size, 4096);
|
| 16 |
+
#endif
|
| 17 |
+
|
| 18 |
+
drm_virtgpu_resource_create_blob args = {
|
| 19 |
+
.blob_mem = blob_mem,
|
| 20 |
+
.blob_flags = blob_flags,
|
| 21 |
+
.bo_handle = 0,
|
| 22 |
+
.res_handle = 0,
|
| 23 |
+
.size = blob_size,
|
| 24 |
+
.pad = 0,
|
| 25 |
+
.cmd_size = 0,
|
| 26 |
+
.cmd = 0,
|
| 27 |
+
.blob_id = blob_id,
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
if (virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &args)) {
|
| 31 |
+
return 0;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
*res_id = args.res_handle;
|
| 35 |
+
return args.bo_handle;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
static void virtgpu_ioctl_gem_close(virtgpu * gpu, uint32_t gem_handle) {
|
| 39 |
+
drm_gem_close args = {
|
| 40 |
+
.handle = gem_handle,
|
| 41 |
+
.pad = 0,
|
| 42 |
+
};
|
| 43 |
+
|
| 44 |
+
const int ret = virtgpu_ioctl(gpu, DRM_IOCTL_GEM_CLOSE, &args);
|
| 45 |
+
assert(!ret);
|
| 46 |
+
#ifdef NDEBUG
|
| 47 |
+
UNUSED(ret);
|
| 48 |
+
#endif
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
static void * virtgpu_ioctl_map(virtgpu * gpu, uint32_t gem_handle, size_t size) {
|
| 52 |
+
drm_virtgpu_map args = {
|
| 53 |
+
.offset = 0,
|
| 54 |
+
.handle = gem_handle,
|
| 55 |
+
.pad = 0,
|
| 56 |
+
};
|
| 57 |
+
|
| 58 |
+
if (virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_MAP, &args)) {
|
| 59 |
+
return NULL;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
void * ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, gpu->fd, args.offset);
|
| 63 |
+
if (ptr == MAP_FAILED) {
|
| 64 |
+
return NULL;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
return ptr;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
void virtgpu_shmem_destroy(virtgpu * gpu, virtgpu_shmem * shmem) {
|
| 71 |
+
munmap(shmem->mmap_ptr, shmem->mmap_size);
|
| 72 |
+
virtgpu_ioctl_gem_close(gpu, shmem->gem_handle);
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
int virtgpu_shmem_create(virtgpu * gpu, size_t size, virtgpu_shmem * shmem) {
|
| 76 |
+
size = align64(size, 16384);
|
| 77 |
+
|
| 78 |
+
uint32_t res_id;
|
| 79 |
+
uint32_t gem_handle = virtgpu_ioctl_resource_create_blob(gpu, VIRTGPU_BLOB_MEM_HOST3D,
|
| 80 |
+
VIRTGPU_BLOB_FLAG_USE_MAPPABLE, size, 0, &res_id);
|
| 81 |
+
|
| 82 |
+
if (!gem_handle) {
|
| 83 |
+
return 1;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
void * ptr = virtgpu_ioctl_map(gpu, gem_handle, size);
|
| 87 |
+
if (!ptr) {
|
| 88 |
+
virtgpu_ioctl_gem_close(gpu, gem_handle);
|
| 89 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: virtgpu_ioctl_map failed\n", __func__);
|
| 90 |
+
return 1;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
shmem->res_id = res_id;
|
| 94 |
+
shmem->mmap_size = size;
|
| 95 |
+
shmem->mmap_ptr = ptr;
|
| 96 |
+
shmem->gem_handle = gem_handle;
|
| 97 |
+
|
| 98 |
+
return 0;
|
| 99 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.h
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include "virtgpu-utils.h"
|
| 4 |
+
|
| 5 |
+
#include <sys/mman.h>
|
| 6 |
+
|
| 7 |
+
#include <atomic>
|
| 8 |
+
#include <cassert>
|
| 9 |
+
#include <cstddef>
|
| 10 |
+
#include <cstdint>
|
| 11 |
+
|
| 12 |
+
struct virtgpu;
|
| 13 |
+
|
| 14 |
+
struct virtgpu_shmem {
|
| 15 |
+
uint32_t res_id;
|
| 16 |
+
size_t mmap_size;
|
| 17 |
+
void * mmap_ptr;
|
| 18 |
+
|
| 19 |
+
uint32_t gem_handle;
|
| 20 |
+
};
|
| 21 |
+
|
| 22 |
+
int virtgpu_shmem_create(virtgpu * gpu, size_t size, virtgpu_shmem * shmem);
|
| 23 |
+
void virtgpu_shmem_destroy(virtgpu * gpu, virtgpu_shmem * shmem);
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.cpp
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "virtgpu-utils.h"
|
| 2 |
+
|
| 3 |
+
#include <malloc.h>
|
| 4 |
+
#include <stdlib.h>
|
| 5 |
+
|
| 6 |
+
#include <cstring>
|
| 7 |
+
|
| 8 |
+
#define NODE_ALLOC_ALIGN 64
|
| 9 |
+
#define NODE_PTR_MASK (~((uintptr_t) NODE_ALLOC_ALIGN - 1))
|
| 10 |
+
#define NODE_LEVEL_MASK ((uintptr_t) NODE_ALLOC_ALIGN - 1)
|
| 11 |
+
#define NULL_NODE 0
|
| 12 |
+
|
| 13 |
+
#define os_malloc_aligned(_size, _align) _aligned_malloc(_size, _align)
|
| 14 |
+
#define os_free_aligned(_ptr) free(_ptr)
|
| 15 |
+
#define p_atomic_cmpxchg(v, old, _new) __sync_val_compare_and_swap((v), (old), (_new))
|
| 16 |
+
|
| 17 |
+
static inline uint64_t util_logbase2_64(uint64_t n) {
|
| 18 |
+
#if defined(HAVE___BUILTIN_CLZLL)
|
| 19 |
+
return ((sizeof(uint64_t) * 8 - 1) - __builtin_clzll(n | 1));
|
| 20 |
+
#else
|
| 21 |
+
uint64_t pos = 0ull;
|
| 22 |
+
if (n >= 1ull << 32) {
|
| 23 |
+
n >>= 32;
|
| 24 |
+
pos += 32;
|
| 25 |
+
}
|
| 26 |
+
if (n >= 1ull << 16) {
|
| 27 |
+
n >>= 16;
|
| 28 |
+
pos += 16;
|
| 29 |
+
}
|
| 30 |
+
if (n >= 1ull << 8) {
|
| 31 |
+
n >>= 8;
|
| 32 |
+
pos += 8;
|
| 33 |
+
}
|
| 34 |
+
if (n >= 1ull << 4) {
|
| 35 |
+
n >>= 4;
|
| 36 |
+
pos += 4;
|
| 37 |
+
}
|
| 38 |
+
if (n >= 1ull << 2) {
|
| 39 |
+
n >>= 2;
|
| 40 |
+
pos += 2;
|
| 41 |
+
}
|
| 42 |
+
if (n >= 1ull << 1) {
|
| 43 |
+
pos += 1;
|
| 44 |
+
}
|
| 45 |
+
return pos;
|
| 46 |
+
#endif
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
void util_sparse_array_init(util_sparse_array * arr, size_t elem_size, size_t node_size) {
|
| 50 |
+
memset(arr, 0, sizeof(*arr));
|
| 51 |
+
arr->elem_size = elem_size;
|
| 52 |
+
arr->node_size_log2 = util_logbase2_64(node_size);
|
| 53 |
+
assert(node_size >= 2 && node_size == (1ull << arr->node_size_log2));
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
static inline void * os_malloc_aligned(size_t size, size_t alignment) {
|
| 57 |
+
void * ptr;
|
| 58 |
+
alignment = (alignment + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
|
| 59 |
+
if (posix_memalign(&ptr, alignment, size) != 0) {
|
| 60 |
+
return NULL;
|
| 61 |
+
}
|
| 62 |
+
return ptr;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
static inline void * _util_sparse_array_node_data(uintptr_t handle) {
|
| 66 |
+
return (void *) (handle & NODE_PTR_MASK);
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
static inline unsigned _util_sparse_array_node_level(uintptr_t handle) {
|
| 70 |
+
return handle & NODE_LEVEL_MASK;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
static inline void _util_sparse_array_node_finish(util_sparse_array * arr, uintptr_t node) {
|
| 74 |
+
if (_util_sparse_array_node_level(node) > 0) {
|
| 75 |
+
uintptr_t * children = (uintptr_t *) _util_sparse_array_node_data(node);
|
| 76 |
+
size_t node_size = 1ull << arr->node_size_log2;
|
| 77 |
+
for (size_t i = 0; i < node_size; i++) {
|
| 78 |
+
if (children[i]) {
|
| 79 |
+
_util_sparse_array_node_finish(arr, children[i]);
|
| 80 |
+
}
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
os_free_aligned(_util_sparse_array_node_data(node));
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
static inline uintptr_t _util_sparse_array_node(void * data, unsigned level) {
|
| 88 |
+
assert(data != NULL);
|
| 89 |
+
assert(((uintptr_t) data & NODE_LEVEL_MASK) == 0);
|
| 90 |
+
assert((level & NODE_PTR_MASK) == 0);
|
| 91 |
+
return (uintptr_t) data | level;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
inline uintptr_t _util_sparse_array_node_alloc(util_sparse_array * arr, unsigned level) {
|
| 95 |
+
size_t size;
|
| 96 |
+
if (level == 0) {
|
| 97 |
+
size = arr->elem_size << arr->node_size_log2;
|
| 98 |
+
} else {
|
| 99 |
+
size = sizeof(uintptr_t) << arr->node_size_log2;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
void * data = os_malloc_aligned(size, NODE_ALLOC_ALIGN);
|
| 103 |
+
memset(data, 0, size);
|
| 104 |
+
|
| 105 |
+
return _util_sparse_array_node(data, level);
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
static inline uintptr_t _util_sparse_array_set_or_free_node(uintptr_t * node_ptr, uintptr_t cmp_node, uintptr_t node) {
|
| 109 |
+
uintptr_t prev_node = p_atomic_cmpxchg(node_ptr, cmp_node, node);
|
| 110 |
+
|
| 111 |
+
if (prev_node != cmp_node) {
|
| 112 |
+
/* We lost the race. Free this one and return the one that was already
|
| 113 |
+
* allocated.
|
| 114 |
+
*/
|
| 115 |
+
os_free_aligned(_util_sparse_array_node_data(node));
|
| 116 |
+
return prev_node;
|
| 117 |
+
} else {
|
| 118 |
+
return node;
|
| 119 |
+
}
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
void * util_sparse_array_get(util_sparse_array * arr, uint64_t idx) {
|
| 123 |
+
const unsigned node_size_log2 = arr->node_size_log2;
|
| 124 |
+
uintptr_t root = p_atomic_read(&arr->root);
|
| 125 |
+
if (unlikely(!root)) {
|
| 126 |
+
unsigned root_level = 0;
|
| 127 |
+
uint64_t idx_iter = idx >> node_size_log2;
|
| 128 |
+
while (idx_iter) {
|
| 129 |
+
idx_iter >>= node_size_log2;
|
| 130 |
+
root_level++;
|
| 131 |
+
}
|
| 132 |
+
uintptr_t new_root = _util_sparse_array_node_alloc(arr, root_level);
|
| 133 |
+
root = _util_sparse_array_set_or_free_node(&arr->root, NULL_NODE, new_root);
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
while (1) {
|
| 137 |
+
unsigned root_level = _util_sparse_array_node_level(root);
|
| 138 |
+
uint64_t root_idx = idx >> (root_level * node_size_log2);
|
| 139 |
+
if (likely(root_idx < (1ull << node_size_log2))) {
|
| 140 |
+
break;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
/* In this case, we have a root but its level is low enough that the
|
| 144 |
+
* requested index is out-of-bounds.
|
| 145 |
+
*/
|
| 146 |
+
uintptr_t new_root = _util_sparse_array_node_alloc(arr, root_level + 1);
|
| 147 |
+
|
| 148 |
+
uintptr_t * new_root_children = (uintptr_t *) _util_sparse_array_node_data(new_root);
|
| 149 |
+
new_root_children[0] = root;
|
| 150 |
+
|
| 151 |
+
/* We only add one at a time instead of the whole tree because it's
|
| 152 |
+
* easier to ensure correctness of both the tree building and the
|
| 153 |
+
* clean-up path. Because we're only adding one node we never have to
|
| 154 |
+
* worry about trying to free multiple things without freeing the old
|
| 155 |
+
* things.
|
| 156 |
+
*/
|
| 157 |
+
root = _util_sparse_array_set_or_free_node(&arr->root, root, new_root);
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
void * node_data = _util_sparse_array_node_data(root);
|
| 161 |
+
unsigned node_level = _util_sparse_array_node_level(root);
|
| 162 |
+
while (node_level > 0) {
|
| 163 |
+
uint64_t child_idx = (idx >> (node_level * node_size_log2)) & ((1ull << node_size_log2) - 1);
|
| 164 |
+
|
| 165 |
+
uintptr_t * children = (uintptr_t *) node_data;
|
| 166 |
+
uintptr_t child = p_atomic_read(&children[child_idx]);
|
| 167 |
+
|
| 168 |
+
if (unlikely(!child)) {
|
| 169 |
+
child = _util_sparse_array_node_alloc(arr, node_level - 1);
|
| 170 |
+
child = _util_sparse_array_set_or_free_node(&children[child_idx], NULL_NODE, child);
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
node_data = _util_sparse_array_node_data(child);
|
| 174 |
+
node_level = _util_sparse_array_node_level(child);
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
uint64_t elem_idx = idx & ((1ull << node_size_log2) - 1);
|
| 178 |
+
return (void *) ((char *) node_data + (elem_idx * arr->elem_size));
|
| 179 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.h
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <atomic>
|
| 4 |
+
#include <cassert>
|
| 5 |
+
#include <cerrno>
|
| 6 |
+
#include <cstdarg>
|
| 7 |
+
#include <cstddef>
|
| 8 |
+
#include <cstdint>
|
| 9 |
+
#include <cstdio>
|
| 10 |
+
#include <cstdlib>
|
| 11 |
+
#include <ctime>
|
| 12 |
+
|
| 13 |
+
#define unlikely(x) __builtin_expect(!!(x), 0)
|
| 14 |
+
#define likely(x) __builtin_expect(!!(x), 1)
|
| 15 |
+
|
| 16 |
+
#ifndef UNUSED
|
| 17 |
+
# define UNUSED(x) (void) (x)
|
| 18 |
+
#endif
|
| 19 |
+
|
| 20 |
+
/** Checks is a value is a power of two. Does not handle zero. */
|
| 21 |
+
#define IS_POT(v) (((v) & ((v) - 1)) == 0)
|
| 22 |
+
|
| 23 |
+
/** Checks is a value is a power of two. Zero handled. */
|
| 24 |
+
#define IS_POT_NONZERO(v) ((v) != 0 && IS_POT(v))
|
| 25 |
+
|
| 26 |
+
/** Align a value to a power of two */
|
| 27 |
+
#define ALIGN_POT(x, pot_align) (((x) + (pot_align) - 1) & ~((pot_align) - 1))
|
| 28 |
+
|
| 29 |
+
#define p_atomic_read(_v) __atomic_load_n((_v), __ATOMIC_ACQUIRE)
|
| 30 |
+
|
| 31 |
+
static inline bool util_is_power_of_two_nonzero64(uint64_t v) {
|
| 32 |
+
return IS_POT_NONZERO(v);
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
static inline uint64_t align64(uint64_t value, uint64_t alignment) {
|
| 36 |
+
assert(util_is_power_of_two_nonzero64(alignment));
|
| 37 |
+
return ALIGN_POT(value, alignment);
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
struct list_head {
|
| 41 |
+
list_head * prev;
|
| 42 |
+
list_head * next;
|
| 43 |
+
};
|
| 44 |
+
|
| 45 |
+
struct util_sparse_array {
|
| 46 |
+
size_t elem_size;
|
| 47 |
+
unsigned node_size_log2;
|
| 48 |
+
|
| 49 |
+
uintptr_t root;
|
| 50 |
+
};
|
| 51 |
+
|
| 52 |
+
void * util_sparse_array_get(util_sparse_array * arr, uint64_t idx);
|
| 53 |
+
void util_sparse_array_init(util_sparse_array * arr, size_t elem_size, size_t node_size);
|
| 54 |
+
|
| 55 |
+
inline void os_time_sleep(int64_t usecs) {
|
| 56 |
+
timespec time;
|
| 57 |
+
time.tv_sec = usecs / 1000000;
|
| 58 |
+
time.tv_nsec = (usecs % 1000000) * 1000;
|
| 59 |
+
while (clock_nanosleep(CLOCK_MONOTONIC, 0, &time, &time) == EINTR)
|
| 60 |
+
;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
struct timer_data {
|
| 64 |
+
long long start;
|
| 65 |
+
long long total;
|
| 66 |
+
long long count;
|
| 67 |
+
};
|
| 68 |
+
|
| 69 |
+
static inline void start_timer(timer_data * timer) {
|
| 70 |
+
timespec ts;
|
| 71 |
+
clock_gettime(CLOCK_MONOTONIC, &ts);
|
| 72 |
+
timer->start = (long long) ts.tv_sec * 1000000000LL + ts.tv_nsec;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
// returns the duration in ns
|
| 76 |
+
static inline long long stop_timer(timer_data * timer) {
|
| 77 |
+
timespec ts;
|
| 78 |
+
clock_gettime(CLOCK_MONOTONIC, &ts);
|
| 79 |
+
long long timer_end = (long long) ts.tv_sec * 1000000000LL + ts.tv_nsec;
|
| 80 |
+
|
| 81 |
+
long long duration = (timer_end - timer->start);
|
| 82 |
+
timer->total += duration;
|
| 83 |
+
timer->count += 1;
|
| 84 |
+
|
| 85 |
+
return duration;
|
| 86 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.cpp
ADDED
|
@@ -0,0 +1,545 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "virtgpu.h"
|
| 2 |
+
#include "ggml-remoting.h"
|
| 3 |
+
|
| 4 |
+
#include <stdio.h>
|
| 5 |
+
#include <unistd.h>
|
| 6 |
+
|
| 7 |
+
#include <cassert>
|
| 8 |
+
#include <cerrno>
|
| 9 |
+
#include <cstdlib>
|
| 10 |
+
|
| 11 |
+
static virt_gpu_result_t virtgpu_open_device(virtgpu * gpu, const drmDevicePtr dev);
|
| 12 |
+
static virt_gpu_result_t virtgpu_open(virtgpu * gpu);
|
| 13 |
+
|
| 14 |
+
static virt_gpu_result_t virtgpu_init_capset(virtgpu * gpu);
|
| 15 |
+
static virt_gpu_result_t virtgpu_init_context(virtgpu * gpu);
|
| 16 |
+
|
| 17 |
+
static int virtgpu_ioctl_context_init(virtgpu * gpu, virgl_renderer_capset capset_id);
|
| 18 |
+
static int virtgpu_ioctl_get_caps(virtgpu * gpu,
|
| 19 |
+
virgl_renderer_capset id,
|
| 20 |
+
uint32_t version,
|
| 21 |
+
void * capset,
|
| 22 |
+
size_t capset_size);
|
| 23 |
+
static uint64_t virtgpu_ioctl_getparam(virtgpu * gpu, uint64_t param);
|
| 24 |
+
static void virtgpu_init_renderer_info(virtgpu * gpu);
|
| 25 |
+
|
| 26 |
+
static void log_call_duration(long long call_duration_ns, const char * name);
|
| 27 |
+
|
| 28 |
+
const uint64_t APIR_HANDSHAKE_MAX_WAIT_MS = 2 * 1000; // 2s
|
| 29 |
+
const uint64_t APIR_LOADLIBRARY_MAX_WAIT_MS = 60 * 1000; // 60s
|
| 30 |
+
|
| 31 |
+
static int virtgpu_handshake(virtgpu * gpu) {
|
| 32 |
+
apir_encoder * encoder;
|
| 33 |
+
apir_decoder * decoder;
|
| 34 |
+
|
| 35 |
+
encoder = remote_call_prepare(gpu, APIR_COMMAND_TYPE_HANDSHAKE, 0);
|
| 36 |
+
if (!encoder) {
|
| 37 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to prepare the remote call encoder", __func__);
|
| 38 |
+
return 1;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
/* write handshake props */
|
| 42 |
+
|
| 43 |
+
uint32_t guest_major = APIR_PROTOCOL_MAJOR;
|
| 44 |
+
uint32_t guest_minor = APIR_PROTOCOL_MINOR;
|
| 45 |
+
apir_encode_uint32_t(encoder, &guest_major);
|
| 46 |
+
apir_encode_uint32_t(encoder, &guest_minor);
|
| 47 |
+
|
| 48 |
+
/* *** */
|
| 49 |
+
|
| 50 |
+
uint32_t ret_magic;
|
| 51 |
+
long long call_duration_ns;
|
| 52 |
+
ret_magic = remote_call(gpu, encoder, &decoder, APIR_HANDSHAKE_MAX_WAIT_MS, &call_duration_ns);
|
| 53 |
+
log_call_duration(call_duration_ns, "API Remoting handshake");
|
| 54 |
+
|
| 55 |
+
if (!decoder) {
|
| 56 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 57 |
+
"%s: failed to initiate the communication with the virglrenderer library. "
|
| 58 |
+
"Most likely, the wrong virglrenderer library was loaded in the hypervisor.",
|
| 59 |
+
__func__);
|
| 60 |
+
return 1;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
/* read handshake return values */
|
| 64 |
+
|
| 65 |
+
uint32_t host_major;
|
| 66 |
+
uint32_t host_minor;
|
| 67 |
+
|
| 68 |
+
if (ret_magic != APIR_HANDSHAKE_MAGIC) {
|
| 69 |
+
GGML_ABORT(GGML_VIRTGPU "%s: handshake with the virglrenderer failed (code=%d | %s)", __func__, ret_magic,
|
| 70 |
+
apir_backend_initialize_error(ret_magic));
|
| 71 |
+
} else {
|
| 72 |
+
apir_decode_uint32_t(decoder, &host_major);
|
| 73 |
+
apir_decode_uint32_t(decoder, &host_minor);
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 77 |
+
|
| 78 |
+
if (ret_magic != APIR_HANDSHAKE_MAGIC) {
|
| 79 |
+
return 1;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
GGML_LOG_INFO(GGML_VIRTGPU "%s: Guest is running with %u.%u\n", __func__, guest_major, guest_minor);
|
| 83 |
+
GGML_LOG_INFO(GGML_VIRTGPU "%s: Host is running with %u.%u\n", __func__, host_major, host_minor);
|
| 84 |
+
|
| 85 |
+
if (guest_major != host_major) {
|
| 86 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "Host major (%d) and guest major (%d) version differ\n", host_major, guest_major);
|
| 87 |
+
} else if (guest_minor != host_minor) {
|
| 88 |
+
GGML_LOG_WARN(GGML_VIRTGPU "Host minor (%d) and guest minor (%d) version differ\n", host_minor, guest_minor);
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
return 0;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
static ApirLoadLibraryReturnCode virtgpu_load_library(virtgpu * gpu) {
|
| 95 |
+
apir_encoder * encoder;
|
| 96 |
+
apir_decoder * decoder;
|
| 97 |
+
ApirLoadLibraryReturnCode ret;
|
| 98 |
+
|
| 99 |
+
encoder = remote_call_prepare(gpu, APIR_COMMAND_TYPE_LOADLIBRARY, 0);
|
| 100 |
+
if (!encoder) {
|
| 101 |
+
GGML_ABORT(GGML_VIRTGPU "%s: hypercall error: failed to prepare the API Remoting command encoder", __func__);
|
| 102 |
+
return APIR_LOAD_LIBRARY_HYPERCALL_INITIALIZATION_ERROR;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
long long call_duration_ns;
|
| 106 |
+
|
| 107 |
+
ret = (ApirLoadLibraryReturnCode) remote_call(gpu, encoder, &decoder, APIR_LOADLIBRARY_MAX_WAIT_MS,
|
| 108 |
+
&call_duration_ns);
|
| 109 |
+
log_call_duration(call_duration_ns, "API Remoting LoadLibrary");
|
| 110 |
+
|
| 111 |
+
if (!decoder) {
|
| 112 |
+
GGML_ABORT(GGML_VIRTGPU "%s: hypercall error: failed to trigger the API Remoting hypercall.\n", __func__);
|
| 113 |
+
return APIR_LOAD_LIBRARY_HYPERCALL_INITIALIZATION_ERROR;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
remote_call_finish(gpu, encoder, decoder);
|
| 117 |
+
|
| 118 |
+
if (ret == APIR_LOAD_LIBRARY_SUCCESS) {
|
| 119 |
+
GGML_LOG_INFO(GGML_VIRTGPU "The API Remoting backend was successfully loaded and initialized\n");
|
| 120 |
+
|
| 121 |
+
return ret;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
// something wrong happened, find out what.
|
| 125 |
+
if (ret < APIR_LOAD_LIBRARY_INIT_BASE_INDEX) {
|
| 126 |
+
if (ret == APIR_LOAD_LIBRARY_ENV_VAR_MISSING) {
|
| 127 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 128 |
+
"%s: virglrenderer could not open the API Remoting backend library, "
|
| 129 |
+
"some environment variables are missing. "
|
| 130 |
+
"Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
|
| 131 |
+
__func__, apir_load_library_error(ret));
|
| 132 |
+
} else if (ret == APIR_LOAD_LIBRARY_CANNOT_OPEN) {
|
| 133 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 134 |
+
"%s: virglrenderer could not open the API Remoting backend library. "
|
| 135 |
+
"Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
|
| 136 |
+
__func__, apir_load_library_error(ret));
|
| 137 |
+
} else if (ret == APIR_LOAD_LIBRARY_ENV_VAR_MISSING) {
|
| 138 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 139 |
+
"%s: could not load the backend library, some symbols are missing. "
|
| 140 |
+
"Make sure virglrenderer is correctly configured by the hypervisor. (%s) ",
|
| 141 |
+
__func__, apir_load_library_error(ret));
|
| 142 |
+
} else {
|
| 143 |
+
GGML_ABORT(GGML_VIRTGPU "%s: virglrenderer could not load the API Remoting backend library. (%s - code %d)",
|
| 144 |
+
__func__, apir_load_library_error(ret), ret);
|
| 145 |
+
}
|
| 146 |
+
return ret;
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
GGML_LOG_INFO(GGML_VIRTGPU "%s: virglrenderer successfully loaded the API Remoting backend library.\n", __func__);
|
| 150 |
+
|
| 151 |
+
ApirLoadLibraryReturnCode apir_ret = (ApirLoadLibraryReturnCode) (ret - APIR_LOAD_LIBRARY_INIT_BASE_INDEX);
|
| 152 |
+
|
| 153 |
+
if (apir_ret == APIR_LOAD_LIBRARY_CANNOT_OPEN) {
|
| 154 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 155 |
+
"%s: the API Remoting backend library couldn't load the GGML backend library. "
|
| 156 |
+
"Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
|
| 157 |
+
__func__, apir_load_library_error(apir_ret));
|
| 158 |
+
} else if (apir_ret == APIR_LOAD_LIBRARY_SYMBOL_MISSING) {
|
| 159 |
+
GGML_ABORT(
|
| 160 |
+
GGML_VIRTGPU
|
| 161 |
+
"%s: the API Remoting backend library couldn't load the GGML backend library, some symbols are missing. "
|
| 162 |
+
"Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
|
| 163 |
+
__func__, apir_load_library_error(apir_ret));
|
| 164 |
+
} else if (apir_ret < APIR_LOAD_LIBRARY_INIT_BASE_INDEX) {
|
| 165 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 166 |
+
"%s: the API Remoting backend library couldn't load the GGML backend library: apir code=%d | %s)",
|
| 167 |
+
__func__, apir_ret, apir_load_library_error(apir_ret));
|
| 168 |
+
} else {
|
| 169 |
+
uint32_t lib_ret = apir_ret - APIR_LOAD_LIBRARY_INIT_BASE_INDEX;
|
| 170 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 171 |
+
"%s: the API Remoting backend library failed to initialize its backend library: apir code=%d)",
|
| 172 |
+
__func__, lib_ret);
|
| 173 |
+
}
|
| 174 |
+
return ret;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
virtgpu * create_virtgpu() {
|
| 178 |
+
virtgpu * gpu = new virtgpu();
|
| 179 |
+
|
| 180 |
+
gpu->use_apir_capset = getenv("GGML_REMOTING_USE_APIR_CAPSET") != nullptr;
|
| 181 |
+
util_sparse_array_init(&gpu->shmem_array, sizeof(virtgpu_shmem), 1024);
|
| 182 |
+
|
| 183 |
+
// Initialize mutex to protect shared data_shmem buffer
|
| 184 |
+
if (mtx_init(&gpu->data_shmem_mutex, mtx_plain) != thrd_success) {
|
| 185 |
+
delete gpu;
|
| 186 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to initialize data_shmem mutex", __func__);
|
| 187 |
+
return NULL;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
if (virtgpu_open(gpu) != APIR_SUCCESS) {
|
| 191 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to open the virtgpu device\n", __func__);
|
| 192 |
+
return NULL;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
if (virtgpu_init_capset(gpu) != APIR_SUCCESS) {
|
| 196 |
+
if (gpu->use_apir_capset) {
|
| 197 |
+
GGML_ABORT(GGML_VIRTGPU
|
| 198 |
+
"%s: failed to initialize the virtgpu APIR capset. Make sure that the virglrenderer library "
|
| 199 |
+
"supports it.",
|
| 200 |
+
__func__);
|
| 201 |
+
} else {
|
| 202 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to initialize the virtgpu Venus capset", __func__);
|
| 203 |
+
}
|
| 204 |
+
return NULL;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
if (virtgpu_init_context(gpu) != APIR_SUCCESS) {
|
| 208 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to initialize the GPU context", __func__);
|
| 209 |
+
return NULL;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
if (virtgpu_shmem_create(gpu, SHMEM_REPLY_SIZE, &gpu->reply_shmem)) {
|
| 213 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to create the shared reply memory pages", __func__);
|
| 214 |
+
return NULL;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
if (virtgpu_shmem_create(gpu, SHMEM_DATA_SIZE, &gpu->data_shmem)) {
|
| 218 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to create the shared data memory pages", __func__);
|
| 219 |
+
return NULL;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
if (virtgpu_handshake(gpu)) {
|
| 223 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to handshake with the virglrenderer library", __func__);
|
| 224 |
+
return NULL;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
if (virtgpu_load_library(gpu) != APIR_LOAD_LIBRARY_SUCCESS) {
|
| 228 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to load the backend library", __func__);
|
| 229 |
+
return NULL;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
return gpu;
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
static virt_gpu_result_t virtgpu_open(virtgpu * gpu) {
|
| 236 |
+
drmDevicePtr devs[8];
|
| 237 |
+
int count = drmGetDevices2(0, devs, ARRAY_SIZE(devs));
|
| 238 |
+
if (count < 0) {
|
| 239 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to enumerate DRM devices\n", __func__);
|
| 240 |
+
return APIR_ERROR_INITIALIZATION_FAILED;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
virt_gpu_result_t result = APIR_ERROR_INITIALIZATION_FAILED;
|
| 244 |
+
for (int i = 0; i < count; i++) {
|
| 245 |
+
result = virtgpu_open_device(gpu, devs[i]);
|
| 246 |
+
if (result == APIR_SUCCESS) {
|
| 247 |
+
break;
|
| 248 |
+
}
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
drmFreeDevices(devs, count);
|
| 252 |
+
|
| 253 |
+
return result;
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
static virt_gpu_result_t virtgpu_open_device(virtgpu * gpu, const drmDevicePtr dev) {
|
| 257 |
+
const char * node_path = dev->nodes[DRM_NODE_RENDER];
|
| 258 |
+
|
| 259 |
+
int fd = open(node_path, O_RDWR | O_CLOEXEC);
|
| 260 |
+
if (fd < 0) {
|
| 261 |
+
GGML_ABORT(GGML_VIRTGPU "%s: failed to open %s", __func__, node_path);
|
| 262 |
+
return APIR_ERROR_INITIALIZATION_FAILED;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
drmVersionPtr version = drmGetVersion(fd);
|
| 266 |
+
if (!version || strcmp(version->name, "virtio_gpu") || version->version_major != 0) {
|
| 267 |
+
if (version) {
|
| 268 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: unknown DRM driver %s version %d\n", __func__, version->name,
|
| 269 |
+
version->version_major);
|
| 270 |
+
} else {
|
| 271 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to get DRM driver version\n", __func__);
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
if (version) {
|
| 275 |
+
drmFreeVersion(version);
|
| 276 |
+
}
|
| 277 |
+
close(fd);
|
| 278 |
+
return APIR_ERROR_INITIALIZATION_FAILED;
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
gpu->fd = fd;
|
| 282 |
+
|
| 283 |
+
drmFreeVersion(version);
|
| 284 |
+
|
| 285 |
+
GGML_LOG_INFO(GGML_VIRTGPU "using DRM device %s\n", node_path);
|
| 286 |
+
|
| 287 |
+
return APIR_SUCCESS;
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
static virt_gpu_result_t virtgpu_init_context(virtgpu * gpu) {
|
| 291 |
+
assert(!gpu->capset.version);
|
| 292 |
+
const int ret = virtgpu_ioctl_context_init(gpu, gpu->capset.id);
|
| 293 |
+
if (ret) {
|
| 294 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to initialize context: %s\n", __func__, strerror(errno));
|
| 295 |
+
return APIR_ERROR_INITIALIZATION_FAILED;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
return APIR_SUCCESS;
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
static virt_gpu_result_t virtgpu_init_capset(virtgpu * gpu) {
|
| 302 |
+
if (gpu->use_apir_capset) {
|
| 303 |
+
GGML_LOG_INFO(GGML_VIRTGPU "Using the APIR capset\n");
|
| 304 |
+
gpu->capset.id = VIRTGPU_DRM_CAPSET_APIR;
|
| 305 |
+
} else {
|
| 306 |
+
GGML_LOG_INFO(GGML_VIRTGPU "Using the Venus capset\n");
|
| 307 |
+
gpu->capset.id = VIRTGPU_DRM_CAPSET_VENUS;
|
| 308 |
+
}
|
| 309 |
+
gpu->capset.version = 0;
|
| 310 |
+
|
| 311 |
+
int ret =
|
| 312 |
+
virtgpu_ioctl_get_caps(gpu, gpu->capset.id, gpu->capset.version, &gpu->capset.data, sizeof(gpu->capset.data));
|
| 313 |
+
|
| 314 |
+
if (ret) {
|
| 315 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to get APIR v%d capset: %s\n", __func__, gpu->capset.version,
|
| 316 |
+
strerror(errno));
|
| 317 |
+
return APIR_ERROR_INITIALIZATION_FAILED;
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
assert(gpu->capset.data.supports_blob_resources);
|
| 321 |
+
|
| 322 |
+
return APIR_SUCCESS;
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
static int virtgpu_ioctl_context_init(virtgpu * gpu, virgl_renderer_capset capset_id) {
|
| 326 |
+
drm_virtgpu_context_set_param ctx_set_params[3] = {
|
| 327 |
+
{
|
| 328 |
+
.param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID,
|
| 329 |
+
.value = capset_id,
|
| 330 |
+
},
|
| 331 |
+
{
|
| 332 |
+
.param = VIRTGPU_CONTEXT_PARAM_NUM_RINGS,
|
| 333 |
+
.value = 1,
|
| 334 |
+
},
|
| 335 |
+
{
|
| 336 |
+
.param = VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK,
|
| 337 |
+
.value = 0, /* don't generate drm_events on fence signaling */
|
| 338 |
+
},
|
| 339 |
+
};
|
| 340 |
+
|
| 341 |
+
drm_virtgpu_context_init args = {
|
| 342 |
+
.num_params = ARRAY_SIZE(ctx_set_params),
|
| 343 |
+
.pad = 0,
|
| 344 |
+
.ctx_set_params = (uintptr_t) &ctx_set_params,
|
| 345 |
+
};
|
| 346 |
+
|
| 347 |
+
return virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_CONTEXT_INIT, &args);
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
static int virtgpu_ioctl_get_caps(virtgpu * gpu,
|
| 351 |
+
virgl_renderer_capset id,
|
| 352 |
+
uint32_t version,
|
| 353 |
+
void * capset,
|
| 354 |
+
size_t capset_size) {
|
| 355 |
+
drm_virtgpu_get_caps args = {
|
| 356 |
+
.cap_set_id = id,
|
| 357 |
+
.cap_set_ver = version,
|
| 358 |
+
.addr = (uintptr_t) capset,
|
| 359 |
+
.size = (__u32) capset_size,
|
| 360 |
+
.pad = 0,
|
| 361 |
+
};
|
| 362 |
+
|
| 363 |
+
return virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_GET_CAPS, &args);
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
static uint64_t virtgpu_ioctl_getparam(virtgpu * gpu, uint64_t param) {
|
| 367 |
+
/* val must be zeroed because kernel only writes the lower 32 bits */
|
| 368 |
+
uint64_t val = 0;
|
| 369 |
+
drm_virtgpu_getparam args = {
|
| 370 |
+
.param = param,
|
| 371 |
+
.value = (uintptr_t) &val,
|
| 372 |
+
};
|
| 373 |
+
|
| 374 |
+
const int ret = virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_GETPARAM, &args);
|
| 375 |
+
return ret ? 0 : val;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
apir_encoder * remote_call_prepare(virtgpu * gpu, ApirCommandType apir_cmd_type, int32_t cmd_flags) {
|
| 379 |
+
/*
|
| 380 |
+
* Prepare the command encoder and its buffer
|
| 381 |
+
*/
|
| 382 |
+
|
| 383 |
+
thread_local char encoder_buffer[4096];
|
| 384 |
+
|
| 385 |
+
thread_local apir_encoder enc;
|
| 386 |
+
enc = {
|
| 387 |
+
.cur = encoder_buffer,
|
| 388 |
+
.start = encoder_buffer,
|
| 389 |
+
.end = encoder_buffer + sizeof(encoder_buffer),
|
| 390 |
+
.fatal = false,
|
| 391 |
+
};
|
| 392 |
+
|
| 393 |
+
/*
|
| 394 |
+
* Fill the command encoder with the common args:
|
| 395 |
+
* - cmd_type (int32_t)
|
| 396 |
+
* - cmd_flags (int32_t)
|
| 397 |
+
* - reply res id (uint32_t)
|
| 398 |
+
*/
|
| 399 |
+
|
| 400 |
+
int32_t cmd_type = apir_cmd_type;
|
| 401 |
+
|
| 402 |
+
// for testing during the hypervisor transition
|
| 403 |
+
if (!gpu->use_apir_capset) {
|
| 404 |
+
cmd_type += VENUS_COMMAND_TYPE_LENGTH;
|
| 405 |
+
}
|
| 406 |
+
apir_encode_int32_t(&enc, &cmd_type);
|
| 407 |
+
apir_encode_int32_t(&enc, &cmd_flags);
|
| 408 |
+
|
| 409 |
+
uint32_t reply_res_id = gpu->reply_shmem.res_id;
|
| 410 |
+
apir_encode_uint32_t(&enc, &reply_res_id);
|
| 411 |
+
|
| 412 |
+
return &enc;
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
void remote_call_finish(virtgpu * gpu, apir_encoder * enc, apir_decoder * dec) {
|
| 416 |
+
UNUSED(gpu);
|
| 417 |
+
|
| 418 |
+
if (!enc) {
|
| 419 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Invalid (null) encoder", __func__);
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
if (!dec) {
|
| 423 |
+
GGML_ABORT(GGML_VIRTGPU "%s: Invalid (null) decoder", __func__);
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
if (apir_encoder_get_fatal(enc)) {
|
| 427 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: Failed to encode the output parameters.", __func__);
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
if (apir_decoder_get_fatal(dec)) {
|
| 431 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: Failed to decode the input parameters.", __func__);
|
| 432 |
+
}
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
uint32_t remote_call(virtgpu * gpu,
|
| 436 |
+
apir_encoder * encoder,
|
| 437 |
+
apir_decoder ** decoder,
|
| 438 |
+
float max_wait_ms,
|
| 439 |
+
long long * call_duration_ns) {
|
| 440 |
+
/*
|
| 441 |
+
* Prepare the reply notification pointer
|
| 442 |
+
*/
|
| 443 |
+
|
| 444 |
+
volatile std::atomic_uint * atomic_reply_notif = (volatile std::atomic_uint *) gpu->reply_shmem.mmap_ptr;
|
| 445 |
+
*atomic_reply_notif = 0;
|
| 446 |
+
|
| 447 |
+
/*
|
| 448 |
+
* Trigger the execbuf ioctl
|
| 449 |
+
*/
|
| 450 |
+
|
| 451 |
+
drm_virtgpu_execbuffer args = {
|
| 452 |
+
.flags = VIRTGPU_EXECBUF_RING_IDX,
|
| 453 |
+
.size = (uint32_t) (encoder->cur - encoder->start),
|
| 454 |
+
.command = (uintptr_t) encoder->start,
|
| 455 |
+
|
| 456 |
+
.bo_handles = 0,
|
| 457 |
+
.num_bo_handles = 0,
|
| 458 |
+
|
| 459 |
+
.fence_fd = 0,
|
| 460 |
+
.ring_idx = 0,
|
| 461 |
+
.syncobj_stride = 0,
|
| 462 |
+
.num_in_syncobjs = 0,
|
| 463 |
+
.num_out_syncobjs = 0,
|
| 464 |
+
.in_syncobjs = 0,
|
| 465 |
+
.out_syncobjs = 0,
|
| 466 |
+
};
|
| 467 |
+
|
| 468 |
+
*decoder = NULL;
|
| 469 |
+
|
| 470 |
+
int ret = drmIoctl(gpu->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &args);
|
| 471 |
+
|
| 472 |
+
if (ret != 0) {
|
| 473 |
+
GGML_ABORT(GGML_VIRTGPU "%s: the virtgpu EXECBUFFER ioctl failed (%d)", __func__, ret);
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
/*
|
| 477 |
+
* Wait for the response notification
|
| 478 |
+
*/
|
| 479 |
+
timer_data wait_host_reply_timer = { 0, 0, 0 };
|
| 480 |
+
|
| 481 |
+
start_timer(&wait_host_reply_timer);
|
| 482 |
+
|
| 483 |
+
timespec ts_start, ts_end;
|
| 484 |
+
clock_gettime(CLOCK_MONOTONIC, &ts_start);
|
| 485 |
+
long long start_time = (long long) ts_start.tv_sec * 1000000000LL + ts_start.tv_nsec;
|
| 486 |
+
|
| 487 |
+
bool timedout = false;
|
| 488 |
+
uint32_t notif_value = 0;
|
| 489 |
+
while (true) {
|
| 490 |
+
notif_value = std::atomic_load_explicit(atomic_reply_notif, std::memory_order_acquire);
|
| 491 |
+
|
| 492 |
+
if (notif_value != 0) {
|
| 493 |
+
break;
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
int64_t base_sleep_us = 15;
|
| 497 |
+
|
| 498 |
+
os_time_sleep(base_sleep_us);
|
| 499 |
+
|
| 500 |
+
if (max_wait_ms) {
|
| 501 |
+
clock_gettime(CLOCK_MONOTONIC, &ts_end);
|
| 502 |
+
long long end_time = (long long) ts_end.tv_sec * 1000000000LL + ts_end.tv_nsec;
|
| 503 |
+
float duration_ms = (end_time - start_time) / 1000000;
|
| 504 |
+
|
| 505 |
+
if (duration_ms > max_wait_ms) {
|
| 506 |
+
timedout = true;
|
| 507 |
+
break;
|
| 508 |
+
}
|
| 509 |
+
}
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
if (call_duration_ns) {
|
| 513 |
+
*call_duration_ns = stop_timer(&wait_host_reply_timer);
|
| 514 |
+
}
|
| 515 |
+
|
| 516 |
+
if (max_wait_ms && timedout) {
|
| 517 |
+
GGML_LOG_ERROR(GGML_VIRTGPU "%s: timed out waiting for the host answer...\n", __func__);
|
| 518 |
+
return APIR_FORWARD_TIMEOUT;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
/*
|
| 522 |
+
* Prepare the decoder
|
| 523 |
+
*/
|
| 524 |
+
static apir_decoder response_dec;
|
| 525 |
+
response_dec.cur = (char *) gpu->reply_shmem.mmap_ptr + sizeof(*atomic_reply_notif);
|
| 526 |
+
response_dec.end = (char *) gpu->reply_shmem.mmap_ptr + gpu->reply_shmem.mmap_size;
|
| 527 |
+
*decoder = &response_dec;
|
| 528 |
+
|
| 529 |
+
// extract the actual return value from the notif flag
|
| 530 |
+
uint32_t returned_value = notif_value - 1;
|
| 531 |
+
return returned_value;
|
| 532 |
+
}
|
| 533 |
+
|
| 534 |
+
static void log_call_duration(long long call_duration_ns, const char * name) {
|
| 535 |
+
double call_duration_ms = (double) call_duration_ns / 1e6; // 1 millisecond = 1e6 nanoseconds
|
| 536 |
+
double call_duration_s = (double) call_duration_ns / 1e9; // 1 second = 1e9 nanoseconds
|
| 537 |
+
|
| 538 |
+
if (call_duration_s > 1) {
|
| 539 |
+
GGML_LOG_INFO(GGML_VIRTGPU "waited %.2fs for the %s host reply...\n", call_duration_s, name);
|
| 540 |
+
} else if (call_duration_ms > 1) {
|
| 541 |
+
GGML_LOG_INFO(GGML_VIRTGPU "waited %.2fms for the %s host reply...\n", call_duration_ms, name);
|
| 542 |
+
} else {
|
| 543 |
+
GGML_LOG_INFO(GGML_VIRTGPU "waited %lldns for the %s host reply...\n", call_duration_ns, name);
|
| 544 |
+
}
|
| 545 |
+
}
|
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.h
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
// clang-format off
|
| 4 |
+
#include "virtgpu-utils.h"
|
| 5 |
+
#include "virtgpu-shm.h"
|
| 6 |
+
#include "virtgpu-apir.h"
|
| 7 |
+
|
| 8 |
+
#include "backend/shared/api_remoting.h"
|
| 9 |
+
#include "backend/shared/apir_cs.h"
|
| 10 |
+
|
| 11 |
+
#include <fcntl.h>
|
| 12 |
+
#include <stdbool.h>
|
| 13 |
+
#include <stdio.h>
|
| 14 |
+
#include <sys/stat.h>
|
| 15 |
+
#include <sys/sysmacros.h>
|
| 16 |
+
#include <threads.h>
|
| 17 |
+
#include <xf86drm.h>
|
| 18 |
+
|
| 19 |
+
#include <cstring>
|
| 20 |
+
|
| 21 |
+
#define VIRGL_RENDERER_UNSTABLE_APIS 1
|
| 22 |
+
#include "apir_hw.h"
|
| 23 |
+
#include <drm/virtgpu_drm.h>
|
| 24 |
+
#include "venus_hw.h"
|
| 25 |
+
// clang-format on
|
| 26 |
+
|
| 27 |
+
#ifndef VIRTGPU_DRM_CAPSET_APIR
|
| 28 |
+
// Will be defined include/drm/virtgpu_drm.h when
|
| 29 |
+
// https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1590/diffs
|
| 30 |
+
// is merged
|
| 31 |
+
# define VIRTGPU_DRM_CAPSET_APIR 10
|
| 32 |
+
#endif
|
| 33 |
+
|
| 34 |
+
// Mesa/Virlgrenderer Venus internal. Only necessary during the
|
| 35 |
+
// Venus->APIR transition in Virglrenderer
|
| 36 |
+
#define VENUS_COMMAND_TYPE_LENGTH 331
|
| 37 |
+
|
| 38 |
+
#ifndef VIRTGPU_DRM_CAPSET_VENUS // only available with Linux >= v6.16
|
| 39 |
+
# define VIRTGPU_DRM_CAPSET_VENUS 4
|
| 40 |
+
#endif
|
| 41 |
+
|
| 42 |
+
typedef uint32_t virgl_renderer_capset;
|
| 43 |
+
|
| 44 |
+
/* from src/virtio/vulkan/vn_renderer_virtgpu.c */
|
| 45 |
+
#define VIRTGPU_PCI_VENDOR_ID 0x1af4
|
| 46 |
+
#define VIRTGPU_PCI_DEVICE_ID 0x1050
|
| 47 |
+
#define VIRTGPU_BLOB_MEM_GUEST_VRAM 0x0004
|
| 48 |
+
#define VIRTGPU_PARAM_GUEST_VRAM 9
|
| 49 |
+
|
| 50 |
+
#define SHMEM_DATA_SIZE 0x1830000 // 24MiB
|
| 51 |
+
#define SHMEM_REPLY_SIZE 0x4000
|
| 52 |
+
|
| 53 |
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
| 54 |
+
|
| 55 |
+
enum virt_gpu_result_t {
|
| 56 |
+
APIR_SUCCESS = 0,
|
| 57 |
+
APIR_ERROR_INITIALIZATION_FAILED = -1,
|
| 58 |
+
};
|
| 59 |
+
|
| 60 |
+
#define PRINTFLIKE(f, a) __attribute__((format(__printf__, f, a)))
|
| 61 |
+
|
| 62 |
+
struct virtgpu {
|
| 63 |
+
bool use_apir_capset;
|
| 64 |
+
|
| 65 |
+
int fd;
|
| 66 |
+
|
| 67 |
+
struct {
|
| 68 |
+
virgl_renderer_capset id;
|
| 69 |
+
uint32_t version;
|
| 70 |
+
virgl_renderer_capset_apir data;
|
| 71 |
+
} capset;
|
| 72 |
+
|
| 73 |
+
util_sparse_array shmem_array;
|
| 74 |
+
|
| 75 |
+
/* APIR communication pages */
|
| 76 |
+
virtgpu_shmem reply_shmem;
|
| 77 |
+
virtgpu_shmem data_shmem;
|
| 78 |
+
|
| 79 |
+
/* Mutex to protect shared data_shmem buffer from concurrent access */
|
| 80 |
+
mtx_t data_shmem_mutex;
|
| 81 |
+
|
| 82 |
+
/* Cached device information to prevent memory leaks and race conditions */
|
| 83 |
+
struct {
|
| 84 |
+
char * description;
|
| 85 |
+
char * name;
|
| 86 |
+
int32_t device_count;
|
| 87 |
+
uint32_t type;
|
| 88 |
+
size_t memory_free;
|
| 89 |
+
size_t memory_total;
|
| 90 |
+
} cached_device_info;
|
| 91 |
+
|
| 92 |
+
/* Cached buffer type information to prevent memory leaks and race conditions */
|
| 93 |
+
struct {
|
| 94 |
+
apir_buffer_type_host_handle_t host_handle;
|
| 95 |
+
char * name;
|
| 96 |
+
size_t alignment;
|
| 97 |
+
size_t max_size;
|
| 98 |
+
} cached_buffer_type;
|
| 99 |
+
};
|
| 100 |
+
|
| 101 |
+
static inline int virtgpu_ioctl(virtgpu * gpu, unsigned long request, void * args) {
|
| 102 |
+
return drmIoctl(gpu->fd, request, args);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
virtgpu * create_virtgpu();
|
| 106 |
+
|
| 107 |
+
apir_encoder * remote_call_prepare(virtgpu * gpu, ApirCommandType apir_cmd_type, int32_t cmd_flags);
|
| 108 |
+
|
| 109 |
+
uint32_t remote_call(virtgpu * gpu,
|
| 110 |
+
apir_encoder * enc,
|
| 111 |
+
apir_decoder ** dec,
|
| 112 |
+
float max_wait_ms,
|
| 113 |
+
long long * call_duration_ns);
|
| 114 |
+
|
| 115 |
+
void remote_call_finish(virtgpu * gpu, apir_encoder * enc, apir_decoder * dec);
|
backend/llama.cpp/ggml/src/ggml-vulkan/CMakeLists.txt
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.19)
|
| 2 |
+
cmake_policy(SET CMP0114 NEW)
|
| 3 |
+
cmake_policy(SET CMP0116 NEW)
|
| 4 |
+
if (POLICY CMP0147)
|
| 5 |
+
# Parallel build custom build steps
|
| 6 |
+
cmake_policy(SET CMP0147 NEW)
|
| 7 |
+
endif()
|
| 8 |
+
|
| 9 |
+
find_package(Vulkan COMPONENTS glslc REQUIRED)
|
| 10 |
+
|
| 11 |
+
if (DEFINED ENV{VULKAN_SDK})
|
| 12 |
+
list(APPEND CMAKE_PREFIX_PATH "$ENV{VULKAN_SDK}")
|
| 13 |
+
endif()
|
| 14 |
+
find_package(SPIRV-Headers CONFIG REQUIRED)
|
| 15 |
+
|
| 16 |
+
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
| 17 |
+
# Parallel build object files
|
| 18 |
+
add_definitions(/MP)
|
| 19 |
+
endif()
|
| 20 |
+
|
| 21 |
+
function(detect_host_compiler)
|
| 22 |
+
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
| 23 |
+
find_program(HOST_C_COMPILER NAMES cl gcc clang NO_CMAKE_FIND_ROOT_PATH)
|
| 24 |
+
find_program(HOST_CXX_COMPILER NAMES cl g++ clang++ NO_CMAKE_FIND_ROOT_PATH)
|
| 25 |
+
else()
|
| 26 |
+
find_program(HOST_C_COMPILER NAMES gcc clang NO_CMAKE_FIND_ROOT_PATH)
|
| 27 |
+
find_program(HOST_CXX_COMPILER NAMES g++ clang++ NO_CMAKE_FIND_ROOT_PATH)
|
| 28 |
+
endif()
|
| 29 |
+
set(HOST_C_COMPILER "${HOST_C_COMPILER}" PARENT_SCOPE)
|
| 30 |
+
set(HOST_CXX_COMPILER "${HOST_CXX_COMPILER}" PARENT_SCOPE)
|
| 31 |
+
endfunction()
|
| 32 |
+
|
| 33 |
+
# Function to test shader extension support
|
| 34 |
+
# Parameters:
|
| 35 |
+
# EXTENSION_NAME - Name of the extension to test (e.g., "GL_EXT_integer_dot_product")
|
| 36 |
+
# TEST_SHADER_FILE - Path to the test shader file
|
| 37 |
+
# RESULT_VARIABLE - Name of the variable to set (ON/OFF) based on test result
|
| 38 |
+
function(test_shader_extension_support EXTENSION_NAME TEST_SHADER_FILE RESULT_VARIABLE)
|
| 39 |
+
execute_process(
|
| 40 |
+
COMMAND ${Vulkan_GLSLC_EXECUTABLE} -o - -fshader-stage=compute --target-env=vulkan1.3 "${TEST_SHADER_FILE}"
|
| 41 |
+
OUTPUT_VARIABLE glslc_output
|
| 42 |
+
ERROR_VARIABLE glslc_error
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
if (${glslc_error} MATCHES ".*extension not supported: ${EXTENSION_NAME}.*")
|
| 46 |
+
message(STATUS "${EXTENSION_NAME} not supported by glslc")
|
| 47 |
+
set(${RESULT_VARIABLE} OFF PARENT_SCOPE)
|
| 48 |
+
else()
|
| 49 |
+
message(STATUS "${EXTENSION_NAME} supported by glslc")
|
| 50 |
+
set(${RESULT_VARIABLE} ON PARENT_SCOPE)
|
| 51 |
+
add_compile_definitions(${RESULT_VARIABLE})
|
| 52 |
+
|
| 53 |
+
# Ensure the extension support is forwarded to vulkan-shaders-gen
|
| 54 |
+
list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -D${RESULT_VARIABLE}=ON)
|
| 55 |
+
set(VULKAN_SHADER_GEN_CMAKE_ARGS "${VULKAN_SHADER_GEN_CMAKE_ARGS}" PARENT_SCOPE)
|
| 56 |
+
endif()
|
| 57 |
+
endfunction()
|
| 58 |
+
|
| 59 |
+
if (Vulkan_FOUND)
|
| 60 |
+
message(STATUS "Vulkan found")
|
| 61 |
+
|
| 62 |
+
ggml_add_backend_library(ggml-vulkan
|
| 63 |
+
ggml-vulkan.cpp
|
| 64 |
+
../../include/ggml-vulkan.h
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
set(VULKAN_SHADER_GEN_CMAKE_ARGS "")
|
| 68 |
+
|
| 69 |
+
# Test all shader extensions
|
| 70 |
+
test_shader_extension_support(
|
| 71 |
+
"GL_KHR_cooperative_matrix"
|
| 72 |
+
"${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/coopmat.comp"
|
| 73 |
+
"GGML_VULKAN_COOPMAT_GLSLC_SUPPORT"
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
test_shader_extension_support(
|
| 77 |
+
"GL_NV_cooperative_matrix2"
|
| 78 |
+
"${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/coopmat2.comp"
|
| 79 |
+
"GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT"
|
| 80 |
+
)
|
| 81 |
+
|
| 82 |
+
test_shader_extension_support(
|
| 83 |
+
"GL_NV_cooperative_matrix_decode_vector"
|
| 84 |
+
"${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/coopmat2_decode_vector.comp"
|
| 85 |
+
"GGML_VULKAN_COOPMAT2_DECODE_VECTOR_GLSLC_SUPPORT"
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
test_shader_extension_support(
|
| 89 |
+
"GL_EXT_integer_dot_product"
|
| 90 |
+
"${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/integer_dot.comp"
|
| 91 |
+
"GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT"
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
test_shader_extension_support(
|
| 95 |
+
"GL_EXT_bfloat16"
|
| 96 |
+
"${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/bfloat16.comp"
|
| 97 |
+
"GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT"
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
target_link_libraries(ggml-vulkan PRIVATE Vulkan::Vulkan)
|
| 101 |
+
target_include_directories(ggml-vulkan PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
| 102 |
+
|
| 103 |
+
# Workaround to the "can't dereference invalidated vector iterator" bug in clang-cl debug build
|
| 104 |
+
# Possibly relevant: https://stackoverflow.com/questions/74748276/visual-studio-no-displays-the-correct-length-of-stdvector
|
| 105 |
+
if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
| 106 |
+
add_compile_definitions(_ITERATOR_DEBUG_LEVEL=0)
|
| 107 |
+
endif()
|
| 108 |
+
|
| 109 |
+
if (GGML_VULKAN_CHECK_RESULTS)
|
| 110 |
+
add_compile_definitions(GGML_VULKAN_CHECK_RESULTS)
|
| 111 |
+
# the result-checking path computes a CPU reference graph via
|
| 112 |
+
# ggml_graph_compute_with_ctx(), which is defined in ggml-cpu
|
| 113 |
+
target_link_libraries(ggml-vulkan PRIVATE ggml-cpu)
|
| 114 |
+
endif()
|
| 115 |
+
|
| 116 |
+
if (GGML_VULKAN_DEBUG)
|
| 117 |
+
add_compile_definitions(GGML_VULKAN_DEBUG)
|
| 118 |
+
endif()
|
| 119 |
+
|
| 120 |
+
if (GGML_VULKAN_MEMORY_DEBUG)
|
| 121 |
+
add_compile_definitions(GGML_VULKAN_MEMORY_DEBUG)
|
| 122 |
+
endif()
|
| 123 |
+
|
| 124 |
+
if (GGML_VULKAN_SHADER_DEBUG_INFO)
|
| 125 |
+
add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO)
|
| 126 |
+
list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DGGML_VULKAN_SHADER_DEBUG_INFO=ON)
|
| 127 |
+
endif()
|
| 128 |
+
|
| 129 |
+
if (GGML_VULKAN_VALIDATE)
|
| 130 |
+
add_compile_definitions(GGML_VULKAN_VALIDATE)
|
| 131 |
+
endif()
|
| 132 |
+
|
| 133 |
+
if (GGML_VULKAN_RUN_TESTS)
|
| 134 |
+
add_compile_definitions(GGML_VULKAN_RUN_TESTS)
|
| 135 |
+
# the test path also calls ggml_graph_compute_with_ctx() (ggml-cpu)
|
| 136 |
+
target_link_libraries(ggml-vulkan PRIVATE ggml-cpu)
|
| 137 |
+
endif()
|
| 138 |
+
|
| 139 |
+
# Set up toolchain for host compilation whether cross-compiling or not
|
| 140 |
+
if (CMAKE_CROSSCOMPILING)
|
| 141 |
+
if (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN)
|
| 142 |
+
set(HOST_CMAKE_TOOLCHAIN_FILE ${GGML_VULKAN_SHADERS_GEN_TOOLCHAIN})
|
| 143 |
+
else()
|
| 144 |
+
detect_host_compiler()
|
| 145 |
+
if (NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER)
|
| 146 |
+
message(FATAL_ERROR "Host compiler not found")
|
| 147 |
+
else()
|
| 148 |
+
message(STATUS "Host compiler: ${HOST_C_COMPILER} ${HOST_CXX_COMPILER}")
|
| 149 |
+
endif()
|
| 150 |
+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/host-toolchain.cmake.in ${CMAKE_BINARY_DIR}/host-toolchain.cmake @ONLY)
|
| 151 |
+
set(HOST_CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/host-toolchain.cmake)
|
| 152 |
+
endif()
|
| 153 |
+
else()
|
| 154 |
+
# For non-cross-compiling, use empty toolchain (use host compiler)
|
| 155 |
+
set(HOST_CMAKE_TOOLCHAIN_FILE "")
|
| 156 |
+
endif()
|
| 157 |
+
|
| 158 |
+
include(ExternalProject)
|
| 159 |
+
|
| 160 |
+
if (CMAKE_CROSSCOMPILING)
|
| 161 |
+
list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${HOST_CMAKE_TOOLCHAIN_FILE})
|
| 162 |
+
message(STATUS "vulkan-shaders-gen toolchain file: ${HOST_CMAKE_TOOLCHAIN_FILE}")
|
| 163 |
+
endif()
|
| 164 |
+
|
| 165 |
+
ExternalProject_Add(
|
| 166 |
+
vulkan-shaders-gen
|
| 167 |
+
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders
|
| 168 |
+
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/$<CONFIG>
|
| 169 |
+
-DCMAKE_INSTALL_BINDIR=.
|
| 170 |
+
-DCMAKE_BUILD_TYPE=$<CONFIG>
|
| 171 |
+
${VULKAN_SHADER_GEN_CMAKE_ARGS}
|
| 172 |
+
|
| 173 |
+
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
|
| 174 |
+
BUILD_ALWAYS TRUE
|
| 175 |
+
|
| 176 |
+
# NOTE: When DESTDIR is set using Makefile generators and
|
| 177 |
+
# "make install" triggers the build step, vulkan-shaders-gen
|
| 178 |
+
# would be installed into the DESTDIR prefix, so it is unset
|
| 179 |
+
# to ensure that does not happen.
|
| 180 |
+
|
| 181 |
+
INSTALL_COMMAND ${CMAKE_COMMAND} -E env --unset=DESTDIR
|
| 182 |
+
${CMAKE_COMMAND} --install . --config $<CONFIG>
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
set (_ggml_vk_host_suffix $<IF:$<STREQUAL:${CMAKE_HOST_SYSTEM_NAME},Windows>,.exe,>)
|
| 186 |
+
set (_ggml_vk_genshaders_dir "${CMAKE_BINARY_DIR}/$<CONFIG>")
|
| 187 |
+
set (_ggml_vk_genshaders_cmd "${_ggml_vk_genshaders_dir}/vulkan-shaders-gen${_ggml_vk_host_suffix}")
|
| 188 |
+
set (_ggml_vk_header "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp")
|
| 189 |
+
set (_ggml_vk_input_dir "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders")
|
| 190 |
+
set (_ggml_vk_output_dir "${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv")
|
| 191 |
+
|
| 192 |
+
file(GLOB _ggml_vk_shader_files CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.comp")
|
| 193 |
+
|
| 194 |
+
# Because external projects do not provide source-level tracking,
|
| 195 |
+
# the vulkan-shaders-gen sources need to be explicitly added to
|
| 196 |
+
# ensure that changes will cascade into shader re-generation.
|
| 197 |
+
|
| 198 |
+
file(GLOB _ggml_vk_shaders_gen_sources
|
| 199 |
+
CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.cpp"
|
| 200 |
+
"${_ggml_vk_input_dir}/*.h")
|
| 201 |
+
|
| 202 |
+
add_custom_command(
|
| 203 |
+
OUTPUT ${_ggml_vk_header}
|
| 204 |
+
COMMAND ${_ggml_vk_genshaders_cmd}
|
| 205 |
+
--output-dir ${_ggml_vk_output_dir}
|
| 206 |
+
--target-hpp ${_ggml_vk_header}
|
| 207 |
+
DEPENDS ${_ggml_vk_shaders_gen_sources}
|
| 208 |
+
vulkan-shaders-gen
|
| 209 |
+
COMMENT "Generate vulkan shaders header"
|
| 210 |
+
)
|
| 211 |
+
target_sources(ggml-vulkan PRIVATE ${_ggml_vk_header})
|
| 212 |
+
|
| 213 |
+
foreach (file_full ${_ggml_vk_shader_files})
|
| 214 |
+
get_filename_component(file ${file_full} NAME)
|
| 215 |
+
set (_ggml_vk_target_cpp "${CMAKE_CURRENT_BINARY_DIR}/${file}.cpp")
|
| 216 |
+
|
| 217 |
+
add_custom_command(
|
| 218 |
+
OUTPUT ${_ggml_vk_target_cpp}
|
| 219 |
+
DEPFILE ${_ggml_vk_target_cpp}.d
|
| 220 |
+
COMMAND ${_ggml_vk_genshaders_cmd}
|
| 221 |
+
--glslc ${Vulkan_GLSLC_EXECUTABLE}
|
| 222 |
+
--source ${file_full}
|
| 223 |
+
--output-dir ${_ggml_vk_output_dir}
|
| 224 |
+
--target-hpp ${_ggml_vk_header}
|
| 225 |
+
--target-cpp ${_ggml_vk_target_cpp}
|
| 226 |
+
DEPENDS ${file_full}
|
| 227 |
+
${_ggml_vk_shaders_gen_sources}
|
| 228 |
+
vulkan-shaders-gen
|
| 229 |
+
COMMENT "Generate vulkan shaders for ${file}"
|
| 230 |
+
)
|
| 231 |
+
target_sources(ggml-vulkan PRIVATE ${_ggml_vk_target_cpp})
|
| 232 |
+
endforeach()
|
| 233 |
+
|
| 234 |
+
else()
|
| 235 |
+
message(WARNING "Vulkan not found")
|
| 236 |
+
endif()
|
backend/llama.cpp/ggml/src/ggml-vulkan/cmake/host-toolchain.cmake.in
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
set(CMAKE_BUILD_TYPE Release)
|
| 2 |
+
set(CMAKE_C_FLAGS -O2)
|
| 3 |
+
set(CMAKE_CXX_FLAGS -O2)
|
| 4 |
+
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
| 5 |
+
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
|
| 6 |
+
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
|
| 7 |
+
set(CMAKE_C_COMPILER "@HOST_C_COMPILER@")
|
| 8 |
+
set(CMAKE_CXX_COMPILER "@HOST_CXX_COMPILER@")
|
| 9 |
+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY @CMAKE_RUNTIME_OUTPUT_DIRECTORY@)
|
| 10 |
+
|
| 11 |
+
if("@CMAKE_C_COMPILER_ID@" STREQUAL "MSVC")
|
| 12 |
+
foreach(CONFIG IN ITEMS DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
|
| 13 |
+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
| 14 |
+
endforeach()
|
| 15 |
+
endif()
|
backend/llama.cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.19)
|
| 2 |
+
project("vulkan-shaders-gen" C CXX)
|
| 3 |
+
|
| 4 |
+
find_package (Threads REQUIRED)
|
| 5 |
+
|
| 6 |
+
if (GGML_VULKAN_COOPMAT_GLSLC_SUPPORT)
|
| 7 |
+
add_compile_definitions(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT)
|
| 8 |
+
message(STATUS "Enabling coopmat glslc support")
|
| 9 |
+
endif()
|
| 10 |
+
if (GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT)
|
| 11 |
+
add_compile_definitions(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT)
|
| 12 |
+
message(STATUS "Enabling coopmat2 glslc support")
|
| 13 |
+
endif()
|
| 14 |
+
if (GGML_VULKAN_COOPMAT2_DECODE_VECTOR_GLSLC_SUPPORT)
|
| 15 |
+
add_compile_definitions(GGML_VULKAN_COOPMAT2_DECODE_VECTOR_GLSLC_SUPPORT)
|
| 16 |
+
message(STATUS "Enabling coopmat2 decode_vector glslc support")
|
| 17 |
+
endif()
|
| 18 |
+
if (GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT)
|
| 19 |
+
add_compile_definitions(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT)
|
| 20 |
+
message(STATUS "Enabling dot glslc support")
|
| 21 |
+
endif()
|
| 22 |
+
if (GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT)
|
| 23 |
+
add_compile_definitions(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT)
|
| 24 |
+
message(STATUS "Enabling bfloat16 glslc support")
|
| 25 |
+
endif()
|
| 26 |
+
if (GGML_VULKAN_SHADER_DEBUG_INFO)
|
| 27 |
+
add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO)
|
| 28 |
+
message(STATUS "Enabling shader debug info")
|
| 29 |
+
endif()
|
| 30 |
+
|
| 31 |
+
set(TARGET vulkan-shaders-gen)
|
| 32 |
+
add_executable(${TARGET} vulkan-shaders-gen.cpp)
|
| 33 |
+
install(TARGETS ${TARGET} RUNTIME)
|
| 34 |
+
target_compile_features(${TARGET} PRIVATE cxx_std_17)
|
| 35 |
+
target_link_libraries(vulkan-shaders-gen PUBLIC Threads::Threads)
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/acc.comp
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "generic_binary_head.glsl"
|
| 5 |
+
|
| 6 |
+
// false for SET, true for ACC
|
| 7 |
+
layout(constant_id = 1) const bool ACC = true;
|
| 8 |
+
|
| 9 |
+
layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
|
| 10 |
+
|
| 11 |
+
void main() {
|
| 12 |
+
const uint idx = gl_GlobalInvocationID.x;
|
| 13 |
+
if (idx >= p.ne) {
|
| 14 |
+
return;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
const uint offset = p.param3;
|
| 18 |
+
const uint src1_i = idx - offset;
|
| 19 |
+
const uint i3 = src1_i / p.nb03;
|
| 20 |
+
const uint rem2 = src1_i - i3 * p.nb03;
|
| 21 |
+
const uint i2 = rem2 / p.nb02;
|
| 22 |
+
const uint rem1 = rem2 - i2 * p.nb02;
|
| 23 |
+
const uint i1 = rem1 / p.nb01;
|
| 24 |
+
const uint i0 = rem1 % p.nb01;
|
| 25 |
+
|
| 26 |
+
uint i00, i01, i02, i03;
|
| 27 |
+
|
| 28 |
+
if (i0 < p.ne10 && i1 < p.ne11 && i2 < p.ne12 && i3 < p.ne13) {
|
| 29 |
+
if (ACC) {
|
| 30 |
+
data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + idx]) + FLOAT_TYPE(data_b[get_boffset() + src1_idx(i0, i1, i2, i3)]));
|
| 31 |
+
} else {
|
| 32 |
+
data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_b[get_boffset() + src1_idx(i0, i1, i2, i3)]));
|
| 33 |
+
}
|
| 34 |
+
} else {
|
| 35 |
+
data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + idx]));
|
| 36 |
+
}
|
| 37 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add.comp
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_shader_16bit_storage : require
|
| 4 |
+
#if ADD_RMS
|
| 5 |
+
#extension GL_KHR_shader_subgroup_arithmetic : enable
|
| 6 |
+
#extension GL_KHR_shader_subgroup_basic : enable
|
| 7 |
+
#endif
|
| 8 |
+
|
| 9 |
+
#include "types.glsl"
|
| 10 |
+
#include "generic_binary_head.glsl"
|
| 11 |
+
|
| 12 |
+
const uint num_threads = 256;
|
| 13 |
+
|
| 14 |
+
layout (binding = 3, std430) buffer PartialBuf {float partial_sums[];};
|
| 15 |
+
|
| 16 |
+
layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in;
|
| 17 |
+
|
| 18 |
+
#if ADD_RMS
|
| 19 |
+
// XXX TODO this could be sized based on number of subgroups, but that't not considered a constant
|
| 20 |
+
shared FLOAT_TYPE sumsh[num_threads];
|
| 21 |
+
#endif
|
| 22 |
+
|
| 23 |
+
void main() {
|
| 24 |
+
uint idx = get_idx();
|
| 25 |
+
uint orig_idx = idx;
|
| 26 |
+
|
| 27 |
+
// num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation
|
| 28 |
+
const uint num_iter = 2;
|
| 29 |
+
|
| 30 |
+
FLOAT_TYPE sum_sq = 0;
|
| 31 |
+
|
| 32 |
+
[[unroll]] for (uint i = 0; i < num_iter; ++i) {
|
| 33 |
+
if (idx >= p.ne) {
|
| 34 |
+
continue;
|
| 35 |
+
}
|
| 36 |
+
uint i00, i01, i02, i03;
|
| 37 |
+
get_indices(idx, i00, i01, i02, i03);
|
| 38 |
+
|
| 39 |
+
FLOAT_TYPE sum = FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) + FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)]);
|
| 40 |
+
sum_sq += sum*sum;
|
| 41 |
+
|
| 42 |
+
data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(sum);
|
| 43 |
+
|
| 44 |
+
idx += num_threads;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
#if ADD_RMS
|
| 48 |
+
if (p.param3 != 0) {
|
| 49 |
+
// reduce the sum within each subgroup, then across subgroups
|
| 50 |
+
const uint NumSubgroups = num_threads / gl_SubgroupSize;
|
| 51 |
+
sum_sq = subgroupAdd(sum_sq);
|
| 52 |
+
if (gl_SubgroupInvocationID == 0) {
|
| 53 |
+
sumsh[gl_SubgroupID] = sum_sq;
|
| 54 |
+
}
|
| 55 |
+
barrier();
|
| 56 |
+
[[unroll]] for (uint s = NumSubgroups / 2; s > 0; s >>= 1) {
|
| 57 |
+
if (gl_SubgroupID < s && gl_SubgroupInvocationID == 0) {
|
| 58 |
+
sum_sq += sumsh[gl_SubgroupID + s];
|
| 59 |
+
sumsh[gl_SubgroupID] = sum_sq;
|
| 60 |
+
}
|
| 61 |
+
barrier();
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
if (gl_SubgroupID == 0 && gl_SubgroupInvocationID == 0) {
|
| 65 |
+
partial_sums[orig_idx / (num_iter * num_threads)] = sum_sq;
|
| 66 |
+
}
|
| 67 |
+
}
|
| 68 |
+
#endif
|
| 69 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add1.comp
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_shader_16bit_storage : require
|
| 4 |
+
|
| 5 |
+
#include "types.glsl"
|
| 6 |
+
#include "generic_binary_head.glsl"
|
| 7 |
+
|
| 8 |
+
const uint num_threads = 256;
|
| 9 |
+
|
| 10 |
+
layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in;
|
| 11 |
+
|
| 12 |
+
void main() {
|
| 13 |
+
uint idx = get_idx();
|
| 14 |
+
|
| 15 |
+
const uint num_iter = 2;
|
| 16 |
+
|
| 17 |
+
[[unroll]] for (uint i = 0; i < num_iter; ++i) {
|
| 18 |
+
if (idx >= p.ne) {
|
| 19 |
+
continue;
|
| 20 |
+
}
|
| 21 |
+
uint i00, i01, i02, i03;
|
| 22 |
+
get_indices(idx, i00, i01, i02, i03);
|
| 23 |
+
|
| 24 |
+
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()]));
|
| 25 |
+
|
| 26 |
+
idx += num_threads;
|
| 27 |
+
}
|
| 28 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add_id.comp
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_control_flow_attributes : require
|
| 4 |
+
|
| 5 |
+
#include "types.glsl"
|
| 6 |
+
|
| 7 |
+
layout (push_constant) uniform parameter
|
| 8 |
+
{
|
| 9 |
+
uint ne0;
|
| 10 |
+
uint ne1;
|
| 11 |
+
uint s01;
|
| 12 |
+
uint s02;
|
| 13 |
+
uint s11;
|
| 14 |
+
uint s21;
|
| 15 |
+
} p;
|
| 16 |
+
|
| 17 |
+
#define BLOCK_SIZE 512
|
| 18 |
+
|
| 19 |
+
layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in;
|
| 20 |
+
|
| 21 |
+
layout (binding = 0) readonly buffer X {A_TYPE data_a[];};
|
| 22 |
+
layout (binding = 1) readonly buffer Y {B_TYPE data_b[];};
|
| 23 |
+
layout (binding = 2) readonly buffer Z {int32_t data_c[];};
|
| 24 |
+
layout (binding = 3) writeonly buffer D {D_TYPE data_d[];};
|
| 25 |
+
|
| 26 |
+
void main() {
|
| 27 |
+
const uint i1 = gl_WorkGroupID.x;
|
| 28 |
+
const uint i2 = gl_WorkGroupID.y;
|
| 29 |
+
|
| 30 |
+
const uint i11 = data_c[i1 + i2 * p.s21];
|
| 31 |
+
|
| 32 |
+
const uint s1 = p.ne0;
|
| 33 |
+
const uint s2 = p.ne0 * p.ne1;
|
| 34 |
+
|
| 35 |
+
const uint d0 = i1 * s1 + i2 * s2;
|
| 36 |
+
const uint a0 = i1 * p.s01 + i2 * p.s02;
|
| 37 |
+
const uint b0 = i11 * p.s11;
|
| 38 |
+
|
| 39 |
+
for (uint i0 = gl_LocalInvocationID.x; i0 < p.ne0; i0 += BLOCK_SIZE) {
|
| 40 |
+
data_d[d0 + i0] = data_a[a0 + i0] + data_b[b0 + i0];
|
| 41 |
+
}
|
| 42 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/arange.comp
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "generic_head.glsl"
|
| 4 |
+
#include "types.glsl"
|
| 5 |
+
|
| 6 |
+
layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
|
| 7 |
+
|
| 8 |
+
layout (binding = 0) writeonly buffer D {D_TYPE data_d[];};
|
| 9 |
+
|
| 10 |
+
void main() {
|
| 11 |
+
const uint i = gl_GlobalInvocationID.x;
|
| 12 |
+
|
| 13 |
+
if (i >= p.KX) {
|
| 14 |
+
return;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
// p.param1 = start, p.param2 = step
|
| 18 |
+
float value = p.param1 + p.param2 * float(i);
|
| 19 |
+
data_d[i] = D_TYPE(value);
|
| 20 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argmax.comp
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "generic_head.glsl"
|
| 4 |
+
#include "types.glsl"
|
| 5 |
+
|
| 6 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 7 |
+
|
| 8 |
+
#define FLT_MAX 3.402823466e+38F
|
| 9 |
+
|
| 10 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 11 |
+
|
| 12 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
|
| 13 |
+
layout (binding = 1) writeonly buffer D {D_TYPE data_d[];};
|
| 14 |
+
|
| 15 |
+
layout (constant_id = 0) const uint BLOCK_SIZE = 32;
|
| 16 |
+
|
| 17 |
+
shared FLOAT_TYPE tmpmax[BLOCK_SIZE];
|
| 18 |
+
shared uint tmp[BLOCK_SIZE];
|
| 19 |
+
|
| 20 |
+
void main() {
|
| 21 |
+
const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x;
|
| 22 |
+
const uint col = gl_LocalInvocationID.x;
|
| 23 |
+
|
| 24 |
+
if (row >= p.KY) {
|
| 25 |
+
return;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
A_TYPE amax = -FLT_MAX;
|
| 29 |
+
uint acol = col;
|
| 30 |
+
|
| 31 |
+
if (col < p.KX) {
|
| 32 |
+
amax = data_a[row*p.KX + col];
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
for (uint i = col + BLOCK_SIZE; i < p.KX; i += BLOCK_SIZE) {
|
| 36 |
+
A_TYPE val = data_a[row*p.KX + i];
|
| 37 |
+
if (val > amax) {
|
| 38 |
+
amax = val;
|
| 39 |
+
acol = i;
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
tmp[col] = acol;
|
| 44 |
+
tmpmax[col] = amax;
|
| 45 |
+
|
| 46 |
+
barrier();
|
| 47 |
+
[[unroll]] for (int s = int(BLOCK_SIZE) / 2; s > 0; s >>= 1) {
|
| 48 |
+
if (col < s && col + s < p.KX) {
|
| 49 |
+
if (tmpmax[col] < tmpmax[col + s]) {
|
| 50 |
+
tmpmax[col] = tmpmax[col + s];
|
| 51 |
+
tmp[col] = tmp[col + s];
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
barrier();
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
if (col == 0) {
|
| 58 |
+
data_d[row] = D_TYPE(tmp[0]);
|
| 59 |
+
}
|
| 60 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort.comp
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 3 |
+
|
| 4 |
+
#include "types.glsl"
|
| 5 |
+
|
| 6 |
+
layout(constant_id = 0) const int BLOCK_SIZE = 1024;
|
| 7 |
+
layout(constant_id = 1) const int NCOLS_PADDED_LOG2 = 10;
|
| 8 |
+
#define ASC 0
|
| 9 |
+
|
| 10 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 11 |
+
|
| 12 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
|
| 13 |
+
layout (binding = 2) writeonly buffer D {int data_d[];};
|
| 14 |
+
|
| 15 |
+
layout (push_constant) uniform parameter {
|
| 16 |
+
uint ncols;
|
| 17 |
+
uint ncols_padded;
|
| 18 |
+
uint ncols_padded_log2;
|
| 19 |
+
uint nrows;
|
| 20 |
+
uint order;
|
| 21 |
+
uint outer_start;
|
| 22 |
+
uint outer_end;
|
| 23 |
+
uint inner_start;
|
| 24 |
+
uint inner_end;
|
| 25 |
+
} p;
|
| 26 |
+
|
| 27 |
+
shared ivec2 dst_row[BLOCK_SIZE];
|
| 28 |
+
|
| 29 |
+
void argsort(bool needs_bounds_check, const uint row) {
|
| 30 |
+
// bitonic sort
|
| 31 |
+
const int col = int(gl_LocalInvocationID.x);
|
| 32 |
+
|
| 33 |
+
const uint row_offset = row * p.ncols;
|
| 34 |
+
|
| 35 |
+
// initialize indices
|
| 36 |
+
dst_row[col] = ivec2(col, floatBitsToInt(data_a[row_offset + col]));
|
| 37 |
+
barrier();
|
| 38 |
+
|
| 39 |
+
uint num_outer_loop_iters = NCOLS_PADDED_LOG2;
|
| 40 |
+
[[unroll]] for (uint k = 2, outer_idx = 0; outer_idx < num_outer_loop_iters; k *= 2, outer_idx++) {
|
| 41 |
+
uint num_inner_loop_iters = outer_idx + 1;
|
| 42 |
+
[[unroll]] for (uint j = k / 2, inner_idx = 0; inner_idx < num_inner_loop_iters; j /= 2, inner_idx++) {
|
| 43 |
+
const int ixj = int(col ^ j);
|
| 44 |
+
|
| 45 |
+
int idx_0 = (col & k) == 0 ? col : ixj;
|
| 46 |
+
int idx_1 = (col & k) == 0 ? ixj : col;
|
| 47 |
+
|
| 48 |
+
ivec2 sh_idx_0 = dst_row[idx_0];
|
| 49 |
+
ivec2 sh_idx_1 = dst_row[idx_1];
|
| 50 |
+
bool idx_0_oob = needs_bounds_check ? sh_idx_0.x >= p.ncols : false;
|
| 51 |
+
bool idx_1_oob = needs_bounds_check ? sh_idx_1.x >= p.ncols : false;
|
| 52 |
+
|
| 53 |
+
if ((idx_0_oob ||
|
| 54 |
+
(!idx_1_oob && intBitsToFloat(sh_idx_0.y) > intBitsToFloat(sh_idx_1.y))) && (ixj > col)) {
|
| 55 |
+
dst_row[idx_0] = sh_idx_1;
|
| 56 |
+
dst_row[idx_1] = sh_idx_0;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
barrier();
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
if (col < p.ncols) {
|
| 64 |
+
if (p.order == ASC) {
|
| 65 |
+
data_d[row_offset + col] = dst_row[col].x;
|
| 66 |
+
} else {
|
| 67 |
+
data_d[row_offset + p.ncols - col - 1] = dst_row[col].x;
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
void main() {
|
| 73 |
+
if (p.ncols == BLOCK_SIZE) {
|
| 74 |
+
uint row = gl_WorkGroupID.y;
|
| 75 |
+
while (row < p.nrows) {
|
| 76 |
+
argsort(false, row);
|
| 77 |
+
row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
|
| 78 |
+
}
|
| 79 |
+
} else {
|
| 80 |
+
uint row = gl_WorkGroupID.y;
|
| 81 |
+
while (row < p.nrows) {
|
| 82 |
+
argsort(true, row);
|
| 83 |
+
row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort_large.comp
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 3 |
+
#extension GL_KHR_memory_scope_semantics : enable
|
| 4 |
+
#pragma use_vulkan_memory_model
|
| 5 |
+
|
| 6 |
+
#include "types.glsl"
|
| 7 |
+
|
| 8 |
+
layout(constant_id = 0) const int BLOCK_SIZE = 1024;
|
| 9 |
+
layout(constant_id = 1) const int WG_UNROLL_FACTOR = 2;
|
| 10 |
+
#define ASC 0
|
| 11 |
+
|
| 12 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 13 |
+
|
| 14 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
|
| 15 |
+
layout (binding = 1) workgroupcoherent buffer B {ivec2 tmp_idx[];};
|
| 16 |
+
layout (binding = 2) workgroupcoherent buffer D {int data_d[];};
|
| 17 |
+
|
| 18 |
+
layout (push_constant) uniform parameter {
|
| 19 |
+
uint ncols;
|
| 20 |
+
uint ncols_padded;
|
| 21 |
+
uint ncols_padded_log2;
|
| 22 |
+
uint nrows;
|
| 23 |
+
uint order;
|
| 24 |
+
uint outer_start;
|
| 25 |
+
uint outer_end;
|
| 26 |
+
uint inner_start;
|
| 27 |
+
uint inner_end;
|
| 28 |
+
} p;
|
| 29 |
+
|
| 30 |
+
void argsort(bool needs_bounds_check, const uint row) {
|
| 31 |
+
// bitonic sort
|
| 32 |
+
int col = int(gl_GlobalInvocationID.x);
|
| 33 |
+
col = (col % BLOCK_SIZE) + (col / BLOCK_SIZE) * BLOCK_SIZE * WG_UNROLL_FACTOR;
|
| 34 |
+
|
| 35 |
+
const uint row_offset = row * p.ncols;
|
| 36 |
+
uint idx_offset = row * p.ncols_padded;
|
| 37 |
+
|
| 38 |
+
bool need_barrier = false;
|
| 39 |
+
|
| 40 |
+
// initialize indices
|
| 41 |
+
if (p.outer_start == 0 && p.inner_start == 0) {
|
| 42 |
+
[[unroll]] for (int u = 0; u < WG_UNROLL_FACTOR; ++u) {
|
| 43 |
+
uint c = u*BLOCK_SIZE + col;
|
| 44 |
+
if (c < p.ncols_padded) {
|
| 45 |
+
ivec2 v = ivec2(c, floatBitsToInt(data_a[row_offset + c]));
|
| 46 |
+
tmp_idx[idx_offset + c] = v;
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
need_barrier = true;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
[[unroll]] for (uint outer_idx = p.outer_start, k = (2 << outer_idx); outer_idx < p.outer_end; k *= 2, outer_idx++) {
|
| 53 |
+
uint inner_end = min(p.inner_end, outer_idx + 1);
|
| 54 |
+
for (uint j = k >> (p.inner_start + 1), inner_idx = p.inner_start; inner_idx < inner_end; j /= 2, inner_idx++) {
|
| 55 |
+
if (need_barrier) {
|
| 56 |
+
controlBarrier(gl_ScopeWorkgroup, gl_ScopeWorkgroup, gl_StorageSemanticsBuffer, gl_SemanticsAcquireRelease);
|
| 57 |
+
}
|
| 58 |
+
need_barrier = true;
|
| 59 |
+
[[unroll]] for (int u = 0; u < WG_UNROLL_FACTOR; ++u) {
|
| 60 |
+
int c = u*BLOCK_SIZE + col;
|
| 61 |
+
const int ixj = int(c ^ j);
|
| 62 |
+
|
| 63 |
+
if (ixj < c) {
|
| 64 |
+
continue;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
int idx_0 = (c & k) == 0 ? c : ixj;
|
| 68 |
+
int idx_1 = (c & k) == 0 ? ixj : c;
|
| 69 |
+
|
| 70 |
+
ivec2 sh_idx_0 = tmp_idx[idx_offset + idx_0];
|
| 71 |
+
ivec2 sh_idx_1 = tmp_idx[idx_offset + idx_1];
|
| 72 |
+
bool idx_0_oob = needs_bounds_check ? sh_idx_0.x >= p.ncols : false;
|
| 73 |
+
bool idx_1_oob = needs_bounds_check ? sh_idx_1.x >= p.ncols : false;
|
| 74 |
+
|
| 75 |
+
if ((idx_0_oob ||
|
| 76 |
+
(!idx_1_oob && intBitsToFloat(sh_idx_0.y) > intBitsToFloat(sh_idx_1.y)))) {
|
| 77 |
+
tmp_idx[idx_offset + idx_0] = sh_idx_1;
|
| 78 |
+
tmp_idx[idx_offset + idx_1] = sh_idx_0;
|
| 79 |
+
}
|
| 80 |
+
}
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
if (p.outer_end == p.ncols_padded_log2 &&
|
| 85 |
+
p.inner_end >= p.ncols_padded_log2 + 1) {
|
| 86 |
+
controlBarrier(gl_ScopeWorkgroup, gl_ScopeWorkgroup, gl_StorageSemanticsBuffer, gl_SemanticsAcquireRelease);
|
| 87 |
+
[[unroll]] for (int u = 0; u < WG_UNROLL_FACTOR; ++u) {
|
| 88 |
+
uint c = u*BLOCK_SIZE + col;
|
| 89 |
+
if (c < p.ncols) {
|
| 90 |
+
if (p.order == ASC) {
|
| 91 |
+
data_d[row_offset + c] = tmp_idx[idx_offset + c].x;
|
| 92 |
+
} else {
|
| 93 |
+
data_d[row_offset + p.ncols - c - 1] = tmp_idx[idx_offset + c].x;
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
void main() {
|
| 101 |
+
if (p.ncols == p.ncols_padded) {
|
| 102 |
+
uint row = gl_WorkGroupID.y;
|
| 103 |
+
while (row < p.nrows) {
|
| 104 |
+
argsort(false, row);
|
| 105 |
+
row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
|
| 106 |
+
}
|
| 107 |
+
} else {
|
| 108 |
+
uint row = gl_WorkGroupID.y;
|
| 109 |
+
while (row < p.nrows) {
|
| 110 |
+
argsort(true, row);
|
| 111 |
+
row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
|
| 5 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; // columns: [K_OC, T_in]
|
| 6 |
+
layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; // output: [T_out, OC]
|
| 7 |
+
|
| 8 |
+
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
| 9 |
+
|
| 10 |
+
layout (push_constant) uniform parameter {
|
| 11 |
+
uint32_t T_out;
|
| 12 |
+
uint32_t OC;
|
| 13 |
+
uint32_t K_OC;
|
| 14 |
+
uint32_t T_in;
|
| 15 |
+
uint32_t K;
|
| 16 |
+
int32_t stride;
|
| 17 |
+
int32_t p0;
|
| 18 |
+
} p;
|
| 19 |
+
|
| 20 |
+
// Load A_TYPE to float
|
| 21 |
+
float load_col(uint32_t idx) {
|
| 22 |
+
#if defined(DATA_A_BF16)
|
| 23 |
+
return bf16_to_fp32(uint32_t(data_a[idx]));
|
| 24 |
+
#else
|
| 25 |
+
return float(data_a[idx]);
|
| 26 |
+
#endif
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
// Store float as D_TYPE
|
| 30 |
+
void store_dst(uint32_t idx, float v) {
|
| 31 |
+
#if defined(DATA_A_BF16)
|
| 32 |
+
data_d[idx] = D_TYPE(fp32_to_bf16(v));
|
| 33 |
+
#else
|
| 34 |
+
data_d[idx] = D_TYPE(v);
|
| 35 |
+
#endif
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
void main() {
|
| 39 |
+
const uint32_t t_out = gl_GlobalInvocationID.x;
|
| 40 |
+
const uint32_t oc = gl_GlobalInvocationID.y;
|
| 41 |
+
if (t_out >= p.T_out || oc >= p.OC) return;
|
| 42 |
+
|
| 43 |
+
const int32_t t_abs = int32_t(t_out) + p.p0; // absolute position in uncropped signal
|
| 44 |
+
|
| 45 |
+
// Gather: only the ceil(K/stride) columns that scatter into t_abs, no modulo
|
| 46 |
+
int32_t t_in_min = (t_abs - int32_t(p.K) + p.stride) / p.stride;
|
| 47 |
+
if (t_in_min < 0) t_in_min = 0;
|
| 48 |
+
int32_t t_in_max = t_abs / p.stride;
|
| 49 |
+
if (t_in_max >= int32_t(p.T_in)) t_in_max = int32_t(p.T_in) - 1;
|
| 50 |
+
|
| 51 |
+
float val = 0.0;
|
| 52 |
+
for (int32_t t_in = t_in_min; t_in <= t_in_max; t_in++) {
|
| 53 |
+
int32_t k = t_abs - t_in * p.stride;
|
| 54 |
+
// col layout: [K_OC, T_in], column index = oc * K + k
|
| 55 |
+
uint32_t col_idx = (oc * p.K + uint32_t(k)) + uint32_t(t_in) * p.K_OC;
|
| 56 |
+
val += load_col(col_idx);
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// dst layout: [T_out, OC], element (t_out, oc) = t_out + oc * T_out
|
| 60 |
+
store_dst(t_out + oc * p.T_out, val);
|
| 61 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/concat.comp
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "generic_binary_head.glsl"
|
| 5 |
+
|
| 6 |
+
layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
|
| 7 |
+
|
| 8 |
+
void main() {
|
| 9 |
+
const uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x;
|
| 10 |
+
const int dim = p.param3;
|
| 11 |
+
|
| 12 |
+
if (idx >= p.ne) {
|
| 13 |
+
return;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
const uint i3 = idx / (p.ne22*p.ne21*p.ne20);
|
| 17 |
+
const uint i3_offset = i3 * p.ne22*p.ne21*p.ne20;
|
| 18 |
+
const uint i2 = (idx - i3_offset) / (p.ne21*p.ne20);
|
| 19 |
+
const uint i2_offset = i2*p.ne21*p.ne20;
|
| 20 |
+
const uint i1 = (idx - i3_offset - i2_offset) / p.ne20;
|
| 21 |
+
const uint i0 = idx - i3_offset - i2_offset - i1*p.ne20;
|
| 22 |
+
|
| 23 |
+
uint o[4] = {0, 0, 0, 0};
|
| 24 |
+
o[dim] = dim == 0 ? p.ne00 : (dim == 1 ? p.ne01 : (dim == 2 ? p.ne02 : p.ne03));
|
| 25 |
+
|
| 26 |
+
const uint src0_idx = i3*p.nb03 + i2*p.nb02 + i1*p.nb01 + i0*p.nb00;
|
| 27 |
+
const uint src1_idx = (i3 - o[3])*p.nb13 + (i2 - o[2])*p.nb12 + (i1 - o[1])*p.nb11 + (i0 - o[0])*p.nb10;
|
| 28 |
+
const uint dst_idx = i3*p.nb23 + i2*p.nb22 + i1*p.nb21 + i0*p.nb20;
|
| 29 |
+
|
| 30 |
+
const bool is_src0 = i0 < p.ne00 && i1 < p.ne01 && i2 < p.ne02 && i3 < p.ne03;
|
| 31 |
+
|
| 32 |
+
#ifndef OPTIMIZATION_ERROR_WORKAROUND
|
| 33 |
+
data_d[get_doffset() + dst_idx] = D_TYPE(is_src0 ? data_a[get_aoffset() + src0_idx] : data_b[get_boffset() + src1_idx]);
|
| 34 |
+
#else
|
| 35 |
+
if (is_src0) {
|
| 36 |
+
data_d[get_doffset() + dst_idx] = data_a[get_aoffset() + src0_idx];
|
| 37 |
+
} else {
|
| 38 |
+
data_d[get_doffset() + dst_idx] = data_b[get_boffset() + src1_idx];
|
| 39 |
+
}
|
| 40 |
+
#endif
|
| 41 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "generic_unary_head.glsl"
|
| 5 |
+
|
| 6 |
+
#extension GL_EXT_control_flow_attributes : require
|
| 7 |
+
|
| 8 |
+
const uint num_threads = 128;
|
| 9 |
+
|
| 10 |
+
layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in;
|
| 11 |
+
|
| 12 |
+
void main() {
|
| 13 |
+
uint idx = get_idx();
|
| 14 |
+
|
| 15 |
+
// num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation
|
| 16 |
+
const uint num_iter = 4;
|
| 17 |
+
|
| 18 |
+
// fast path for when all four iterations are in-bounds
|
| 19 |
+
if (idx + (num_iter-1)*num_threads < p.ne) {
|
| 20 |
+
[[unroll]] for (uint i = 0; i < num_iter; ++i) {
|
| 21 |
+
|
| 22 |
+
#if defined(DATA_A_BF16)
|
| 23 |
+
data_d[get_doffset() + idx] = D_TYPE(bf16_to_fp32(uint32_t(data_a[get_aoffset() + idx])));
|
| 24 |
+
#elif defined(DATA_D_BF16)
|
| 25 |
+
float f = float(data_a[get_aoffset() + idx]);
|
| 26 |
+
data_d[get_doffset() + idx] = D_TYPE(fp32_to_bf16(f));
|
| 27 |
+
#elif !defined(OPTIMIZATION_ERROR_WORKAROUND)
|
| 28 |
+
data_d[get_doffset() + idx] = D_TYPE(data_a[get_aoffset() + idx]);
|
| 29 |
+
#else
|
| 30 |
+
data_d[get_doffset() + idx] = data_a[get_aoffset() + idx];
|
| 31 |
+
#endif
|
| 32 |
+
idx += num_threads;
|
| 33 |
+
}
|
| 34 |
+
} else {
|
| 35 |
+
[[unroll]] for (uint i = 0; i < num_iter; ++i) {
|
| 36 |
+
if (idx >= p.ne) {
|
| 37 |
+
continue;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
#if defined(DATA_A_BF16)
|
| 41 |
+
data_d[get_doffset() + idx] = D_TYPE(bf16_to_fp32(uint32_t(data_a[get_aoffset() + idx])));
|
| 42 |
+
#elif defined(DATA_D_BF16)
|
| 43 |
+
float f = float(data_a[get_aoffset() + idx]);
|
| 44 |
+
data_d[get_doffset() + idx] = D_TYPE(fp32_to_bf16(f));
|
| 45 |
+
#elif !defined(OPTIMIZATION_ERROR_WORKAROUND)
|
| 46 |
+
data_d[get_doffset() + idx] = D_TYPE(data_a[get_aoffset() + idx]);
|
| 47 |
+
#else
|
| 48 |
+
data_d[get_doffset() + idx] = data_a[get_aoffset() + idx];
|
| 49 |
+
#endif
|
| 50 |
+
idx += num_threads;
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_dw.comp
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
|
| 5 |
+
layout (push_constant) uniform parameter
|
| 6 |
+
{
|
| 7 |
+
uint ne;
|
| 8 |
+
uint batches;
|
| 9 |
+
uint channels;
|
| 10 |
+
uint dst_w;
|
| 11 |
+
uint dst_h;
|
| 12 |
+
uint src_w;
|
| 13 |
+
uint src_h;
|
| 14 |
+
uint knl_w;
|
| 15 |
+
uint knl_h;
|
| 16 |
+
int stride_x;
|
| 17 |
+
int stride_y;
|
| 18 |
+
int pad_x;
|
| 19 |
+
int pad_y;
|
| 20 |
+
int dilation_x;
|
| 21 |
+
int dilation_y;
|
| 22 |
+
} p;
|
| 23 |
+
|
| 24 |
+
layout (binding = 0) readonly buffer A {A_TYPE knl_data[];};
|
| 25 |
+
layout (binding = 1) readonly buffer B {B_TYPE src_data[];};
|
| 26 |
+
layout (binding = 2) writeonly buffer D {D_TYPE dst_data[];};
|
| 27 |
+
|
| 28 |
+
layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
|
| 29 |
+
|
| 30 |
+
FLOAT_TYPE conv_2d_dw_whcn(uint idx) {
|
| 31 |
+
uint i0 = idx / p.dst_w;
|
| 32 |
+
uint dst_x = idx - i0 * p.dst_w;
|
| 33 |
+
uint i1 = i0 / p.dst_h;
|
| 34 |
+
uint dst_y = i0 - i1 * p.dst_h;
|
| 35 |
+
uint n = i1 / p.channels;
|
| 36 |
+
uint c = i1 - n * p.channels;
|
| 37 |
+
|
| 38 |
+
uint src_i = n * p.channels * p.src_h * p.src_w + c * p.src_h * p.src_w;
|
| 39 |
+
uint knl_i = c * p.knl_h * p.knl_w;
|
| 40 |
+
|
| 41 |
+
FLOAT_TYPE sum = 0.0;
|
| 42 |
+
for (uint knl_y = 0; knl_y < p.knl_h; ++knl_y) {
|
| 43 |
+
uint src_y = dst_y * p.stride_y + knl_y * p.dilation_y - p.pad_y;
|
| 44 |
+
if (src_y >= p.src_h) { // src_y < 0 will wrap to a large unsigned int
|
| 45 |
+
continue;
|
| 46 |
+
}
|
| 47 |
+
for (uint knl_x = 0; knl_x < p.knl_w; ++knl_x) {
|
| 48 |
+
uint src_x = dst_x * p.stride_x + knl_x * p.dilation_x - p.pad_x;
|
| 49 |
+
if (src_x >= p.src_w) { // src_x < 0 will wrap to a large unsigned int
|
| 50 |
+
continue;
|
| 51 |
+
}
|
| 52 |
+
FLOAT_TYPE v = FLOAT_TYPE(src_data[src_i + src_y * p.src_w + src_x]);
|
| 53 |
+
FLOAT_TYPE k = FLOAT_TYPE(knl_data[knl_i + knl_y * p.knl_w + knl_x]);
|
| 54 |
+
sum = fma(v, k, sum);
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
return sum;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
FLOAT_TYPE conv_2d_dw_cwhn(uint idx) {
|
| 61 |
+
uint i0 = idx / p.channels;
|
| 62 |
+
uint c = idx - i0 * p.channels;
|
| 63 |
+
uint i1 = i0 / p.dst_w;
|
| 64 |
+
uint dst_x = i0 - i1 * p.dst_w;
|
| 65 |
+
uint n = i1 / p.dst_h;
|
| 66 |
+
uint dst_y = i1 - n * p.dst_h;
|
| 67 |
+
|
| 68 |
+
uint src_i = n * p.channels * p.src_h * p.src_w;
|
| 69 |
+
uint src_row = p.src_w * p.channels;
|
| 70 |
+
uint knl_row = p.knl_w * p.channels;
|
| 71 |
+
|
| 72 |
+
FLOAT_TYPE sum = 0.0;
|
| 73 |
+
for (uint knl_y = 0; knl_y < p.knl_h; ++knl_y) {
|
| 74 |
+
uint src_y = dst_y * p.stride_y + knl_y * p.dilation_y - p.pad_y;
|
| 75 |
+
if (src_y >= p.src_h) { // src_y < 0 will wrap to a large unsigned int
|
| 76 |
+
continue;
|
| 77 |
+
}
|
| 78 |
+
for (uint knl_x = 0; knl_x < p.knl_w; ++knl_x) {
|
| 79 |
+
uint src_x = dst_x * p.stride_x + knl_x * p.dilation_x - p.pad_x;
|
| 80 |
+
if (src_x >= p.src_w) { // src_x < 0 will wrap to a large unsigned int
|
| 81 |
+
continue;
|
| 82 |
+
}
|
| 83 |
+
FLOAT_TYPE v = FLOAT_TYPE(src_data[src_i + src_y * src_row + src_x * p.channels + c]);
|
| 84 |
+
FLOAT_TYPE k = FLOAT_TYPE(knl_data[ knl_y * knl_row + knl_x * p.channels + c]);
|
| 85 |
+
sum = fma(v, k, sum);
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
return sum;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
void main() {
|
| 92 |
+
uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x;
|
| 93 |
+
if (idx >= p.ne) {
|
| 94 |
+
return;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
FLOAT_TYPE result =
|
| 98 |
+
#ifdef WHCN
|
| 99 |
+
conv_2d_dw_whcn(idx);
|
| 100 |
+
#else
|
| 101 |
+
conv_2d_dw_cwhn(idx);
|
| 102 |
+
#endif
|
| 103 |
+
dst_data[idx] = D_TYPE(result);
|
| 104 |
+
}
|
| 105 |
+
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 4 |
+
#ifdef COOPMAT2
|
| 5 |
+
#extension GL_NV_cooperative_matrix2 : enable
|
| 6 |
+
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
|
| 7 |
+
#extension GL_KHR_memory_scope_semantics : enable
|
| 8 |
+
#endif
|
| 9 |
+
|
| 10 |
+
#ifdef COOPMAT
|
| 11 |
+
#extension GL_KHR_cooperative_matrix : enable
|
| 12 |
+
#extension GL_KHR_shader_subgroup_basic : enable
|
| 13 |
+
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
|
| 14 |
+
#extension GL_KHR_memory_scope_semantics : enable
|
| 15 |
+
#endif
|
| 16 |
+
|
| 17 |
+
#ifdef USE_COLLECTIVES
|
| 18 |
+
# extension GL_KHR_shader_subgroup_shuffle : enable
|
| 19 |
+
#endif
|
| 20 |
+
|
| 21 |
+
#include "types.glsl"
|
| 22 |
+
|
| 23 |
+
// shape notation: [dim(N), ..., dim(0)] -- stride(dim(j)) >= stride(dim(i)) if i > j
|
| 24 |
+
layout(binding = 0) readonly buffer A {
|
| 25 |
+
A_TYPE knl_data[];
|
| 26 |
+
}; // src0 - kernel: [KW, KH, Cin, Cout] for conv_2d, [KW, KH, Cout, Cin] for conv_transposed_2d
|
| 27 |
+
|
| 28 |
+
layout(binding = 1) readonly buffer B {
|
| 29 |
+
B_TYPE src_data[];
|
| 30 |
+
}; // src1 - input: [W, H, Cin, N] -- channel_first format
|
| 31 |
+
|
| 32 |
+
layout(binding = 2) writeonly buffer D {
|
| 33 |
+
D_TYPE dst_data[];
|
| 34 |
+
}; // dst - result: [OW, OH, Cout, N]
|
| 35 |
+
|
| 36 |
+
layout(push_constant) uniform parameter {
|
| 37 |
+
// I/O channels, batch size
|
| 38 |
+
uint32_t Cout;
|
| 39 |
+
uint32_t Cin;
|
| 40 |
+
uint32_t N;
|
| 41 |
+
|
| 42 |
+
// Tensor spatial sizes: input, output
|
| 43 |
+
uint32_t W;
|
| 44 |
+
uint32_t H;
|
| 45 |
+
uint32_t OW;
|
| 46 |
+
uint32_t OH;
|
| 47 |
+
|
| 48 |
+
// Strides in elements
|
| 49 |
+
uint32_t nb01;
|
| 50 |
+
uint32_t nb02;
|
| 51 |
+
uint32_t nb03;
|
| 52 |
+
|
| 53 |
+
uint32_t nb11;
|
| 54 |
+
uint32_t nb12;
|
| 55 |
+
uint32_t nb13;
|
| 56 |
+
|
| 57 |
+
uint32_t nb1;
|
| 58 |
+
uint32_t nb2;
|
| 59 |
+
uint32_t nb3;
|
| 60 |
+
|
| 61 |
+
// fastdiv helper values
|
| 62 |
+
uint32_t OWmp; uint32_t OWL;
|
| 63 |
+
uint32_t OWOHmp; uint32_t OWOHL;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
p;
|
| 67 |
+
|
| 68 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 69 |
+
// Blocktile sizes
|
| 70 |
+
layout(constant_id = 1) const uint BS_K = 128;
|
| 71 |
+
layout(constant_id = 2) const uint BS_CRS = 16;
|
| 72 |
+
layout(constant_id = 3) const uint BS_NPQ = 128;
|
| 73 |
+
// Thread-tile sizes
|
| 74 |
+
layout(constant_id = 4) const uint TS_K = 8;
|
| 75 |
+
layout(constant_id = 5) const uint use_collectives = 1;
|
| 76 |
+
layout(constant_id = 6) const uint SHMEM_PAD = 4;
|
| 77 |
+
// Stride, padding, dilation
|
| 78 |
+
layout(constant_id = 7) const uint s0 = 1;
|
| 79 |
+
layout(constant_id = 8) const uint s1 = 1;
|
| 80 |
+
layout(constant_id = 9) const uint p0 = 0;
|
| 81 |
+
layout(constant_id = 10) const uint p1 = 0;
|
| 82 |
+
layout(constant_id = 11) const uint d0 = 1;
|
| 83 |
+
layout(constant_id = 12) const uint d1 = 1;
|
| 84 |
+
// Kernel spatial sizes
|
| 85 |
+
layout(constant_id = 13) const uint KW = 1;
|
| 86 |
+
layout(constant_id = 14) const uint KH = 1;
|
| 87 |
+
// when set, skip bounds checks and address clamps (K/CRS/NPQ are tile-aligned)
|
| 88 |
+
layout(constant_id = 15) const uint aligned = 0;
|
| 89 |
+
// stage cm2 result through shmem (Csh) for coalesced stores. cm1 always does this.
|
| 90 |
+
layout(constant_id = 16) const uint csh_store = 0;
|
| 91 |
+
|
| 92 |
+
#ifdef COOPMAT
|
| 93 |
+
// cm1 subgroup tile: each subgroup computes a WM x WN region as a grid of
|
| 94 |
+
// TM x TN x TK fragments. Requires WM%TM == WN%TN == BS_K%WM == BS_NPQ%WN ==
|
| 95 |
+
// BS_CRS%TK == 0, and WG_SIZE == (BS_K/WM) * (BS_NPQ/WN) * subgroup_size.
|
| 96 |
+
layout(constant_id = 17) const uint WM = 32;
|
| 97 |
+
layout(constant_id = 18) const uint WN = 32;
|
| 98 |
+
const uint TM = 16;
|
| 99 |
+
const uint TN = 16;
|
| 100 |
+
const uint TK = 16;
|
| 101 |
+
const uint cms_per_row = WM / TM;
|
| 102 |
+
const uint cms_per_col = WN / TN;
|
| 103 |
+
const uint warps_M = BS_K / WM;
|
| 104 |
+
const uint warps_N = BS_NPQ / WN;
|
| 105 |
+
#endif
|
| 106 |
+
|
| 107 |
+
// without padding, H_idx/W_idx are in bounds by construction (non-TRANSPOSE only)
|
| 108 |
+
#ifdef TRANSPOSE
|
| 109 |
+
const bool hw_in_bounds = false;
|
| 110 |
+
#else
|
| 111 |
+
const bool hw_in_bounds = (p0 == 0) && (p1 == 0);
|
| 112 |
+
#endif
|
| 113 |
+
|
| 114 |
+
// TRANSPOSE stride alignment is trivially satisfied for stride 1
|
| 115 |
+
#ifdef TRANSPOSE
|
| 116 |
+
const bool stride_in_bounds = (s0 == 1) && (s1 == 1);
|
| 117 |
+
#else
|
| 118 |
+
const bool stride_in_bounds = true;
|
| 119 |
+
#endif
|
| 120 |
+
|
| 121 |
+
uint32_t tid = gl_LocalInvocationID.x;
|
| 122 |
+
const uint32_t WG_SIZE = gl_WorkGroupSize.x;
|
| 123 |
+
|
| 124 |
+
uint splitWork(uint work_size, uint block_size) {
|
| 125 |
+
return (block_size + work_size - 1) / block_size;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
uint32_t K = p.Cout;
|
| 129 |
+
uint32_t CRS = p.Cin * KH * KW;
|
| 130 |
+
uint32_t NPQ = p.N * p.OH * p.OW;
|
| 131 |
+
|
| 132 |
+
uint32_t n_elems_out = K * NPQ;
|
| 133 |
+
|
| 134 |
+
// Number of blocktiles per input
|
| 135 |
+
uint32_t NB_CRS = splitWork(CRS, BS_CRS);
|
| 136 |
+
|
| 137 |
+
#if defined(COOPMAT2) || defined(COOPMAT)
|
| 138 |
+
#define SHMEM_TYPE float16_t
|
| 139 |
+
#else
|
| 140 |
+
#define SHMEM_TYPE float
|
| 141 |
+
#endif
|
| 142 |
+
|
| 143 |
+
const uint32_t Ash_stride = BS_CRS + SHMEM_PAD;
|
| 144 |
+
const uint32_t Bsh_stride = BS_NPQ + SHMEM_PAD;
|
| 145 |
+
|
| 146 |
+
const uint32_t Ash_numel = BS_K * BS_CRS;
|
| 147 |
+
const uint32_t Bsh_numel = BS_CRS * BS_NPQ;
|
| 148 |
+
|
| 149 |
+
const uint32_t Ash_len = BS_K * Ash_stride;
|
| 150 |
+
const uint32_t Bsh_len = BS_CRS * Bsh_stride;
|
| 151 |
+
|
| 152 |
+
shared SHMEM_TYPE Ash[Ash_len]; // K x CRS
|
| 153 |
+
shared SHMEM_TYPE Bsh[Bsh_len]; // CRS x NPQ
|
| 154 |
+
|
| 155 |
+
#if defined(COOPMAT2) || defined(COOPMAT)
|
| 156 |
+
// stage matC through shmem so global stores are row-major (NPQ-contiguous)
|
| 157 |
+
const uint32_t Csh_stride = BS_NPQ;
|
| 158 |
+
#ifdef COOPMAT
|
| 159 |
+
const uint32_t Csh_len = BS_K * Csh_stride;
|
| 160 |
+
#else
|
| 161 |
+
const uint32_t Csh_len = csh_store != 0 ? BS_K * Csh_stride : 8; // 8 to workaround compiler bug
|
| 162 |
+
#endif
|
| 163 |
+
shared SHMEM_TYPE Csh[Csh_len]; // K x NPQ
|
| 164 |
+
#endif
|
| 165 |
+
|
| 166 |
+
// Threadtile sizes
|
| 167 |
+
const uint32_t TS_NPQ = BS_K * BS_NPQ / WG_SIZE / TS_K;
|
| 168 |
+
|
| 169 |
+
// Number of threadtiles per blocktile
|
| 170 |
+
const uint32_t NT_K = BS_K / TS_K;
|
| 171 |
+
const uint32_t NT_NPQ = BS_NPQ / TS_NPQ;
|
| 172 |
+
|
| 173 |
+
/*
|
| 174 |
+
Compute
|
| 175 |
+
KxCRS @ CRSxNPQ = K x NPQ
|
| 176 |
+
K=Cout
|
| 177 |
+
C=Cin
|
| 178 |
+
R,S=KH,KW
|
| 179 |
+
P,Q=OH,OW
|
| 180 |
+
*/
|
| 181 |
+
|
| 182 |
+
uint32_t B_idx_K = gl_WorkGroupID.x;
|
| 183 |
+
uint32_t B_idx_NPQ = gl_WorkGroupID.y + gl_WorkGroupID.z * 512;
|
| 184 |
+
|
| 185 |
+
uint32_t T_y = tid / NT_NPQ;
|
| 186 |
+
uint32_t T_x = tid % NT_NPQ;
|
| 187 |
+
|
| 188 |
+
uint32_t Ar = tid / BS_CRS;
|
| 189 |
+
uint32_t Ac = tid % BS_CRS;
|
| 190 |
+
const uint32_t ArpWg = WG_SIZE / BS_CRS;
|
| 191 |
+
|
| 192 |
+
uint32_t Br = tid / BS_NPQ;
|
| 193 |
+
uint32_t Bc = tid % BS_NPQ;
|
| 194 |
+
const uint32_t BrpWg = WG_SIZE / BS_NPQ;
|
| 195 |
+
|
| 196 |
+
// see init_fastdiv_values in ggml-vulkan.cpp
|
| 197 |
+
uint fastdiv(uint n, uint mp, uint L) {
|
| 198 |
+
uint msbs, lsbs;
|
| 199 |
+
// msbs = mulhi(n, mp)
|
| 200 |
+
umulExtended(n, mp, msbs, lsbs);
|
| 201 |
+
return (msbs + n) >> L;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
#ifdef COOPMAT2
|
| 205 |
+
#define ACC_TYPE float16_t
|
| 206 |
+
|
| 207 |
+
ACC_TYPE perElemOpStore(const in uint32_t r, const in uint32_t c, const in ACC_TYPE elem)
|
| 208 |
+
{
|
| 209 |
+
uint32_t K_idx = B_idx_K * BS_K + r;
|
| 210 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + c;
|
| 211 |
+
uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL); // divide by p.OH * p.OW;
|
| 212 |
+
uint32_t OH_idx = fastdiv(NPQ_idx - N_idx * p.OH * p.OW, p.OWmp, p.OWL); // divide by p.OW;
|
| 213 |
+
uint32_t OW_idx = NPQ_idx - N_idx * p.OH * p.OW - OH_idx * p.OW;
|
| 214 |
+
uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + K_idx * p.nb2 + N_idx * p.nb3;
|
| 215 |
+
if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
|
| 216 |
+
dst_data[dst_idx] = D_TYPE(elem);
|
| 217 |
+
}
|
| 218 |
+
return elem;
|
| 219 |
+
}
|
| 220 |
+
#endif
|
| 221 |
+
|
| 222 |
+
void main() {
|
| 223 |
+
if (B_idx_NPQ * BS_NPQ >= NPQ) {
|
| 224 |
+
return;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
#ifdef COOPMAT2
|
| 228 |
+
coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator> matC;
|
| 229 |
+
matC = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator>(0.0);
|
| 230 |
+
#elif defined(COOPMAT)
|
| 231 |
+
coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator> sums[cms_per_row * cms_per_col];
|
| 232 |
+
[[unroll]] for (uint i = 0; i < cms_per_row * cms_per_col; i++) {
|
| 233 |
+
sums[i] = coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator>(0.0);
|
| 234 |
+
}
|
| 235 |
+
const uint warp_r = gl_SubgroupID / warps_N;
|
| 236 |
+
const uint warp_c = gl_SubgroupID % warps_N;
|
| 237 |
+
#else
|
| 238 |
+
float regC[TS_K][TS_NPQ];
|
| 239 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 240 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 241 |
+
regC[T_ly][T_lx] = 0.0;
|
| 242 |
+
}
|
| 243 |
+
}
|
| 244 |
+
#endif
|
| 245 |
+
/* Advance block in CRS dim */
|
| 246 |
+
[[dont_unroll]] for (uint32_t B_idx_CRS = 0; B_idx_CRS < NB_CRS; B_idx_CRS++) {
|
| 247 |
+
uint32_t CRS_idx_a;
|
| 248 |
+
uint32_t Cin_idx_a;
|
| 249 |
+
uint32_t KH_idx_a;
|
| 250 |
+
uint32_t KW_idx_a;
|
| 251 |
+
|
| 252 |
+
#ifdef USE_COLLECTIVES
|
| 253 |
+
uint32_t cached_CRS_idx;
|
| 254 |
+
uint32_t cached_Cin_idx;
|
| 255 |
+
uint32_t cached_KH_idx;
|
| 256 |
+
uint32_t cached_KW_idx;
|
| 257 |
+
if (use_collectives == 1) {
|
| 258 |
+
cached_CRS_idx = B_idx_CRS * BS_CRS + gl_SubgroupInvocationID;
|
| 259 |
+
cached_Cin_idx = cached_CRS_idx / (KW * KH);
|
| 260 |
+
uint32_t cached_CRS_remainder = cached_CRS_idx % (KW * KH);
|
| 261 |
+
cached_KH_idx = cached_CRS_remainder / KW;
|
| 262 |
+
cached_KW_idx = cached_CRS_remainder % KW;
|
| 263 |
+
|
| 264 |
+
CRS_idx_a = subgroupShuffle(cached_CRS_idx, Ac);
|
| 265 |
+
Cin_idx_a = subgroupShuffle(cached_Cin_idx, Ac);
|
| 266 |
+
KH_idx_a = subgroupShuffle(cached_KH_idx, Ac);
|
| 267 |
+
KW_idx_a = subgroupShuffle(cached_KW_idx, Ac);
|
| 268 |
+
} else {
|
| 269 |
+
CRS_idx_a = B_idx_CRS * BS_CRS + Ac; // Global CRS_idx_a (column index of A)
|
| 270 |
+
Cin_idx_a = CRS_idx_a / (KW * KH);
|
| 271 |
+
uint32_t CRS_remainder = CRS_idx_a % (KW * KH);
|
| 272 |
+
KH_idx_a = CRS_remainder / KW;
|
| 273 |
+
KW_idx_a = CRS_remainder % KW;
|
| 274 |
+
}
|
| 275 |
+
#else
|
| 276 |
+
CRS_idx_a = B_idx_CRS * BS_CRS + Ac; // Global CRS_idx_a (column index of A)
|
| 277 |
+
Cin_idx_a = CRS_idx_a / (KW * KH);
|
| 278 |
+
CRS_remainder = CRS_idx_a % (KW * KH);
|
| 279 |
+
KH_idx_a = CRS_remainder / KW;
|
| 280 |
+
KW_idx_a = CRS_remainder % KW;
|
| 281 |
+
#endif
|
| 282 |
+
|
| 283 |
+
/* Load kernel to A_block: (BS_K x BS_CRS)*/
|
| 284 |
+
UNROLL for (uint32_t r_offset = 0; r_offset < BS_K; r_offset += ArpWg) {
|
| 285 |
+
uint32_t B_ly = r_offset + Ar;
|
| 286 |
+
uint32_t B_lx = Ac;
|
| 287 |
+
uint32_t K_idx = B_idx_K * BS_K + B_ly; /* Global K_idx (row index of A)*/
|
| 288 |
+
#ifdef TRANSPOSE
|
| 289 |
+
uint32_t knl_idx = KW_idx_a + KH_idx_a * p.nb01 + K_idx * p.nb02 + Cin_idx_a * p.nb03;
|
| 290 |
+
#else
|
| 291 |
+
uint32_t knl_idx = KW_idx_a + KH_idx_a * p.nb01 + Cin_idx_a * p.nb02 + K_idx * p.nb03;
|
| 292 |
+
#endif
|
| 293 |
+
if (aligned == 0) {
|
| 294 |
+
knl_idx = min(knl_idx, K * CRS - 1);
|
| 295 |
+
}
|
| 296 |
+
float val = knl_data[knl_idx];
|
| 297 |
+
if (aligned == 0 && (K_idx >= K || CRS_idx_a >= CRS)) {
|
| 298 |
+
val = 0.0;
|
| 299 |
+
}
|
| 300 |
+
Ash[B_ly * Ash_stride + B_lx] = SHMEM_TYPE(val);
|
| 301 |
+
}
|
| 302 |
+
/* Load input to B_block: (BS_CRS x BS_NPQ) */
|
| 303 |
+
UNROLL for (uint32_t r_offset = 0; r_offset < BS_CRS; r_offset += BrpWg) {
|
| 304 |
+
uint32_t B_ly = r_offset + Br; /* Row index of B block */
|
| 305 |
+
uint32_t B_lx = Bc;
|
| 306 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + B_lx; /* Global NPQ index (column index of B) */
|
| 307 |
+
uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL); // divide by p.OH * p.OW;
|
| 308 |
+
uint32_t NPQ_remainder = NPQ_idx - N_idx * p.OH * p.OW;
|
| 309 |
+
uint32_t OH_idx = fastdiv(NPQ_remainder, p.OWmp, p.OWL); // divide by p.OW;
|
| 310 |
+
uint32_t OW_idx = NPQ_remainder - OH_idx * p.OW;
|
| 311 |
+
|
| 312 |
+
uint32_t CRS_idx_b;
|
| 313 |
+
uint32_t Cin_idx_b;
|
| 314 |
+
uint32_t KH_idx_b;
|
| 315 |
+
uint32_t KW_idx_b;
|
| 316 |
+
#ifdef USE_COLLECTIVES
|
| 317 |
+
if (use_collectives == 1) {
|
| 318 |
+
CRS_idx_b = subgroupShuffle(cached_CRS_idx, r_offset + Br);
|
| 319 |
+
Cin_idx_b = subgroupShuffle(cached_Cin_idx, r_offset + Br);
|
| 320 |
+
KH_idx_b = subgroupShuffle(cached_KH_idx, r_offset + Br);
|
| 321 |
+
KW_idx_b = subgroupShuffle(cached_KW_idx, r_offset + Br);
|
| 322 |
+
} else {
|
| 323 |
+
CRS_idx_b = B_idx_CRS * BS_CRS + B_ly; /* Global CRS index (row index of B) */
|
| 324 |
+
Cin_idx_b = CRS_idx_b / (KW * KH);
|
| 325 |
+
uint32_t CRS_remainder = CRS_idx_b % (KW * KH);
|
| 326 |
+
KH_idx_b = CRS_remainder / KW;
|
| 327 |
+
KW_idx_b = CRS_remainder % KW;
|
| 328 |
+
}
|
| 329 |
+
#else
|
| 330 |
+
CRS_idx_b = B_idx_CRS * BS_CRS + B_ly; /* Global CRS index (row index of B) */
|
| 331 |
+
Cin_idx_b = CRS_idx_b / (KW * KH);
|
| 332 |
+
uint32_t CRS_remainder = CRS_idx_b % (KW * KH);
|
| 333 |
+
KH_idx_b = CRS_remainder / KW;
|
| 334 |
+
KW_idx_b = CRS_remainder % KW;
|
| 335 |
+
#endif
|
| 336 |
+
|
| 337 |
+
#ifdef TRANSPOSE
|
| 338 |
+
uint32_t H_idx_x_s1 = OH_idx - KH_idx_b * d1 + p1;
|
| 339 |
+
uint32_t W_idx_x_s0 = OW_idx - KW_idx_b * d0 + p0;
|
| 340 |
+
uint32_t H_idx = H_idx_x_s1 / s1;
|
| 341 |
+
uint32_t W_idx = W_idx_x_s0 / s0;
|
| 342 |
+
#else
|
| 343 |
+
uint32_t H_idx = OH_idx * s1 + KH_idx_b * d1 - p1;
|
| 344 |
+
uint32_t W_idx = OW_idx * s0 + KW_idx_b * d0 - p0;
|
| 345 |
+
#endif
|
| 346 |
+
uint32_t src_idx = W_idx + H_idx * p.nb11 + Cin_idx_b * p.nb12 + N_idx * p.nb13;
|
| 347 |
+
// skip clamp when address can't go OOB
|
| 348 |
+
if (aligned == 0 || !hw_in_bounds || !stride_in_bounds) {
|
| 349 |
+
src_idx = min(max(src_idx, 0), p.Cin * p.N * p.W * p.H - 1);
|
| 350 |
+
}
|
| 351 |
+
float val = src_data[src_idx];
|
| 352 |
+
bool oob = false;
|
| 353 |
+
if (aligned == 0 && (CRS_idx_b >= CRS || NPQ_idx >= NPQ)) {
|
| 354 |
+
oob = true;
|
| 355 |
+
}
|
| 356 |
+
// also catches lower-bound underflow (idx wraps to 0x80000000+)
|
| 357 |
+
if (!hw_in_bounds && (H_idx >= p.H || W_idx >= p.W)) {
|
| 358 |
+
oob = true;
|
| 359 |
+
}
|
| 360 |
+
#ifdef TRANSPOSE
|
| 361 |
+
if (!stride_in_bounds &&
|
| 362 |
+
((H_idx_x_s1 - H_idx * s1 != 0) || (W_idx_x_s0 - W_idx * s0 != 0))) {
|
| 363 |
+
oob = true;
|
| 364 |
+
}
|
| 365 |
+
#endif
|
| 366 |
+
if (oob) {
|
| 367 |
+
val = 0.0;
|
| 368 |
+
}
|
| 369 |
+
Bsh[B_ly * Bsh_stride + B_lx] = SHMEM_TYPE(val);
|
| 370 |
+
}
|
| 371 |
+
barrier();
|
| 372 |
+
#ifdef COOPMAT2
|
| 373 |
+
coopmat<float16_t, gl_ScopeWorkgroup, BS_K, BS_CRS, gl_MatrixUseA> matA;
|
| 374 |
+
coopmat<float16_t, gl_ScopeWorkgroup, BS_CRS, BS_NPQ, gl_MatrixUseB> matB;
|
| 375 |
+
|
| 376 |
+
coopMatLoad(matA, Ash, 0, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 377 |
+
coopMatLoad(matB, Bsh, 0, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 378 |
+
matC = coopMatMulAdd(matA, matB, matC);
|
| 379 |
+
#elif defined(COOPMAT)
|
| 380 |
+
// each subgroup multiplies its grid of fragments per TK-sized CRS chunk
|
| 381 |
+
[[unroll]] for (uint k_step = 0; k_step < BS_CRS / TK; k_step++) {
|
| 382 |
+
coopmat<float16_t, gl_ScopeSubgroup, TM, TK, gl_MatrixUseA> cache_a[cms_per_row];
|
| 383 |
+
[[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
|
| 384 |
+
const uint a_off = (warp_r * WM + cm_row * TM) * Ash_stride + k_step * TK;
|
| 385 |
+
coopMatLoad(cache_a[cm_row], Ash, a_off, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 386 |
+
}
|
| 387 |
+
[[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
|
| 388 |
+
coopmat<float16_t, gl_ScopeSubgroup, TK, TN, gl_MatrixUseB> cache_b;
|
| 389 |
+
const uint b_off = k_step * TK * Bsh_stride + warp_c * WN + cm_col * TN;
|
| 390 |
+
coopMatLoad(cache_b, Bsh, b_off, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 391 |
+
[[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
|
| 392 |
+
sums[cm_col * cms_per_row + cm_row] = coopMatMulAdd(cache_a[cm_row], cache_b, sums[cm_col * cms_per_row + cm_row]);
|
| 393 |
+
}
|
| 394 |
+
}
|
| 395 |
+
}
|
| 396 |
+
#else
|
| 397 |
+
if (T_y * TS_K < K) {
|
| 398 |
+
UNROLL for (uint32_t CRS_lidx = 0; CRS_lidx < BS_CRS; CRS_lidx++) {
|
| 399 |
+
float regA[TS_K];
|
| 400 |
+
float regB[TS_NPQ];
|
| 401 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 402 |
+
regA[T_ly] = Ash[(T_y * TS_K + T_ly) * Ash_stride + CRS_lidx];
|
| 403 |
+
}
|
| 404 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 405 |
+
regB[T_lx] = Bsh[CRS_lidx * Bsh_stride + T_x * TS_NPQ + T_lx];
|
| 406 |
+
}
|
| 407 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 408 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 409 |
+
regC[T_ly][T_lx] = fma(regA[T_ly], regB[T_lx], regC[T_ly][T_lx]);
|
| 410 |
+
}
|
| 411 |
+
}
|
| 412 |
+
}
|
| 413 |
+
}
|
| 414 |
+
#endif
|
| 415 |
+
barrier();
|
| 416 |
+
}
|
| 417 |
+
/* Save C* */
|
| 418 |
+
#if defined(COOPMAT2) || defined(COOPMAT)
|
| 419 |
+
// stage matC into Csh, then write to dst with coalesced NPQ-contiguous stores
|
| 420 |
+
#ifdef COOPMAT
|
| 421 |
+
const bool use_staged_store = true;
|
| 422 |
+
#else
|
| 423 |
+
const bool use_staged_store = (csh_store != 0);
|
| 424 |
+
#endif
|
| 425 |
+
if (use_staged_store) {
|
| 426 |
+
#ifdef COOPMAT
|
| 427 |
+
// cm1: each subgroup stores its fragment grid into its Csh slot
|
| 428 |
+
[[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
|
| 429 |
+
[[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
|
| 430 |
+
const uint csh_off = (warp_r * WM + cm_row * TM) * Csh_stride + warp_c * WN + cm_col * TN;
|
| 431 |
+
coopMatStore(sums[cm_col * cms_per_row + cm_row], Csh, csh_off, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 432 |
+
}
|
| 433 |
+
}
|
| 434 |
+
#else
|
| 435 |
+
coopMatStore(matC, Csh, 0, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 436 |
+
#endif
|
| 437 |
+
barrier();
|
| 438 |
+
|
| 439 |
+
// cooperative shmem->global: WG threads spread across BS_NPQ (the
|
| 440 |
+
// contiguous direction of dst), each iter covers store_rows_per_iter K-rows
|
| 441 |
+
const uint32_t store_rows_per_iter = WG_SIZE / BS_NPQ;
|
| 442 |
+
const uint32_t store_iters = BS_K / store_rows_per_iter;
|
| 443 |
+
const uint32_t k_thread_offset = tid / BS_NPQ;
|
| 444 |
+
const uint32_t npq_thread = tid % BS_NPQ;
|
| 445 |
+
[[unroll]] for (uint32_t i = 0; i < store_iters; i++) {
|
| 446 |
+
uint32_t k_local = i * store_rows_per_iter + k_thread_offset;
|
| 447 |
+
uint32_t K_idx = B_idx_K * BS_K + k_local;
|
| 448 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + npq_thread;
|
| 449 |
+
uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL);
|
| 450 |
+
uint32_t OH_idx = fastdiv(NPQ_idx - N_idx * p.OH * p.OW, p.OWmp, p.OWL);
|
| 451 |
+
uint32_t OW_idx = NPQ_idx - N_idx * p.OH * p.OW - OH_idx * p.OW;
|
| 452 |
+
uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + K_idx * p.nb2 + N_idx * p.nb3;
|
| 453 |
+
if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
|
| 454 |
+
dst_data[dst_idx] = D_TYPE(Csh[k_local * Csh_stride + npq_thread]);
|
| 455 |
+
}
|
| 456 |
+
}
|
| 457 |
+
}
|
| 458 |
+
#ifdef COOPMAT2
|
| 459 |
+
else {
|
| 460 |
+
coopMatPerElementNV(matC, matC, perElemOpStore);
|
| 461 |
+
}
|
| 462 |
+
#endif
|
| 463 |
+
#else
|
| 464 |
+
if (T_y * TS_K < K) {
|
| 465 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 466 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 467 |
+
uint32_t K_idx = B_idx_K * BS_K + T_y * TS_K + T_ly;
|
| 468 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + T_x * TS_NPQ + T_lx;
|
| 469 |
+
uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL); // divide by p.OH * p.OW;
|
| 470 |
+
uint32_t OH_idx = fastdiv(NPQ_idx - N_idx * p.OH * p.OW, p.OWmp, p.OWL); // divide by p.OW;
|
| 471 |
+
uint32_t OW_idx = NPQ_idx - N_idx * p.OH * p.OW - OH_idx * p.OW;
|
| 472 |
+
uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + K_idx * p.nb2 + N_idx * p.nb3;
|
| 473 |
+
if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
|
| 474 |
+
dst_data[dst_idx] = regC[T_ly][T_lx];
|
| 475 |
+
}
|
| 476 |
+
}
|
| 477 |
+
}
|
| 478 |
+
}
|
| 479 |
+
#endif
|
| 480 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 4 |
+
#ifdef COOPMAT2
|
| 5 |
+
#extension GL_NV_cooperative_matrix2 : enable
|
| 6 |
+
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
|
| 7 |
+
#extension GL_KHR_memory_scope_semantics : enable
|
| 8 |
+
#endif
|
| 9 |
+
|
| 10 |
+
#ifdef COOPMAT
|
| 11 |
+
#extension GL_KHR_cooperative_matrix : enable
|
| 12 |
+
#extension GL_KHR_shader_subgroup_basic : enable
|
| 13 |
+
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
|
| 14 |
+
#extension GL_KHR_memory_scope_semantics : enable
|
| 15 |
+
#endif
|
| 16 |
+
|
| 17 |
+
#include "types.glsl"
|
| 18 |
+
|
| 19 |
+
// shape notation: [dim(N), ..., dim(0)] -- stride(dim(j)) >= stride(dim(i)) if i > j
|
| 20 |
+
layout(binding = 0) readonly buffer A {
|
| 21 |
+
A_TYPE knl_data[];
|
| 22 |
+
}; // src0 - kernel: [KW, KH, KD, IC*OC]
|
| 23 |
+
|
| 24 |
+
layout(binding = 1) readonly buffer B {
|
| 25 |
+
B_TYPE src_data[];
|
| 26 |
+
}; // src1 - input: [IW, IH, ID, IC*N] -- channel_first format
|
| 27 |
+
|
| 28 |
+
layout(binding = 2) writeonly buffer D {
|
| 29 |
+
D_TYPE dst_data[];
|
| 30 |
+
}; // dst - result: [OW, OH, OD, OC*N]
|
| 31 |
+
|
| 32 |
+
layout(push_constant) uniform parameter {
|
| 33 |
+
// I/O channels, batch size
|
| 34 |
+
uint32_t OC;
|
| 35 |
+
uint32_t IC;
|
| 36 |
+
uint32_t N;
|
| 37 |
+
|
| 38 |
+
// Tensor spatial sizes: input, output
|
| 39 |
+
uint32_t IW;
|
| 40 |
+
uint32_t IH;
|
| 41 |
+
uint32_t ID;
|
| 42 |
+
uint32_t OW;
|
| 43 |
+
uint32_t OH;
|
| 44 |
+
uint32_t OD;
|
| 45 |
+
|
| 46 |
+
// Strides in elements
|
| 47 |
+
uint32_t nb01;
|
| 48 |
+
uint32_t nb02;
|
| 49 |
+
uint32_t nb03;
|
| 50 |
+
|
| 51 |
+
uint32_t nb11;
|
| 52 |
+
uint32_t nb12;
|
| 53 |
+
uint32_t nb13;
|
| 54 |
+
|
| 55 |
+
uint32_t nb1;
|
| 56 |
+
uint32_t nb2;
|
| 57 |
+
uint32_t nb3;
|
| 58 |
+
|
| 59 |
+
// fastdiv helper values
|
| 60 |
+
uint32_t OWmp; uint32_t OWL;
|
| 61 |
+
uint32_t OWOHmp; uint32_t OWOHL;
|
| 62 |
+
uint32_t OWOHODmp; uint32_t OWOHODL;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
p;
|
| 66 |
+
|
| 67 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 68 |
+
// Blocktile sizes
|
| 69 |
+
layout(constant_id = 1) const uint BS_K = 128;
|
| 70 |
+
layout(constant_id = 2) const uint BS_CRS = 16;
|
| 71 |
+
layout(constant_id = 3) const uint BS_NPQ = 128;
|
| 72 |
+
// Thread-tile sizes
|
| 73 |
+
layout(constant_id = 4) const uint TS_K = 8;
|
| 74 |
+
layout(constant_id = 5) const uint SHMEM_PAD = 4;
|
| 75 |
+
// Stride, padding, dilation
|
| 76 |
+
layout(constant_id = 6) const uint s0 = 1;
|
| 77 |
+
layout(constant_id = 7) const uint s1 = 1;
|
| 78 |
+
layout(constant_id = 8) const uint s2 = 1;
|
| 79 |
+
layout(constant_id = 9) const uint p0 = 0;
|
| 80 |
+
layout(constant_id = 10) const uint p1 = 0;
|
| 81 |
+
layout(constant_id = 11) const uint p2 = 0;
|
| 82 |
+
layout(constant_id = 12) const uint d0 = 1;
|
| 83 |
+
layout(constant_id = 13) const uint d1 = 1;
|
| 84 |
+
layout(constant_id = 14) const uint d2 = 1;
|
| 85 |
+
// Kernel spatial sizes
|
| 86 |
+
layout(constant_id = 15) const uint KW = 1;
|
| 87 |
+
layout(constant_id = 16) const uint KH = 1;
|
| 88 |
+
layout(constant_id = 17) const uint KD = 1;
|
| 89 |
+
// when set, skip bounds checks and address clamps (K/CRS/NPQ are tile-aligned)
|
| 90 |
+
layout(constant_id = 18) const uint aligned = 0;
|
| 91 |
+
// stage cm2 result through shmem (Csh) for coalesced stores. cm1 always does this.
|
| 92 |
+
layout(constant_id = 19) const uint csh_store = 0;
|
| 93 |
+
|
| 94 |
+
#ifdef COOPMAT
|
| 95 |
+
// cm1 subgroup tile: each subgroup computes a WM x WN region as a grid of
|
| 96 |
+
// TM x TN x TK fragments. Requires WM%TM == WN%TN == BS_K%WM == BS_NPQ%WN ==
|
| 97 |
+
// BS_CRS%TK == 0, and WG_SIZE == (BS_K/WM) * (BS_NPQ/WN) * subgroup_size.
|
| 98 |
+
layout(constant_id = 20) const uint WM = 32;
|
| 99 |
+
layout(constant_id = 21) const uint WN = 32;
|
| 100 |
+
const uint TM = 16;
|
| 101 |
+
const uint TN = 16;
|
| 102 |
+
const uint TK = 16;
|
| 103 |
+
const uint cms_per_row = WM / TM;
|
| 104 |
+
const uint cms_per_col = WN / TN;
|
| 105 |
+
const uint warps_M = BS_K / WM;
|
| 106 |
+
const uint warps_N = BS_NPQ / WN;
|
| 107 |
+
#endif
|
| 108 |
+
|
| 109 |
+
// without padding, ID_idx/IH_idx/IW_idx are in bounds by construction
|
| 110 |
+
const bool dhw_in_bounds = (p0 == 0) && (p1 == 0) && (p2 == 0);
|
| 111 |
+
|
| 112 |
+
uint32_t tid = gl_LocalInvocationID.x;
|
| 113 |
+
const uint32_t WG_SIZE = gl_WorkGroupSize.x;
|
| 114 |
+
|
| 115 |
+
uint splitWork(uint work_size, uint block_size) {
|
| 116 |
+
return (block_size + work_size - 1) / block_size;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
uint32_t K = p.OC;
|
| 120 |
+
uint32_t CRS = p.IC * KD * KH * KW;
|
| 121 |
+
uint32_t NPQ = p.N * p.OD * p.OH * p.OW;
|
| 122 |
+
|
| 123 |
+
// Number of blocktiles per input
|
| 124 |
+
uint32_t NB_CRS = splitWork(CRS, BS_CRS);
|
| 125 |
+
|
| 126 |
+
#if defined(COOPMAT2) || defined(COOPMAT)
|
| 127 |
+
#define SHMEM_TYPE float16_t
|
| 128 |
+
#else
|
| 129 |
+
#define SHMEM_TYPE float
|
| 130 |
+
#endif
|
| 131 |
+
|
| 132 |
+
const uint32_t Ash_stride = BS_CRS + SHMEM_PAD;
|
| 133 |
+
const uint32_t Bsh_stride = BS_NPQ + SHMEM_PAD;
|
| 134 |
+
|
| 135 |
+
const uint32_t Ash_len = BS_K * Ash_stride;
|
| 136 |
+
const uint32_t Bsh_len = BS_CRS * Bsh_stride;
|
| 137 |
+
|
| 138 |
+
shared SHMEM_TYPE Ash[Ash_len]; // K x CRS
|
| 139 |
+
shared SHMEM_TYPE Bsh[Bsh_len]; // CRS x NPQ
|
| 140 |
+
|
| 141 |
+
#if defined(COOPMAT2) || defined(COOPMAT)
|
| 142 |
+
// stage matC through shmem so global stores are row-major (NPQ-contiguous)
|
| 143 |
+
const uint32_t Csh_stride = BS_NPQ;
|
| 144 |
+
#ifdef COOPMAT
|
| 145 |
+
const uint32_t Csh_len = BS_K * Csh_stride;
|
| 146 |
+
#else
|
| 147 |
+
const uint32_t Csh_len = csh_store != 0 ? BS_K * Csh_stride : 8; // 8 to workaround compiler bug
|
| 148 |
+
#endif
|
| 149 |
+
shared SHMEM_TYPE Csh[Csh_len]; // K x NPQ
|
| 150 |
+
#endif
|
| 151 |
+
|
| 152 |
+
// Threadtile sizes
|
| 153 |
+
const uint32_t TS_NPQ = BS_K * BS_NPQ / WG_SIZE / TS_K;
|
| 154 |
+
|
| 155 |
+
// Number of threadtiles per blocktile
|
| 156 |
+
const uint32_t NT_NPQ = BS_NPQ / TS_NPQ;
|
| 157 |
+
|
| 158 |
+
/*
|
| 159 |
+
Compute
|
| 160 |
+
KxCRS @ CRSxNPQ = K x NPQ
|
| 161 |
+
K=OC
|
| 162 |
+
C=IC
|
| 163 |
+
D,R,S=KD,KH,KW
|
| 164 |
+
Z,P,Q=OD,OH,OW
|
| 165 |
+
*/
|
| 166 |
+
|
| 167 |
+
uint32_t B_idx_K = gl_WorkGroupID.x;
|
| 168 |
+
uint32_t B_idx_NPQ = gl_WorkGroupID.y + gl_WorkGroupID.z * 512;
|
| 169 |
+
|
| 170 |
+
uint32_t T_y = tid / NT_NPQ;
|
| 171 |
+
uint32_t T_x = tid % NT_NPQ;
|
| 172 |
+
|
| 173 |
+
uint32_t Ar = tid / BS_CRS;
|
| 174 |
+
uint32_t Ac = tid % BS_CRS;
|
| 175 |
+
const uint32_t ArpWg = WG_SIZE / BS_CRS;
|
| 176 |
+
|
| 177 |
+
uint32_t Br = tid / BS_NPQ;
|
| 178 |
+
uint32_t Bc = tid % BS_NPQ;
|
| 179 |
+
const uint32_t BrpWg = WG_SIZE / BS_NPQ;
|
| 180 |
+
|
| 181 |
+
// see init_fastdiv_values in ggml-vulkan.cpp
|
| 182 |
+
uint fastdiv(uint n, uint mp, uint L) {
|
| 183 |
+
uint msbs, lsbs;
|
| 184 |
+
// msbs = mulhi(n, mp)
|
| 185 |
+
umulExtended(n, mp, msbs, lsbs);
|
| 186 |
+
return (msbs + n) >> L;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
void split_crs(uint32_t crs_idx, out uint32_t ic, out uint32_t kd, out uint32_t kh, out uint32_t kw) {
|
| 190 |
+
const uint32_t KHKW = KH * KW;
|
| 191 |
+
const uint32_t KDKHKW = KD * KHKW;
|
| 192 |
+
ic = crs_idx / KDKHKW;
|
| 193 |
+
uint32_t rem = crs_idx - ic * KDKHKW;
|
| 194 |
+
kd = rem / KHKW;
|
| 195 |
+
rem = rem - kd * KHKW;
|
| 196 |
+
kh = rem / KW;
|
| 197 |
+
kw = rem - kh * KW;
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
void split_npq(uint32_t npq_idx, out uint32_t n, out uint32_t od, out uint32_t oh, out uint32_t ow) {
|
| 201 |
+
const uint32_t OWOH = p.OW * p.OH;
|
| 202 |
+
n = fastdiv(npq_idx, p.OWOHODmp, p.OWOHODL);
|
| 203 |
+
uint32_t rem = npq_idx - n * p.OD * OWOH;
|
| 204 |
+
od = fastdiv(rem, p.OWOHmp, p.OWOHL);
|
| 205 |
+
rem = rem - od * OWOH;
|
| 206 |
+
oh = fastdiv(rem, p.OWmp, p.OWL);
|
| 207 |
+
ow = rem - oh * p.OW;
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
#ifdef COOPMAT2
|
| 211 |
+
#define ACC_TYPE float16_t
|
| 212 |
+
|
| 213 |
+
ACC_TYPE perElemOpStore(const in uint32_t r, const in uint32_t c, const in ACC_TYPE elem)
|
| 214 |
+
{
|
| 215 |
+
uint32_t K_idx = B_idx_K * BS_K + r;
|
| 216 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + c;
|
| 217 |
+
uint32_t N_idx;
|
| 218 |
+
uint32_t OD_idx;
|
| 219 |
+
uint32_t OH_idx;
|
| 220 |
+
uint32_t OW_idx;
|
| 221 |
+
split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
|
| 222 |
+
uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + OD_idx * p.nb2 + (N_idx * p.OC + K_idx) * p.nb3;
|
| 223 |
+
if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
|
| 224 |
+
dst_data[dst_idx] = D_TYPE(elem);
|
| 225 |
+
}
|
| 226 |
+
return elem;
|
| 227 |
+
}
|
| 228 |
+
#endif
|
| 229 |
+
|
| 230 |
+
void main() {
|
| 231 |
+
if (B_idx_NPQ * BS_NPQ >= NPQ) {
|
| 232 |
+
return;
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
#ifdef COOPMAT2
|
| 236 |
+
coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator> matC;
|
| 237 |
+
matC = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator>(0.0);
|
| 238 |
+
#elif defined(COOPMAT)
|
| 239 |
+
coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator> sums[cms_per_row * cms_per_col];
|
| 240 |
+
[[unroll]] for (uint i = 0; i < cms_per_row * cms_per_col; i++) {
|
| 241 |
+
sums[i] = coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator>(0.0);
|
| 242 |
+
}
|
| 243 |
+
const uint warp_r = gl_SubgroupID / warps_N;
|
| 244 |
+
const uint warp_c = gl_SubgroupID % warps_N;
|
| 245 |
+
#else
|
| 246 |
+
float regC[TS_K][TS_NPQ];
|
| 247 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 248 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 249 |
+
regC[T_ly][T_lx] = 0.0;
|
| 250 |
+
}
|
| 251 |
+
}
|
| 252 |
+
#endif
|
| 253 |
+
/* Advance block in CRS dim */
|
| 254 |
+
[[dont_unroll]] for (uint32_t B_idx_CRS = 0; B_idx_CRS < NB_CRS; B_idx_CRS++) {
|
| 255 |
+
uint32_t CRS_idx_a = B_idx_CRS * BS_CRS + Ac;
|
| 256 |
+
uint32_t IC_idx_a;
|
| 257 |
+
uint32_t KD_idx_a;
|
| 258 |
+
uint32_t KH_idx_a;
|
| 259 |
+
uint32_t KW_idx_a;
|
| 260 |
+
split_crs(CRS_idx_a, IC_idx_a, KD_idx_a, KH_idx_a, KW_idx_a);
|
| 261 |
+
|
| 262 |
+
/* Load kernel to A_block: (BS_K x BS_CRS)*/
|
| 263 |
+
UNROLL for (uint32_t r_offset = 0; r_offset < BS_K; r_offset += ArpWg) {
|
| 264 |
+
uint32_t B_ly = r_offset + Ar;
|
| 265 |
+
uint32_t B_lx = Ac;
|
| 266 |
+
uint32_t K_idx = B_idx_K * BS_K + B_ly; /* Global K_idx (row index of A)*/
|
| 267 |
+
uint32_t knl_idx = KW_idx_a + KH_idx_a * p.nb01 + KD_idx_a * p.nb02 + (K_idx * p.IC + IC_idx_a) * p.nb03;
|
| 268 |
+
if (aligned == 0) {
|
| 269 |
+
knl_idx = min(knl_idx, K * CRS - 1);
|
| 270 |
+
}
|
| 271 |
+
float val = knl_data[knl_idx];
|
| 272 |
+
if (aligned == 0 && (K_idx >= K || CRS_idx_a >= CRS)) {
|
| 273 |
+
val = 0.0;
|
| 274 |
+
}
|
| 275 |
+
Ash[B_ly * Ash_stride + B_lx] = SHMEM_TYPE(val);
|
| 276 |
+
}
|
| 277 |
+
/* Load input to B_block: (BS_CRS x BS_NPQ) */
|
| 278 |
+
UNROLL for (uint32_t r_offset = 0; r_offset < BS_CRS; r_offset += BrpWg) {
|
| 279 |
+
uint32_t B_ly = r_offset + Br; /* Row index of B block */
|
| 280 |
+
uint32_t B_lx = Bc;
|
| 281 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + B_lx; /* Global NPQ index (column index of B) */
|
| 282 |
+
uint32_t N_idx;
|
| 283 |
+
uint32_t OD_idx;
|
| 284 |
+
uint32_t OH_idx;
|
| 285 |
+
uint32_t OW_idx;
|
| 286 |
+
split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
|
| 287 |
+
|
| 288 |
+
uint32_t CRS_idx_b = B_idx_CRS * BS_CRS + B_ly;
|
| 289 |
+
uint32_t IC_idx_b;
|
| 290 |
+
uint32_t KD_idx_b;
|
| 291 |
+
uint32_t KH_idx_b;
|
| 292 |
+
uint32_t KW_idx_b;
|
| 293 |
+
split_crs(CRS_idx_b, IC_idx_b, KD_idx_b, KH_idx_b, KW_idx_b);
|
| 294 |
+
|
| 295 |
+
uint32_t ID_idx = OD_idx * s2 + KD_idx_b * d2 - p2;
|
| 296 |
+
uint32_t IH_idx = OH_idx * s1 + KH_idx_b * d1 - p1;
|
| 297 |
+
uint32_t IW_idx = OW_idx * s0 + KW_idx_b * d0 - p0;
|
| 298 |
+
|
| 299 |
+
uint32_t src_idx = IW_idx + IH_idx * p.nb11 + ID_idx * p.nb12 + (N_idx * p.IC + IC_idx_b) * p.nb13;
|
| 300 |
+
// skip clamp when address can't go OOB
|
| 301 |
+
if (aligned == 0 || !dhw_in_bounds) {
|
| 302 |
+
src_idx = min(src_idx, p.IC * p.N * p.IW * p.IH * p.ID - 1);
|
| 303 |
+
}
|
| 304 |
+
float val = src_data[src_idx];
|
| 305 |
+
bool oob = false;
|
| 306 |
+
if (aligned == 0 && (CRS_idx_b >= CRS || NPQ_idx >= NPQ)) {
|
| 307 |
+
oob = true;
|
| 308 |
+
}
|
| 309 |
+
// also catches lower-bound underflow (idx wraps to 0x80000000+)
|
| 310 |
+
if (!dhw_in_bounds && (ID_idx >= p.ID || IH_idx >= p.IH || IW_idx >= p.IW)) {
|
| 311 |
+
oob = true;
|
| 312 |
+
}
|
| 313 |
+
if (oob) {
|
| 314 |
+
val = 0.0;
|
| 315 |
+
}
|
| 316 |
+
Bsh[B_ly * Bsh_stride + B_lx] = SHMEM_TYPE(val);
|
| 317 |
+
}
|
| 318 |
+
barrier();
|
| 319 |
+
#ifdef COOPMAT2
|
| 320 |
+
coopmat<float16_t, gl_ScopeWorkgroup, BS_K, BS_CRS, gl_MatrixUseA> matA;
|
| 321 |
+
coopmat<float16_t, gl_ScopeWorkgroup, BS_CRS, BS_NPQ, gl_MatrixUseB> matB;
|
| 322 |
+
|
| 323 |
+
coopMatLoad(matA, Ash, 0, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 324 |
+
coopMatLoad(matB, Bsh, 0, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 325 |
+
matC = coopMatMulAdd(matA, matB, matC);
|
| 326 |
+
#elif defined(COOPMAT)
|
| 327 |
+
// each subgroup multiplies its grid of fragments per TK-sized CRS chunk
|
| 328 |
+
[[unroll]] for (uint k_step = 0; k_step < BS_CRS / TK; k_step++) {
|
| 329 |
+
coopmat<float16_t, gl_ScopeSubgroup, TM, TK, gl_MatrixUseA> cache_a[cms_per_row];
|
| 330 |
+
[[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
|
| 331 |
+
const uint a_off = (warp_r * WM + cm_row * TM) * Ash_stride + k_step * TK;
|
| 332 |
+
coopMatLoad(cache_a[cm_row], Ash, a_off, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 333 |
+
}
|
| 334 |
+
[[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
|
| 335 |
+
coopmat<float16_t, gl_ScopeSubgroup, TK, TN, gl_MatrixUseB> cache_b;
|
| 336 |
+
const uint b_off = k_step * TK * Bsh_stride + warp_c * WN + cm_col * TN;
|
| 337 |
+
coopMatLoad(cache_b, Bsh, b_off, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 338 |
+
[[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
|
| 339 |
+
sums[cm_col * cms_per_row + cm_row] = coopMatMulAdd(cache_a[cm_row], cache_b, sums[cm_col * cms_per_row + cm_row]);
|
| 340 |
+
}
|
| 341 |
+
}
|
| 342 |
+
}
|
| 343 |
+
#else
|
| 344 |
+
if (T_y * TS_K < K) {
|
| 345 |
+
UNROLL for (uint32_t CRS_lidx = 0; CRS_lidx < BS_CRS; CRS_lidx++) {
|
| 346 |
+
float regA[TS_K];
|
| 347 |
+
float regB[TS_NPQ];
|
| 348 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 349 |
+
regA[T_ly] = Ash[(T_y * TS_K + T_ly) * Ash_stride + CRS_lidx];
|
| 350 |
+
}
|
| 351 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 352 |
+
regB[T_lx] = Bsh[CRS_lidx * Bsh_stride + T_x * TS_NPQ + T_lx];
|
| 353 |
+
}
|
| 354 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 355 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 356 |
+
regC[T_ly][T_lx] = fma(regA[T_ly], regB[T_lx], regC[T_ly][T_lx]);
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
}
|
| 360 |
+
}
|
| 361 |
+
#endif
|
| 362 |
+
barrier();
|
| 363 |
+
}
|
| 364 |
+
/* Save C* */
|
| 365 |
+
#if defined(COOPMAT2) || defined(COOPMAT)
|
| 366 |
+
// stage matC into Csh, then write to dst with coalesced NPQ-contiguous stores
|
| 367 |
+
#ifdef COOPMAT
|
| 368 |
+
const bool use_staged_store = true;
|
| 369 |
+
#else
|
| 370 |
+
const bool use_staged_store = (csh_store != 0);
|
| 371 |
+
#endif
|
| 372 |
+
if (use_staged_store) {
|
| 373 |
+
#ifdef COOPMAT
|
| 374 |
+
// cm1: each subgroup stores its fragment grid into its Csh slot
|
| 375 |
+
[[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
|
| 376 |
+
[[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
|
| 377 |
+
const uint csh_off = (warp_r * WM + cm_row * TM) * Csh_stride + warp_c * WN + cm_col * TN;
|
| 378 |
+
coopMatStore(sums[cm_col * cms_per_row + cm_row], Csh, csh_off, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 379 |
+
}
|
| 380 |
+
}
|
| 381 |
+
#else
|
| 382 |
+
coopMatStore(matC, Csh, 0, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
|
| 383 |
+
#endif
|
| 384 |
+
barrier();
|
| 385 |
+
|
| 386 |
+
// cooperative shmem->global: WG threads spread across BS_NPQ (the
|
| 387 |
+
// contiguous direction of dst), each iter covers store_rows_per_iter K-rows
|
| 388 |
+
const uint32_t store_rows_per_iter = WG_SIZE / BS_NPQ;
|
| 389 |
+
const uint32_t store_iters = BS_K / store_rows_per_iter;
|
| 390 |
+
const uint32_t k_thread_offset = tid / BS_NPQ;
|
| 391 |
+
const uint32_t npq_thread = tid % BS_NPQ;
|
| 392 |
+
[[unroll]] for (uint32_t i = 0; i < store_iters; i++) {
|
| 393 |
+
uint32_t k_local = i * store_rows_per_iter + k_thread_offset;
|
| 394 |
+
uint32_t K_idx = B_idx_K * BS_K + k_local;
|
| 395 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + npq_thread;
|
| 396 |
+
uint32_t N_idx;
|
| 397 |
+
uint32_t OD_idx;
|
| 398 |
+
uint32_t OH_idx;
|
| 399 |
+
uint32_t OW_idx;
|
| 400 |
+
split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
|
| 401 |
+
uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + OD_idx * p.nb2 + (N_idx * p.OC + K_idx) * p.nb3;
|
| 402 |
+
if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
|
| 403 |
+
dst_data[dst_idx] = D_TYPE(Csh[k_local * Csh_stride + npq_thread]);
|
| 404 |
+
}
|
| 405 |
+
}
|
| 406 |
+
}
|
| 407 |
+
#ifdef COOPMAT2
|
| 408 |
+
else {
|
| 409 |
+
coopMatPerElementNV(matC, matC, perElemOpStore);
|
| 410 |
+
}
|
| 411 |
+
#endif
|
| 412 |
+
#else
|
| 413 |
+
if (T_y * TS_K < K) {
|
| 414 |
+
for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
|
| 415 |
+
for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
|
| 416 |
+
uint32_t K_idx = B_idx_K * BS_K + T_y * TS_K + T_ly;
|
| 417 |
+
uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + T_x * TS_NPQ + T_lx;
|
| 418 |
+
uint32_t N_idx;
|
| 419 |
+
uint32_t OD_idx;
|
| 420 |
+
uint32_t OH_idx;
|
| 421 |
+
uint32_t OW_idx;
|
| 422 |
+
split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
|
| 423 |
+
uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + OD_idx * p.nb2 + (N_idx * p.OC + K_idx) * p.nb3;
|
| 424 |
+
if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
|
| 425 |
+
dst_data[dst_idx] = D_TYPE(regC[T_ly][T_lx]);
|
| 426 |
+
}
|
| 427 |
+
}
|
| 428 |
+
}
|
| 429 |
+
}
|
| 430 |
+
#endif
|
| 431 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv_transpose_1d.comp
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
|
| 5 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; // src0 - kernel: [K, Cout, Cin]
|
| 6 |
+
layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; // src1 - input: [L, Cin]
|
| 7 |
+
layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; // dst - result [KL, Cout]
|
| 8 |
+
|
| 9 |
+
layout(local_size_x = 128 , local_size_y = 1, local_size_z = 1) in;
|
| 10 |
+
|
| 11 |
+
layout (push_constant) uniform parameter {
|
| 12 |
+
uint32_t Cout;
|
| 13 |
+
uint32_t Cin;
|
| 14 |
+
uint32_t K;
|
| 15 |
+
uint32_t L;
|
| 16 |
+
uint32_t KL;
|
| 17 |
+
|
| 18 |
+
uint32_t nb01;
|
| 19 |
+
uint32_t nb02;
|
| 20 |
+
uint32_t nb11;
|
| 21 |
+
uint32_t nb1;
|
| 22 |
+
|
| 23 |
+
int32_t s0;
|
| 24 |
+
} p;
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
uint32_t Cout_idx = gl_WorkGroupID.x;
|
| 28 |
+
const uint32_t bs = gl_WorkGroupSize.x;
|
| 29 |
+
uint32_t tid = gl_LocalInvocationID.x;
|
| 30 |
+
// Code is more straightforward if we assume it is bs*s0+K instead of (bs-1)*s0+K.
|
| 31 |
+
uint32_t tmp_len = bs*p.s0+p.K;
|
| 32 |
+
shared D_TYPE tmp[4096];
|
| 33 |
+
|
| 34 |
+
uint splitWork(uint workSize){
|
| 35 |
+
return (bs + workSize -1) / bs;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
void main(){
|
| 39 |
+
for(uint32_t i = 0; i < splitWork(tmp_len); i++){
|
| 40 |
+
uint32_t idx = i*bs+tid;
|
| 41 |
+
if(idx < tmp_len){
|
| 42 |
+
tmp[idx] = 0.0;
|
| 43 |
+
}
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
uint32_t L_blocks = splitWork(p.L);
|
| 47 |
+
for(uint32_t L_block_id = 0; L_block_id < L_blocks; L_block_id++){
|
| 48 |
+
if(L_block_id > 0){
|
| 49 |
+
barrier();
|
| 50 |
+
// Shift values in tmp to the current processing window
|
| 51 |
+
for(int i = 0; i < splitWork(tmp_len); i++){
|
| 52 |
+
uint32_t idx = i*bs+tid;
|
| 53 |
+
if(idx >= bs*p.s0 && idx < tmp_len){
|
| 54 |
+
tmp[idx-bs*p.s0] = tmp[idx];
|
| 55 |
+
tmp[idx] = 0.0;
|
| 56 |
+
}else if(idx >= p.K && idx < bs*p.s0){
|
| 57 |
+
tmp[idx] = 0.0;
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
barrier();
|
| 62 |
+
|
| 63 |
+
// Save contributions of the block to tmp
|
| 64 |
+
uint32_t L_idx = L_block_id*bs + tid;
|
| 65 |
+
for(uint32_t K_idx = 0; K_idx < p.K; K_idx++){
|
| 66 |
+
D_TYPE dp = 0.0;
|
| 67 |
+
for(uint32_t Cin_idx = 0; Cin_idx < p.Cin; Cin_idx++){
|
| 68 |
+
A_TYPE elemKrn = data_a[K_idx + Cout_idx * p.nb01 + Cin_idx * p.nb02];
|
| 69 |
+
if(L_idx < p.L){
|
| 70 |
+
B_TYPE elemInp = data_b[L_idx + Cin_idx*p.nb11];
|
| 71 |
+
dp = fma(elemKrn, elemInp, dp);
|
| 72 |
+
}
|
| 73 |
+
}
|
| 74 |
+
tmp[tid*p.s0 + K_idx] += dp;
|
| 75 |
+
barrier();
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
// Save the computed values except the last block that can have different size
|
| 79 |
+
uint32_t KLb_idx = L_block_id*bs*p.s0;
|
| 80 |
+
if(L_block_id < L_blocks-1){
|
| 81 |
+
for(uint32_t s0_idx = 0; s0_idx < p.s0; s0_idx++){
|
| 82 |
+
uint32_t sh_idx = p.s0*tid+s0_idx;
|
| 83 |
+
uint32_t KL_idx = KLb_idx+sh_idx;
|
| 84 |
+
if(KL_idx < p.KL){
|
| 85 |
+
data_d[KL_idx + Cout_idx*p.nb1] = tmp[sh_idx];
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
for(uint32_t i = 0; i < splitWork(tmp_len); i++){
|
| 92 |
+
uint32_t idx = i*bs+tid;
|
| 93 |
+
uint32_t KL_idx = (L_blocks-1)*bs*p.s0+idx;
|
| 94 |
+
if(KL_idx < p.KL){
|
| 95 |
+
data_d[KL_idx + Cout_idx*p.nb1] = tmp[idx];
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy.comp
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "generic_unary_head.glsl"
|
| 5 |
+
|
| 6 |
+
layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
|
| 7 |
+
|
| 8 |
+
void main() {
|
| 9 |
+
const uint idx = get_idx();
|
| 10 |
+
|
| 11 |
+
if (idx >= p.ne) {
|
| 12 |
+
return;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
#if defined(DATA_A_BF16)
|
| 16 |
+
data_d[get_doffset() + dst_idx(idx)] = D_TYPE(bf16_to_fp32(uint32_t(data_a[get_aoffset() + src0_idx(idx)])));
|
| 17 |
+
#elif defined(DATA_D_BF16)
|
| 18 |
+
float f = float(data_a[get_aoffset() + src0_idx(idx)]);
|
| 19 |
+
data_d[get_doffset() + dst_idx(idx)] = D_TYPE(fp32_to_bf16(f));
|
| 20 |
+
#elif !defined(OPTIMIZATION_ERROR_WORKAROUND)
|
| 21 |
+
data_d[get_doffset() + dst_idx(idx)] = D_TYPE(data_a[get_aoffset() + src0_idx(idx)]);
|
| 22 |
+
#else
|
| 23 |
+
data_d[get_doffset() + dst_idx(idx)] = data_a[get_aoffset() + src0_idx(idx)];
|
| 24 |
+
#endif
|
| 25 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "generic_unary_head.glsl"
|
| 5 |
+
#include "dequant_funcs.glsl"
|
| 6 |
+
|
| 7 |
+
#if defined(DATA_A_IQ4_NL) || defined(DATA_A_MXFP4) || defined(DATA_A_NVFP4)
|
| 8 |
+
// 16 invocations needed for init_iq_shmem
|
| 9 |
+
layout(local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
|
| 10 |
+
#else
|
| 11 |
+
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
| 12 |
+
#endif
|
| 13 |
+
|
| 14 |
+
void main() {
|
| 15 |
+
#ifdef NEEDS_INIT_IQ_SHMEM
|
| 16 |
+
init_iq_shmem(gl_WorkGroupSize);
|
| 17 |
+
if (gl_LocalInvocationIndex.x != 0) {
|
| 18 |
+
return;
|
| 19 |
+
}
|
| 20 |
+
#endif
|
| 21 |
+
|
| 22 |
+
const uint idx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * QUANT_K;
|
| 23 |
+
|
| 24 |
+
if (idx >= p.ne) {
|
| 25 |
+
return;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
uint dst_idx = get_doffset() + dst_idx(idx);
|
| 29 |
+
uint src_idx = src0_idx_quant(idx, QUANT_K);
|
| 30 |
+
|
| 31 |
+
const uint a_offset = 0;
|
| 32 |
+
const uint ib = src_idx;
|
| 33 |
+
const vec2 dm = get_dm(ib, a_offset);
|
| 34 |
+
|
| 35 |
+
[[unroll]] for (int j = 0; j < QUANT_K; j += 4) {
|
| 36 |
+
vec4 v = dequantize4(ib, j / QUANT_R, a_offset);
|
| 37 |
+
v = v * dm.x + vec4(dm.y);
|
| 38 |
+
|
| 39 |
+
#if QUANT_R == 2
|
| 40 |
+
data_d[dst_idx + j/2 + 0] = v[0];
|
| 41 |
+
data_d[dst_idx + j/2 + QUANT_K/2 + 0] = v[1];
|
| 42 |
+
data_d[dst_idx + j/2 + 1] = v[2];
|
| 43 |
+
data_d[dst_idx + j/2 + QUANT_K/2 + 1] = v[3];
|
| 44 |
+
#else
|
| 45 |
+
data_d[dst_idx + j + 0] = v[0];
|
| 46 |
+
data_d[dst_idx + j + 1] = v[1];
|
| 47 |
+
data_d[dst_idx + j + 2] = v[2];
|
| 48 |
+
data_d[dst_idx + j + 3] = v[3];
|
| 49 |
+
#endif
|
| 50 |
+
}
|
| 51 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
|
| 5 |
+
#if defined(SET_ROWS) && QUANT_K == 1
|
| 6 |
+
layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
|
| 7 |
+
const uint BLOCK_SIZE = 512;
|
| 8 |
+
#else
|
| 9 |
+
layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
|
| 10 |
+
const uint BLOCK_SIZE = 32;
|
| 11 |
+
#endif
|
| 12 |
+
|
| 13 |
+
layout (binding = 0) readonly buffer S {float data_s[];};
|
| 14 |
+
|
| 15 |
+
#if defined(SET_ROWS)
|
| 16 |
+
#include "generic_binary_head.glsl"
|
| 17 |
+
layout (binding = 1) readonly buffer C {B_TYPE data_i[];};
|
| 18 |
+
layout (binding = 2) writeonly buffer Q {A_TYPE data_q[];};
|
| 19 |
+
|
| 20 |
+
#if B_SIZE == 64
|
| 21 |
+
#define DATA_I_SWIZZLE .x
|
| 22 |
+
#else
|
| 23 |
+
#define DATA_I_SWIZZLE
|
| 24 |
+
#endif
|
| 25 |
+
|
| 26 |
+
#else
|
| 27 |
+
#include "generic_unary_head.glsl"
|
| 28 |
+
layout (binding = 1) writeonly buffer Q {A_TYPE data_q[];};
|
| 29 |
+
#endif
|
| 30 |
+
|
| 31 |
+
#if defined(DATA_A_Q4_0)
|
| 32 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 33 |
+
{
|
| 34 |
+
float amax = 0.0;
|
| 35 |
+
float vmax = 0.0;
|
| 36 |
+
|
| 37 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q4_0; ++j) {
|
| 38 |
+
const float v = data_s[src_idx + j];
|
| 39 |
+
if (amax < abs(v)) {
|
| 40 |
+
amax = abs(v);
|
| 41 |
+
vmax = v;
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
const float d = vmax / -8;
|
| 46 |
+
const float id = (d != 0.0) ? 1.0/d : 0.0;
|
| 47 |
+
|
| 48 |
+
data_q[dst_idx].d = float16_t(d);
|
| 49 |
+
|
| 50 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q4_0/2; ++j) {
|
| 51 |
+
const float x0 = data_s[src_idx + 0 + j]*id;
|
| 52 |
+
const float x1 = data_s[src_idx + QUANT_K_Q4_0/2 + j]*id;
|
| 53 |
+
|
| 54 |
+
const uint xi0 = min(15, int(x0 + 8.5));
|
| 55 |
+
const uint xi1 = min(15, int(x1 + 8.5));
|
| 56 |
+
|
| 57 |
+
data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4));
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
#endif
|
| 61 |
+
|
| 62 |
+
#if defined(DATA_A_Q4_1)
|
| 63 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 64 |
+
{
|
| 65 |
+
float vmin = 1.0/0.0;
|
| 66 |
+
float vmax = -vmin;
|
| 67 |
+
|
| 68 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q4_1; ++j) {
|
| 69 |
+
const float v = data_s[src_idx + j];
|
| 70 |
+
|
| 71 |
+
if (v < vmin) vmin = v;
|
| 72 |
+
if (v > vmax) vmax = v;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
const float d = (vmax - vmin) / ((1 << 4) - 1);
|
| 76 |
+
const float id = (d != 0.0) ? 1.0/d : 0.0;
|
| 77 |
+
|
| 78 |
+
data_q[dst_idx].d = float16_t(d);
|
| 79 |
+
data_q[dst_idx].m = float16_t(vmin);
|
| 80 |
+
|
| 81 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q4_1/2; ++j) {
|
| 82 |
+
const float x0 = (data_s[src_idx + 0 + j] - vmin)*id;
|
| 83 |
+
const float x1 = (data_s[src_idx + QUANT_K_Q4_1/2 + j] - vmin)*id;
|
| 84 |
+
|
| 85 |
+
const uint xi0 = min(15, int(x0 + 0.5));
|
| 86 |
+
const uint xi1 = min(15, int(x1 + 0.5));
|
| 87 |
+
|
| 88 |
+
data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4));
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
#endif
|
| 92 |
+
|
| 93 |
+
#if defined(DATA_A_Q5_0)
|
| 94 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 95 |
+
{
|
| 96 |
+
float amax = 0.0;
|
| 97 |
+
float vmax = 0.0;
|
| 98 |
+
|
| 99 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q5_0; ++j) {
|
| 100 |
+
const float v = data_s[src_idx + j];
|
| 101 |
+
if (amax < abs(v)) {
|
| 102 |
+
amax = abs(v);
|
| 103 |
+
vmax = v;
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
const float d = vmax / -16;
|
| 108 |
+
const float id = (d != 0.0) ? 1.0/d : 0.0;
|
| 109 |
+
|
| 110 |
+
data_q[dst_idx].d = float16_t(d);
|
| 111 |
+
|
| 112 |
+
uint32_t qh = 0;
|
| 113 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q5_0/2; ++j) {
|
| 114 |
+
const float x0 = data_s[src_idx + 0 + j]*id;
|
| 115 |
+
const float x1 = data_s[src_idx + QUANT_K_Q5_0/2 + j]*id;
|
| 116 |
+
|
| 117 |
+
const uint xi0 = min(31, int(x0 + 16.5));
|
| 118 |
+
const uint xi1 = min(31, int(x1 + 16.5));
|
| 119 |
+
|
| 120 |
+
data_q[dst_idx].qs[j] = uint8_t((xi0 & 0xf) | ((xi1 & 0xf) << 4));
|
| 121 |
+
qh |= ((xi0 & 0x10u) >> 4) << (j + 0);
|
| 122 |
+
qh |= ((xi1 & 0x10u) >> 4) << (j + QUANT_K_Q5_0/2);
|
| 123 |
+
}
|
| 124 |
+
data_q[dst_idx].qh[0] = uint16_t(qh & 0xFFFF);
|
| 125 |
+
data_q[dst_idx].qh[1] = uint16_t(qh >> 16);
|
| 126 |
+
}
|
| 127 |
+
#endif
|
| 128 |
+
|
| 129 |
+
#if defined(DATA_A_Q5_1)
|
| 130 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 131 |
+
{
|
| 132 |
+
float min = data_s[src_idx + 0];
|
| 133 |
+
float max = min;
|
| 134 |
+
|
| 135 |
+
[[unroll]] for (int j = 1; j < QUANT_K_Q5_1; ++j) {
|
| 136 |
+
const float v = data_s[src_idx + j];
|
| 137 |
+
min = v < min ? v : min;
|
| 138 |
+
max = v > max ? v : max;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
const float d = (max - min) / 31;
|
| 142 |
+
const float id = (d != 0) ? 1.0/d : 0.0;
|
| 143 |
+
|
| 144 |
+
data_q[dst_idx].d = float16_t(d);
|
| 145 |
+
data_q[dst_idx].m = float16_t(min);
|
| 146 |
+
|
| 147 |
+
uint32_t qh = 0;
|
| 148 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q5_1/2; ++j) {
|
| 149 |
+
const float x0 = (data_s[src_idx + 0 + j] - min)*id;
|
| 150 |
+
const float x1 = (data_s[src_idx + QUANT_K_Q5_1/2 + j] - min)*id;
|
| 151 |
+
|
| 152 |
+
const uint xi0 = uint(x0 + 0.5);
|
| 153 |
+
const uint xi1 = uint(x1 + 0.5);
|
| 154 |
+
|
| 155 |
+
data_q[dst_idx].qs[j] = uint8_t((xi0 & 0xf) | ((xi1 & 0xf) << 4));
|
| 156 |
+
qh |= ((xi0 & 0x10u) >> 4) << (j + 0);
|
| 157 |
+
qh |= ((xi1 & 0x10u) >> 4) << (j + QUANT_K_Q5_1/2);
|
| 158 |
+
}
|
| 159 |
+
data_q[dst_idx].qh = qh;
|
| 160 |
+
}
|
| 161 |
+
#endif
|
| 162 |
+
|
| 163 |
+
#if defined(DATA_A_Q8_0)
|
| 164 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 165 |
+
{
|
| 166 |
+
float amax = 0.0; // absolute max
|
| 167 |
+
|
| 168 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q8_0; j++) {
|
| 169 |
+
const float v = data_s[src_idx + j];
|
| 170 |
+
amax = max(amax, abs(v));
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
const float d = amax / ((1 << 7) - 1);
|
| 174 |
+
const float id = (d != 0.0) ? 1.0/d : 0.0;
|
| 175 |
+
|
| 176 |
+
data_q[dst_idx].d = float16_t(d);
|
| 177 |
+
|
| 178 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q8_0; ++j) {
|
| 179 |
+
const float x0 = data_s[src_idx + j]*id;
|
| 180 |
+
|
| 181 |
+
data_q[dst_idx].qs[j] = int8_t(round(x0));
|
| 182 |
+
}
|
| 183 |
+
}
|
| 184 |
+
#endif
|
| 185 |
+
|
| 186 |
+
#if defined(DATA_A_Q1_0)
|
| 187 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 188 |
+
{
|
| 189 |
+
float sum_abs = 0.0;
|
| 190 |
+
|
| 191 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q1_0; j++) {
|
| 192 |
+
sum_abs += abs(data_s[src_idx + j]);
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
const float d = sum_abs / QUANT_K_Q1_0;
|
| 196 |
+
|
| 197 |
+
data_q[dst_idx].d = float16_t(d);
|
| 198 |
+
|
| 199 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q1_0 / 8; ++j) {
|
| 200 |
+
data_q[dst_idx].qs[j] = uint8_t(0);
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
[[unroll]] for (int j = 0; j < QUANT_K_Q1_0; ++j) {
|
| 204 |
+
if (data_s[src_idx + j] >= 0.0) {
|
| 205 |
+
data_q[dst_idx].qs[j / 8] |= uint8_t(1 << (j % 8));
|
| 206 |
+
}
|
| 207 |
+
}
|
| 208 |
+
}
|
| 209 |
+
#endif
|
| 210 |
+
|
| 211 |
+
#if defined(DATA_A_IQ4_NL)
|
| 212 |
+
uint best_index(float x) {
|
| 213 |
+
if (x <= kvalues_iq4nl[0]) return 0;
|
| 214 |
+
if (x >= kvalues_iq4nl[15]) return 15;
|
| 215 |
+
int ml = 0, mu = 15;
|
| 216 |
+
while (mu-ml > 1) {
|
| 217 |
+
int mav = (ml+mu)/2;
|
| 218 |
+
if (x < kvalues_iq4nl[mav]) mu = mav; else ml = mav;
|
| 219 |
+
}
|
| 220 |
+
return x - kvalues_iq4nl[mu-1] < kvalues_iq4nl[mu] - x ? mu-1 : mu;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 224 |
+
{
|
| 225 |
+
float amax = 0.0;
|
| 226 |
+
float vmax = 0.0;
|
| 227 |
+
|
| 228 |
+
[[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL; ++j) {
|
| 229 |
+
const float v = data_s[src_idx + j];
|
| 230 |
+
if (amax < abs(v)) {
|
| 231 |
+
amax = abs(v);
|
| 232 |
+
vmax = v;
|
| 233 |
+
}
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
float d = vmax / kvalues_iq4nl[0];
|
| 237 |
+
const float id = (d != 0.0) ? 1.0/d : 0.0;
|
| 238 |
+
|
| 239 |
+
float sumqx = 0, sumq2 = 0;
|
| 240 |
+
[[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL/2; ++j) {
|
| 241 |
+
const float x0 = data_s[src_idx + 0 + j]*id;
|
| 242 |
+
const float x1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*id;
|
| 243 |
+
const uint xi0 = best_index(x0);
|
| 244 |
+
const uint xi1 = best_index(x1);
|
| 245 |
+
data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4));
|
| 246 |
+
const float v0 = kvalues_iq4nl[xi0];
|
| 247 |
+
const float v1 = kvalues_iq4nl[xi1];
|
| 248 |
+
const float w0 = data_s[src_idx + 0 + j]*data_s[src_idx + 0 + j];
|
| 249 |
+
const float w1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*data_s[src_idx + QUANT_K_IQ4_NL/2 + j];
|
| 250 |
+
sumqx += w0*v0*data_s[src_idx + j] + w1*v1*data_s[src_idx + QUANT_K_IQ4_NL/2 + j];
|
| 251 |
+
sumq2 += w0*v0*v0 + w1*v1*v1;
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
data_q[dst_idx].d = float16_t(sumq2 > 0 ? sumqx/sumq2 : d);
|
| 255 |
+
|
| 256 |
+
}
|
| 257 |
+
#endif
|
| 258 |
+
|
| 259 |
+
#if defined(DATA_A_F32) || defined(DATA_A_F16)
|
| 260 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 261 |
+
{
|
| 262 |
+
data_q[dst_idx] = A_TYPE(data_s[src_idx]);
|
| 263 |
+
}
|
| 264 |
+
#endif
|
| 265 |
+
|
| 266 |
+
#if defined(DATA_A_BF16)
|
| 267 |
+
void quantize(uint dst_idx, uint src_idx)
|
| 268 |
+
{
|
| 269 |
+
data_q[dst_idx] = A_TYPE(fp32_to_bf16(data_s[src_idx]));
|
| 270 |
+
}
|
| 271 |
+
#endif
|
| 272 |
+
|
| 273 |
+
#if defined(SET_ROWS)
|
| 274 |
+
|
| 275 |
+
void main() {
|
| 276 |
+
#ifdef NEEDS_INIT_IQ_SHMEM
|
| 277 |
+
init_iq_shmem(gl_WorkGroupSize);
|
| 278 |
+
#endif
|
| 279 |
+
|
| 280 |
+
const uint idx = ((gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x) * BLOCK_SIZE + gl_LocalInvocationID.x) * QUANT_K;
|
| 281 |
+
|
| 282 |
+
if (idx >= p.ne) {
|
| 283 |
+
return;
|
| 284 |
+
}
|
| 285 |
+
|
| 286 |
+
uint i00, i01, i02, i03;
|
| 287 |
+
get_indices(idx, i00, i01, i02, i03);
|
| 288 |
+
|
| 289 |
+
uint i12 = fastmod(i03, p.ne12);
|
| 290 |
+
uint i11 = fastmod(i02, p.ne11);
|
| 291 |
+
uint i10 = i01;
|
| 292 |
+
|
| 293 |
+
uint i1 = data_i[src1_idx(i10, i11, i12, 0) + get_boffset()] DATA_I_SWIZZLE;
|
| 294 |
+
|
| 295 |
+
uint src0_idx = src0_idx(i00, i01, i02, i03) + get_aoffset();
|
| 296 |
+
uint dst_idx = dst_idx(i00 / QUANT_K, i1, i02, i03) + get_doffset();
|
| 297 |
+
|
| 298 |
+
quantize(dst_idx, src0_idx);
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
#else
|
| 302 |
+
|
| 303 |
+
void main() {
|
| 304 |
+
#ifdef NEEDS_INIT_IQ_SHMEM
|
| 305 |
+
init_iq_shmem(gl_WorkGroupSize);
|
| 306 |
+
#endif
|
| 307 |
+
|
| 308 |
+
const uint idx = (gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x) * QUANT_K;
|
| 309 |
+
|
| 310 |
+
if (idx >= p.ne) {
|
| 311 |
+
return;
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
uint dst_idx = dst_idx_quant(idx, QUANT_K);
|
| 315 |
+
uint src_idx = get_aoffset() + src0_idx(idx);
|
| 316 |
+
|
| 317 |
+
quantize(dst_idx, src_idx);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
#endif
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_transpose.comp
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "generic_unary_head.glsl"
|
| 5 |
+
|
| 6 |
+
// workgroup does 32x32 tile, but uses 32x8 threads
|
| 7 |
+
#define TILE_DIM 32
|
| 8 |
+
layout(local_size_x = 32, local_size_y = 8, local_size_z = 1) in;
|
| 9 |
+
|
| 10 |
+
shared uint sh[TILE_DIM][TILE_DIM + 1];
|
| 11 |
+
|
| 12 |
+
void iter(uvec3 wg_id) {
|
| 13 |
+
const uint tile_col = wg_id.x;
|
| 14 |
+
const uint tile_row = wg_id.y;
|
| 15 |
+
|
| 16 |
+
const uint tid_col = gl_LocalInvocationID.x;
|
| 17 |
+
const uint tid_row = gl_LocalInvocationID.y;
|
| 18 |
+
|
| 19 |
+
const uint i2 = wg_id.z % p.ne12;
|
| 20 |
+
const uint i3 = wg_id.z / p.ne12;
|
| 21 |
+
const uint i02 = i2;
|
| 22 |
+
const uint i03 = i3;
|
| 23 |
+
|
| 24 |
+
// The workgroup does TILE_DIM x TILE_DIM, but swaps the LSBs of the
|
| 25 |
+
// src coords to make memory accesses contiguous, dst has tid.x in i0,
|
| 26 |
+
// src has tid.x in i01
|
| 27 |
+
|
| 28 |
+
[[unroll]] for (uint y = 0; y < 4; ++y) {
|
| 29 |
+
const uint i00 = tile_col * TILE_DIM + tid_row + 8 * y;
|
| 30 |
+
const uint i01 = tile_row * TILE_DIM + tid_col;
|
| 31 |
+
if (i00 < p.ne00 && i01 < p.ne01 && i02 < p.ne02 && i03 < p.ne03) {
|
| 32 |
+
const uint src_idx = i00 * p.nb00 + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
|
| 33 |
+
sh[tid_row + 8 * y][tid_col] = uint(data_a[get_aoffset() + src_idx]);
|
| 34 |
+
}
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
barrier();
|
| 38 |
+
|
| 39 |
+
[[unroll]] for (uint y = 0; y < 4; ++y) {
|
| 40 |
+
const uint i0 = tile_col * TILE_DIM + tid_col;
|
| 41 |
+
const uint i1 = tile_row * TILE_DIM + tid_row + 8 * y;
|
| 42 |
+
if (i0 < p.ne10 && i1 < p.ne11 && i2 < p.ne12 && i3 < p.ne13) {
|
| 43 |
+
const uint dst_idx = i0 * p.nb10 + i1 * p.nb11 + i2 * p.nb12 + i3 * p.nb13;
|
| 44 |
+
// load transposed
|
| 45 |
+
data_d[get_doffset() + dst_idx] = D_TYPE(sh[tid_col][tid_row + 8 * y]);
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
|
| 51 |
+
|
| 52 |
+
void main() {
|
| 53 |
+
uint z = gl_WorkGroupID.z;
|
| 54 |
+
uint y = gl_WorkGroupID.y;
|
| 55 |
+
bool need_barrier = false;
|
| 56 |
+
for (uint z = gl_WorkGroupID.z; z < p.ne12 * p.ne13; z += gl_NumWorkGroups.z) {
|
| 57 |
+
for (uint y = gl_WorkGroupID.y; y < CEIL_DIV(p.ne11, TILE_DIM); y += gl_NumWorkGroups.y) {
|
| 58 |
+
for (uint x = gl_WorkGroupID.x; x < CEIL_DIV(p.ne10, TILE_DIM); x += gl_NumWorkGroups.x) {
|
| 59 |
+
if (need_barrier) {
|
| 60 |
+
barrier();
|
| 61 |
+
}
|
| 62 |
+
need_barrier = true;
|
| 63 |
+
iter(uvec3(x, y, z));
|
| 64 |
+
}
|
| 65 |
+
}
|
| 66 |
+
}
|
| 67 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_equal.comp
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 4 |
+
|
| 5 |
+
#include "types.glsl"
|
| 6 |
+
#include "generic_head.glsl"
|
| 7 |
+
|
| 8 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 9 |
+
|
| 10 |
+
layout (binding = 0) readonly buffer X {A_TYPE data_a[];};
|
| 11 |
+
layout (binding = 1) readonly buffer Y {B_TYPE data_b[];};
|
| 12 |
+
layout (binding = 2) buffer D {D_TYPE data_d[];};
|
| 13 |
+
|
| 14 |
+
const uint CHUNK_SIZE = 512;
|
| 15 |
+
|
| 16 |
+
void main() {
|
| 17 |
+
const uint base = gl_WorkGroupID.x * CHUNK_SIZE;
|
| 18 |
+
const uint col = gl_LocalInvocationID.x;
|
| 19 |
+
|
| 20 |
+
uint count = 0;
|
| 21 |
+
[[unroll]]
|
| 22 |
+
for (uint i = 0; i < CHUNK_SIZE; i += gl_WorkGroupSize.x) {
|
| 23 |
+
const uint idx = base + i + col;
|
| 24 |
+
if (idx >= p.KX) {
|
| 25 |
+
break;
|
| 26 |
+
}
|
| 27 |
+
count += uint(data_a[idx] == data_b[idx]);
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
atomicAdd(data_d[0], D_TYPE(count));
|
| 31 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_experts.comp
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 4 |
+
|
| 5 |
+
#include "types.glsl"
|
| 6 |
+
|
| 7 |
+
layout (push_constant) uniform parameter
|
| 8 |
+
{
|
| 9 |
+
uint32_t ne00;
|
| 10 |
+
uint32_t ne01;
|
| 11 |
+
uint32_t nb00;
|
| 12 |
+
uint32_t nb01;
|
| 13 |
+
uint32_t a_offset;
|
| 14 |
+
} p;
|
| 15 |
+
|
| 16 |
+
#define BLOCK_SIZE 256
|
| 17 |
+
|
| 18 |
+
layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in;
|
| 19 |
+
|
| 20 |
+
layout (binding = 0) readonly buffer A {uint data_a[];};
|
| 21 |
+
layout (binding = 1) writeonly buffer D {uint data_d[];};
|
| 22 |
+
|
| 23 |
+
shared uint vals[BLOCK_SIZE];
|
| 24 |
+
|
| 25 |
+
void main() {
|
| 26 |
+
const uint expert_id = gl_WorkGroupID.x;
|
| 27 |
+
const uint num_elements = p.ne00 * p.ne01;
|
| 28 |
+
const uint tid = gl_LocalInvocationID.x;
|
| 29 |
+
|
| 30 |
+
uint count = 0;
|
| 31 |
+
for (uint idx = tid; idx < num_elements; idx += BLOCK_SIZE) {
|
| 32 |
+
const uint i01 = idx / p.ne00;
|
| 33 |
+
const uint i00 = idx % p.ne00;
|
| 34 |
+
const uint a = data_a[p.a_offset + i01 * p.nb01 + i00 * p.nb00];
|
| 35 |
+
|
| 36 |
+
count += uint(a == expert_id);
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
vals[tid] = count;
|
| 40 |
+
barrier();
|
| 41 |
+
[[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) {
|
| 42 |
+
if (tid < s) {
|
| 43 |
+
vals[tid] += vals[tid + s];
|
| 44 |
+
}
|
| 45 |
+
barrier();
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
if (tid == 0) {
|
| 49 |
+
data_d[expert_id] = vals[0];
|
| 50 |
+
}
|
| 51 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum.comp
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "sum_rows.glsl"
|
| 5 |
+
|
| 6 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 7 |
+
#extension GL_KHR_shader_subgroup_arithmetic : enable
|
| 8 |
+
#extension GL_KHR_shader_subgroup_basic : enable
|
| 9 |
+
|
| 10 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 11 |
+
|
| 12 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
|
| 13 |
+
layout (binding = 1) writeonly buffer D {D_TYPE data_d[];};
|
| 14 |
+
|
| 15 |
+
layout (constant_id = 0) const uint BLOCK_SIZE = 128;
|
| 16 |
+
layout (constant_id = 1) const uint SUBGROUP_SIZE = 32;
|
| 17 |
+
layout (constant_id = 2) const uint ELEM_PER_THREAD = 4;
|
| 18 |
+
|
| 19 |
+
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
|
| 20 |
+
|
| 21 |
+
shared FLOAT_TYPE partial[BLOCK_SIZE / SUBGROUP_SIZE];
|
| 22 |
+
shared FLOAT_TYPE last_sum;
|
| 23 |
+
|
| 24 |
+
void main() {
|
| 25 |
+
const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x;
|
| 26 |
+
const uint tid = gl_LocalInvocationID.x;
|
| 27 |
+
|
| 28 |
+
const uint i03 = fastdiv(row, p.ne0_12mp, p.ne0_12L);
|
| 29 |
+
const uint i03_offset = i03 * p.ne01*p.ne02;
|
| 30 |
+
const uint i02 = fastdiv(row - i03_offset, p.ne0_1mp, p.ne0_1L);
|
| 31 |
+
const uint i01 = row - i03_offset - i02*p.ne01;
|
| 32 |
+
|
| 33 |
+
const uint src_idx = get_aoffset() + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
|
| 34 |
+
const uint dst_idx = get_doffset() + i01 * p.nb11 + i02 * p.nb12 + i03 * p.nb13;
|
| 35 |
+
|
| 36 |
+
uint subgroup_id = tid / SUBGROUP_SIZE;
|
| 37 |
+
|
| 38 |
+
if (tid == 0) {
|
| 39 |
+
last_sum = 0;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
uint col = tid * ELEM_PER_THREAD;
|
| 43 |
+
uint num_iter = CEIL_DIV(p.n_cols, BLOCK_SIZE * ELEM_PER_THREAD);
|
| 44 |
+
for (int i = 0; i < num_iter; ++i) {
|
| 45 |
+
FLOAT_TYPE v[ELEM_PER_THREAD];
|
| 46 |
+
FLOAT_TYPE thread_sum = 0;
|
| 47 |
+
[[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
|
| 48 |
+
if (col + j < p.n_cols) {
|
| 49 |
+
thread_sum += FLOAT_TYPE(data_a[src_idx + col + j]);
|
| 50 |
+
}
|
| 51 |
+
v[j] = thread_sum;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
thread_sum = subgroupExclusiveAdd(thread_sum);
|
| 55 |
+
[[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
|
| 56 |
+
v[j] += thread_sum;
|
| 57 |
+
}
|
| 58 |
+
// Store the largest partial sum for each subgroup, then add the partials for all
|
| 59 |
+
// lower subgroups and the final partial sum from the previous iteration.
|
| 60 |
+
if (gl_SubgroupInvocationID == SUBGROUP_SIZE - 1) {
|
| 61 |
+
partial[subgroup_id] = v[ELEM_PER_THREAD - 1];
|
| 62 |
+
}
|
| 63 |
+
barrier();
|
| 64 |
+
for (int s = 0; s < subgroup_id; ++s) {
|
| 65 |
+
[[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
|
| 66 |
+
v[j] += partial[s];
|
| 67 |
+
}
|
| 68 |
+
}
|
| 69 |
+
[[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
|
| 70 |
+
v[j] += last_sum;
|
| 71 |
+
}
|
| 72 |
+
barrier();
|
| 73 |
+
if (tid == BLOCK_SIZE - 1) {
|
| 74 |
+
last_sum = v[ELEM_PER_THREAD - 1];
|
| 75 |
+
}
|
| 76 |
+
[[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
|
| 77 |
+
if (col + j < p.n_cols) {
|
| 78 |
+
data_d[dst_idx + col + j] = D_TYPE(v[j]);
|
| 79 |
+
}
|
| 80 |
+
}
|
| 81 |
+
col += BLOCK_SIZE * ELEM_PER_THREAD;
|
| 82 |
+
}
|
| 83 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass1.comp
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "sum_rows.glsl"
|
| 5 |
+
|
| 6 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 7 |
+
#extension GL_KHR_shader_subgroup_arithmetic : enable
|
| 8 |
+
#extension GL_KHR_shader_subgroup_basic : enable
|
| 9 |
+
|
| 10 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 11 |
+
|
| 12 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
|
| 13 |
+
layout (binding = 1) writeonly buffer D {D_TYPE data_d[];};
|
| 14 |
+
layout (binding = 2) writeonly buffer T {D_TYPE data_t[];};
|
| 15 |
+
|
| 16 |
+
layout (constant_id = 0) const uint BLOCK_SIZE = 128;
|
| 17 |
+
layout (constant_id = 1) const uint SUBGROUP_SIZE = 32;
|
| 18 |
+
|
| 19 |
+
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
|
| 20 |
+
|
| 21 |
+
shared FLOAT_TYPE partial[BLOCK_SIZE / SUBGROUP_SIZE];
|
| 22 |
+
|
| 23 |
+
void main() {
|
| 24 |
+
const uint row = gl_WorkGroupID.y;
|
| 25 |
+
const uint tid = gl_LocalInvocationID.x;
|
| 26 |
+
const uint col = gl_GlobalInvocationID.x;
|
| 27 |
+
|
| 28 |
+
const uint i03 = fastdiv(row, p.ne0_12mp, p.ne0_12L);
|
| 29 |
+
const uint i03_offset = i03 * p.ne01*p.ne02;
|
| 30 |
+
const uint i02 = fastdiv(row - i03_offset, p.ne0_1mp, p.ne0_1L);
|
| 31 |
+
const uint i01 = row - i03_offset - i02*p.ne01;
|
| 32 |
+
|
| 33 |
+
const uint src_idx = get_aoffset() + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
|
| 34 |
+
const uint dst_idx = get_doffset() + i01 * p.nb11 + i02 * p.nb12 + i03 * p.nb13;
|
| 35 |
+
|
| 36 |
+
uint subgroup_id = tid / SUBGROUP_SIZE;
|
| 37 |
+
|
| 38 |
+
FLOAT_TYPE v = 0;
|
| 39 |
+
if (col < p.n_cols) {
|
| 40 |
+
v = FLOAT_TYPE(data_a[src_idx + col]);
|
| 41 |
+
}
|
| 42 |
+
v = subgroupInclusiveAdd(v);
|
| 43 |
+
|
| 44 |
+
// Store the largest partial sum for each subgroup, then add the partials for all
|
| 45 |
+
// lower subgroups and the final partial sum from the previous iteration.
|
| 46 |
+
if (gl_SubgroupInvocationID == SUBGROUP_SIZE - 1) {
|
| 47 |
+
partial[subgroup_id] = v;
|
| 48 |
+
}
|
| 49 |
+
barrier();
|
| 50 |
+
for (int j = 0; j < subgroup_id; ++j) {
|
| 51 |
+
v += partial[j];
|
| 52 |
+
}
|
| 53 |
+
barrier();
|
| 54 |
+
if (tid == BLOCK_SIZE - 1) {
|
| 55 |
+
data_t[gl_WorkGroupID.x + gl_NumWorkGroups.x * row] = v;
|
| 56 |
+
}
|
| 57 |
+
if (col < p.n_cols) {
|
| 58 |
+
data_d[dst_idx + col] = D_TYPE(v);
|
| 59 |
+
}
|
| 60 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass2.comp
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "types.glsl"
|
| 4 |
+
#include "sum_rows.glsl"
|
| 5 |
+
|
| 6 |
+
#extension GL_EXT_control_flow_attributes : enable
|
| 7 |
+
#extension GL_KHR_shader_subgroup_arithmetic : enable
|
| 8 |
+
#extension GL_KHR_shader_subgroup_basic : enable
|
| 9 |
+
|
| 10 |
+
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
| 11 |
+
|
| 12 |
+
layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
|
| 13 |
+
layout (binding = 1) buffer D {D_TYPE data_d[];};
|
| 14 |
+
layout (binding = 2) readonly buffer T {D_TYPE data_t[];};
|
| 15 |
+
|
| 16 |
+
layout (constant_id = 0) const uint BLOCK_SIZE = 128;
|
| 17 |
+
layout (constant_id = 1) const uint SUBGROUP_SIZE = 32;
|
| 18 |
+
|
| 19 |
+
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
|
| 20 |
+
|
| 21 |
+
shared FLOAT_TYPE temp[BLOCK_SIZE / SUBGROUP_SIZE];
|
| 22 |
+
|
| 23 |
+
void main() {
|
| 24 |
+
const uint row = gl_WorkGroupID.y;
|
| 25 |
+
const uint tid = gl_LocalInvocationID.x;
|
| 26 |
+
|
| 27 |
+
const uint i03 = fastdiv(row, p.ne0_12mp, p.ne0_12L);
|
| 28 |
+
const uint i03_offset = i03 * p.ne01*p.ne02;
|
| 29 |
+
const uint i02 = fastdiv(row - i03_offset, p.ne0_1mp, p.ne0_1L);
|
| 30 |
+
const uint i01 = row - i03_offset - i02*p.ne01;
|
| 31 |
+
|
| 32 |
+
const uint src_idx = get_aoffset() + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
|
| 33 |
+
const uint dst_idx = get_doffset() + i01 * p.nb11 + i02 * p.nb12 + i03 * p.nb13;
|
| 34 |
+
|
| 35 |
+
const uint col = gl_GlobalInvocationID.x;
|
| 36 |
+
|
| 37 |
+
float v = 0;
|
| 38 |
+
// prefetch value we're adding to
|
| 39 |
+
if (col < p.n_cols) {
|
| 40 |
+
v = data_d[dst_idx + col];
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
// compute the sum of all previous blocks
|
| 44 |
+
uint c = tid;
|
| 45 |
+
float sum = 0;
|
| 46 |
+
while (c < gl_WorkGroupID.x) {
|
| 47 |
+
sum += data_t[c + gl_NumWorkGroups.x * row];
|
| 48 |
+
c += BLOCK_SIZE;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
sum = subgroupAdd(sum);
|
| 52 |
+
if (gl_SubgroupInvocationID == 0) {
|
| 53 |
+
temp[gl_SubgroupID] = sum;
|
| 54 |
+
}
|
| 55 |
+
barrier();
|
| 56 |
+
sum = 0;
|
| 57 |
+
[[unroll]] for (uint s = 0; s < BLOCK_SIZE / SUBGROUP_SIZE; ++s) {
|
| 58 |
+
sum += temp[s];
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// Add the sum to what the first pass computed
|
| 62 |
+
if (col < p.n_cols) {
|
| 63 |
+
data_d[dst_idx + col] = v + sum;
|
| 64 |
+
}
|
| 65 |
+
}
|
| 66 |
+
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_f32.comp
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "dequant_head.glsl"
|
| 4 |
+
|
| 5 |
+
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
| 6 |
+
|
| 7 |
+
layout (binding = 0) readonly buffer A {float data_a[];};
|
| 8 |
+
layout (binding = 1) writeonly buffer D {D_TYPE data_b[];};
|
| 9 |
+
|
| 10 |
+
void main() {
|
| 11 |
+
const uint i = gl_GlobalInvocationID.x * 16;
|
| 12 |
+
|
| 13 |
+
if (i >= p.nel) {
|
| 14 |
+
return;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
[[unroll]] for (uint l = 0; l < 16; l++) {
|
| 18 |
+
data_b[i + l] = D_TYPE(data_a[i + l]);
|
| 19 |
+
}
|
| 20 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl
ADDED
|
@@ -0,0 +1,692 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(DATA_A_F32) && !defined(DATA_A_F16)
|
| 2 |
+
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
|
| 3 |
+
#endif
|
| 4 |
+
|
| 5 |
+
#include "types.glsl"
|
| 6 |
+
|
| 7 |
+
#if defined(DATA_A_F32)
|
| 8 |
+
FLOAT_TYPE dequantize1(uint ib, uint iqs, uint a_offset) {
|
| 9 |
+
return data_a[a_offset + ib];
|
| 10 |
+
}
|
| 11 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 12 |
+
return vec2(data_a[a_offset + ib], data_a[a_offset + ib + 1]);
|
| 13 |
+
}
|
| 14 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 15 |
+
return vec4(data_a[a_offset + ib ], data_a[a_offset + ib + 1],
|
| 16 |
+
data_a[a_offset + ib + 2], data_a[a_offset + ib + 3]);
|
| 17 |
+
}
|
| 18 |
+
vec4 dequantize4_2aligned(uint ib, uint iqs, uint a_offset) {
|
| 19 |
+
return vec4(data_a[a_offset + ib ], data_a[a_offset + ib + 1],
|
| 20 |
+
data_a[a_offset + ib + 2], data_a[a_offset + ib + 3]);
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
#endif
|
| 24 |
+
|
| 25 |
+
#if defined(DATA_A_F16)
|
| 26 |
+
FLOAT_TYPE dequantize1(uint ib, uint iqs, uint a_offset) {
|
| 27 |
+
return data_a[a_offset + ib];
|
| 28 |
+
}
|
| 29 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 30 |
+
return vec2(data_a[a_offset + ib], data_a[a_offset + ib + 1]);
|
| 31 |
+
}
|
| 32 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 33 |
+
return vec4(data_a[a_offset + ib ], data_a[a_offset + ib + 1],
|
| 34 |
+
data_a[a_offset + ib + 2], data_a[a_offset + ib + 3]);
|
| 35 |
+
}
|
| 36 |
+
vec4 dequantize4_2aligned(uint ib, uint iqs, uint a_offset) {
|
| 37 |
+
const vec2 a = data_a_packed32[(a_offset + ib)/2];
|
| 38 |
+
const vec2 b = data_a_packed32[(a_offset + ib)/2 + 1];
|
| 39 |
+
return vec4(a, b);
|
| 40 |
+
}
|
| 41 |
+
#endif
|
| 42 |
+
|
| 43 |
+
#if defined(DATA_A_BF16)
|
| 44 |
+
FLOAT_TYPE dequantize1(uint ib, uint iqs, uint a_offset) {
|
| 45 |
+
return bf16_to_fp32(data_a[a_offset + ib]);
|
| 46 |
+
}
|
| 47 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 48 |
+
return vec2(bf16_to_fp32(data_a[a_offset + ib]), bf16_to_fp32(data_a[a_offset + ib + 1]));
|
| 49 |
+
}
|
| 50 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 51 |
+
return vec4(bf16_to_fp32(data_a[a_offset + ib ]), bf16_to_fp32(data_a[a_offset + ib + 1]),
|
| 52 |
+
bf16_to_fp32(data_a[a_offset + ib + 2]), bf16_to_fp32(data_a[a_offset + ib + 3]));
|
| 53 |
+
}
|
| 54 |
+
vec4 dequantize4_2aligned(uint ib, uint iqs, uint a_offset) {
|
| 55 |
+
const uint a = data_a_packed32[(a_offset + ib)/2];
|
| 56 |
+
const uint b = data_a_packed32[(a_offset + ib)/2 + 1];
|
| 57 |
+
return vec4(uintBitsToFloat((a & 0x0000ffff) << 16),
|
| 58 |
+
uintBitsToFloat( a & 0xffff0000),
|
| 59 |
+
uintBitsToFloat((b & 0x0000ffff) << 16),
|
| 60 |
+
uintBitsToFloat( b & 0xffff0000));
|
| 61 |
+
}
|
| 62 |
+
#endif
|
| 63 |
+
|
| 64 |
+
#if defined(DATA_A_Q4_0)
|
| 65 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 66 |
+
const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
|
| 67 |
+
return (vec2(vui & 0xF, vui >> 4) - 8.0f);
|
| 68 |
+
}
|
| 69 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 70 |
+
const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
|
| 71 |
+
return (vec4(vui & 0xF, (vui >> 4) & 0xF, (vui >> 8) & 0xF, vui >> 12) - 8.0f);
|
| 72 |
+
}
|
| 73 |
+
#endif
|
| 74 |
+
|
| 75 |
+
#if defined(DATA_A_Q4_1)
|
| 76 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 77 |
+
const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
|
| 78 |
+
return vec2(vui & 0xF, vui >> 4);
|
| 79 |
+
}
|
| 80 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 81 |
+
const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
|
| 82 |
+
return vec4(vui & 0xF, (vui >> 4) & 0xF, (vui >> 8) & 0xF, vui >> 12);
|
| 83 |
+
}
|
| 84 |
+
#endif
|
| 85 |
+
|
| 86 |
+
#if defined(DATA_A_Q5_0)
|
| 87 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 88 |
+
const uint uint_qh = uint(data_a[a_offset + ib].qh[1]) << 16 | data_a[a_offset + ib].qh[0];
|
| 89 |
+
const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
|
| 90 |
+
const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
|
| 91 |
+
return (vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y) - 16.0f);
|
| 92 |
+
}
|
| 93 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 94 |
+
const uint uint_qh = uint(data_a_packed16[a_offset + ib].qh[1]) << 16 | data_a_packed16[a_offset + ib].qh[0];
|
| 95 |
+
const ivec2 qh0 = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
|
| 96 |
+
const ivec2 qh1 = ivec2(((uint_qh >> (iqs + 1)) << 4) & 0x10, (uint_qh >> (iqs + 13)) & 0x10);
|
| 97 |
+
const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
|
| 98 |
+
return (vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y) - 16.0f);
|
| 99 |
+
}
|
| 100 |
+
#endif
|
| 101 |
+
|
| 102 |
+
#if defined(DATA_A_Q5_1)
|
| 103 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 104 |
+
const uint uint_qh = data_a[a_offset + ib].qh;
|
| 105 |
+
const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
|
| 106 |
+
const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
|
| 107 |
+
return vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y);
|
| 108 |
+
}
|
| 109 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 110 |
+
const uint uint_qh = data_a_packed16[a_offset + ib].qh;
|
| 111 |
+
const ivec2 qh0 = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
|
| 112 |
+
const ivec2 qh1 = ivec2(((uint_qh >> (iqs + 1)) << 4) & 0x10, (uint_qh >> (iqs + 13)) & 0x10);
|
| 113 |
+
const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
|
| 114 |
+
return vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y);
|
| 115 |
+
}
|
| 116 |
+
#endif
|
| 117 |
+
|
| 118 |
+
#if defined(DATA_A_Q8_0)
|
| 119 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 120 |
+
return vec2(int(data_a[a_offset + ib].qs[iqs]), int(data_a[a_offset + ib].qs[iqs + 1]));
|
| 121 |
+
}
|
| 122 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 123 |
+
const i8vec2 v0 = unpack8(int32_t(data_a_packed16[a_offset + ib].qs[iqs/2])).xy; // vec4 used due to #12147
|
| 124 |
+
const i8vec2 v1 = unpack8(int32_t(data_a_packed16[a_offset + ib].qs[iqs/2 + 1])).xy;
|
| 125 |
+
return vec4(v0.x, v0.y, v1.x, v1.y);
|
| 126 |
+
}
|
| 127 |
+
#endif
|
| 128 |
+
|
| 129 |
+
#if defined(DATA_A_Q1_0)
|
| 130 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 131 |
+
const uint bits = uint(data_a[a_offset + ib].qs[iqs / 8u]) >> (iqs % 8u);
|
| 132 |
+
return vec2(
|
| 133 |
+
(bits & 1u) != 0u ? 1.0f : -1.0f,
|
| 134 |
+
(bits & 2u) != 0u ? 1.0f : -1.0f);
|
| 135 |
+
}
|
| 136 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 137 |
+
const uint bits = uint(data_a[a_offset + ib].qs[iqs / 8u]) >> (iqs % 8u);
|
| 138 |
+
return vec4(
|
| 139 |
+
(bits & 1u) != 0u ? 1.0f : -1.0f,
|
| 140 |
+
(bits & 2u) != 0u ? 1.0f : -1.0f,
|
| 141 |
+
(bits & 4u) != 0u ? 1.0f : -1.0f,
|
| 142 |
+
(bits & 8u) != 0u ? 1.0f : -1.0f);
|
| 143 |
+
}
|
| 144 |
+
#endif
|
| 145 |
+
|
| 146 |
+
#if defined(DATA_A_IQ1_S)
|
| 147 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 148 |
+
const uint ib32 = iqs / 32;
|
| 149 |
+
const uint ib8 = iqs / 8;
|
| 150 |
+
const int i8 = int(iqs % 8);
|
| 151 |
+
const uint qh = data_a[a_offset + ib].qh[ib32];
|
| 152 |
+
const uint qs = data_a[a_offset + ib].qs[ib8];
|
| 153 |
+
const float dl = float(2 * bitfieldExtract(qh, 12, 3) + 1);
|
| 154 |
+
const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
|
| 155 |
+
const uint idxhi = bitfieldExtract(qh, 3 * int(ib8 & 3), 3);
|
| 156 |
+
const int16_t grid = int16_t(iq1s_grid[qs | (idxhi << 8)]);
|
| 157 |
+
// Signed bitfield extract.
|
| 158 |
+
const ivec2 gvec = ivec2(
|
| 159 |
+
bitfieldExtract(grid, 2 * (i8), 2),
|
| 160 |
+
bitfieldExtract(grid, 2 * (i8 + 1), 2)
|
| 161 |
+
);
|
| 162 |
+
return dl * (vec2(gvec) + delta);
|
| 163 |
+
}
|
| 164 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 165 |
+
const uint ib32 = iqs / 32;
|
| 166 |
+
const uint ib8 = iqs / 8;
|
| 167 |
+
const int i8 = int(iqs % 8);
|
| 168 |
+
const uint qh = data_a[a_offset + ib].qh[ib32];
|
| 169 |
+
const uint qs = data_a[a_offset + ib].qs[ib8];
|
| 170 |
+
const float dl = 2 * bitfieldExtract(qh, 12, 3) + 1;
|
| 171 |
+
const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
|
| 172 |
+
const int16_t grid = int16_t(iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)]);
|
| 173 |
+
// Signed bitfield extract.
|
| 174 |
+
const ivec4 gvec = ivec4(
|
| 175 |
+
bitfieldExtract(grid, 2 * (i8), 2),
|
| 176 |
+
bitfieldExtract(grid, 2 * (i8 + 1), 2),
|
| 177 |
+
bitfieldExtract(grid, 2 * (i8 + 2), 2),
|
| 178 |
+
bitfieldExtract(grid, 2 * (i8 + 3), 2)
|
| 179 |
+
);
|
| 180 |
+
return dl * (vec4(gvec) + delta);
|
| 181 |
+
}
|
| 182 |
+
#endif
|
| 183 |
+
|
| 184 |
+
#if defined(DATA_A_IQ1_M)
|
| 185 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 186 |
+
const uint ib8 = iqs / 8;
|
| 187 |
+
const uint ib16 = iqs / 16;
|
| 188 |
+
const int i8 = int(iqs % 8);
|
| 189 |
+
const uint sc = data_a[a_offset + ib].scales[iqs / 64];
|
| 190 |
+
const uint qs = data_a[a_offset + ib].qs[ib8];
|
| 191 |
+
const uint qh = data_a[a_offset + ib].qh[ib16] >> (4 * (ib8 & 1));
|
| 192 |
+
const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1;
|
| 193 |
+
const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA;
|
| 194 |
+
const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]);
|
| 195 |
+
// Signed bitfield extract.
|
| 196 |
+
const ivec2 gvec = ivec2(
|
| 197 |
+
bitfieldExtract(grid, 2 * (i8), 2),
|
| 198 |
+
bitfieldExtract(grid, 2 * (i8 + 1), 2)
|
| 199 |
+
);
|
| 200 |
+
return dl * (vec2(gvec) + delta);
|
| 201 |
+
}
|
| 202 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 203 |
+
const uint ib8 = iqs / 8;
|
| 204 |
+
const uint ib16 = iqs / 16;
|
| 205 |
+
const int i8 = int(iqs % 8);
|
| 206 |
+
const uint sc = data_a[a_offset + ib].scales[iqs / 64];
|
| 207 |
+
const uint qs = data_a[a_offset + ib].qs[ib8];
|
| 208 |
+
const uint qh = data_a[a_offset + ib].qh[ib16] >> (4 * (ib8 & 1));
|
| 209 |
+
const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1;
|
| 210 |
+
const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA;
|
| 211 |
+
const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]);
|
| 212 |
+
// Signed bitfield extract.
|
| 213 |
+
const ivec4 gvec = ivec4(
|
| 214 |
+
bitfieldExtract(grid, 2 * (i8), 2),
|
| 215 |
+
bitfieldExtract(grid, 2 * (i8 + 1), 2),
|
| 216 |
+
bitfieldExtract(grid, 2 * (i8 + 2), 2),
|
| 217 |
+
bitfieldExtract(grid, 2 * (i8 + 3), 2)
|
| 218 |
+
);
|
| 219 |
+
return dl * (vec4(gvec) + delta);
|
| 220 |
+
}
|
| 221 |
+
#endif
|
| 222 |
+
|
| 223 |
+
#if defined(DATA_A_IQ2_XXS)
|
| 224 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 225 |
+
const uint ib32 = iqs / 32;
|
| 226 |
+
const uint ib8 = (iqs / 8) % 4;
|
| 227 |
+
const uint qs = data_a[a_offset + ib].qs[8 * ib32 + ib8];
|
| 228 |
+
// Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale)
|
| 229 |
+
const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[4 * ib32 + 2],
|
| 230 |
+
data_a_packed16[a_offset + ib].qs[4 * ib32 + 3]));
|
| 231 |
+
const float db = 0.25 * (0.5 + (signs >> 28));
|
| 232 |
+
const uint sign7 = bitfieldExtract(signs, 7 * int(ib8), 7);
|
| 233 |
+
// Add parity bit
|
| 234 |
+
const uint sign8 = sign7 | (bitCount(sign7) << 7);
|
| 235 |
+
const uint sign = sign8 >> (iqs % 8);
|
| 236 |
+
const u8vec4 grid = unpack8(iq2xxs_grid[qs][(iqs % 8) / 4] >> (8 * (iqs % 4)));
|
| 237 |
+
bool sign0 = (sign & 1) != 0;
|
| 238 |
+
bool sign1 = (sign & 2) != 0;
|
| 239 |
+
return db * vec2(
|
| 240 |
+
grid.x * (sign0 ? -1.0 : 1.0),
|
| 241 |
+
grid.y * (sign1 ? -1.0 : 1.0)
|
| 242 |
+
);
|
| 243 |
+
}
|
| 244 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 245 |
+
const uint ib32 = iqs / 32;
|
| 246 |
+
const uint ib8 = (iqs / 8) % 4;
|
| 247 |
+
const uint qs = data_a[a_offset + ib].qs[8 * ib32 + ib8];
|
| 248 |
+
// Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale)
|
| 249 |
+
const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[4 * ib32 + 2],
|
| 250 |
+
data_a_packed16[a_offset + ib].qs[4 * ib32 + 3]));
|
| 251 |
+
const float db = 0.25 * (0.5 + (signs >> 28));
|
| 252 |
+
const uint sign7 = bitfieldExtract(signs, 7 * int(ib8), 7);
|
| 253 |
+
// Add parity bit
|
| 254 |
+
const uint sign8 = sign7 | (bitCount(sign7) << 7);
|
| 255 |
+
const uint sign = sign8 >> (iqs % 8);
|
| 256 |
+
const u8vec4 grid = unpack8(iq2xxs_grid[qs][(iqs % 8) / 4] >> (8 * (iqs % 4)));
|
| 257 |
+
bool sign0 = (sign & 1) != 0;
|
| 258 |
+
bool sign1 = (sign & 2) != 0;
|
| 259 |
+
bool sign2 = (sign & 4) != 0;
|
| 260 |
+
bool sign3 = (sign & 8) != 0;
|
| 261 |
+
return db * vec4(
|
| 262 |
+
grid.x * (sign0 ? -1.0 : 1.0),
|
| 263 |
+
grid.y * (sign1 ? -1.0 : 1.0),
|
| 264 |
+
grid.z * (sign2 ? -1.0 : 1.0),
|
| 265 |
+
grid.w * (sign3 ? -1.0 : 1.0)
|
| 266 |
+
);
|
| 267 |
+
}
|
| 268 |
+
#endif
|
| 269 |
+
|
| 270 |
+
#if defined(DATA_A_IQ2_XS)
|
| 271 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 272 |
+
const uint scale = (data_a[a_offset + ib].scales[iqs / 32] >> (4 * ((iqs / 16) & 1))) & 0xf;
|
| 273 |
+
const uint qs = data_a[a_offset + ib].qs[iqs / 8];
|
| 274 |
+
const float db = 0.25 * (0.5 + scale);
|
| 275 |
+
const uint sign7 = qs >> 9;
|
| 276 |
+
// Add parity bit
|
| 277 |
+
const uint sign8 = sign7 | (bitCount(sign7) << 7);
|
| 278 |
+
const uint sign = sign8 >> (iqs % 8);
|
| 279 |
+
const u8vec4 grid = unpack8(iq2xs_grid[qs & 511][(iqs % 8) / 4] >> (8 * (iqs % 4)));
|
| 280 |
+
bool sign0 = (sign & 1) != 0;
|
| 281 |
+
bool sign1 = (sign & 2) != 0;
|
| 282 |
+
return db * vec2(
|
| 283 |
+
grid.x * (sign0 ? -1.0 : 1.0),
|
| 284 |
+
grid.y * (sign1 ? -1.0 : 1.0)
|
| 285 |
+
);
|
| 286 |
+
}
|
| 287 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 288 |
+
const uint scale = (data_a[a_offset + ib].scales[iqs / 32] >> (4 * ((iqs / 16) & 1))) & 0xf;
|
| 289 |
+
const uint qs = data_a[a_offset + ib].qs[iqs / 8];
|
| 290 |
+
const float db = 0.25 * (0.5 + scale);
|
| 291 |
+
const uint sign7 = qs >> 9;
|
| 292 |
+
// Add parity bit
|
| 293 |
+
const uint sign8 = sign7 | (bitCount(sign7) << 7);
|
| 294 |
+
const uint sign = sign8 >> (iqs % 8);
|
| 295 |
+
const u8vec4 grid = unpack8(iq2xs_grid[qs & 511][(iqs % 8) / 4] >> (8 * (iqs % 4)));
|
| 296 |
+
bool sign0 = (sign & 1) != 0;
|
| 297 |
+
bool sign1 = (sign & 2) != 0;
|
| 298 |
+
bool sign2 = (sign & 4) != 0;
|
| 299 |
+
bool sign3 = (sign & 8) != 0;
|
| 300 |
+
return db * vec4(
|
| 301 |
+
grid.x * (sign0 ? -1.0 : 1.0),
|
| 302 |
+
grid.y * (sign1 ? -1.0 : 1.0),
|
| 303 |
+
grid.z * (sign2 ? -1.0 : 1.0),
|
| 304 |
+
grid.w * (sign3 ? -1.0 : 1.0)
|
| 305 |
+
);
|
| 306 |
+
}
|
| 307 |
+
#endif
|
| 308 |
+
|
| 309 |
+
#if defined(DATA_A_IQ2_S)
|
| 310 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 311 |
+
const uint ib32 = iqs / 32;
|
| 312 |
+
const uint ib8 = iqs / 8;
|
| 313 |
+
|
| 314 |
+
const uint scale = (data_a[a_offset + ib].scales[ib32] >> (4 * ((iqs / 16) & 1))) & 0xf;
|
| 315 |
+
const uint qs = data_a[a_offset + ib].qs[ib8];
|
| 316 |
+
const uint qh = data_a[a_offset + ib].qh[ib32];
|
| 317 |
+
const uint qhshift = 2 * (ib8 % 4);
|
| 318 |
+
const uint sign = data_a[a_offset + ib].qs[QUANT_K / 8 + ib8] >> (iqs % 8);
|
| 319 |
+
|
| 320 |
+
const float db = 0.25 * (0.5 + scale);
|
| 321 |
+
const u8vec4 grid = unpack8(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(iqs % 8) / 4]);
|
| 322 |
+
bool sign0 = (sign & 1) != 0;
|
| 323 |
+
bool sign1 = (sign & 2) != 0;
|
| 324 |
+
return db * vec2(
|
| 325 |
+
grid[iqs % 4] * (sign0 ? -1.0 : 1.0),
|
| 326 |
+
grid[(iqs % 4) + 1] * (sign1 ? -1.0 : 1.0)
|
| 327 |
+
);
|
| 328 |
+
}
|
| 329 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 330 |
+
const uint ib32 = iqs / 32;
|
| 331 |
+
const uint ib8 = iqs / 8;
|
| 332 |
+
|
| 333 |
+
const uint scale = (data_a[a_offset + ib].scales[ib32] >> (4 * ((iqs / 16) & 1))) & 0xf;
|
| 334 |
+
const uint qs = data_a[a_offset + ib].qs[ib8];
|
| 335 |
+
const uint qh = data_a[a_offset + ib].qh[ib32];
|
| 336 |
+
const uint qhshift = 2 * (ib8 % 4);
|
| 337 |
+
const uint sign = data_a[a_offset + ib].qs[QUANT_K / 8 + ib8] >> (iqs % 8);
|
| 338 |
+
|
| 339 |
+
const float db = 0.25 * (0.5 + scale);
|
| 340 |
+
const u8vec4 grid = unpack8(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(iqs % 8) / 4]);
|
| 341 |
+
bool sign0 = (sign & 1) != 0;
|
| 342 |
+
bool sign1 = (sign & 2) != 0;
|
| 343 |
+
bool sign2 = (sign & 4) != 0;
|
| 344 |
+
bool sign3 = (sign & 8) != 0;
|
| 345 |
+
return db * vec4(
|
| 346 |
+
grid.x * (sign0 ? -1.0 : 1.0),
|
| 347 |
+
grid.y * (sign1 ? -1.0 : 1.0),
|
| 348 |
+
grid.z * (sign2 ? -1.0 : 1.0),
|
| 349 |
+
grid.w * (sign3 ? -1.0 : 1.0)
|
| 350 |
+
);
|
| 351 |
+
}
|
| 352 |
+
#endif
|
| 353 |
+
|
| 354 |
+
#if defined(DATA_A_IQ3_XXS)
|
| 355 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 356 |
+
const uint ib4 = iqs / 4;
|
| 357 |
+
const uint ib32 = iqs / 32;
|
| 358 |
+
const uint is = QUANT_K / 4 + 4 * ib32;
|
| 359 |
+
const uint qs = data_a[a_offset + ib].qs[ib4];
|
| 360 |
+
// Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale)
|
| 361 |
+
const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[is / 2],
|
| 362 |
+
data_a_packed16[a_offset + ib].qs[is / 2 + 1]));
|
| 363 |
+
const float db = 0.5 * (0.5 + (signs >> 28));
|
| 364 |
+
const uint sign7 = bitfieldExtract(signs, 7 * (int(ib4 / 2) % 4), 7);
|
| 365 |
+
// Add parity bit
|
| 366 |
+
const uint sign8 = sign7 | (bitCount(sign7) << 7);
|
| 367 |
+
const uint sign = sign8 >> (iqs % 8);
|
| 368 |
+
const u8vec4 grid = unpack8(iq3xxs_grid[qs] >> (8 * (iqs % 4)));
|
| 369 |
+
bool sign0 = (sign & 1) != 0;
|
| 370 |
+
bool sign1 = (sign & 2) != 0;
|
| 371 |
+
return db * vec2(
|
| 372 |
+
grid.x * (sign0 ? -1.0 : 1.0),
|
| 373 |
+
grid.y * (sign1 ? -1.0 : 1.0)
|
| 374 |
+
);
|
| 375 |
+
}
|
| 376 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 377 |
+
const uint ib4 = iqs / 4;
|
| 378 |
+
const uint ib32 = iqs / 32;
|
| 379 |
+
const uint is = QUANT_K / 4 + 4 * ib32;
|
| 380 |
+
const uint qs = data_a[a_offset + ib].qs[ib4];
|
| 381 |
+
const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[is / 2],
|
| 382 |
+
data_a_packed16[a_offset + ib].qs[is / 2 + 1]));
|
| 383 |
+
const float db = 0.5 * (0.5 + (signs >> 28));
|
| 384 |
+
const uint sign7 = bitfieldExtract(signs, 7 * (int(ib4 / 2) % 4), 7);
|
| 385 |
+
// Add parity bit
|
| 386 |
+
const uint sign8 = sign7 | (bitCount(sign7) << 7);
|
| 387 |
+
const uint sign = sign8 >> (iqs % 8);
|
| 388 |
+
const u8vec4 grid = unpack8(iq3xxs_grid[qs]);
|
| 389 |
+
bool sign0 = (sign & 1) != 0;
|
| 390 |
+
bool sign1 = (sign & 2) != 0;
|
| 391 |
+
bool sign2 = (sign & 4) != 0;
|
| 392 |
+
bool sign3 = (sign & 8) != 0;
|
| 393 |
+
return db * vec4(
|
| 394 |
+
grid.x * (sign0 ? -1.0 : 1.0),
|
| 395 |
+
grid.y * (sign1 ? -1.0 : 1.0),
|
| 396 |
+
grid.z * (sign2 ? -1.0 : 1.0),
|
| 397 |
+
grid.w * (sign3 ? -1.0 : 1.0)
|
| 398 |
+
);
|
| 399 |
+
}
|
| 400 |
+
#endif
|
| 401 |
+
|
| 402 |
+
#if defined(DATA_A_IQ3_S)
|
| 403 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 404 |
+
const uint qs = data_a[a_offset + ib].qs[iqs / 4];
|
| 405 |
+
const uint qh = data_a[a_offset + ib].qh[iqs / 32];
|
| 406 |
+
const uint sign = data_a[a_offset + ib].signs[iqs / 8] >> (iqs % 8);
|
| 407 |
+
const uint scale = data_a[a_offset + ib].scales[iqs / 64];
|
| 408 |
+
bool sign0 = (sign & 1) != 0;
|
| 409 |
+
bool sign1 = (sign & 2) != 0;
|
| 410 |
+
const float db = 1 + 2 * ((scale >> (4 * ((iqs / 32) & 1))) & 0xf);
|
| 411 |
+
const uint32_t grid = iq3s_grid[qs | ((qh << (8 - ((iqs / 4) % 8))) & 256)] >> (8 * (iqs % 4));
|
| 412 |
+
return db * vec2(
|
| 413 |
+
int(grid & 0xFF) * (sign0 ? -1.0 : 1.0),
|
| 414 |
+
int((grid >> 8) & 0xFF) * (sign1 ? -1.0 : 1.0)
|
| 415 |
+
);
|
| 416 |
+
}
|
| 417 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 418 |
+
const uint ib4 = iqs / 4;
|
| 419 |
+
const uint ib32 = iqs / 32;
|
| 420 |
+
const uint qs = data_a[a_offset + ib].qs[ib4];
|
| 421 |
+
const uint qh = data_a[a_offset + ib].qh[ib32];
|
| 422 |
+
const uint sign = data_a[a_offset + ib].signs[iqs / 8] >> (iqs % 8);
|
| 423 |
+
const uint scale = data_a[a_offset + ib].scales[ib32 / 2];
|
| 424 |
+
bool sign0 = (sign & 1) != 0;
|
| 425 |
+
bool sign1 = (sign & 2) != 0;
|
| 426 |
+
bool sign2 = (sign & 4) != 0;
|
| 427 |
+
bool sign3 = (sign & 8) != 0;
|
| 428 |
+
const float db = 1 + 2 * ((scale >> (4 * (ib32 & 1))) & 0xf);
|
| 429 |
+
const uint32_t grid = iq3s_grid[qs | ((qh << (8 - ib4 % 8)) & 256)] >> (8 * (iqs % 4));
|
| 430 |
+
return db * vec4(
|
| 431 |
+
int(grid & 0xFF) * (sign0 ? -1.0 : 1.0),
|
| 432 |
+
int((grid >> 8) & 0xFF) * (sign1 ? -1.0 : 1.0),
|
| 433 |
+
int((grid >> 16) & 0xFF) * (sign2 ? -1.0 : 1.0),
|
| 434 |
+
int((grid >> 24) & 0xFF) * (sign3 ? -1.0 : 1.0)
|
| 435 |
+
);
|
| 436 |
+
}
|
| 437 |
+
#endif
|
| 438 |
+
|
| 439 |
+
#if defined(DATA_A_IQ4_XS)
|
| 440 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 441 |
+
const uint ib32 = iqs / 32;
|
| 442 |
+
const uint iq = 16 * ib32 + (iqs % 16);
|
| 443 |
+
|
| 444 |
+
const uint sl = (data_a[a_offset + ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF;
|
| 445 |
+
const uint sh = (data_a[a_offset + ib].scales_h >> (2 * ib32)) & 3;
|
| 446 |
+
const uint qshift = (iqs & 16) >> 2;
|
| 447 |
+
u8vec2 qs = u8vec2(data_a[a_offset + ib].qs[iq], data_a[a_offset + ib].qs[iq + 1]);
|
| 448 |
+
qs = (qs >> qshift) & uint8_t(0xF);
|
| 449 |
+
|
| 450 |
+
const float dl = float(int(sl | (sh << 4)) - 32);
|
| 451 |
+
return dl * vec2(kvalues_iq4nl[qs.x], kvalues_iq4nl[qs.y]);
|
| 452 |
+
}
|
| 453 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 454 |
+
const uint ib32 = iqs / 32;
|
| 455 |
+
const uint iq = 16 * ib32 + (iqs % 16);
|
| 456 |
+
|
| 457 |
+
const uint sl = (data_a[a_offset + ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF;
|
| 458 |
+
const uint sh = (data_a[a_offset + ib].scales_h >> (2 * ib32)) & 3;
|
| 459 |
+
const uint qshift = (iqs & 16) >> 2;
|
| 460 |
+
const u8vec4 qs = unpack8((data_a_packed32[a_offset + ib].qs[iq/4] >> qshift) & 0x0F0F0F0F);
|
| 461 |
+
|
| 462 |
+
const float dl = float(int(sl | (sh << 4)) - 32);
|
| 463 |
+
return dl * vec4(
|
| 464 |
+
kvalues_iq4nl[qs.x], kvalues_iq4nl[qs.y],
|
| 465 |
+
kvalues_iq4nl[qs.z], kvalues_iq4nl[qs.w]);
|
| 466 |
+
}
|
| 467 |
+
#endif
|
| 468 |
+
|
| 469 |
+
#if defined(DATA_A_IQ4_NL)
|
| 470 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 471 |
+
const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
|
| 472 |
+
return vec2(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[vui >> 4]);
|
| 473 |
+
}
|
| 474 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 475 |
+
const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
|
| 476 |
+
return vec4(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[(vui >> 4) & 0xF], kvalues_iq4nl[(vui >> 8) & 0xF], kvalues_iq4nl[vui >> 12]);
|
| 477 |
+
}
|
| 478 |
+
#endif
|
| 479 |
+
|
| 480 |
+
#if defined(DATA_A_MXFP4)
|
| 481 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 482 |
+
const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
|
| 483 |
+
return vec2(kvalues_mxfp4[vui & 0xF], kvalues_mxfp4[vui >> 4]) * 0.5;
|
| 484 |
+
}
|
| 485 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 486 |
+
vec2 v0 = dequantize(ib, iqs, a_offset);
|
| 487 |
+
vec2 v1 = dequantize(ib, iqs + 1, a_offset);
|
| 488 |
+
return vec4(v0.x, v0.y, v1.x, v1.y);
|
| 489 |
+
}
|
| 490 |
+
#endif
|
| 491 |
+
|
| 492 |
+
#if defined(DATA_A_NVFP4)
|
| 493 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 494 |
+
const uint sub = iqs >> 4;
|
| 495 |
+
const float d = ue4m3_to_fp32(data_a[a_offset + ib].d[sub]);
|
| 496 |
+
const uint j = iqs & 7;
|
| 497 |
+
const uint shift = (iqs & 8) >> 1; // 0 or 4
|
| 498 |
+
const uint vui0 = uint(data_a[a_offset + ib].qs[sub * 8u + j]);
|
| 499 |
+
const uint vui1 = uint(data_a[a_offset + ib].qs[sub * 8u + j + 1]);
|
| 500 |
+
const uint qs0 = (vui0 >> shift) & 0xF;
|
| 501 |
+
const uint qs1 = (vui1 >> shift) & 0xF;
|
| 502 |
+
return vec2(float(kvalues_mxfp4[qs0]), float(kvalues_mxfp4[qs1])) * d * 0.5;
|
| 503 |
+
}
|
| 504 |
+
vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
|
| 505 |
+
const vec2 v0 = dequantize(ib, iqs, a_offset);
|
| 506 |
+
const vec2 v1 = dequantize(ib, iqs + 2u, a_offset);
|
| 507 |
+
return vec4(v0.x, v0.y, v1.x, v1.y);
|
| 508 |
+
}
|
| 509 |
+
#endif
|
| 510 |
+
|
| 511 |
+
#if defined(DATA_A_F32) || defined(DATA_A_F16) || defined(DATA_A_BF16)
|
| 512 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 513 |
+
return vec2(0, 0);
|
| 514 |
+
}
|
| 515 |
+
#endif
|
| 516 |
+
|
| 517 |
+
#if defined(DATA_A_IQ1_M)
|
| 518 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 519 |
+
const uint16_t[4] scales = data_a[a_offset + ib].scales;
|
| 520 |
+
const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12;
|
| 521 |
+
const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x);
|
| 522 |
+
return vec2(d, 0);
|
| 523 |
+
}
|
| 524 |
+
#endif
|
| 525 |
+
|
| 526 |
+
#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)
|
| 527 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 528 |
+
return vec2(float(data_a[a_offset + ib].d), 0);
|
| 529 |
+
}
|
| 530 |
+
#endif
|
| 531 |
+
|
| 532 |
+
#if defined(DATA_A_Q1_0)
|
| 533 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 534 |
+
const float d = float(data_a[a_offset + ib].d);
|
| 535 |
+
return vec2(d, 0);
|
| 536 |
+
}
|
| 537 |
+
#endif
|
| 538 |
+
|
| 539 |
+
#if defined(DATA_A_MXFP4)
|
| 540 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 541 |
+
return vec2(e8m0_to_fp32(data_a[a_offset + ib].e), 0);
|
| 542 |
+
}
|
| 543 |
+
#endif
|
| 544 |
+
|
| 545 |
+
#if defined(DATA_A_NVFP4)
|
| 546 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 547 |
+
return vec2(1.0, 0.0);
|
| 548 |
+
}
|
| 549 |
+
#endif
|
| 550 |
+
|
| 551 |
+
#if defined(DATA_A_Q4_1) || defined(DATA_A_Q5_1)
|
| 552 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 553 |
+
const vec2 dm = vec2(data_a_packed32[a_offset + ib].dm);
|
| 554 |
+
return dm;
|
| 555 |
+
}
|
| 556 |
+
#endif
|
| 557 |
+
|
| 558 |
+
#if defined(DATA_A_Q2_K)
|
| 559 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 560 |
+
iqs /= 2;
|
| 561 |
+
const uint qsi = (iqs / 64) * 32 + (iqs % 16) * 2; // 0,2,4..30
|
| 562 |
+
const uint scalesi = iqs / 8; // 0..15
|
| 563 |
+
const uint qsshift = ((iqs % 64) / 16) * 2; // 0,2,4,6
|
| 564 |
+
|
| 565 |
+
const uvec2 qs = uvec2(data_a[a_offset + ib].qs[qsi], data_a[a_offset + ib].qs[qsi + 1]);
|
| 566 |
+
const uint scales = data_a[a_offset + ib].scales[scalesi];
|
| 567 |
+
const vec2 dm = vec2(data_a[a_offset + ib].dm);
|
| 568 |
+
|
| 569 |
+
return dm.x * float(scales & 0xF) * vec2((qs >> qsshift) & 3) - dm.y * float(scales >> 4);
|
| 570 |
+
}
|
| 571 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 572 |
+
return vec2(1, 0);
|
| 573 |
+
}
|
| 574 |
+
#endif
|
| 575 |
+
|
| 576 |
+
#if defined(DATA_A_Q3_K)
|
| 577 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 578 |
+
iqs /= 2;
|
| 579 |
+
const uint n = iqs / 64; // 0,1
|
| 580 |
+
const uint qsi = n * 32 + (iqs % 16) * 2; // 0,2,4..62
|
| 581 |
+
const uint hmi = (iqs % 16) * 2; // 0,2,4..30
|
| 582 |
+
const uint j = (iqs % 64) / 4; // 0..3
|
| 583 |
+
const uint is = iqs / 8; // 0..15
|
| 584 |
+
const uint halfsplit = ((iqs % 64) / 16); // 0,1,2,3
|
| 585 |
+
const uint qsshift = halfsplit * 2; // 0,2,4,6
|
| 586 |
+
const uint m = 1 << (4 * n + halfsplit); // 1,2,4,8,16,32,64,128
|
| 587 |
+
|
| 588 |
+
const int8_t us = int8_t(((data_a[a_offset + ib].scales[is % 8] >> (4 * int(is / 8))) & 0xF)
|
| 589 |
+
| (((data_a[a_offset + ib].scales[8 + (is % 4)] >> (2 * int(is / 4))) & 3) << 4));
|
| 590 |
+
const float dl = float(data_a[a_offset + ib].d) * float(us - 32);
|
| 591 |
+
|
| 592 |
+
return vec2(dl * float(int8_t((data_a[a_offset + ib].qs[qsi ] >> qsshift) & 3) - (((data_a[a_offset + ib].hmask[hmi ] & m) != 0) ? 0 : 4)),
|
| 593 |
+
dl * float(int8_t((data_a[a_offset + ib].qs[qsi + 1] >> qsshift) & 3) - (((data_a[a_offset + ib].hmask[hmi + 1] & m) != 0) ? 0 : 4)));
|
| 594 |
+
}
|
| 595 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 596 |
+
return vec2(1, 0);
|
| 597 |
+
}
|
| 598 |
+
#endif
|
| 599 |
+
|
| 600 |
+
#if defined(DATA_A_Q4_K)
|
| 601 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 602 |
+
iqs /= 2;
|
| 603 |
+
const uint n = iqs / 32; // 0,1,2,3
|
| 604 |
+
const uint b = (iqs % 32) / 16; // 0,1
|
| 605 |
+
const uint is = 2 * n + b; // 0..7
|
| 606 |
+
const uint qsi = n * 32 + (iqs % 16) * 2; // 0,2,4..126
|
| 607 |
+
|
| 608 |
+
const vec2 loadd = vec2(data_a[a_offset + ib].dm);
|
| 609 |
+
|
| 610 |
+
const uint scidx0 = (is < 4) ? is : (is + 4);
|
| 611 |
+
const uint scidx1 = (is < 4) ? is : (is - 4);
|
| 612 |
+
const uint scidxmask1 = (is < 4) ? 0x30 : 0xC0;
|
| 613 |
+
const uint scidxshift1 = (is < 4) ? 0 : 2;
|
| 614 |
+
const uint mbidx0 = is + 4;
|
| 615 |
+
const uint mbidx1 = (is < 4) ? is + 4 : is;
|
| 616 |
+
const uint mbidxmask0 = (is < 4) ? 0xF : 0xF0;
|
| 617 |
+
const uint mbidxshift0 = (is < 4) ? 0 : 4;
|
| 618 |
+
const uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0;
|
| 619 |
+
const uint mbidxshift1 = (is < 4) ? 0 : 2;
|
| 620 |
+
|
| 621 |
+
const uint8_t sc = uint8_t((data_a[a_offset + ib].scales[scidx0] & 0xF) | ((data_a[a_offset + ib].scales[scidx1] & scidxmask1) >> scidxshift1));
|
| 622 |
+
const uint8_t mbyte = uint8_t((data_a[a_offset + ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0 | ((data_a[a_offset + ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1));
|
| 623 |
+
|
| 624 |
+
const float d = loadd.x * sc;
|
| 625 |
+
const float m = -loadd.y * mbyte;
|
| 626 |
+
|
| 627 |
+
return vec2(fma(d, float((data_a[a_offset + ib].qs[qsi ] >> (b * 4)) & 0xF), m),
|
| 628 |
+
fma(d, float((data_a[a_offset + ib].qs[qsi + 1] >> (b * 4)) & 0xF), m));
|
| 629 |
+
}
|
| 630 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 631 |
+
return vec2(1, 0);
|
| 632 |
+
}
|
| 633 |
+
#endif
|
| 634 |
+
|
| 635 |
+
#if defined(DATA_A_Q5_K)
|
| 636 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 637 |
+
iqs /= 2;
|
| 638 |
+
const uint n = iqs / 32; // 0,1,2,3
|
| 639 |
+
const uint b = (iqs % 32) / 16; // 0,1
|
| 640 |
+
const uint is = 2 * n + b; // 0..7
|
| 641 |
+
const uint qsi = n * 32 + (iqs % 16) * 2; // 0,2,4..126
|
| 642 |
+
const uint qhi = (iqs % 16) * 2; // 0,2,4..30
|
| 643 |
+
|
| 644 |
+
const uint8_t hm = uint8_t(1 << (iqs / 16));
|
| 645 |
+
|
| 646 |
+
const vec2 loadd = vec2(data_a[a_offset + ib].dm);
|
| 647 |
+
|
| 648 |
+
const uint scidx0 = (is < 4) ? is : (is + 4);
|
| 649 |
+
const uint scidx1 = (is < 4) ? is : (is - 4);
|
| 650 |
+
const uint scidxmask1 = (is < 4) ? 0x30 : 0xC0;
|
| 651 |
+
const uint scidxshift1 = (is < 4) ? 0 : 2;
|
| 652 |
+
const uint mbidx0 = is + 4;
|
| 653 |
+
const uint mbidx1 = (is < 4) ? is + 4 : is;
|
| 654 |
+
const uint mbidxmask0 = (is < 4) ? 0xF : 0xF0;
|
| 655 |
+
const uint mbidxshift0 = (is < 4) ? 0 : 4;
|
| 656 |
+
const uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0;
|
| 657 |
+
const uint mbidxshift1 = (is < 4) ? 0 : 2;
|
| 658 |
+
|
| 659 |
+
const uint8_t sc = uint8_t((data_a[a_offset + ib].scales[scidx0] & 0xF) | ((data_a[a_offset + ib].scales[scidx1] & scidxmask1) >> scidxshift1));
|
| 660 |
+
const uint8_t mbyte = uint8_t(((data_a[a_offset + ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0) | ((data_a[a_offset + ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1));
|
| 661 |
+
|
| 662 |
+
const float d = loadd.x * sc;
|
| 663 |
+
const float m = -loadd.y * mbyte;
|
| 664 |
+
|
| 665 |
+
return vec2(fma(d, float((data_a[a_offset + ib].qs[qsi ] >> (b * 4)) & 0xF) + float((data_a[a_offset + ib].qh[qhi ] & hm) != 0 ? 16 : 0), m),
|
| 666 |
+
fma(d, float((data_a[a_offset + ib].qs[qsi + 1] >> (b * 4)) & 0xF) + float((data_a[a_offset + ib].qh[qhi + 1] & hm) != 0 ? 16 : 0), m));
|
| 667 |
+
}
|
| 668 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 669 |
+
return vec2(1, 0);
|
| 670 |
+
}
|
| 671 |
+
#endif
|
| 672 |
+
|
| 673 |
+
#if defined(DATA_A_Q6_K)
|
| 674 |
+
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
| 675 |
+
iqs /= 2;
|
| 676 |
+
const uint n = iqs / 64; // 0,1
|
| 677 |
+
const uint b = (iqs % 64) / 32; // 0,1
|
| 678 |
+
const uint is_b = (iqs % 16) / 8; // 0,1
|
| 679 |
+
const uint qhshift = ((iqs % 64) / 16) * 2; // 0,2,4,6
|
| 680 |
+
const uint is = 8 * n + qhshift + is_b; // 0..15
|
| 681 |
+
const uint qsi = n * 64 + (iqs % 32) * 2; // 0,2,4..126
|
| 682 |
+
const uint qhi = n * 32 + (iqs % 16) * 2; // 0,2,4..62
|
| 683 |
+
|
| 684 |
+
const float dscale = float(data_a[a_offset + ib].d) * float(data_a[a_offset + ib].scales[is]);
|
| 685 |
+
|
| 686 |
+
return vec2(dscale * float(int8_t(((data_a[a_offset + ib].ql[qsi ] >> (b * 4)) & 0xF) | (((data_a[a_offset + ib].qh[qhi ] >> qhshift) & 3) << 4)) - 32),
|
| 687 |
+
dscale * float(int8_t(((data_a[a_offset + ib].ql[qsi + 1] >> (b * 4)) & 0xF) | (((data_a[a_offset + ib].qh[qhi + 1] >> qhshift) & 3) << 4)) - 32));
|
| 688 |
+
}
|
| 689 |
+
vec2 get_dm(uint ib, uint a_offset) {
|
| 690 |
+
return vec2(1, 0);
|
| 691 |
+
}
|
| 692 |
+
#endif
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl
ADDED
|
@@ -0,0 +1,1376 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
// Each format defines a scalar dequantFunc<T> plus a V=4 dequantFunc<T>_v
|
| 3 |
+
// passed as the optional vector decoder to coopMatLoadTensorNV via
|
| 4 |
+
// GL_NV_cooperative_matrix_decode_vector. When the driver doesn't support
|
| 5 |
+
// the extension, ggml-vulkan.cpp strips it from the compiled SPIR-V.
|
| 6 |
+
#ifdef GL_NV_cooperative_matrix_decode_vector
|
| 7 |
+
#extension GL_NV_cooperative_matrix_decode_vector : enable
|
| 8 |
+
#endif
|
| 9 |
+
|
| 10 |
+
#include "types.glsl"
|
| 11 |
+
|
| 12 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufF32 {
|
| 13 |
+
vec4 block;
|
| 14 |
+
};
|
| 15 |
+
|
| 16 |
+
float16_t dequantFuncF32(const in decodeBufF32 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 17 |
+
{
|
| 18 |
+
const vec4 v = bl.block;
|
| 19 |
+
const uint idx = coordInBlock[1];
|
| 20 |
+
const f16vec4 vf16 = f16vec4(v);
|
| 21 |
+
return vf16[idx];
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ1_0 {
|
| 25 |
+
block_q1_0 block;
|
| 26 |
+
};
|
| 27 |
+
|
| 28 |
+
float16_t dequantFuncQ1_0(const in decodeBufQ1_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 29 |
+
{
|
| 30 |
+
const float16_t d = bl.block.d;
|
| 31 |
+
const uint idx = coordInBlock[1];
|
| 32 |
+
const uint bit = (uint(bl.block.qs[(idx & 0x78) >> 3]) >> (idx & 0x7)) & 1u;
|
| 33 |
+
return bit != 0u ? d : -d;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
f16vec4 dequantFuncQ1_0_v(const in decodeBufQ1_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 37 |
+
{
|
| 38 |
+
const float16_t d = bl.block.d;
|
| 39 |
+
const float16_t md = -d;
|
| 40 |
+
const uint idx = coordInBlock[1];
|
| 41 |
+
const uint qs_nib = uint(bl.block.qs[idx >> 3]) >> (idx & 0x4u);
|
| 42 |
+
return f16vec4(
|
| 43 |
+
(qs_nib & 1u) != 0u ? d : md,
|
| 44 |
+
(qs_nib & 2u) != 0u ? d : md,
|
| 45 |
+
(qs_nib & 4u) != 0u ? d : md,
|
| 46 |
+
(qs_nib & 8u) != 0u ? d : md);
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ4_0 {
|
| 50 |
+
block_q4_0_packed16 block;
|
| 51 |
+
};
|
| 52 |
+
|
| 53 |
+
float16_t dequantFuncQ4_0(const in decodeBufQ4_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 54 |
+
{
|
| 55 |
+
const float16_t d = bl.block.d;
|
| 56 |
+
const uint idx = coordInBlock[1];
|
| 57 |
+
const uint shift = (idx & 0x10) >> 2;
|
| 58 |
+
uint32_t qs = uint32_t(bl.block.qs[(idx & 0xE) >> 1]);
|
| 59 |
+
qs >>= shift;
|
| 60 |
+
qs &= 0x0F0F;
|
| 61 |
+
qs = unpack8(qs)[idx & 1];
|
| 62 |
+
float16_t ret = (float16_t(qs) - float16_t(8)) * d;
|
| 63 |
+
return ret;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
f16vec4 dequantFuncQ4_0_v(const in decodeBufQ4_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 67 |
+
{
|
| 68 |
+
const float16_t d = bl.block.d;
|
| 69 |
+
const uint idx = coordInBlock[1];
|
| 70 |
+
const uint shift = (idx & 0x10) >> 2; // 0 or 4
|
| 71 |
+
const uint qs_i = (idx & 0xE) >> 1; // even, in {0,2,4,6}
|
| 72 |
+
const uint qsw = uint32_t(bl.block.qs[qs_i ])
|
| 73 |
+
| (uint32_t(bl.block.qs[qs_i + 1u]) << 16);
|
| 74 |
+
// shift in {0,4}: per-byte mask 0x0F isolates the wanted nibble in each byte.
|
| 75 |
+
const uint q4 = (qsw >> shift) & 0x0F0F0F0Fu;
|
| 76 |
+
const u8vec4 q = unpack8(q4);
|
| 77 |
+
return f16vec4((vec4(q) - vec4(8.0)) * vec4(float(d)));
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ4_1 {
|
| 81 |
+
block_q4_1 block;
|
| 82 |
+
};
|
| 83 |
+
|
| 84 |
+
layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ4_1_packed32 {
|
| 85 |
+
block_q4_1_packed32 block;
|
| 86 |
+
};
|
| 87 |
+
|
| 88 |
+
float16_t dequantFuncQ4_1(const in decodeBufQ4_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 89 |
+
{
|
| 90 |
+
const float16_t d = bl.block.d;
|
| 91 |
+
const float16_t m = bl.block.m;
|
| 92 |
+
const uint idx = coordInBlock[1];
|
| 93 |
+
const uint iqs = idx & 0xF;
|
| 94 |
+
const uint shift = (idx & 0x10) >> 2;
|
| 95 |
+
uint32_t qs = bl.block.qs[iqs];
|
| 96 |
+
qs >>= shift;
|
| 97 |
+
qs &= 0xF;
|
| 98 |
+
float16_t ret = float16_t(qs) * d + m;
|
| 99 |
+
return ret;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
f16vec4 dequantFuncQ4_1_v(const in decodeBufQ4_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 103 |
+
{
|
| 104 |
+
decodeBufQ4_1_packed32 bl32 = decodeBufQ4_1_packed32(bl);
|
| 105 |
+
const float16_t d = bl.block.d;
|
| 106 |
+
const float16_t m = bl.block.m;
|
| 107 |
+
const uint idx = coordInBlock[1];
|
| 108 |
+
const uint shift = (idx & 0x10) >> 2; // 0 or 4
|
| 109 |
+
const uint qs_w = (idx & 0xC) >> 2; // iqs / 4 in [0,4)
|
| 110 |
+
const uint qsw = uint32_t(bl32.block.qs[qs_w]);
|
| 111 |
+
const u8vec4 q = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
|
| 112 |
+
return f16vec4(vec4(q) * vec4(float(d)) + vec4(float(m)));
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ5_0 {
|
| 116 |
+
block_q5_0 block;
|
| 117 |
+
};
|
| 118 |
+
|
| 119 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ5_0_packed16 {
|
| 120 |
+
block_q5_0_packed16 block;
|
| 121 |
+
};
|
| 122 |
+
|
| 123 |
+
float16_t dequantFuncQ5_0(const in decodeBufQ5_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 124 |
+
{
|
| 125 |
+
const float16_t d = bl.block.d;
|
| 126 |
+
const uint idx = coordInBlock[1];
|
| 127 |
+
const uint iqs = idx & 0xF;
|
| 128 |
+
|
| 129 |
+
const uint uint_qh = uint(bl.block.qh[1]) << 16 | bl.block.qh[0];
|
| 130 |
+
const uint qh = ((uint_qh >> idx) << 4) & 0x10;
|
| 131 |
+
|
| 132 |
+
const uint shift = (idx & 0x10) >> 2;
|
| 133 |
+
uint32_t qs = bl.block.qs[iqs];
|
| 134 |
+
qs >>= shift;
|
| 135 |
+
qs &= 0xF;
|
| 136 |
+
|
| 137 |
+
float16_t ret = (float16_t(qs | qh) - float16_t(16)) * d;
|
| 138 |
+
return ret;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
f16vec4 dequantFuncQ5_0_v(const in decodeBufQ5_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 142 |
+
{
|
| 143 |
+
decodeBufQ5_0_packed16 bl16 = decodeBufQ5_0_packed16(bl);
|
| 144 |
+
const float16_t d = bl.block.d;
|
| 145 |
+
const uint idx = coordInBlock[1];
|
| 146 |
+
const uint shift = (idx & 0x10) >> 2; // 0 or 4
|
| 147 |
+
const uint qs_i = (idx & 0xC) >> 1; // packed16 word index, in {0,2,4,6}
|
| 148 |
+
const uint qsw = uint32_t(bl16.block.qs[qs_i ])
|
| 149 |
+
| (uint32_t(bl16.block.qs[qs_i + 1u]) << 16);
|
| 150 |
+
const u8vec4 ql = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
|
| 151 |
+
|
| 152 |
+
const uint uint_qh = uint(bl16.block.qh[1]) << 16 | uint(bl16.block.qh[0]);
|
| 153 |
+
const uint qh_pack = uint_qh >> idx; // bits 0..3 = element idx..idx+3 high bits
|
| 154 |
+
const uvec4 qh_high = (uvec4(qh_pack, qh_pack >> 1u, qh_pack >> 2u, qh_pack >> 3u) & uvec4(0x01u)) << 4u;
|
| 155 |
+
|
| 156 |
+
return f16vec4((vec4(ql) + vec4(qh_high) - vec4(16.0)) * vec4(float(d)));
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufQ5_1 {
|
| 160 |
+
block_q5_1 block;
|
| 161 |
+
};
|
| 162 |
+
|
| 163 |
+
layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufQ5_1_packed32 {
|
| 164 |
+
block_q5_1_packed32 block;
|
| 165 |
+
};
|
| 166 |
+
|
| 167 |
+
float16_t dequantFuncQ5_1(const in decodeBufQ5_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 168 |
+
{
|
| 169 |
+
const float16_t d = bl.block.d;
|
| 170 |
+
const float16_t m = bl.block.m;
|
| 171 |
+
const uint idx = coordInBlock[1];
|
| 172 |
+
const uint iqs = idx & 0xF;
|
| 173 |
+
|
| 174 |
+
const uint uint_qh = bl.block.qh;
|
| 175 |
+
const uint qh = ((uint_qh >> idx) << 4) & 0x10;
|
| 176 |
+
|
| 177 |
+
const uint shift = (idx & 0x10) >> 2;
|
| 178 |
+
uint32_t qs = bl.block.qs[iqs];
|
| 179 |
+
qs >>= shift;
|
| 180 |
+
qs &= 0xF;
|
| 181 |
+
|
| 182 |
+
float16_t ret = float16_t(qs | qh) * d + m;
|
| 183 |
+
return ret;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
f16vec4 dequantFuncQ5_1_v(const in decodeBufQ5_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 187 |
+
{
|
| 188 |
+
decodeBufQ5_1_packed32 bl32 = decodeBufQ5_1_packed32(bl);
|
| 189 |
+
const float16_t d = bl.block.d;
|
| 190 |
+
const float16_t m = bl.block.m;
|
| 191 |
+
const uint idx = coordInBlock[1];
|
| 192 |
+
const uint shift = (idx & 0x10) >> 2; // 0 or 4
|
| 193 |
+
const uint qs_w = (idx & 0xC) >> 2; // iqs / 4 in [0,4)
|
| 194 |
+
const uint qsw = uint32_t(bl32.block.qs[qs_w]);
|
| 195 |
+
const u8vec4 ql = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
|
| 196 |
+
|
| 197 |
+
const uint qh_pack = bl.block.qh >> idx; // bits 0..3 = element idx..idx+3 high bits
|
| 198 |
+
const uvec4 qh_high = (uvec4(qh_pack, qh_pack >> 1u, qh_pack >> 2u, qh_pack >> 3u) & uvec4(0x01u)) << 4u;
|
| 199 |
+
|
| 200 |
+
return f16vec4((vec4(ql) + vec4(qh_high)) * vec4(float(d)) + vec4(float(m)));
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ8_0 {
|
| 204 |
+
block_q8_0_packed16 block;
|
| 205 |
+
};
|
| 206 |
+
|
| 207 |
+
float16_t dequantFuncQ8_0(const in decodeBufQ8_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 208 |
+
{
|
| 209 |
+
const float16_t d = bl.block.d;
|
| 210 |
+
const uint idx = coordInBlock[1];
|
| 211 |
+
const uint iqs = idx;
|
| 212 |
+
|
| 213 |
+
// Load 16b and select the byte for this element
|
| 214 |
+
int32_t qs = unpack8(bl.block.qs[(iqs & 0x1E) >> 1])[iqs & 1];
|
| 215 |
+
float16_t ret = float16_t(qs) * d;
|
| 216 |
+
return ret;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
f16vec4 dequantFuncQ8_0_v(const in decodeBufQ8_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 220 |
+
{
|
| 221 |
+
const float16_t d = bl.block.d;
|
| 222 |
+
const uint idx = coordInBlock[1];
|
| 223 |
+
const uint base = idx >> 1u;
|
| 224 |
+
const uint w = uint(uint16_t(bl.block.qs[base]))
|
| 225 |
+
| (uint(uint16_t(bl.block.qs[base + 1u])) << 16u);
|
| 226 |
+
const i8vec4 qi = unpack8(int32_t(w));
|
| 227 |
+
return f16vec4(vec4(qi) * vec4(float(d)));
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ2_K {
|
| 231 |
+
block_q2_K block;
|
| 232 |
+
};
|
| 233 |
+
|
| 234 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ2_K_packed16 {
|
| 235 |
+
block_q2_K_packed16 block;
|
| 236 |
+
};
|
| 237 |
+
|
| 238 |
+
layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ2_K_packed32 {
|
| 239 |
+
block_q2_K_packed32 block;
|
| 240 |
+
};
|
| 241 |
+
|
| 242 |
+
float16_t dequantFuncQ2_K(const in decodeBufQ2_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 243 |
+
{
|
| 244 |
+
decodeBufQ2_K_packed16 bl16 = decodeBufQ2_K_packed16(bl);
|
| 245 |
+
const f16vec2 dm = bl.block.dm;
|
| 246 |
+
const uint idx = coordInBlock[1];
|
| 247 |
+
|
| 248 |
+
const uint scalesi = (idx & 0xF0) >> 4; // 0..15
|
| 249 |
+
const uint qsshift = (idx & 0x60) >> 4; // 0,2,4,6
|
| 250 |
+
|
| 251 |
+
uint qs = uint32_t(bl16.block.qs[((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1)]);
|
| 252 |
+
qs = (qs >> qsshift) & 0x0303;
|
| 253 |
+
qs = unpack8(qs)[idx & 1];
|
| 254 |
+
|
| 255 |
+
const uint scales = bl.block.scales[scalesi];
|
| 256 |
+
float16_t ret = dm.x * float16_t(scales & 0xF) * float16_t(qs) - dm.y * float16_t(scales >> 4);
|
| 257 |
+
return ret;
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
f16vec4 dequantFuncQ2_K_v(const in decodeBufQ2_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 261 |
+
{
|
| 262 |
+
decodeBufQ2_K_packed32 bl32 = decodeBufQ2_K_packed32(bl);
|
| 263 |
+
const f16vec2 dm = bl.block.dm;
|
| 264 |
+
const uint idx = coordInBlock[1];
|
| 265 |
+
|
| 266 |
+
const uint scalesi = idx >> 4; // 0..15
|
| 267 |
+
const uint qsshift = (idx & 0x60) >> 4; // 0,2,4,6
|
| 268 |
+
|
| 269 |
+
// qs_i (packed16) = ((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1) is even for idx % 4 == 0,
|
| 270 |
+
// so qs_w (packed32) = qs_i / 2 = ((idx & 0x80) >> 4) + ((idx & 0x1Cu) >> 2).
|
| 271 |
+
const uint qs_w = ((idx & 0x80) >> 4) + ((idx & 0x1Cu) >> 2);
|
| 272 |
+
const uint qsw = uint32_t(bl32.block.qs[qs_w]);
|
| 273 |
+
const uint qs4 = (qsw >> qsshift) & 0x03030303u;
|
| 274 |
+
const u8vec4 qi = unpack8(qs4);
|
| 275 |
+
|
| 276 |
+
const uint scales = bl.block.scales[scalesi];
|
| 277 |
+
const float16_t d_sub = dm.x * float16_t(scales & 0xF);
|
| 278 |
+
const float16_t m_sub = dm.y * float16_t(scales >> 4);
|
| 279 |
+
return f16vec4(vec4(qi) * vec4(float(d_sub)) - vec4(float(m_sub)));
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ3_K {
|
| 283 |
+
block_q3_K block;
|
| 284 |
+
};
|
| 285 |
+
|
| 286 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ3_K_packed16 {
|
| 287 |
+
block_q3_K_packed16 block;
|
| 288 |
+
};
|
| 289 |
+
|
| 290 |
+
float16_t dequantFuncQ3_K(const in decodeBufQ3_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 291 |
+
{
|
| 292 |
+
const uint idx = coordInBlock[1];
|
| 293 |
+
const uint iqs = idx;
|
| 294 |
+
|
| 295 |
+
const uint n = iqs / 128; // 0,1
|
| 296 |
+
const uint qsi = n * 32 + (iqs % 32); // 0..63
|
| 297 |
+
const uint hmi = (iqs % 32); // 0..31
|
| 298 |
+
const uint j = (iqs % 128) / 8; // 0..15
|
| 299 |
+
const uint is = iqs / 16; // 0..15
|
| 300 |
+
const uint halfsplit = ((iqs % 128) / 32); // 0,1,2,3
|
| 301 |
+
const uint qsshift = halfsplit * 2; // 0,2,4,6
|
| 302 |
+
const uint m = 1 << (4 * n + halfsplit); // 1,2,4,8,16,32,64,128
|
| 303 |
+
|
| 304 |
+
uint32_t scaleidx0 = (is < 8) ? is : (is-8);
|
| 305 |
+
uint32_t scaleidx0shift = (is < 8) ? 0 : 4;
|
| 306 |
+
uint32_t scaleidx1 = is + 8 - (is/4)*4;
|
| 307 |
+
uint32_t scaleidx1shift = (is/4)*2;
|
| 308 |
+
|
| 309 |
+
const int8_t us = int8_t(((bl.block.scales[scaleidx0] >> scaleidx0shift) & 0xF) | (((bl.block.scales[scaleidx1] >> scaleidx1shift) & 3) << 4));
|
| 310 |
+
|
| 311 |
+
const float16_t dl = bl.block.d * float16_t(us - 32);
|
| 312 |
+
|
| 313 |
+
float16_t ret = dl * float16_t(int8_t((bl.block.qs[qsi ] >> qsshift) & 3) - (((bl.block.hmask[hmi ] & m) != 0) ? 0 : 4));
|
| 314 |
+
|
| 315 |
+
return ret;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
f16vec4 dequantFuncQ3_K_v(const in decodeBufQ3_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 319 |
+
{
|
| 320 |
+
decodeBufQ3_K_packed16 bl16 = decodeBufQ3_K_packed16(bl);
|
| 321 |
+
const uint idx = coordInBlock[1];
|
| 322 |
+
|
| 323 |
+
const uint n = idx >> 7; // 0,1
|
| 324 |
+
const uint is = idx >> 4; // 0..15
|
| 325 |
+
const uint halfsplit = (idx & 0x60) >> 5; // 0,1,2,3
|
| 326 |
+
const uint qsshift = halfsplit << 1; // 0,2,4,6
|
| 327 |
+
const uint hbit = (n << 2) + halfsplit; // 0..7 (bit position in hmask byte)
|
| 328 |
+
|
| 329 |
+
uint32_t scaleidx0 = (is < 8) ? is : (is - 8);
|
| 330 |
+
uint32_t scaleidx0shift = (is < 8) ? 0u : 4u;
|
| 331 |
+
uint32_t scaleidx1 = is + 8 - (is / 4) * 4;
|
| 332 |
+
uint32_t scaleidx1shift = (is / 4) * 2;
|
| 333 |
+
|
| 334 |
+
const int8_t us = int8_t(
|
| 335 |
+
((bl.block.scales[scaleidx0] >> scaleidx0shift) & 0xF) |
|
| 336 |
+
(((bl.block.scales[scaleidx1] >> scaleidx1shift) & 3) << 4));
|
| 337 |
+
const float16_t dl = bl.block.d * float16_t(int(us) - 32);
|
| 338 |
+
|
| 339 |
+
// For idx % 4 == 0: (idx & 0x1F) == (idx & 0x1C) is a multiple of 4.
|
| 340 |
+
const uint qsi = (n << 5) + (idx & 0x1Cu);
|
| 341 |
+
const uint hmi = (idx & 0x1Cu);
|
| 342 |
+
|
| 343 |
+
// Two adjacent uint16 packed16 reads, combined into a uint32 in registers.
|
| 344 |
+
// After this: byte j of qsw / hmw holds the data for element idx+j.
|
| 345 |
+
const uint qsw = uint32_t(bl16.block.qs[qsi >> 1])
|
| 346 |
+
| (uint32_t(bl16.block.qs[(qsi >> 1) + 1u]) << 16);
|
| 347 |
+
const uint hmw = uint32_t(bl16.block.hmask[hmi >> 1])
|
| 348 |
+
| (uint32_t(bl16.block.hmask[(hmi >> 1) + 1u]) << 16);
|
| 349 |
+
|
| 350 |
+
// qsshift in {0,2,4,6} and hbit in {0..7}: per-byte masks isolate the wanted bits
|
| 351 |
+
// with no inter-byte leakage.
|
| 352 |
+
const uint ql4 = (qsw >> qsshift) & 0x03030303u;
|
| 353 |
+
const uint qh4 = (hmw >> hbit) & 0x01010101u;
|
| 354 |
+
|
| 355 |
+
const ivec4 q = ivec4(unpack8(ql4 | (qh4 << 2))) - ivec4(4);
|
| 356 |
+
return f16vec4(vec4(q) * vec4(float(dl)));
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K {
|
| 360 |
+
block_q4_K block;
|
| 361 |
+
};
|
| 362 |
+
|
| 363 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed16 {
|
| 364 |
+
block_q4_K_packed16 block;
|
| 365 |
+
};
|
| 366 |
+
|
| 367 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed32 {
|
| 368 |
+
block_q4_K_packed32 block;
|
| 369 |
+
};
|
| 370 |
+
|
| 371 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed128 {
|
| 372 |
+
block_q4_K_packed128 block;
|
| 373 |
+
};
|
| 374 |
+
|
| 375 |
+
#if defined(IS_MUL_MM2)
|
| 376 |
+
|
| 377 |
+
// For Q4_K and Q5_K in the mat-mul shader, we decode a tile's worth of scales
|
| 378 |
+
// into shared memory and then process the whole tile using those scales.
|
| 379 |
+
// There is a fetch function that loads into private variables and then a store
|
| 380 |
+
// function that stores into shared memory.
|
| 381 |
+
// Q4_K and Q5_K have the same encoding of scales, so everything is shared except
|
| 382 |
+
// the part that fetches from the structure (which has a different block layout).
|
| 383 |
+
#if defined(DATA_A_Q4_K) || defined(DATA_A_Q5_K)
|
| 384 |
+
const uint shAscales_stride = (BM + 2);
|
| 385 |
+
// 1 scale per 32 elements -> 8 scales per block, per row
|
| 386 |
+
shared vec2 shAscales[8 * shAscales_stride];
|
| 387 |
+
uvec4 row_v;
|
| 388 |
+
#endif
|
| 389 |
+
|
| 390 |
+
#if defined(DATA_A_Q4_K)
|
| 391 |
+
layout (binding = 0) readonly buffer A_Q4_K_128 {block_q4_K_packed128 data_a_q4_k_packed128[];};
|
| 392 |
+
|
| 393 |
+
void fetch_scalesQ4_K(uint ir_BM, uint pos_a, uint stride_a, uint block_k, uint tid, bool in_bounds)
|
| 394 |
+
{
|
| 395 |
+
uint tids_per_row = BLOCK_SIZE / BM;
|
| 396 |
+
uint is_per_tid = 8 / tids_per_row;
|
| 397 |
+
uint is_start = is_per_tid * (tid % tids_per_row);
|
| 398 |
+
uint tid_row = tid / tids_per_row;
|
| 399 |
+
|
| 400 |
+
uint row = ir_BM + tid_row;
|
| 401 |
+
uint block_index = pos_a + row * stride_a + (block_k / QUANT_K);
|
| 402 |
+
if (in_bounds || row < p.M) {
|
| 403 |
+
row_v = data_a_q4_k_packed128[block_index].q4k[0];
|
| 404 |
+
}
|
| 405 |
+
}
|
| 406 |
+
#endif
|
| 407 |
+
#if defined(DATA_A_Q5_K)
|
| 408 |
+
layout (binding = 0) readonly buffer A_Q5_K_128 {block_q5_K_packed128 data_a_q5_k_packed128[];};
|
| 409 |
+
|
| 410 |
+
void fetch_scalesQ5_K(uint ir_BM, uint pos_a, uint stride_a, uint block_k, uint tid, bool in_bounds)
|
| 411 |
+
{
|
| 412 |
+
uint tids_per_row = BLOCK_SIZE / BM;
|
| 413 |
+
uint is_per_tid = 8 / tids_per_row;
|
| 414 |
+
uint is_start = is_per_tid * (tid % tids_per_row);
|
| 415 |
+
uint tid_row = tid / tids_per_row;
|
| 416 |
+
|
| 417 |
+
uint row = ir_BM + tid_row;
|
| 418 |
+
uint block_index = pos_a + row * stride_a + (block_k / QUANT_K);
|
| 419 |
+
if (in_bounds || row < p.M) {
|
| 420 |
+
row_v = data_a_q5_k_packed128[block_index].q5k[0];
|
| 421 |
+
}
|
| 422 |
+
}
|
| 423 |
+
#endif
|
| 424 |
+
|
| 425 |
+
#if defined(DATA_A_Q4_K) || defined(DATA_A_Q5_K)
|
| 426 |
+
void store_scalesQ4_K(uint tid)
|
| 427 |
+
{
|
| 428 |
+
barrier();
|
| 429 |
+
|
| 430 |
+
uint tids_per_row = BLOCK_SIZE / BM;
|
| 431 |
+
uint is_per_tid = 8 / tids_per_row;
|
| 432 |
+
uint is_start = is_per_tid * (tid % tids_per_row);
|
| 433 |
+
uint tid_row = tid / tids_per_row;
|
| 434 |
+
|
| 435 |
+
[[unroll]] for (uint idx = 0; idx < is_per_tid; ++idx) {
|
| 436 |
+
uint is = idx + is_start;
|
| 437 |
+
uvec4 v = row_v;
|
| 438 |
+
const vec2 loadd = vec2(unpackFloat2x16(v.x));
|
| 439 |
+
|
| 440 |
+
uint32_t sc;
|
| 441 |
+
uint32_t mbyte;
|
| 442 |
+
|
| 443 |
+
uint32_t scale0 = v.y;
|
| 444 |
+
uint32_t scale4 = v.z;
|
| 445 |
+
uint32_t scale8 = v.w;
|
| 446 |
+
|
| 447 |
+
uint32_t sc_lo = scale0;
|
| 448 |
+
uint32_t mb_lo = scale4;
|
| 449 |
+
uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
|
| 450 |
+
uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
|
| 451 |
+
|
| 452 |
+
sc = is < 4 ? sc_lo : sc_hi;
|
| 453 |
+
mbyte = is < 4 ? mb_lo : mb_hi;
|
| 454 |
+
sc = sc >> (8 * (is & 3));
|
| 455 |
+
mbyte = mbyte >> (8 * (is & 3));
|
| 456 |
+
sc &= 0x3F;
|
| 457 |
+
mbyte &= 0x3F;
|
| 458 |
+
|
| 459 |
+
const float d = loadd.x * float(sc);
|
| 460 |
+
const float m = loadd.y * float(mbyte);
|
| 461 |
+
shAscales[is * shAscales_stride + tid_row] = vec2(d,m);
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
barrier();
|
| 465 |
+
}
|
| 466 |
+
#endif
|
| 467 |
+
|
| 468 |
+
#endif
|
| 469 |
+
|
| 470 |
+
float16_t dequantFuncQ4_K(const in decodeBufQ4_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 471 |
+
{
|
| 472 |
+
decodeBufQ4_K_packed16 bl16 = decodeBufQ4_K_packed16(bl);
|
| 473 |
+
decodeBufQ4_K_packed128 bl128 = decodeBufQ4_K_packed128(bl);
|
| 474 |
+
const uint idx = coordInBlock[1];
|
| 475 |
+
|
| 476 |
+
const uint b = (idx & 0x20) >> 5; // 0,1
|
| 477 |
+
const uint is = (idx & 0xE0) >> 5; // 0..7
|
| 478 |
+
|
| 479 |
+
#if defined(IS_MUL_MM2) && defined(DATA_A_Q4_K)
|
| 480 |
+
vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
|
| 481 |
+
float d = v.x;
|
| 482 |
+
float m = v.y;
|
| 483 |
+
#else
|
| 484 |
+
uvec4 v = bl128.block.q4k[0];
|
| 485 |
+
const vec2 loadd = vec2(unpackFloat2x16(v.x));
|
| 486 |
+
|
| 487 |
+
uint32_t sc;
|
| 488 |
+
uint32_t mbyte;
|
| 489 |
+
|
| 490 |
+
uint32_t scale0 = v.y;
|
| 491 |
+
uint32_t scale4 = v.z;
|
| 492 |
+
uint32_t scale8 = v.w;
|
| 493 |
+
|
| 494 |
+
uint32_t sc_lo = scale0;
|
| 495 |
+
uint32_t mb_lo = scale4;
|
| 496 |
+
uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
|
| 497 |
+
uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
|
| 498 |
+
|
| 499 |
+
sc = is < 4 ? sc_lo : sc_hi;
|
| 500 |
+
mbyte = is < 4 ? mb_lo : mb_hi;
|
| 501 |
+
sc = sc >> (8 * (is & 3));
|
| 502 |
+
mbyte = mbyte >> (8 * (is & 3));
|
| 503 |
+
sc &= 0x3F;
|
| 504 |
+
mbyte &= 0x3F;
|
| 505 |
+
|
| 506 |
+
const float d = loadd.x * float(sc);
|
| 507 |
+
const float m = loadd.y * float(mbyte);
|
| 508 |
+
#endif
|
| 509 |
+
|
| 510 |
+
uint qs = uint32_t(bl16.block.qs[((idx & 0xC0) >> 2) + ((idx & 0x1E) >> 1)]);
|
| 511 |
+
qs = (qs >> (b * 4 + 8 * (idx & 1))) & 0xF;
|
| 512 |
+
|
| 513 |
+
float ret = d * float(qs) - m;
|
| 514 |
+
|
| 515 |
+
return float16_t(ret);
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
f16vec4 dequantFuncQ4_K_v(const in decodeBufQ4_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 519 |
+
{
|
| 520 |
+
decodeBufQ4_K_packed32 bl32 = decodeBufQ4_K_packed32(bl);
|
| 521 |
+
decodeBufQ4_K_packed128 bl128 = decodeBufQ4_K_packed128(bl);
|
| 522 |
+
const uint idx = coordInBlock[1];
|
| 523 |
+
|
| 524 |
+
const uint is = idx >> 5; // 0..7
|
| 525 |
+
|
| 526 |
+
#if defined(IS_MUL_MM2) && defined(DATA_A_Q4_K)
|
| 527 |
+
vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
|
| 528 |
+
float d = v.x;
|
| 529 |
+
float m = v.y;
|
| 530 |
+
#else
|
| 531 |
+
uvec4 v = bl128.block.q4k[0];
|
| 532 |
+
const vec2 loadd = vec2(unpackFloat2x16(v.x));
|
| 533 |
+
|
| 534 |
+
uint32_t sc;
|
| 535 |
+
uint32_t mbyte;
|
| 536 |
+
|
| 537 |
+
uint32_t scale0 = v.y;
|
| 538 |
+
uint32_t scale4 = v.z;
|
| 539 |
+
uint32_t scale8 = v.w;
|
| 540 |
+
|
| 541 |
+
uint32_t sc_lo = scale0;
|
| 542 |
+
uint32_t mb_lo = scale4;
|
| 543 |
+
uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
|
| 544 |
+
uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
|
| 545 |
+
|
| 546 |
+
sc = is < 4 ? sc_lo : sc_hi;
|
| 547 |
+
mbyte = is < 4 ? mb_lo : mb_hi;
|
| 548 |
+
sc = sc >> (8 * (is & 3));
|
| 549 |
+
mbyte = mbyte >> (8 * (is & 3));
|
| 550 |
+
sc &= 0x3F;
|
| 551 |
+
mbyte &= 0x3F;
|
| 552 |
+
|
| 553 |
+
const float d = loadd.x * float(sc);
|
| 554 |
+
const float m = loadd.y * float(mbyte);
|
| 555 |
+
#endif
|
| 556 |
+
|
| 557 |
+
// idx in [0,256); vector decode uses idx a multiple of 4. packed32 word index:
|
| 558 |
+
// (qs_i >> 1) == (idx >> 6) * 8 + ((idx & 0x1E) >> 2). sh is 0 or 4 only, so a
|
| 559 |
+
// single (w >> sh) & 0x0F0F0F0F isolates all four nibbles without inter-byte leakage.
|
| 560 |
+
const uint sh = (idx & 0x20u) >> 3u;
|
| 561 |
+
const uint w = uint32_t(bl32.block.qs[(idx >> 6) * 8u + ((idx & 0x1Eu) >> 2)]);
|
| 562 |
+
const u8vec4 q = unpack8((w >> sh) & 0x0F0F0F0Fu);
|
| 563 |
+
|
| 564 |
+
return f16vec4(vec4(d) * vec4(q) - vec4(m));
|
| 565 |
+
}
|
| 566 |
+
|
| 567 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K {
|
| 568 |
+
block_q5_K block;
|
| 569 |
+
};
|
| 570 |
+
|
| 571 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed16 {
|
| 572 |
+
block_q5_K_packed16 block;
|
| 573 |
+
};
|
| 574 |
+
|
| 575 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed128 {
|
| 576 |
+
block_q5_K_packed128 block;
|
| 577 |
+
};
|
| 578 |
+
|
| 579 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed32 {
|
| 580 |
+
block_q5_K_packed32 block;
|
| 581 |
+
};
|
| 582 |
+
|
| 583 |
+
float16_t dequantFuncQ5_K(const in decodeBufQ5_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 584 |
+
{
|
| 585 |
+
decodeBufQ5_K_packed16 bl16 = decodeBufQ5_K_packed16(bl);
|
| 586 |
+
decodeBufQ5_K_packed128 bl128 = decodeBufQ5_K_packed128(bl);
|
| 587 |
+
const uint idx = coordInBlock[1];
|
| 588 |
+
|
| 589 |
+
const uint b = (idx & 0x20) >> 5; // 0,1
|
| 590 |
+
const uint is = (idx & 0xE0) >> 5; // 0..7
|
| 591 |
+
|
| 592 |
+
#if defined(IS_MUL_MM2) && defined(DATA_A_Q5_K)
|
| 593 |
+
vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
|
| 594 |
+
float d = v.x;
|
| 595 |
+
float m = v.y;
|
| 596 |
+
#else
|
| 597 |
+
uvec4 v = bl128.block.q5k[0];
|
| 598 |
+
|
| 599 |
+
const f16vec2 loadd = unpackFloat2x16(v.x);
|
| 600 |
+
|
| 601 |
+
uint32_t sc;
|
| 602 |
+
uint32_t mbyte;
|
| 603 |
+
|
| 604 |
+
uint32_t scale0 = v.y;
|
| 605 |
+
uint32_t scale4 = v.z;
|
| 606 |
+
uint32_t scale8 = v.w;
|
| 607 |
+
|
| 608 |
+
uint32_t sc_lo = scale0;
|
| 609 |
+
uint32_t mb_lo = scale4;
|
| 610 |
+
uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
|
| 611 |
+
uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
|
| 612 |
+
|
| 613 |
+
sc = is < 4 ? sc_lo : sc_hi;
|
| 614 |
+
mbyte = is < 4 ? mb_lo : mb_hi;
|
| 615 |
+
sc = sc >> (8 * (is & 3));
|
| 616 |
+
mbyte = mbyte >> (8 * (is & 3));
|
| 617 |
+
sc &= 0x3F;
|
| 618 |
+
mbyte &= 0x3F;
|
| 619 |
+
|
| 620 |
+
const float16_t d = loadd.x * float16_t(sc);
|
| 621 |
+
const float16_t m = loadd.y * float16_t(mbyte);
|
| 622 |
+
#endif
|
| 623 |
+
|
| 624 |
+
uint qh = uint32_t(bl16.block.qh[(idx & 0x1E) >> 1]);
|
| 625 |
+
qh = ((qh >> is) & 0x101) << 4;
|
| 626 |
+
|
| 627 |
+
uint qs = uint32_t(bl16.block.qs[((idx & 0xC0) >> 2) + ((idx & 0x1E) >> 1)]);
|
| 628 |
+
qs = (qs >> (b * 4)) & 0x0F0F;
|
| 629 |
+
qs = unpack8(qs | qh)[idx & 1];
|
| 630 |
+
|
| 631 |
+
float ret = d * float(qs) - m;
|
| 632 |
+
|
| 633 |
+
return float16_t(ret);
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
f16vec4 dequantFuncQ5_K_v(const in decodeBufQ5_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 637 |
+
{
|
| 638 |
+
decodeBufQ5_K_packed32 bl32 = decodeBufQ5_K_packed32(bl);
|
| 639 |
+
decodeBufQ5_K_packed128 bl128 = decodeBufQ5_K_packed128(bl);
|
| 640 |
+
const uint idx = coordInBlock[1];
|
| 641 |
+
const uint is = idx >> 5;
|
| 642 |
+
|
| 643 |
+
#if defined(IS_MUL_MM2) && defined(DATA_A_Q5_K)
|
| 644 |
+
vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
|
| 645 |
+
float d = v.x;
|
| 646 |
+
float m = v.y;
|
| 647 |
+
#else
|
| 648 |
+
uvec4 v = bl128.block.q5k[0];
|
| 649 |
+
|
| 650 |
+
const f16vec2 loadd = unpackFloat2x16(v.x);
|
| 651 |
+
|
| 652 |
+
uint32_t sc;
|
| 653 |
+
uint32_t mbyte;
|
| 654 |
+
|
| 655 |
+
uint32_t scale0 = v.y;
|
| 656 |
+
uint32_t scale4 = v.z;
|
| 657 |
+
uint32_t scale8 = v.w;
|
| 658 |
+
|
| 659 |
+
uint32_t sc_lo = scale0;
|
| 660 |
+
uint32_t mb_lo = scale4;
|
| 661 |
+
uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
|
| 662 |
+
uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
|
| 663 |
+
|
| 664 |
+
sc = is < 4 ? sc_lo : sc_hi;
|
| 665 |
+
mbyte = is < 4 ? mb_lo : mb_hi;
|
| 666 |
+
sc = sc >> (8 * (is & 3));
|
| 667 |
+
mbyte = mbyte >> (8 * (is & 3));
|
| 668 |
+
sc &= 0x3F;
|
| 669 |
+
mbyte &= 0x3F;
|
| 670 |
+
|
| 671 |
+
const float16_t d = loadd.x * float16_t(sc);
|
| 672 |
+
const float16_t m = loadd.y * float16_t(mbyte);
|
| 673 |
+
#endif
|
| 674 |
+
|
| 675 |
+
// sh is 0 or 4; mask 0x0F0F0F0F covers the four nibbles regardless (no inter-byte leakage).
|
| 676 |
+
const uint sh = (idx & 0x20u) >> 3u;
|
| 677 |
+
const uint qs_w = (idx >> 6) * 8u + ((idx & 0x1Eu) >> 2);
|
| 678 |
+
const uint qh_w = (idx & 0x1Eu) >> 2;
|
| 679 |
+
|
| 680 |
+
const uint ql4 = (uint32_t(bl32.block.qs[qs_w]) >> sh) & 0x0F0F0F0Fu;
|
| 681 |
+
// qh stores bit `is` per element across 4 consecutive bytes; one shift+mask handles all 4.
|
| 682 |
+
const uint qh4 = ((uint32_t(bl32.block.qh[qh_w]) >> is) & 0x01010101u) << 4u;
|
| 683 |
+
|
| 684 |
+
const u8vec4 qi = unpack8(ql4 | qh4);
|
| 685 |
+
return f16vec4(vec4(qi) * vec4(d) - vec4(m));
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ6_K {
|
| 689 |
+
block_q6_K block;
|
| 690 |
+
};
|
| 691 |
+
|
| 692 |
+
layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ6_K_packed16 {
|
| 693 |
+
block_q6_K_packed16 block;
|
| 694 |
+
};
|
| 695 |
+
|
| 696 |
+
float16_t dequantFuncQ6_K(const in decodeBufQ6_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 697 |
+
{
|
| 698 |
+
decodeBufQ6_K_packed16 bl16 = decodeBufQ6_K_packed16(bl);
|
| 699 |
+
const uint idx = coordInBlock[1];
|
| 700 |
+
|
| 701 |
+
const uint b = (idx & 0x40) >> 6; // 0,1
|
| 702 |
+
const uint qhshift = (idx & 0x60) >> 4; // 0,2,4,6
|
| 703 |
+
const uint is = (idx & 0xF0) >> 4; // 0..15
|
| 704 |
+
|
| 705 |
+
const float16_t dscale = bl.block.d * float16_t(bl.block.scales[is]);
|
| 706 |
+
|
| 707 |
+
uint ql = uint32_t(bl16.block.ql[((idx & 0x80) >> 2) + ((idx & 0x3E) >> 1)]);
|
| 708 |
+
ql = (ql >> (b * 4)) & 0x0F0F;
|
| 709 |
+
|
| 710 |
+
uint qh = uint32_t(bl16.block.qh[((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1)]);
|
| 711 |
+
qh = ((qh >> qhshift) & 0x0303) << 4;
|
| 712 |
+
|
| 713 |
+
int q = unpack8(ql | qh)[idx & 1];
|
| 714 |
+
|
| 715 |
+
float16_t ret = dscale * float16_t(q - 32);
|
| 716 |
+
|
| 717 |
+
return ret;
|
| 718 |
+
}
|
| 719 |
+
|
| 720 |
+
f16vec4 dequantFuncQ6_K_v(const in decodeBufQ6_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 721 |
+
{
|
| 722 |
+
decodeBufQ6_K_packed16 bl16 = decodeBufQ6_K_packed16(bl);
|
| 723 |
+
const uint idx = coordInBlock[1];
|
| 724 |
+
|
| 725 |
+
const uint b = (idx & 0x40) >> 6;
|
| 726 |
+
const uint qhshift = (idx & 0x60) >> 4; // 0,2,4,6
|
| 727 |
+
const uint is = idx >> 4;
|
| 728 |
+
const uint sh = b * 4; // 0 or 4
|
| 729 |
+
|
| 730 |
+
const float16_t dscale = bl.block.d * float16_t(bl.block.scales[is]);
|
| 731 |
+
|
| 732 |
+
const uint ql_i = ((idx & 0x80) >> 2) + ((idx & 0x3E) >> 1);
|
| 733 |
+
const uint qh_i = ((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1);
|
| 734 |
+
|
| 735 |
+
// Two adjacent uint16 packed16 reads, combined into a uint32 in registers.
|
| 736 |
+
// After this: byte j of qlw / qhw holds the data for element idx+j.
|
| 737 |
+
const uint qlw = uint32_t(bl16.block.ql[ql_i ]) | (uint32_t(bl16.block.ql[ql_i + 1]) << 16);
|
| 738 |
+
const uint qhw = uint32_t(bl16.block.qh[qh_i ]) | (uint32_t(bl16.block.qh[qh_i + 1]) << 16);
|
| 739 |
+
|
| 740 |
+
// sh in {0,4} and qhshift in {0,2,4,6}: per-byte masks 0x0F / 0x03 keep only the
|
| 741 |
+
// wanted bits with no inter-byte leakage; place qh's 2 bits at nibble high position.
|
| 742 |
+
const uint ql4 = (qlw >> sh) & 0x0F0F0F0Fu;
|
| 743 |
+
const uint qh4 = ((qhw >> qhshift) & 0x03030303u) << 4u;
|
| 744 |
+
|
| 745 |
+
const ivec4 qi = ivec4(unpack8(ql4 | qh4));
|
| 746 |
+
return f16vec4((vec4(qi) - vec4(32.0f)) * vec4(float(dscale)));
|
| 747 |
+
}
|
| 748 |
+
|
| 749 |
+
#if defined(DATA_A_IQ1_S)
|
| 750 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ1_S {
|
| 751 |
+
block_iq1_s block;
|
| 752 |
+
};
|
| 753 |
+
|
| 754 |
+
float16_t dequantFuncIQ1_S(const in decodeBufIQ1_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 755 |
+
{
|
| 756 |
+
const float16_t d = bl.block.d;
|
| 757 |
+
const uint idx = coordInBlock[1];
|
| 758 |
+
|
| 759 |
+
const uint ib32 = (idx & 0xE0) >> 5;
|
| 760 |
+
const uint ib8 = (idx & 0xF8) >> 3;
|
| 761 |
+
|
| 762 |
+
const uint qh = bl.block.qh[ib32];
|
| 763 |
+
const uint qs = bl.block.qs[ib8];
|
| 764 |
+
const float dl = d * float(2 * bitfieldExtract(qh, 12, 3) + 1);
|
| 765 |
+
const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
|
| 766 |
+
const uint grid = iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)];
|
| 767 |
+
|
| 768 |
+
float16_t ret = float16_t(dl) * (float16_t(bitfieldExtract(int(grid), 2 * int(idx % 8), 2)) + float16_t(delta));
|
| 769 |
+
return ret;
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
f16vec4 dequantFuncIQ1_S_v(const in decodeBufIQ1_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 773 |
+
{
|
| 774 |
+
const float16_t d = bl.block.d;
|
| 775 |
+
const uint idx = coordInBlock[1];
|
| 776 |
+
|
| 777 |
+
const uint ib32 = idx >> 5;
|
| 778 |
+
const uint ib8 = idx >> 3;
|
| 779 |
+
const int i8b = int(idx & 4); // 0 or 4
|
| 780 |
+
|
| 781 |
+
const uint qh = bl.block.qh[ib32];
|
| 782 |
+
const uint qs = bl.block.qs[ib8];
|
| 783 |
+
const float dl = float(d) * float(2 * bitfieldExtract(qh, 12, 3) + 1);
|
| 784 |
+
const float delta = ((qh & 0x8000u) != 0u) ? -IQ1S_DELTA : IQ1S_DELTA;
|
| 785 |
+
const uint grid = iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)];
|
| 786 |
+
|
| 787 |
+
const ivec4 q = ivec4(
|
| 788 |
+
bitfieldExtract(int(grid), 2 * (i8b + 0), 2),
|
| 789 |
+
bitfieldExtract(int(grid), 2 * (i8b + 1), 2),
|
| 790 |
+
bitfieldExtract(int(grid), 2 * (i8b + 2), 2),
|
| 791 |
+
bitfieldExtract(int(grid), 2 * (i8b + 3), 2));
|
| 792 |
+
return f16vec4((vec4(q) + vec4(delta)) * dl);
|
| 793 |
+
}
|
| 794 |
+
#endif
|
| 795 |
+
|
| 796 |
+
#if defined(DATA_A_IQ1_M)
|
| 797 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ1_M {
|
| 798 |
+
block_iq1_m block;
|
| 799 |
+
};
|
| 800 |
+
|
| 801 |
+
layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufIQ1_M_packed64 {
|
| 802 |
+
block_iq1_m_packed64 block;
|
| 803 |
+
};
|
| 804 |
+
|
| 805 |
+
float16_t dequantFuncIQ1_M(const in decodeBufIQ1_M bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 806 |
+
{
|
| 807 |
+
decodeBufIQ1_M_packed64 bl64 = decodeBufIQ1_M_packed64(bl);
|
| 808 |
+
const uint idx = coordInBlock[1];
|
| 809 |
+
|
| 810 |
+
uvec2 scales = unpack32(bl64.block.scales);
|
| 811 |
+
const float16_t d = uint16BitsToHalf(uint16_t(((scales.x & 0xF000) >> 12) | ((scales.x & 0xF0000000) >> 24) | ((scales.y & 0xF000) >> 4) | ((scales.y & 0xF0000000) >> 16)));
|
| 812 |
+
|
| 813 |
+
const uint ib8 = (idx & 0xF8) >> 3;
|
| 814 |
+
const uint ib16 = (idx & 0xF0) >> 4;
|
| 815 |
+
const int i8 = int(idx % 8);
|
| 816 |
+
const uint sc = bl.block.scales[ib8 / 8];
|
| 817 |
+
const uint qs = bl.block.qs[ib8];
|
| 818 |
+
const uint qh = bl.block.qh[ib16] >> (4 * (ib8 & 1));
|
| 819 |
+
const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1;
|
| 820 |
+
const float delta = ((qh & 8) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
|
| 821 |
+
const uint grid = iq1s_grid[qs | ((qh & 7) << 8)];
|
| 822 |
+
|
| 823 |
+
float16_t ret = d * float16_t(dl) * (float16_t(bitfieldExtract(int(grid), 2 * i8, 2)) + float16_t(delta));
|
| 824 |
+
return ret;
|
| 825 |
+
}
|
| 826 |
+
|
| 827 |
+
f16vec4 dequantFuncIQ1_M_v(const in decodeBufIQ1_M bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 828 |
+
{
|
| 829 |
+
decodeBufIQ1_M_packed64 bl64 = decodeBufIQ1_M_packed64(bl);
|
| 830 |
+
const uint idx = coordInBlock[1];
|
| 831 |
+
|
| 832 |
+
uvec2 scales = unpack32(bl64.block.scales);
|
| 833 |
+
const float16_t d = uint16BitsToHalf(uint16_t(((scales.x & 0xF000) >> 12) | ((scales.x & 0xF0000000) >> 24) | ((scales.y & 0xF000) >> 4) | ((scales.y & 0xF0000000) >> 16)));
|
| 834 |
+
|
| 835 |
+
const uint ib8 = idx >> 3;
|
| 836 |
+
const uint ib16 = idx >> 4;
|
| 837 |
+
const int i8b = int(idx & 4); // 0 or 4 -- i8 base for the V=4 group
|
| 838 |
+
|
| 839 |
+
const uint sc = bl.block.scales[ib8 / 8];
|
| 840 |
+
const uint qs = bl.block.qs[ib8];
|
| 841 |
+
const uint qh = bl.block.qh[ib16] >> (4 * (ib8 & 1));
|
| 842 |
+
const float dl = 2.0 * float(bitfieldExtract(sc, 3 * int(ib16 & 3), 3)) + 1.0;
|
| 843 |
+
const float delta = ((qh & 8u) != 0u) ? -IQ1S_DELTA : IQ1S_DELTA;
|
| 844 |
+
const uint grid = iq1s_grid[qs | ((qh & 7u) << 8)];
|
| 845 |
+
|
| 846 |
+
const ivec4 q = ivec4(
|
| 847 |
+
bitfieldExtract(int(grid), 2 * (i8b + 0), 2),
|
| 848 |
+
bitfieldExtract(int(grid), 2 * (i8b + 1), 2),
|
| 849 |
+
bitfieldExtract(int(grid), 2 * (i8b + 2), 2),
|
| 850 |
+
bitfieldExtract(int(grid), 2 * (i8b + 3), 2));
|
| 851 |
+
return f16vec4((vec4(q) + vec4(delta)) * (float(d) * dl));
|
| 852 |
+
}
|
| 853 |
+
#endif
|
| 854 |
+
|
| 855 |
+
#if defined(DATA_A_IQ2_XXS)
|
| 856 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XXS {
|
| 857 |
+
block_iq2_xxs block;
|
| 858 |
+
};
|
| 859 |
+
|
| 860 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XXS_packed16 {
|
| 861 |
+
block_iq2_xxs_packed16 block;
|
| 862 |
+
};
|
| 863 |
+
|
| 864 |
+
float16_t dequantFuncIQ2_XXS(const in decodeBufIQ2_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 865 |
+
{
|
| 866 |
+
decodeBufIQ2_XXS_packed16 bl16 = decodeBufIQ2_XXS_packed16(bl);
|
| 867 |
+
const float16_t d = bl.block.d;
|
| 868 |
+
const uint idx = coordInBlock[1];
|
| 869 |
+
|
| 870 |
+
const uint ib32 = (idx & 0xE0) >> 5; // 0..7
|
| 871 |
+
const uint ib8 = (idx & 0x18) >> 3; // 0..3
|
| 872 |
+
const uint iqs = 8 * ib32 + ib8;
|
| 873 |
+
|
| 874 |
+
const uint qs = bl.block.qs[iqs];
|
| 875 |
+
const uint signscale = pack32(u16vec2(bl16.block.qs[4*ib32+2], bl16.block.qs[4*ib32+3]));
|
| 876 |
+
|
| 877 |
+
const float dscale = float(bl.block.d) * 0.25 * (0.5 + float(signscale >> 28));
|
| 878 |
+
uint sign = bitfieldExtract(signscale, 7 * int(ib8), 7);
|
| 879 |
+
sign |= bitCount(sign) << 7;
|
| 880 |
+
|
| 881 |
+
uint g2 = iq2xxs_grid[qs][(idx & 4) >> 2];
|
| 882 |
+
g2 >>= (idx & 2) * 8;
|
| 883 |
+
const vec2 g = vec2(unpack8(g2));
|
| 884 |
+
|
| 885 |
+
vec2 ret = dscale * g * ((sign & (1 << (idx & 7))) != 0 ? -1.0hf : 1.0hf);
|
| 886 |
+
return float16_t(ret[idx & 1]);
|
| 887 |
+
}
|
| 888 |
+
|
| 889 |
+
f16vec4 dequantFuncIQ2_XXS_v(const in decodeBufIQ2_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 890 |
+
{
|
| 891 |
+
decodeBufIQ2_XXS_packed16 bl16 = decodeBufIQ2_XXS_packed16(bl);
|
| 892 |
+
const uint idx = coordInBlock[1];
|
| 893 |
+
|
| 894 |
+
const uint ib32 = idx >> 5;
|
| 895 |
+
const uint ib8 = (idx & 0x18) >> 3;
|
| 896 |
+
const uint iqs = 8 * ib32 + ib8;
|
| 897 |
+
|
| 898 |
+
const uint qs = bl.block.qs[iqs];
|
| 899 |
+
const uint signscale = pack32(u16vec2(bl16.block.qs[4*ib32+2], bl16.block.qs[4*ib32+3]));
|
| 900 |
+
const float dscale = float(bl.block.d) * 0.25 * (0.5 + float(signscale >> 28));
|
| 901 |
+
|
| 902 |
+
uint sign = bitfieldExtract(signscale, 7 * int(ib8), 7);
|
| 903 |
+
sign |= bitCount(sign) << 7;
|
| 904 |
+
const uint sb = sign >> (idx & 7u);
|
| 905 |
+
|
| 906 |
+
const uint g2 = iq2xxs_grid[qs][(idx & 4) >> 2];
|
| 907 |
+
const u8vec4 g = unpack8(g2);
|
| 908 |
+
|
| 909 |
+
return f16vec4(
|
| 910 |
+
dscale * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
|
| 911 |
+
dscale * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
|
| 912 |
+
dscale * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
|
| 913 |
+
dscale * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
|
| 914 |
+
}
|
| 915 |
+
#endif
|
| 916 |
+
|
| 917 |
+
#if defined(DATA_A_IQ2_XS)
|
| 918 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XS {
|
| 919 |
+
block_iq2_xs block;
|
| 920 |
+
};
|
| 921 |
+
|
| 922 |
+
float16_t dequantFuncIQ2_XS(const in decodeBufIQ2_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 923 |
+
{
|
| 924 |
+
const float16_t d = bl.block.d;
|
| 925 |
+
const uint idx = coordInBlock[1];
|
| 926 |
+
|
| 927 |
+
const uint is = (idx & 0xE0) >> 5; // 0..8
|
| 928 |
+
const uint sshift = (idx & 0x10) >> 2; // 0,4
|
| 929 |
+
const uint iqs = (idx & 0xF8) >> 3; // 0..63
|
| 930 |
+
|
| 931 |
+
const uint16_t qs = bl.block.qs[iqs];
|
| 932 |
+
const float dscale = float(bl.block.d) * 0.25 * (0.5 + float((bl.block.scales[is] >> sshift) & 0xF));
|
| 933 |
+
|
| 934 |
+
uint sign = uint(qs >> 9);
|
| 935 |
+
sign |= bitCount(sign) << 7;
|
| 936 |
+
uint g2 = iq2xs_grid[qs & 0x1FF][(idx & 4) >> 2];
|
| 937 |
+
g2 >>= (idx & 2) * 8;
|
| 938 |
+
const vec2 g = vec2(unpack8(g2));
|
| 939 |
+
|
| 940 |
+
vec2 ret = dscale * g * ((sign & (1 << (idx & 7))) != 0 ? -1.0hf : 1.0hf);
|
| 941 |
+
return float16_t(ret[idx & 1]);
|
| 942 |
+
}
|
| 943 |
+
|
| 944 |
+
f16vec4 dequantFuncIQ2_XS_v(const in decodeBufIQ2_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 945 |
+
{
|
| 946 |
+
const uint idx = coordInBlock[1];
|
| 947 |
+
|
| 948 |
+
const uint is = idx >> 5;
|
| 949 |
+
const uint sshift = (idx & 0x10) >> 2;
|
| 950 |
+
const uint iqs = idx >> 3;
|
| 951 |
+
|
| 952 |
+
const uint16_t qs = bl.block.qs[iqs];
|
| 953 |
+
const float dscale = float(bl.block.d) * 0.25 * (0.5 + float((bl.block.scales[is] >> sshift) & 0xF));
|
| 954 |
+
|
| 955 |
+
uint sign = uint(qs >> 9);
|
| 956 |
+
sign |= bitCount(sign) << 7;
|
| 957 |
+
const uint sb = sign >> (idx & 7u);
|
| 958 |
+
|
| 959 |
+
const uint g2 = iq2xs_grid[qs & 0x1FF][(idx & 4) >> 2];
|
| 960 |
+
const u8vec4 g = unpack8(g2);
|
| 961 |
+
|
| 962 |
+
return f16vec4(
|
| 963 |
+
dscale * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
|
| 964 |
+
dscale * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
|
| 965 |
+
dscale * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
|
| 966 |
+
dscale * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
|
| 967 |
+
}
|
| 968 |
+
#endif
|
| 969 |
+
|
| 970 |
+
#if defined(DATA_A_IQ2_S)
|
| 971 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_S {
|
| 972 |
+
block_iq2_s block;
|
| 973 |
+
};
|
| 974 |
+
|
| 975 |
+
float16_t dequantFuncIQ2_S(const in decodeBufIQ2_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 976 |
+
{
|
| 977 |
+
uint idx = coordInBlock[1];
|
| 978 |
+
|
| 979 |
+
const uint ib32 = (idx & 0xE0) >> 5; // 0..7
|
| 980 |
+
const uint ib8 = (idx & 0xF8) >> 3; // 0..31
|
| 981 |
+
const uint qhshift = 2 * (ib8 % 4);
|
| 982 |
+
|
| 983 |
+
const uint scale = (bl.block.scales[ib32] >> ((idx & 0x10) >> 2)) & 0xf;
|
| 984 |
+
const uint qs = bl.block.qs[ib8];
|
| 985 |
+
const uint qh = bl.block.qh[ib32];
|
| 986 |
+
const uint sign = bl.block.qs[QUANT_K / 8 + ib8] >> (idx & 0x6);
|
| 987 |
+
|
| 988 |
+
const float d = float(bl.block.d);
|
| 989 |
+
const float db = d * 0.25 * (0.5 + scale);
|
| 990 |
+
const ivec2 sign01 = 1 - (2 & ivec2(sign << 1, sign));
|
| 991 |
+
uint g2 = iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(idx & 4) >> 2];
|
| 992 |
+
g2 >>= (idx & 2) * 8;
|
| 993 |
+
const vec2 v = db * vec2(sign01) * vec2(unpack8(g2));
|
| 994 |
+
return float16_t(v[idx & 1]);
|
| 995 |
+
}
|
| 996 |
+
|
| 997 |
+
f16vec4 dequantFuncIQ2_S_v(const in decodeBufIQ2_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 998 |
+
{
|
| 999 |
+
const uint idx = coordInBlock[1];
|
| 1000 |
+
|
| 1001 |
+
const uint ib32 = idx >> 5;
|
| 1002 |
+
const uint ib8 = idx >> 3;
|
| 1003 |
+
const uint qhshift = 2 * (ib8 % 4);
|
| 1004 |
+
|
| 1005 |
+
const uint scale = (bl.block.scales[ib32] >> ((idx & 0x10) >> 2)) & 0xf;
|
| 1006 |
+
const uint qs = bl.block.qs[ib8];
|
| 1007 |
+
const uint qh = bl.block.qh[ib32];
|
| 1008 |
+
const uint sb = uint(bl.block.qs[QUANT_K / 8 + ib8]) >> (idx & 0x6u);
|
| 1009 |
+
|
| 1010 |
+
const float d = float(bl.block.d);
|
| 1011 |
+
const float db = d * 0.25 * (0.5 + scale);
|
| 1012 |
+
|
| 1013 |
+
const uint g2 = iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(idx & 4) >> 2];
|
| 1014 |
+
const u8vec4 g = unpack8(g2);
|
| 1015 |
+
|
| 1016 |
+
return f16vec4(
|
| 1017 |
+
db * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
|
| 1018 |
+
db * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
|
| 1019 |
+
db * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
|
| 1020 |
+
db * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
|
| 1021 |
+
}
|
| 1022 |
+
#endif
|
| 1023 |
+
|
| 1024 |
+
#if defined(DATA_A_IQ3_XXS)
|
| 1025 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_XXS {
|
| 1026 |
+
block_iq3_xxs block;
|
| 1027 |
+
};
|
| 1028 |
+
|
| 1029 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_XXS_packed16 {
|
| 1030 |
+
block_iq3_xxs_packed16 block;
|
| 1031 |
+
};
|
| 1032 |
+
|
| 1033 |
+
float16_t dequantFuncIQ3_XXS(const in decodeBufIQ3_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1034 |
+
{
|
| 1035 |
+
decodeBufIQ3_XXS_packed16 bl16 = decodeBufIQ3_XXS_packed16(bl);
|
| 1036 |
+
uint idx = coordInBlock[1];
|
| 1037 |
+
|
| 1038 |
+
const uint iqs = (idx & 0xFC) >> 2; // 0..63
|
| 1039 |
+
const uint is = QUANT_K / 4 + ((idx & 0xE0) >> 3);// 8 values
|
| 1040 |
+
|
| 1041 |
+
const float d = float(bl.block.d);
|
| 1042 |
+
const uint qs = bl.block.qs[iqs];
|
| 1043 |
+
const uint signs = pack32(u16vec2(
|
| 1044 |
+
bl16.block.qs[is/2+0],
|
| 1045 |
+
bl16.block.qs[is/2+1]
|
| 1046 |
+
));
|
| 1047 |
+
const float db = d * 0.5 * (0.5 + (signs >> 28));
|
| 1048 |
+
const uint32_t sign7 = bitfieldExtract(signs, 7 * (int(iqs / 2) % 4), 7);
|
| 1049 |
+
const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (idx & 0x6);
|
| 1050 |
+
const ivec2 sign01 = ivec2(1 - (2 & ivec2(sign << 1, sign)));
|
| 1051 |
+
const uint grid = iq3xxs_grid[qs] >> (16 * ((idx & 2) >> 1));
|
| 1052 |
+
const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy);
|
| 1053 |
+
return float16_t(v[idx & 1]);
|
| 1054 |
+
}
|
| 1055 |
+
|
| 1056 |
+
f16vec4 dequantFuncIQ3_XXS_v(const in decodeBufIQ3_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1057 |
+
{
|
| 1058 |
+
decodeBufIQ3_XXS_packed16 bl16 = decodeBufIQ3_XXS_packed16(bl);
|
| 1059 |
+
const uint idx = coordInBlock[1];
|
| 1060 |
+
|
| 1061 |
+
const uint iqs = idx >> 2;
|
| 1062 |
+
const uint is = QUANT_K / 4 + ((idx & 0xE0) >> 3);
|
| 1063 |
+
|
| 1064 |
+
const float d = float(bl.block.d);
|
| 1065 |
+
const uint qs = bl.block.qs[iqs];
|
| 1066 |
+
const uint signs = pack32(u16vec2(bl16.block.qs[is/2+0], bl16.block.qs[is/2+1]));
|
| 1067 |
+
const float db = d * 0.5 * (0.5 + (signs >> 28));
|
| 1068 |
+
|
| 1069 |
+
const uint sign7 = bitfieldExtract(signs, 7 * (int(iqs / 2) % 4), 7);
|
| 1070 |
+
const uint sb = (sign7 | (bitCount(sign7) << 7)) >> (idx & 0x6u);
|
| 1071 |
+
|
| 1072 |
+
const uint grid = iq3xxs_grid[qs];
|
| 1073 |
+
const u8vec4 g = unpack8(grid);
|
| 1074 |
+
|
| 1075 |
+
return f16vec4(
|
| 1076 |
+
db * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
|
| 1077 |
+
db * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
|
| 1078 |
+
db * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
|
| 1079 |
+
db * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
|
| 1080 |
+
}
|
| 1081 |
+
#endif
|
| 1082 |
+
|
| 1083 |
+
#if defined(DATA_A_IQ3_S)
|
| 1084 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_S {
|
| 1085 |
+
block_iq3_s block;
|
| 1086 |
+
};
|
| 1087 |
+
|
| 1088 |
+
float16_t dequantFuncIQ3_S(const in decodeBufIQ3_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1089 |
+
{
|
| 1090 |
+
uint idx = coordInBlock[1];
|
| 1091 |
+
|
| 1092 |
+
const uint iqs = (idx & 0xFC) >> 2; // 0..63
|
| 1093 |
+
const uint iqh = (idx & 0xE0) >> 5;
|
| 1094 |
+
|
| 1095 |
+
const float d = float(bl.block.d);
|
| 1096 |
+
const uint qs = bl.block.qs[iqs];
|
| 1097 |
+
const uint qh = bl.block.qh[iqh];
|
| 1098 |
+
const int8_t sign = int8_t(bl.block.signs[iqs / 2] >> (idx & 0x6));
|
| 1099 |
+
const uint scale = bl.block.scales[iqs / 16];
|
| 1100 |
+
const ivec2 sign01 = ivec2(1 - (2 & ivec2(sign << 1, sign)));
|
| 1101 |
+
const float db = d * (1 + 2 * ((scale >> (4 * (iqh & 1))) & 0xf));
|
| 1102 |
+
const uint32_t grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)] >> ((idx & 2) << 3);
|
| 1103 |
+
const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy);
|
| 1104 |
+
|
| 1105 |
+
return float16_t(v[idx & 1]);
|
| 1106 |
+
}
|
| 1107 |
+
|
| 1108 |
+
f16vec4 dequantFuncIQ3_S_v(const in decodeBufIQ3_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1109 |
+
{
|
| 1110 |
+
const uint idx = coordInBlock[1];
|
| 1111 |
+
|
| 1112 |
+
const uint iqs = idx >> 2;
|
| 1113 |
+
const uint iqh = idx >> 5;
|
| 1114 |
+
|
| 1115 |
+
const float d = float(bl.block.d);
|
| 1116 |
+
const uint qs = bl.block.qs[iqs];
|
| 1117 |
+
const uint qh = bl.block.qh[iqh];
|
| 1118 |
+
const uint sb = uint(bl.block.signs[iqs / 2]) >> (idx & 0x6u);
|
| 1119 |
+
const uint scale = bl.block.scales[iqs / 16];
|
| 1120 |
+
const float db = d * (1 + 2 * ((scale >> (4 * (iqh & 1))) & 0xf));
|
| 1121 |
+
|
| 1122 |
+
const uint grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)];
|
| 1123 |
+
const u8vec4 g = unpack8(grid);
|
| 1124 |
+
|
| 1125 |
+
return f16vec4(
|
| 1126 |
+
db * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
|
| 1127 |
+
db * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
|
| 1128 |
+
db * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
|
| 1129 |
+
db * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
|
| 1130 |
+
}
|
| 1131 |
+
#endif
|
| 1132 |
+
|
| 1133 |
+
#if defined(DATA_A_IQ4_XS)
|
| 1134 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_XS {
|
| 1135 |
+
block_iq4_xs block;
|
| 1136 |
+
};
|
| 1137 |
+
|
| 1138 |
+
layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufIQ4_XS_packed32 {
|
| 1139 |
+
block_iq4_xs_packed32 block;
|
| 1140 |
+
};
|
| 1141 |
+
|
| 1142 |
+
float16_t dequantFuncIQ4_XS(const in decodeBufIQ4_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1143 |
+
{
|
| 1144 |
+
const float16_t d = bl.block.d;
|
| 1145 |
+
const uint idx = coordInBlock[1];
|
| 1146 |
+
|
| 1147 |
+
const uint ib32 = (idx & 0xE0) >> 5; // 0..7
|
| 1148 |
+
|
| 1149 |
+
const uint sl = (bl.block.scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF;
|
| 1150 |
+
const uint sh = ((bl.block.scales_h) >> (2 * ib32)) & 3;
|
| 1151 |
+
const uint qshift = (idx & 16) >> 2;
|
| 1152 |
+
const uint q = (bl.block.qs[16 * ib32 + (idx % 16)] >> qshift) & 0xF;
|
| 1153 |
+
|
| 1154 |
+
float16_t ret = d * float16_t(int(sl | (sh << 4)) - 32) * float16_t(kvalues_iq4nl[q]);
|
| 1155 |
+
return ret;
|
| 1156 |
+
}
|
| 1157 |
+
|
| 1158 |
+
f16vec4 dequantFuncIQ4_XS_v(const in decodeBufIQ4_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1159 |
+
{
|
| 1160 |
+
decodeBufIQ4_XS_packed32 bl32 = decodeBufIQ4_XS_packed32(bl);
|
| 1161 |
+
const float16_t d = bl.block.d;
|
| 1162 |
+
const uint idx = coordInBlock[1];
|
| 1163 |
+
|
| 1164 |
+
const uint ib32 = idx >> 5; // 0..7
|
| 1165 |
+
const uint sl = (bl32.block.scales_l >> (4 * ib32)) & 0xF;
|
| 1166 |
+
const uint sh = (uint(bl32.block.scales_h) >> (2 * ib32)) & 0x3;
|
| 1167 |
+
const uint qshift = (idx & 0x10) >> 2; // {0, 4}
|
| 1168 |
+
const uint qs_w = 4 * ib32 + ((idx & 0xC) >> 2); // iqs / 4, in [0,32)
|
| 1169 |
+
|
| 1170 |
+
const float16_t dl = d * float16_t(int(sl | (sh << 4)) - 32);
|
| 1171 |
+
|
| 1172 |
+
const uint qsw = bl32.block.qs[qs_w];
|
| 1173 |
+
const u8vec4 qv = unpack8((qsw >> qshift) & 0x0F0F0F0Fu);
|
| 1174 |
+
const vec4 ret = vec4(
|
| 1175 |
+
float(kvalues_iq4nl[qv.x]),
|
| 1176 |
+
float(kvalues_iq4nl[qv.y]),
|
| 1177 |
+
float(kvalues_iq4nl[qv.z]),
|
| 1178 |
+
float(kvalues_iq4nl[qv.w])) * float(dl);
|
| 1179 |
+
return f16vec4(ret);
|
| 1180 |
+
}
|
| 1181 |
+
#endif
|
| 1182 |
+
|
| 1183 |
+
#if defined(DATA_A_IQ4_NL)
|
| 1184 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_NL {
|
| 1185 |
+
block_iq4_nl block;
|
| 1186 |
+
};
|
| 1187 |
+
|
| 1188 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_NL_packed16 {
|
| 1189 |
+
block_iq4_nl_packed16 block;
|
| 1190 |
+
};
|
| 1191 |
+
|
| 1192 |
+
float16_t dequantFuncIQ4_NL(const in decodeBufIQ4_NL bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1193 |
+
{
|
| 1194 |
+
const float16_t d = bl.block.d;
|
| 1195 |
+
const uint idx = coordInBlock[1];
|
| 1196 |
+
const uint iqs = idx & 0xF;
|
| 1197 |
+
const uint shift = (idx & 0x10) >> 2;
|
| 1198 |
+
uint32_t qs = bl.block.qs[iqs];
|
| 1199 |
+
qs >>= shift;
|
| 1200 |
+
qs &= 0xF;
|
| 1201 |
+
float16_t ret = float16_t(kvalues_iq4nl[qs]) * d;
|
| 1202 |
+
return ret;
|
| 1203 |
+
}
|
| 1204 |
+
|
| 1205 |
+
f16vec4 dequantFuncIQ4_NL_v(const in decodeBufIQ4_NL bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1206 |
+
{
|
| 1207 |
+
decodeBufIQ4_NL_packed16 bl16 = decodeBufIQ4_NL_packed16(bl);
|
| 1208 |
+
const float16_t d = bl.block.d;
|
| 1209 |
+
const uint idx = coordInBlock[1];
|
| 1210 |
+
const uint shift = (idx & 0x10) >> 2; // 0 or 4
|
| 1211 |
+
const uint qs_i = (idx & 0xC) >> 1; // packed16 word index, in {0,2,4,6}
|
| 1212 |
+
const uint qsw = uint32_t(bl16.block.qs[qs_i ])
|
| 1213 |
+
| (uint32_t(bl16.block.qs[qs_i + 1u]) << 16);
|
| 1214 |
+
// shift in {0,4}: per-byte mask 0x0F isolates the wanted nibble in each byte.
|
| 1215 |
+
const u8vec4 q = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
|
| 1216 |
+
return f16vec4(
|
| 1217 |
+
float(d) * float(kvalues_iq4nl[q.x]),
|
| 1218 |
+
float(d) * float(kvalues_iq4nl[q.y]),
|
| 1219 |
+
float(d) * float(kvalues_iq4nl[q.z]),
|
| 1220 |
+
float(d) * float(kvalues_iq4nl[q.w]));
|
| 1221 |
+
}
|
| 1222 |
+
#endif
|
| 1223 |
+
|
| 1224 |
+
#if defined(DATA_A_MXFP4)
|
| 1225 |
+
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufMXFP4 {
|
| 1226 |
+
block_mxfp4 block;
|
| 1227 |
+
};
|
| 1228 |
+
|
| 1229 |
+
float16_t dequantFuncMXFP4(const in decodeBufMXFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1230 |
+
{
|
| 1231 |
+
const float d = e8m0_to_fp32(bl.block.e);
|
| 1232 |
+
const uint idx = coordInBlock[1];
|
| 1233 |
+
const uint iqs = idx & 0xF;
|
| 1234 |
+
const uint shift = (idx & 0x10) >> 2;
|
| 1235 |
+
uint32_t qs = bl.block.qs[iqs];
|
| 1236 |
+
qs >>= shift;
|
| 1237 |
+
qs &= 0xF;
|
| 1238 |
+
float16_t ret = float16_t(kvalues_mxfp4[qs] * d * 0.5);
|
| 1239 |
+
return ret;
|
| 1240 |
+
}
|
| 1241 |
+
|
| 1242 |
+
f16vec4 dequantFuncMXFP4_v(const in decodeBufMXFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1243 |
+
{
|
| 1244 |
+
const float d = e8m0_to_fp32(bl.block.e);
|
| 1245 |
+
const uint idx = coordInBlock[1];
|
| 1246 |
+
const uint iqs = idx & 0xF;
|
| 1247 |
+
const uint shift = (idx & 0x10) >> 2;
|
| 1248 |
+
uvec4 qv = uvec4(
|
| 1249 |
+
uint(bl.block.qs[iqs]),
|
| 1250 |
+
uint(bl.block.qs[iqs + 1u]),
|
| 1251 |
+
uint(bl.block.qs[iqs + 2u]),
|
| 1252 |
+
uint(bl.block.qs[iqs + 3u]));
|
| 1253 |
+
qv = (qv >> shift) & 0xFu;
|
| 1254 |
+
const vec4 ret = vec4(
|
| 1255 |
+
float(kvalues_mxfp4[qv.x]),
|
| 1256 |
+
float(kvalues_mxfp4[qv.y]),
|
| 1257 |
+
float(kvalues_mxfp4[qv.z]),
|
| 1258 |
+
float(kvalues_mxfp4[qv.w])) * d * 0.5f;
|
| 1259 |
+
return f16vec4(ret);
|
| 1260 |
+
}
|
| 1261 |
+
#endif
|
| 1262 |
+
|
| 1263 |
+
#if defined(DATA_A_NVFP4)
|
| 1264 |
+
layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufNVFP4 {
|
| 1265 |
+
block_nvfp4 block;
|
| 1266 |
+
};
|
| 1267 |
+
|
| 1268 |
+
layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufNVFP4_packed32 {
|
| 1269 |
+
block_nvfp4_packed32 block;
|
| 1270 |
+
};
|
| 1271 |
+
|
| 1272 |
+
float16_t dequantFuncNVFP4(const in decodeBufNVFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1273 |
+
{
|
| 1274 |
+
const uint idx = coordInBlock[1];
|
| 1275 |
+
const uint sub = (idx & 0x30) >> 4;
|
| 1276 |
+
const uint iqs = ((idx & 0x30) >> 1) + (idx & 0x7);
|
| 1277 |
+
const uint shift = (idx & 0x8) >> 1;
|
| 1278 |
+
const float d = ue4m3_to_fp32(bl.block.d[sub]);
|
| 1279 |
+
uint qs = uint(bl.block.qs[iqs]);
|
| 1280 |
+
qs = (qs >> shift) & 0xF;
|
| 1281 |
+
return float16_t(kvalues_mxfp4[qs] * d * 0.5);
|
| 1282 |
+
}
|
| 1283 |
+
|
| 1284 |
+
f16vec4 dequantFuncNVFP4_v(const in decodeBufNVFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
| 1285 |
+
{
|
| 1286 |
+
decodeBufNVFP4_packed32 bl32 = decodeBufNVFP4_packed32(bl);
|
| 1287 |
+
const uint idx = coordInBlock[1];
|
| 1288 |
+
const uint sub = idx >> 4;
|
| 1289 |
+
const uint qs_w = ((idx & 0x30) >> 3) + ((idx & 0x4u) >> 2); // iqs / 4, in [0,8)
|
| 1290 |
+
const uint shift = (idx & 0x8) >> 1;
|
| 1291 |
+
const float d = ue4m3_to_fp32(bl.block.d[sub]);
|
| 1292 |
+
|
| 1293 |
+
const uint qsw = uint32_t(bl32.block.qs[qs_w]);
|
| 1294 |
+
const u8vec4 qv = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
|
| 1295 |
+
const vec4 ret = vec4(
|
| 1296 |
+
float(kvalues_mxfp4[qv.x]),
|
| 1297 |
+
float(kvalues_mxfp4[qv.y]),
|
| 1298 |
+
float(kvalues_mxfp4[qv.z]),
|
| 1299 |
+
float(kvalues_mxfp4[qv.w])) * d * 0.5f;
|
| 1300 |
+
return f16vec4(ret);
|
| 1301 |
+
}
|
| 1302 |
+
#endif
|
| 1303 |
+
|
| 1304 |
+
#if defined(DATA_A_Q1_0)
|
| 1305 |
+
#define dequantFuncA dequantFuncQ1_0
|
| 1306 |
+
#define dequantFuncA_v dequantFuncQ1_0_v
|
| 1307 |
+
#elif defined(DATA_A_Q4_0)
|
| 1308 |
+
#define dequantFuncA dequantFuncQ4_0
|
| 1309 |
+
#define dequantFuncA_v dequantFuncQ4_0_v
|
| 1310 |
+
#elif defined(DATA_A_Q4_1)
|
| 1311 |
+
#define dequantFuncA dequantFuncQ4_1
|
| 1312 |
+
#define dequantFuncA_v dequantFuncQ4_1_v
|
| 1313 |
+
#elif defined(DATA_A_Q5_0)
|
| 1314 |
+
#define dequantFuncA dequantFuncQ5_0
|
| 1315 |
+
#define dequantFuncA_v dequantFuncQ5_0_v
|
| 1316 |
+
#elif defined(DATA_A_Q5_1)
|
| 1317 |
+
#define dequantFuncA dequantFuncQ5_1
|
| 1318 |
+
#define dequantFuncA_v dequantFuncQ5_1_v
|
| 1319 |
+
#elif defined(DATA_A_Q8_0)
|
| 1320 |
+
#define dequantFuncA dequantFuncQ8_0
|
| 1321 |
+
#define dequantFuncA_v dequantFuncQ8_0_v
|
| 1322 |
+
#elif defined(DATA_A_Q2_K)
|
| 1323 |
+
#define dequantFuncA dequantFuncQ2_K
|
| 1324 |
+
#define dequantFuncA_v dequantFuncQ2_K_v
|
| 1325 |
+
#elif defined(DATA_A_Q3_K)
|
| 1326 |
+
#define dequantFuncA dequantFuncQ3_K
|
| 1327 |
+
#define dequantFuncA_v dequantFuncQ3_K_v
|
| 1328 |
+
#elif defined(DATA_A_Q4_K)
|
| 1329 |
+
#define dequantFuncA dequantFuncQ4_K
|
| 1330 |
+
#define dequantFuncA_v dequantFuncQ4_K_v
|
| 1331 |
+
#define fetch_scales fetch_scalesQ4_K
|
| 1332 |
+
#define store_scales store_scalesQ4_K
|
| 1333 |
+
#elif defined(DATA_A_Q5_K)
|
| 1334 |
+
#define dequantFuncA dequantFuncQ5_K
|
| 1335 |
+
#define dequantFuncA_v dequantFuncQ5_K_v
|
| 1336 |
+
#define fetch_scales fetch_scalesQ5_K
|
| 1337 |
+
#define store_scales store_scalesQ4_K
|
| 1338 |
+
#elif defined(DATA_A_Q6_K)
|
| 1339 |
+
#define dequantFuncA dequantFuncQ6_K
|
| 1340 |
+
#define dequantFuncA_v dequantFuncQ6_K_v
|
| 1341 |
+
#elif defined(DATA_A_IQ1_S)
|
| 1342 |
+
#define dequantFuncA dequantFuncIQ1_S
|
| 1343 |
+
#define dequantFuncA_v dequantFuncIQ1_S_v
|
| 1344 |
+
#elif defined(DATA_A_IQ1_M)
|
| 1345 |
+
#define dequantFuncA dequantFuncIQ1_M
|
| 1346 |
+
#define dequantFuncA_v dequantFuncIQ1_M_v
|
| 1347 |
+
#elif defined(DATA_A_IQ2_XXS)
|
| 1348 |
+
#define dequantFuncA dequantFuncIQ2_XXS
|
| 1349 |
+
#define dequantFuncA_v dequantFuncIQ2_XXS_v
|
| 1350 |
+
#elif defined(DATA_A_IQ2_XS)
|
| 1351 |
+
#define dequantFuncA dequantFuncIQ2_XS
|
| 1352 |
+
#define dequantFuncA_v dequantFuncIQ2_XS_v
|
| 1353 |
+
#elif defined(DATA_A_IQ2_S)
|
| 1354 |
+
#define dequantFuncA dequantFuncIQ2_S
|
| 1355 |
+
#define dequantFuncA_v dequantFuncIQ2_S_v
|
| 1356 |
+
#elif defined(DATA_A_IQ3_XXS)
|
| 1357 |
+
#define dequantFuncA dequantFuncIQ3_XXS
|
| 1358 |
+
#define dequantFuncA_v dequantFuncIQ3_XXS_v
|
| 1359 |
+
#elif defined(DATA_A_IQ3_S)
|
| 1360 |
+
#define dequantFuncA dequantFuncIQ3_S
|
| 1361 |
+
#define dequantFuncA_v dequantFuncIQ3_S_v
|
| 1362 |
+
#elif defined(DATA_A_IQ4_XS)
|
| 1363 |
+
#define dequantFuncA dequantFuncIQ4_XS
|
| 1364 |
+
#define dequantFuncA_v dequantFuncIQ4_XS_v
|
| 1365 |
+
#elif defined(DATA_A_IQ4_NL)
|
| 1366 |
+
#define dequantFuncA dequantFuncIQ4_NL
|
| 1367 |
+
#define dequantFuncA_v dequantFuncIQ4_NL_v
|
| 1368 |
+
#elif defined(DATA_A_MXFP4)
|
| 1369 |
+
#define dequantFuncA dequantFuncMXFP4
|
| 1370 |
+
#define dequantFuncA_v dequantFuncMXFP4_v
|
| 1371 |
+
#elif defined(DATA_A_NVFP4)
|
| 1372 |
+
#define dequantFuncA dequantFuncNVFP4
|
| 1373 |
+
#define dequantFuncA_v dequantFuncNVFP4_v
|
| 1374 |
+
#elif defined(DATA_A_F32)
|
| 1375 |
+
#define dequantFuncA dequantFuncF32
|
| 1376 |
+
#endif
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_head.glsl
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#extension GL_EXT_control_flow_attributes : require
|
| 2 |
+
#extension GL_EXT_shader_16bit_storage : require
|
| 3 |
+
|
| 4 |
+
layout (push_constant) uniform parameter
|
| 5 |
+
{
|
| 6 |
+
uint M;
|
| 7 |
+
uint K;
|
| 8 |
+
uint stride_a;
|
| 9 |
+
uint stride_b;
|
| 10 |
+
uint nel;
|
| 11 |
+
} p;
|
| 12 |
+
|
| 13 |
+
#include "types.glsl"
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_m.comp
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
|
| 4 |
+
|
| 5 |
+
#include "dequant_head.glsl"
|
| 6 |
+
|
| 7 |
+
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
| 8 |
+
|
| 9 |
+
layout (binding = 0) readonly buffer A {block_iq1_m data_a[];};
|
| 10 |
+
layout (binding = 1) writeonly buffer D {D_TYPE data_b[];};
|
| 11 |
+
|
| 12 |
+
void main() {
|
| 13 |
+
// Each thread handles 1 subblock (32 values with 2 scales)
|
| 14 |
+
const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8;
|
| 15 |
+
|
| 16 |
+
init_iq_shmem(gl_WorkGroupSize);
|
| 17 |
+
|
| 18 |
+
if (ib >= p.nel / 256) {
|
| 19 |
+
return;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
const uint ib32 = gl_LocalInvocationID.x % 8;
|
| 23 |
+
const uint ib64 = ib32 / 2;
|
| 24 |
+
const uint b_idx = 256 * ib + 32 * ib32;
|
| 25 |
+
|
| 26 |
+
const uint16_t[4] scales = data_a[ib].scales;
|
| 27 |
+
const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12;
|
| 28 |
+
const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x);
|
| 29 |
+
|
| 30 |
+
const uint sc = data_a[ib].scales[ib64];
|
| 31 |
+
[[unroll]] for (int l = 0; l < 4; ++l) {
|
| 32 |
+
const uint ib16 = 2 * ib32 + l / 2;
|
| 33 |
+
const float dl = d * (2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1);
|
| 34 |
+
const uint qh = data_a[ib].qh[ib16] >> (4 * (l & 1));
|
| 35 |
+
const uint qs = data_a[ib].qs[4 * ib32 + l];
|
| 36 |
+
const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA;
|
| 37 |
+
const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]);
|
| 38 |
+
[[unroll]] for (int j = 0; j < 8; ++j) {
|
| 39 |
+
data_b[b_idx + 8 * l + j] = D_TYPE(dl * (bitfieldExtract(grid, 2*j, 2) + delta));
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
}
|
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_s.comp
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#version 450
|
| 2 |
+
|
| 3 |
+
#include "dequant_head.glsl"
|
| 4 |
+
|
| 5 |
+
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
| 6 |
+
|
| 7 |
+
layout (binding = 0) readonly buffer A {block_iq1_s data_a[];};
|
| 8 |
+
layout (binding = 1) writeonly buffer D {D_TYPE data_b[];};
|
| 9 |
+
|
| 10 |
+
void main() {
|
| 11 |
+
// Each thread handles 1 subblock (32 values with 2 scales)
|
| 12 |
+
const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8;
|
| 13 |
+
|
| 14 |
+
init_iq_shmem(gl_WorkGroupSize);
|
| 15 |
+
|
| 16 |
+
if (ib >= p.nel / 256) {
|
| 17 |
+
return;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
const uint ib32 = gl_LocalInvocationID.x % 8;
|
| 21 |
+
const uint b_idx = 256 * ib + 32 * ib32;
|
| 22 |
+
|
| 23 |
+
uint qh = data_a[ib].qh[ib32];
|
| 24 |
+
const float d = float(data_a[ib].d);
|
| 25 |
+
const float dl = d * float(2 * bitfieldExtract(qh, 12, 3) + 1);
|
| 26 |
+
const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
|
| 27 |
+
[[unroll]] for (uint l = 0; l < 4; ++l) {
|
| 28 |
+
const uint qs = data_a[ib].qs[4 * ib32 + l];
|
| 29 |
+
const uint hi = bitfieldExtract(qh, 3 * int(l), 3);
|
| 30 |
+
const int16_t grid = int16_t(iq1s_grid[qs | (hi << 8)]);
|
| 31 |
+
[[unroll]] for (int j = 0; j < 8; ++j) {
|
| 32 |
+
data_b[b_idx + 8 * l + j] = D_TYPE(dl * (bitfieldExtract(grid, 2*j, 2) + delta));
|
| 33 |
+
}
|
| 34 |
+
}
|
| 35 |
+
}
|