Upload patch_llamacpp_hpcq_seg.py
Browse files- patch_llamacpp_hpcq_seg.py +977 -0
patch_llamacpp_hpcq_seg.py
ADDED
|
@@ -0,0 +1,977 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Patch llama.cpp to natively run HPCQ.SEG.V1 segmented Q2_K / Q3_K models
|
| 3 |
+
with ZERO weight expansion in RAM/VRAM.
|
| 4 |
+
|
| 5 |
+
How it works
|
| 6 |
+
------------
|
| 7 |
+
* Tensors remain in their native ``GGML_TYPE_Q2_K`` (2.625 bpw) and
|
| 8 |
+
``GGML_TYPE_Q3_K`` (3.4375 bpw) formats in RAM/VRAM (and stay ``mmap``-backed
|
| 9 |
+
on disk).
|
| 10 |
+
* Only the compact ``HQS1`` nibble stream (128 bytes per 256-weight superblock)
|
| 11 |
+
is bound to the tensor's payload address range in ``libggml-base``.
|
| 12 |
+
* No ``uint16_t`` order tables or ``uint8_t`` unpacked label arrays are
|
| 13 |
+
allocated on the heap. Instead, ``uint16_t ord[256]`` (512 bytes) is
|
| 14 |
+
reconstructed on the stack (CPU) or in ``__shared__`` memory (CUDA) per
|
| 15 |
+
256-weight superblock:
|
| 16 |
+
- CPU ``dequantize_row_q2_K`` / ``dequantize_row_q3_K``: scatters each block's
|
| 17 |
+
256 dequantized values via the 512-byte stack ``ord[256]``.
|
| 18 |
+
- CPU ``vec_dot`` (``ggml-cpu.c``): wraps ``ggml_vec_dot_q2_K_q8_K`` and
|
| 19 |
+
``ggml_vec_dot_q3_K_q8_K``. For unsegmented tensors it tail-calls the stock
|
| 20 |
+
SIMD kernel directly; for segmented tensors it gathers ``block_q8_K y_perm``
|
| 21 |
+
(292 bytes on the stack) per superblock and calls the native AVX2/AVX512/
|
| 22 |
+
NEON SIMD ``vec_dot`` on ``(&x[i], &y_perm)``.
|
| 23 |
+
- CUDA ``dequantize_block_q2_K`` / ``dequantize_block_q3_K`` (``convert.cu``)
|
| 24 |
+
+ ``ggml_cuda_mul_mat`` (``ggml-cuda.cu``): scatters each 256-weight
|
| 25 |
+
superblock in ``__shared__`` memory and routes segmented ``src0`` to the
|
| 26 |
+
pooled-scratch ``ggml_cuda_mul_mat_cublas`` path.
|
| 27 |
+
|
| 28 |
+
Usage
|
| 29 |
+
-----
|
| 30 |
+
python3 tools/patch_llamacpp_hpcq_seg.py --selftest
|
| 31 |
+
python3 tools/patch_llamacpp_hpcq_seg.py --llama /home/node/Desktop/Dev/llama.cpp --check
|
| 32 |
+
python3 tools/patch_llamacpp_hpcq_seg.py --llama /home/node/Desktop/Dev/llama.cpp --apply
|
| 33 |
+
python3 tools/patch_llamacpp_hpcq_seg.py --llama /home/node/Desktop/Dev/llama.cpp --revert
|
| 34 |
+
"""
|
| 35 |
+
|
| 36 |
+
from __future__ import annotations
|
| 37 |
+
|
| 38 |
+
import argparse
|
| 39 |
+
import shutil
|
| 40 |
+
import subprocess
|
| 41 |
+
import sys
|
| 42 |
+
import tempfile
|
| 43 |
+
from pathlib import Path
|
| 44 |
+
|
| 45 |
+
BEGIN = "HPCQ_SEG_PATCH_BEGIN"
|
| 46 |
+
END = "HPCQ_SEG_PATCH_END"
|
| 47 |
+
HEADER_REL = "ggml/include/hpcq-seg.h"
|
| 48 |
+
|
| 49 |
+
# --------------------------------------------------------------------------
|
| 50 |
+
# 1. C/C++/CUDA header: ggml/include/hpcq-seg.h
|
| 51 |
+
# --------------------------------------------------------------------------
|
| 52 |
+
|
| 53 |
+
HEADER = r"""// hpcq-seg.h — Zero-expansion HPCQ.SEG.V1 band-major support for Q2_K / Q3_K.
|
| 54 |
+
// Generated by HPC-Quantize tools/patch_llamacpp_hpcq_seg.py.
|
| 55 |
+
#pragma once
|
| 56 |
+
|
| 57 |
+
#include <stdint.h>
|
| 58 |
+
#include <stddef.h>
|
| 59 |
+
#include <string.h>
|
| 60 |
+
#include <stdbool.h>
|
| 61 |
+
#include "ggml.h"
|
| 62 |
+
|
| 63 |
+
#ifdef __cplusplus
|
| 64 |
+
extern "C" {
|
| 65 |
+
#endif
|
| 66 |
+
|
| 67 |
+
#define HPCQ_SEG_PREFIX "HPCQ.SEG.V1."
|
| 68 |
+
#define HPCQ_SEG_MAX_ENTRIES 2048
|
| 69 |
+
|
| 70 |
+
#ifdef __CUDACC__
|
| 71 |
+
#define HPCQ_HD __host__ __device__
|
| 72 |
+
#else
|
| 73 |
+
#define HPCQ_HD
|
| 74 |
+
#endif
|
| 75 |
+
|
| 76 |
+
struct hpcq_seg_entry {
|
| 77 |
+
uintptr_t base; // payload start (host ptr on CPU, device ptr on CUDA)
|
| 78 |
+
uintptr_t end; // payload end (exclusive)
|
| 79 |
+
int64_t block_bytes; // 84 for Q2_K, 110 for Q3_K
|
| 80 |
+
int64_t n_blocks; // number of 256-weight superblocks
|
| 81 |
+
uint8_t enc; // 0 = 4-bit nibbles (128B/blk), 1 = 8-bit (256B/blk)
|
| 82 |
+
uint8_t * packed; // compact packed label stream (128B or 256B per block)
|
| 83 |
+
void * dev_packed; // lazily allocated device copy for CUDA (or NULL)
|
| 84 |
+
};
|
| 85 |
+
|
| 86 |
+
GGML_API void ggml_hpcq_seg_bind_raw(
|
| 87 |
+
const void * payload, int64_t n_bytes,
|
| 88 |
+
const uint8_t * hqs1, size_t hqs1_len, int64_t block_bytes);
|
| 89 |
+
|
| 90 |
+
GGML_API const struct hpcq_seg_entry * ggml_hpcq_seg_find(
|
| 91 |
+
const void * ptr, int64_t block_bytes, int64_t * out_block_idx);
|
| 92 |
+
|
| 93 |
+
GGML_API void ggml_hpcq_seg_set_dev_packed(
|
| 94 |
+
const struct hpcq_seg_entry * entry, void * dev_packed);
|
| 95 |
+
|
| 96 |
+
// Reconstruct slot -> original_position permutation `order[256]` on the stack
|
| 97 |
+
// or in __shared__ memory from a single 256-weight block's packed labels.
|
| 98 |
+
// Matches `np.argsort(labels, kind="stable")`: slot `s` holds original pos `order[s]`.
|
| 99 |
+
static inline HPCQ_HD void hpcq_seg_make_order_block(
|
| 100 |
+
const uint8_t * blk_packed, uint8_t enc, uint16_t * order) {
|
| 101 |
+
if (enc == 0) {
|
| 102 |
+
uint16_t start[16];
|
| 103 |
+
for (int b = 0; b < 16; ++b) start[b] = 0;
|
| 104 |
+
for (int p = 0; p < 256; ++p) {
|
| 105 |
+
const uint8_t lab = (blk_packed[p >> 1] >> ((p & 1) * 4)) & 0x0F;
|
| 106 |
+
start[lab]++;
|
| 107 |
+
}
|
| 108 |
+
uint16_t acc = 0;
|
| 109 |
+
for (int b = 0; b < 16; ++b) {
|
| 110 |
+
const uint16_t c = start[b];
|
| 111 |
+
start[b] = acc;
|
| 112 |
+
acc = (uint16_t) (acc + c);
|
| 113 |
+
}
|
| 114 |
+
for (uint16_t p = 0; p < 256; ++p) {
|
| 115 |
+
const uint8_t lab = (blk_packed[p >> 1] >> ((p & 1) * 4)) & 0x0F;
|
| 116 |
+
order[start[lab]++] = p;
|
| 117 |
+
}
|
| 118 |
+
} else {
|
| 119 |
+
uint16_t start[256];
|
| 120 |
+
for (int b = 0; b < 256; ++b) start[b] = 0;
|
| 121 |
+
for (int p = 0; p < 256; ++p) start[blk_packed[p]]++;
|
| 122 |
+
uint16_t acc = 0;
|
| 123 |
+
for (int b = 0; b < 256; ++b) {
|
| 124 |
+
const uint16_t c = start[b];
|
| 125 |
+
start[b] = acc;
|
| 126 |
+
acc = (uint16_t) (acc + c);
|
| 127 |
+
}
|
| 128 |
+
for (uint16_t p = 0; p < 256; ++p) {
|
| 129 |
+
order[start[blk_packed[p]]++] = p;
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
#ifdef __cplusplus
|
| 135 |
+
}
|
| 136 |
+
#endif
|
| 137 |
+
"""
|
| 138 |
+
|
| 139 |
+
# --------------------------------------------------------------------------
|
| 140 |
+
# 2. ggml/src/ggml.c: registry implementation in libggml-base
|
| 141 |
+
# --------------------------------------------------------------------------
|
| 142 |
+
|
| 143 |
+
GGML_C_INCLUDE = f"""
|
| 144 |
+
// {BEGIN}: hpcq seg header
|
| 145 |
+
#include "hpcq-seg.h"
|
| 146 |
+
// {END}
|
| 147 |
+
"""
|
| 148 |
+
|
| 149 |
+
GGML_C_API = f"""
|
| 150 |
+
// {BEGIN}: compact nibble registry (no order/F16 expansion)
|
| 151 |
+
static int hpcq_seg_g_count = 0;
|
| 152 |
+
static struct hpcq_seg_entry hpcq_seg_g_entries[HPCQ_SEG_MAX_ENTRIES];
|
| 153 |
+
|
| 154 |
+
void ggml_hpcq_seg_bind_raw(
|
| 155 |
+
const void * payload, int64_t n_bytes,
|
| 156 |
+
const uint8_t * hqs1, size_t hqs1_len, int64_t block_bytes) {{
|
| 157 |
+
if (payload == NULL || hqs1 == NULL || n_bytes <= 0 || block_bytes <= 0) return;
|
| 158 |
+
if (hqs1_len < 10 || hqs1[0] != 'H' || hqs1[1] != 'Q' || hqs1[2] != 'S' || hqs1[3] != '1') return;
|
| 159 |
+
const uint8_t enc = hqs1[5];
|
| 160 |
+
const uint32_t n_labels = (uint32_t) hqs1[6] | ((uint32_t) hqs1[7] << 8) |
|
| 161 |
+
((uint32_t) hqs1[8] << 16) | ((uint32_t) hqs1[9] << 24);
|
| 162 |
+
if (n_labels == 0 || (n_labels % 256) != 0) return;
|
| 163 |
+
const int64_t n_blocks = (int64_t) (n_labels / 256);
|
| 164 |
+
if (n_blocks * block_bytes != n_bytes) return;
|
| 165 |
+
const size_t stride = (enc == 0) ? 128u : 256u;
|
| 166 |
+
const size_t need = (size_t) n_blocks * stride;
|
| 167 |
+
if (hqs1_len < 10u + need) return;
|
| 168 |
+
|
| 169 |
+
const uintptr_t base = (uintptr_t) payload;
|
| 170 |
+
const uintptr_t end = base + (uintptr_t) n_bytes;
|
| 171 |
+
for (int i = 0; i < hpcq_seg_g_count; ++i) {{
|
| 172 |
+
if (hpcq_seg_g_entries[i].base == base) {{
|
| 173 |
+
if (hpcq_seg_g_entries[i].packed) free(hpcq_seg_g_entries[i].packed);
|
| 174 |
+
uint8_t * copy = (uint8_t *) malloc(need);
|
| 175 |
+
if (!copy) return;
|
| 176 |
+
memcpy(copy, hqs1 + 10, need);
|
| 177 |
+
hpcq_seg_g_entries[i].end = end;
|
| 178 |
+
hpcq_seg_g_entries[i].block_bytes = block_bytes;
|
| 179 |
+
hpcq_seg_g_entries[i].n_blocks = n_blocks;
|
| 180 |
+
hpcq_seg_g_entries[i].enc = enc;
|
| 181 |
+
hpcq_seg_g_entries[i].packed = copy;
|
| 182 |
+
hpcq_seg_g_entries[i].dev_packed = NULL;
|
| 183 |
+
return;
|
| 184 |
+
}}
|
| 185 |
+
}}
|
| 186 |
+
if (hpcq_seg_g_count >= HPCQ_SEG_MAX_ENTRIES) return;
|
| 187 |
+
uint8_t * copy = (uint8_t *) malloc(need);
|
| 188 |
+
if (!copy) return;
|
| 189 |
+
memcpy(copy, hqs1 + 10, need);
|
| 190 |
+
struct hpcq_seg_entry * e = &hpcq_seg_g_entries[hpcq_seg_g_count++];
|
| 191 |
+
e->base = base;
|
| 192 |
+
e->end = end;
|
| 193 |
+
e->block_bytes = block_bytes;
|
| 194 |
+
e->n_blocks = n_blocks;
|
| 195 |
+
e->enc = enc;
|
| 196 |
+
e->packed = copy;
|
| 197 |
+
e->dev_packed = NULL;
|
| 198 |
+
}}
|
| 199 |
+
|
| 200 |
+
const struct hpcq_seg_entry * ggml_hpcq_seg_find(
|
| 201 |
+
const void * ptr, int64_t block_bytes, int64_t * out_block_idx) {{
|
| 202 |
+
const uintptr_t p = (uintptr_t) ptr;
|
| 203 |
+
const int n = hpcq_seg_g_count;
|
| 204 |
+
for (int i = 0; i < n; ++i) {{
|
| 205 |
+
const struct hpcq_seg_entry * e = &hpcq_seg_g_entries[i];
|
| 206 |
+
if (p >= e->base && p < e->end && e->block_bytes == block_bytes) {{
|
| 207 |
+
if (out_block_idx) {{
|
| 208 |
+
*out_block_idx = (int64_t) ((p - e->base) / (uintptr_t) block_bytes);
|
| 209 |
+
}}
|
| 210 |
+
return e;
|
| 211 |
+
}}
|
| 212 |
+
}}
|
| 213 |
+
return NULL;
|
| 214 |
+
}}
|
| 215 |
+
|
| 216 |
+
void ggml_hpcq_seg_set_dev_packed(const struct hpcq_seg_entry * entry, void * dev_packed) {{
|
| 217 |
+
if (!entry) return;
|
| 218 |
+
const int n = hpcq_seg_g_count;
|
| 219 |
+
for (int i = 0; i < n; ++i) {{
|
| 220 |
+
if (&hpcq_seg_g_entries[i] == entry) {{
|
| 221 |
+
hpcq_seg_g_entries[i].dev_packed = dev_packed;
|
| 222 |
+
return;
|
| 223 |
+
}}
|
| 224 |
+
}}
|
| 225 |
+
}}
|
| 226 |
+
// {END}
|
| 227 |
+
"""
|
| 228 |
+
|
| 229 |
+
# --------------------------------------------------------------------------
|
| 230 |
+
# 3. ggml/src/ggml-quants.c: stack-based scatter in dequantize_row_q2_K / q3_K
|
| 231 |
+
# --------------------------------------------------------------------------
|
| 232 |
+
|
| 233 |
+
Q2K_DEQ_OLD = """ const int nb = k / QK_K;
|
| 234 |
+
|
| 235 |
+
for (int i = 0; i < nb; i++) {
|
| 236 |
+
|
| 237 |
+
const float d = GGML_FP16_TO_FP32(x[i].d);
|
| 238 |
+
const float min = GGML_FP16_TO_FP32(x[i].dmin);
|
| 239 |
+
|
| 240 |
+
const uint8_t * q = x[i].qs;
|
| 241 |
+
|
| 242 |
+
int is = 0;
|
| 243 |
+
float dl, ml;
|
| 244 |
+
for (int n = 0; n < QK_K; n += 128) {
|
| 245 |
+
int shift = 0;
|
| 246 |
+
for (int j = 0; j < 4; ++j) {
|
| 247 |
+
|
| 248 |
+
uint8_t sc = x[i].scales[is++];
|
| 249 |
+
dl = d * (sc & 0xF); ml = min * (sc >> 4);
|
| 250 |
+
for (int l = 0; l < 16; ++l) *y++ = dl * ((int8_t)((q[l] >> shift) & 3)) - ml;
|
| 251 |
+
|
| 252 |
+
sc = x[i].scales[is++];
|
| 253 |
+
dl = d * (sc & 0xF); ml = min * (sc >> 4);
|
| 254 |
+
for (int l = 0; l < 16; ++l) *y++ = dl * ((int8_t)((q[l+16] >> shift) & 3)) - ml;
|
| 255 |
+
|
| 256 |
+
shift += 2;
|
| 257 |
+
}
|
| 258 |
+
q += 32;
|
| 259 |
+
}
|
| 260 |
+
}
|
| 261 |
+
}"""
|
| 262 |
+
|
| 263 |
+
Q2K_DEQ_NEW = f""" const int nb = k / QK_K;
|
| 264 |
+
|
| 265 |
+
// {BEGIN}: stack-based per-block scatter for segmented Q2_K
|
| 266 |
+
int64_t hpcq_b0 = 0;
|
| 267 |
+
const struct hpcq_seg_entry * hpcq_seg = ggml_hpcq_seg_find(x, (int64_t) sizeof(block_q2_K), &hpcq_b0);
|
| 268 |
+
const size_t hpcq_stride = (hpcq_seg && hpcq_seg->enc != 0) ? 256u : 128u;
|
| 269 |
+
uint16_t hpcq_ord[QK_K];
|
| 270 |
+
// {END}
|
| 271 |
+
|
| 272 |
+
for (int i = 0; i < nb; i++) {{
|
| 273 |
+
|
| 274 |
+
float * y_out = y + i * QK_K;
|
| 275 |
+
if (hpcq_seg) {{
|
| 276 |
+
hpcq_seg_make_order_block(hpcq_seg->packed + (size_t) (hpcq_b0 + i) * hpcq_stride, hpcq_seg->enc, hpcq_ord);
|
| 277 |
+
}}
|
| 278 |
+
|
| 279 |
+
const float d = GGML_FP16_TO_FP32(x[i].d);
|
| 280 |
+
const float min = GGML_FP16_TO_FP32(x[i].dmin);
|
| 281 |
+
|
| 282 |
+
const uint8_t * q = x[i].qs;
|
| 283 |
+
|
| 284 |
+
int is = 0;
|
| 285 |
+
int base = 0;
|
| 286 |
+
float dl, ml;
|
| 287 |
+
for (int n = 0; n < QK_K; n += 128) {{
|
| 288 |
+
int shift = 0;
|
| 289 |
+
for (int j = 0; j < 4; ++j) {{
|
| 290 |
+
|
| 291 |
+
uint8_t sc = x[i].scales[is++];
|
| 292 |
+
dl = d * (sc & 0xF); ml = min * (sc >> 4);
|
| 293 |
+
for (int l = 0; l < 16; ++l) {{
|
| 294 |
+
const float v = dl * ((int8_t)((q[l] >> shift) & 3)) - ml;
|
| 295 |
+
if (hpcq_seg) y_out[hpcq_ord[base + l]] = v; else y_out[base + l] = v;
|
| 296 |
+
}}
|
| 297 |
+
base += 16;
|
| 298 |
+
|
| 299 |
+
sc = x[i].scales[is++];
|
| 300 |
+
dl = d * (sc & 0xF); ml = min * (sc >> 4);
|
| 301 |
+
for (int l = 0; l < 16; ++l) {{
|
| 302 |
+
const float v = dl * ((int8_t)((q[l+16] >> shift) & 3)) - ml;
|
| 303 |
+
if (hpcq_seg) y_out[hpcq_ord[base + l]] = v; else y_out[base + l] = v;
|
| 304 |
+
}}
|
| 305 |
+
base += 16;
|
| 306 |
+
|
| 307 |
+
shift += 2;
|
| 308 |
+
}}
|
| 309 |
+
q += 32;
|
| 310 |
+
}}
|
| 311 |
+
}}
|
| 312 |
+
}}"""
|
| 313 |
+
|
| 314 |
+
Q3K_DEQ_OLD = """ for (int i = 0; i < nb; i++) {
|
| 315 |
+
|
| 316 |
+
const float d_all = GGML_FP16_TO_FP32(x[i].d);
|
| 317 |
+
|
| 318 |
+
const uint8_t * GGML_RESTRICT q = x[i].qs;
|
| 319 |
+
const uint8_t * GGML_RESTRICT hm = x[i].hmask;
|
| 320 |
+
uint8_t m = 1;
|
| 321 |
+
|
| 322 |
+
memcpy(aux, x[i].scales, 12);
|
| 323 |
+
uint32_t tmp = aux[2];
|
| 324 |
+
aux[2] = ((aux[0] >> 4) & kmask2) | (((tmp >> 4) & kmask1) << 4);
|
| 325 |
+
aux[3] = ((aux[1] >> 4) & kmask2) | (((tmp >> 6) & kmask1) << 4);
|
| 326 |
+
aux[0] = (aux[0] & kmask2) | (((tmp >> 0) & kmask1) << 4);
|
| 327 |
+
aux[1] = (aux[1] & kmask2) | (((tmp >> 2) & kmask1) << 4);
|
| 328 |
+
|
| 329 |
+
int is = 0;
|
| 330 |
+
float dl;
|
| 331 |
+
for (int n = 0; n < QK_K; n += 128) {
|
| 332 |
+
int shift = 0;
|
| 333 |
+
for (int j = 0; j < 4; ++j) {
|
| 334 |
+
|
| 335 |
+
dl = d_all * (scales[is++] - 32);
|
| 336 |
+
for (int l = 0; l < 16; ++l) {
|
| 337 |
+
*y++ = dl * ((int8_t)((q[l+ 0] >> shift) & 3) - ((hm[l+ 0] & m) ? 0 : 4));
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
dl = d_all * (scales[is++] - 32);
|
| 341 |
+
for (int l = 0; l < 16; ++l) {
|
| 342 |
+
*y++ = dl * ((int8_t)((q[l+16] >> shift) & 3) - ((hm[l+16] & m) ? 0 : 4));
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
shift += 2;
|
| 346 |
+
m <<= 1;
|
| 347 |
+
}
|
| 348 |
+
q += 32;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
}
|
| 352 |
+
}"""
|
| 353 |
+
|
| 354 |
+
Q3K_DEQ_NEW = f""" // {BEGIN}: stack-based per-block scatter for segmented Q3_K
|
| 355 |
+
int64_t hpcq_b0 = 0;
|
| 356 |
+
const struct hpcq_seg_entry * hpcq_seg = ggml_hpcq_seg_find(x, (int64_t) sizeof(block_q3_K), &hpcq_b0);
|
| 357 |
+
const size_t hpcq_stride = (hpcq_seg && hpcq_seg->enc != 0) ? 256u : 128u;
|
| 358 |
+
uint16_t hpcq_ord[QK_K];
|
| 359 |
+
// {END}
|
| 360 |
+
|
| 361 |
+
for (int i = 0; i < nb; i++) {{
|
| 362 |
+
|
| 363 |
+
float * y_out = y + i * QK_K;
|
| 364 |
+
if (hpcq_seg) {{
|
| 365 |
+
hpcq_seg_make_order_block(hpcq_seg->packed + (size_t) (hpcq_b0 + i) * hpcq_stride, hpcq_seg->enc, hpcq_ord);
|
| 366 |
+
}}
|
| 367 |
+
|
| 368 |
+
const float d_all = GGML_FP16_TO_FP32(x[i].d);
|
| 369 |
+
|
| 370 |
+
const uint8_t * GGML_RESTRICT q = x[i].qs;
|
| 371 |
+
const uint8_t * GGML_RESTRICT hm = x[i].hmask;
|
| 372 |
+
uint8_t m = 1;
|
| 373 |
+
|
| 374 |
+
memcpy(aux, x[i].scales, 12);
|
| 375 |
+
uint32_t tmp = aux[2];
|
| 376 |
+
aux[2] = ((aux[0] >> 4) & kmask2) | (((tmp >> 4) & kmask1) << 4);
|
| 377 |
+
aux[3] = ((aux[1] >> 4) & kmask2) | (((tmp >> 6) & kmask1) << 4);
|
| 378 |
+
aux[0] = (aux[0] & kmask2) | (((tmp >> 0) & kmask1) << 4);
|
| 379 |
+
aux[1] = (aux[1] & kmask2) | (((tmp >> 2) & kmask1) << 4);
|
| 380 |
+
|
| 381 |
+
int is = 0;
|
| 382 |
+
int base = 0;
|
| 383 |
+
float dl;
|
| 384 |
+
for (int n = 0; n < QK_K; n += 128) {{
|
| 385 |
+
int shift = 0;
|
| 386 |
+
for (int j = 0; j < 4; ++j) {{
|
| 387 |
+
|
| 388 |
+
dl = d_all * (scales[is++] - 32);
|
| 389 |
+
for (int l = 0; l < 16; ++l) {{
|
| 390 |
+
const float v = dl * ((int8_t)((q[l+ 0] >> shift) & 3) - ((hm[l+ 0] & m) ? 0 : 4));
|
| 391 |
+
if (hpcq_seg) y_out[hpcq_ord[base + l]] = v; else y_out[base + l] = v;
|
| 392 |
+
}}
|
| 393 |
+
base += 16;
|
| 394 |
+
|
| 395 |
+
dl = d_all * (scales[is++] - 32);
|
| 396 |
+
for (int l = 0; l < 16; ++l) {{
|
| 397 |
+
const float v = dl * ((int8_t)((q[l+16] >> shift) & 3) - ((hm[l+16] & m) ? 0 : 4));
|
| 398 |
+
if (hpcq_seg) y_out[hpcq_ord[base + l]] = v; else y_out[base + l] = v;
|
| 399 |
+
}}
|
| 400 |
+
base += 16;
|
| 401 |
+
|
| 402 |
+
shift += 2;
|
| 403 |
+
m <<= 1;
|
| 404 |
+
}}
|
| 405 |
+
q += 32;
|
| 406 |
+
}}
|
| 407 |
+
|
| 408 |
+
}}
|
| 409 |
+
}}"""
|
| 410 |
+
|
| 411 |
+
# --------------------------------------------------------------------------
|
| 412 |
+
# 4. ggml/src/ggml-cpu/ggml-cpu.c: stack-gathered SIMD vec_dot wrappers
|
| 413 |
+
# --------------------------------------------------------------------------
|
| 414 |
+
|
| 415 |
+
CPU_VECDOT_WRAPPERS = f"""
|
| 416 |
+
// {BEGIN}: stack-gathered SIMD vec_dot wrappers for segmented Q2_K / Q3_K
|
| 417 |
+
#include "hpcq-seg.h"
|
| 418 |
+
|
| 419 |
+
static void hpcq_vec_dot_q2_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {{
|
| 420 |
+
int64_t b0 = 0;
|
| 421 |
+
const struct hpcq_seg_entry * seg = ggml_hpcq_seg_find(vx, (int64_t) sizeof(block_q2_K), &b0);
|
| 422 |
+
if (seg == NULL) {{
|
| 423 |
+
ggml_vec_dot_q2_K_q8_K(n, s, bs, vx, bx, vy, by, nrc);
|
| 424 |
+
return;
|
| 425 |
+
}}
|
| 426 |
+
const block_q2_K * GGML_RESTRICT x = (const block_q2_K *) vx;
|
| 427 |
+
const block_q8_K * GGML_RESTRICT y = (const block_q8_K *) vy;
|
| 428 |
+
const int nb = n / QK_K;
|
| 429 |
+
const size_t stride = (seg->enc != 0) ? 256u : 128u;
|
| 430 |
+
uint16_t ord[QK_K];
|
| 431 |
+
block_q8_K y_perm;
|
| 432 |
+
float sumf = 0.0f;
|
| 433 |
+
for (int i = 0; i < nb; ++i) {{
|
| 434 |
+
hpcq_seg_make_order_block(seg->packed + (size_t) (b0 + i) * stride, seg->enc, ord);
|
| 435 |
+
y_perm.d = y[i].d;
|
| 436 |
+
for (int g = 0; g < 16; ++g) {{
|
| 437 |
+
int16_t bsum = 0;
|
| 438 |
+
for (int l = 0; l < 16; ++l) {{
|
| 439 |
+
const int8_t qv = y[i].qs[ord[16 * g + l]];
|
| 440 |
+
y_perm.qs[16 * g + l] = qv;
|
| 441 |
+
bsum = (int16_t) (bsum + qv);
|
| 442 |
+
}}
|
| 443 |
+
y_perm.bsums[g] = bsum;
|
| 444 |
+
}}
|
| 445 |
+
float blk_s = 0.0f;
|
| 446 |
+
ggml_vec_dot_q2_K_q8_K(QK_K, &blk_s, bs, &x[i], bx, &y_perm, by, 1);
|
| 447 |
+
sumf += blk_s;
|
| 448 |
+
}}
|
| 449 |
+
*s = sumf;
|
| 450 |
+
}}
|
| 451 |
+
|
| 452 |
+
static void hpcq_vec_dot_q3_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {{
|
| 453 |
+
int64_t b0 = 0;
|
| 454 |
+
const struct hpcq_seg_entry * seg = ggml_hpcq_seg_find(vx, (int64_t) sizeof(block_q3_K), &b0);
|
| 455 |
+
if (seg == NULL) {{
|
| 456 |
+
ggml_vec_dot_q3_K_q8_K(n, s, bs, vx, bx, vy, by, nrc);
|
| 457 |
+
return;
|
| 458 |
+
}}
|
| 459 |
+
const block_q3_K * GGML_RESTRICT x = (const block_q3_K *) vx;
|
| 460 |
+
const block_q8_K * GGML_RESTRICT y = (const block_q8_K *) vy;
|
| 461 |
+
const int nb = n / QK_K;
|
| 462 |
+
const size_t stride = (seg->enc != 0) ? 256u : 128u;
|
| 463 |
+
uint16_t ord[QK_K];
|
| 464 |
+
block_q8_K y_perm;
|
| 465 |
+
float sumf = 0.0f;
|
| 466 |
+
for (int i = 0; i < nb; ++i) {{
|
| 467 |
+
hpcq_seg_make_order_block(seg->packed + (size_t) (b0 + i) * stride, seg->enc, ord);
|
| 468 |
+
y_perm.d = y[i].d;
|
| 469 |
+
for (int g = 0; g < 16; ++g) {{
|
| 470 |
+
int16_t bsum = 0;
|
| 471 |
+
for (int l = 0; l < 16; ++l) {{
|
| 472 |
+
const int8_t qv = y[i].qs[ord[16 * g + l]];
|
| 473 |
+
y_perm.qs[16 * g + l] = qv;
|
| 474 |
+
bsum = (int16_t) (bsum + qv);
|
| 475 |
+
}}
|
| 476 |
+
y_perm.bsums[g] = bsum;
|
| 477 |
+
}}
|
| 478 |
+
float blk_s = 0.0f;
|
| 479 |
+
ggml_vec_dot_q3_K_q8_K(QK_K, &blk_s, bs, &x[i], bx, &y_perm, by, 1);
|
| 480 |
+
sumf += blk_s;
|
| 481 |
+
}}
|
| 482 |
+
*s = sumf;
|
| 483 |
+
}}
|
| 484 |
+
// {END}
|
| 485 |
+
"""
|
| 486 |
+
|
| 487 |
+
CPU_TRAITS_OLD = """ [GGML_TYPE_Q2_K] = {
|
| 488 |
+
.from_float = quantize_row_q2_K,
|
| 489 |
+
.vec_dot = ggml_vec_dot_q2_K_q8_K,
|
| 490 |
+
.vec_dot_type = GGML_TYPE_Q8_K,
|
| 491 |
+
.nrows = 1,
|
| 492 |
+
},
|
| 493 |
+
[GGML_TYPE_Q3_K] = {
|
| 494 |
+
.from_float = quantize_row_q3_K,
|
| 495 |
+
.vec_dot = ggml_vec_dot_q3_K_q8_K,
|
| 496 |
+
.vec_dot_type = GGML_TYPE_Q8_K,
|
| 497 |
+
.nrows = 1,
|
| 498 |
+
},"""
|
| 499 |
+
|
| 500 |
+
CPU_TRAITS_NEW = f""" [GGML_TYPE_Q2_K] = {{
|
| 501 |
+
.from_float = quantize_row_q2_K,
|
| 502 |
+
.vec_dot = hpcq_vec_dot_q2_K_q8_K, // {BEGIN}
|
| 503 |
+
.vec_dot_type = GGML_TYPE_Q8_K,
|
| 504 |
+
.nrows = 1,
|
| 505 |
+
}},
|
| 506 |
+
[GGML_TYPE_Q3_K] = {{
|
| 507 |
+
.from_float = quantize_row_q3_K,
|
| 508 |
+
.vec_dot = hpcq_vec_dot_q3_K_q8_K, // {END}
|
| 509 |
+
.vec_dot_type = GGML_TYPE_Q8_K,
|
| 510 |
+
.nrows = 1,
|
| 511 |
+
}},"""
|
| 512 |
+
|
| 513 |
+
# --------------------------------------------------------------------------
|
| 514 |
+
# 5. ggml/src/ggml-cuda/convert.cu & ggml-cuda.cu: shared-mem scatter on GPU
|
| 515 |
+
# --------------------------------------------------------------------------
|
| 516 |
+
|
| 517 |
+
CUDA_CONVERT_OLD_KERNELS = """template<typename dst_t>
|
| 518 |
+
static __global__ void dequantize_block_q2_K(const void * __restrict__ vx, dst_t * __restrict__ yy) {
|
| 519 |
+
const int64_t i = blockIdx.x;
|
| 520 |
+
|
| 521 |
+
dequantize_q2_K(vx, i, yy + i*QK_K, threadIdx.x);
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
template<typename dst_t>
|
| 525 |
+
static __global__ void dequantize_block_q3_K(const void * __restrict__ vx, dst_t * __restrict__ yy) {
|
| 526 |
+
const int64_t i = blockIdx.x;
|
| 527 |
+
|
| 528 |
+
dequantize_q3_K(vx, i, yy + i*QK_K, threadIdx.x);
|
| 529 |
+
}"""
|
| 530 |
+
|
| 531 |
+
CUDA_CONVERT_NEW_KERNELS = f"""// {BEGIN}: shared-memory per-block scatter for segmented Q2_K / Q3_K on CUDA
|
| 532 |
+
#include "hpcq-seg.h"
|
| 533 |
+
|
| 534 |
+
static inline const uint8_t * hpcq_cuda_get_dev_packed(
|
| 535 |
+
const void * vx, int64_t bs, int64_t * out_b0, uint8_t * out_enc) {{
|
| 536 |
+
const struct hpcq_seg_entry * seg = ggml_hpcq_seg_find(vx, bs, out_b0);
|
| 537 |
+
if (!seg) return nullptr;
|
| 538 |
+
*out_enc = seg->enc;
|
| 539 |
+
if (seg->dev_packed == nullptr) {{
|
| 540 |
+
const size_t stride = (seg->enc != 0) ? 256u : 128u;
|
| 541 |
+
const size_t nbytes = (size_t) seg->n_blocks * stride;
|
| 542 |
+
void * d_ptr = nullptr;
|
| 543 |
+
if (cudaMalloc(&d_ptr, nbytes) == cudaSuccess && d_ptr != nullptr) {{
|
| 544 |
+
if (cudaMemcpy(d_ptr, seg->packed, nbytes, cudaMemcpyHostToDevice) == cudaSuccess) {{
|
| 545 |
+
ggml_hpcq_seg_set_dev_packed(seg, d_ptr);
|
| 546 |
+
}} else {{
|
| 547 |
+
cudaFree(d_ptr);
|
| 548 |
+
d_ptr = nullptr;
|
| 549 |
+
}}
|
| 550 |
+
}}
|
| 551 |
+
}}
|
| 552 |
+
return (const uint8_t *) seg->dev_packed;
|
| 553 |
+
}}
|
| 554 |
+
|
| 555 |
+
template<typename dst_t>
|
| 556 |
+
static __global__ void dequantize_block_q2_K(
|
| 557 |
+
const void * __restrict__ vx, dst_t * __restrict__ yy,
|
| 558 |
+
const uint8_t * __restrict__ d_packed = nullptr, int64_t b0 = 0, uint8_t enc = 0) {{
|
| 559 |
+
const int64_t i = blockIdx.x;
|
| 560 |
+
if (d_packed == nullptr) {{
|
| 561 |
+
dequantize_q2_K(vx, i, yy + i*QK_K, threadIdx.x);
|
| 562 |
+
return;
|
| 563 |
+
}}
|
| 564 |
+
__shared__ dst_t sh_y[QK_K];
|
| 565 |
+
__shared__ uint16_t sh_ord[QK_K];
|
| 566 |
+
dequantize_q2_K(vx, i, sh_y, threadIdx.x);
|
| 567 |
+
if (threadIdx.x == 0) {{
|
| 568 |
+
const size_t stride = (enc != 0) ? 256u : 128u;
|
| 569 |
+
hpcq_seg_make_order_block(d_packed + (size_t) (b0 + i) * stride, enc, sh_ord);
|
| 570 |
+
}}
|
| 571 |
+
__syncthreads();
|
| 572 |
+
dst_t * y_out = yy + i * QK_K;
|
| 573 |
+
for (int s = threadIdx.x; s < QK_K; s += 64) {{
|
| 574 |
+
y_out[sh_ord[s]] = sh_y[s];
|
| 575 |
+
}}
|
| 576 |
+
}}
|
| 577 |
+
|
| 578 |
+
template<typename dst_t>
|
| 579 |
+
static __global__ void dequantize_block_q3_K(
|
| 580 |
+
const void * __restrict__ vx, dst_t * __restrict__ yy,
|
| 581 |
+
const uint8_t * __restrict__ d_packed = nullptr, int64_t b0 = 0, uint8_t enc = 0) {{
|
| 582 |
+
const int64_t i = blockIdx.x;
|
| 583 |
+
if (d_packed == nullptr) {{
|
| 584 |
+
dequantize_q3_K(vx, i, yy + i*QK_K, threadIdx.x);
|
| 585 |
+
return;
|
| 586 |
+
}}
|
| 587 |
+
__shared__ dst_t sh_y[QK_K];
|
| 588 |
+
__shared__ uint16_t sh_ord[QK_K];
|
| 589 |
+
dequantize_q3_K(vx, i, sh_y, threadIdx.x);
|
| 590 |
+
if (threadIdx.x == 0) {{
|
| 591 |
+
const size_t stride = (enc != 0) ? 256u : 128u;
|
| 592 |
+
hpcq_seg_make_order_block(d_packed + (size_t) (b0 + i) * stride, enc, sh_ord);
|
| 593 |
+
}}
|
| 594 |
+
__syncthreads();
|
| 595 |
+
dst_t * y_out = yy + i * QK_K;
|
| 596 |
+
for (int s = threadIdx.x; s < QK_K; s += 64) {{
|
| 597 |
+
y_out[sh_ord[s]] = sh_y[s];
|
| 598 |
+
}}
|
| 599 |
+
}}
|
| 600 |
+
// {END}"""
|
| 601 |
+
|
| 602 |
+
CUDA_CONVERT_OLD_LAUNCH = """template<typename dst_t>
|
| 603 |
+
static void dequantize_row_q2_K_cuda(const void * vx, dst_t * y, const int64_t k, cudaStream_t stream) {
|
| 604 |
+
const int nb = k / QK_K;
|
| 605 |
+
dequantize_block_q2_K<<<nb, 64, 0, stream>>>(vx, y);
|
| 606 |
+
}
|
| 607 |
+
|
| 608 |
+
template<typename dst_t>
|
| 609 |
+
static void dequantize_row_q3_K_cuda(const void * vx, dst_t * y, const int64_t k, cudaStream_t stream) {
|
| 610 |
+
const int nb = k / QK_K;
|
| 611 |
+
dequantize_block_q3_K<<<nb, 64, 0, stream>>>(vx, y);
|
| 612 |
+
}"""
|
| 613 |
+
|
| 614 |
+
CUDA_CONVERT_NEW_LAUNCH = f"""template<typename dst_t>
|
| 615 |
+
static void dequantize_row_q2_K_cuda(const void * vx, dst_t * y, const int64_t k, cudaStream_t stream) {{
|
| 616 |
+
const int nb = k / QK_K;
|
| 617 |
+
int64_t b0 = 0; uint8_t enc = 0;
|
| 618 |
+
const uint8_t * d_packed = hpcq_cuda_get_dev_packed(vx, (int64_t) sizeof(block_q2_K), &b0, &enc);
|
| 619 |
+
dequantize_block_q2_K<<<nb, 64, 0, stream>>>(vx, y, d_packed, b0, enc);
|
| 620 |
+
}}
|
| 621 |
+
|
| 622 |
+
template<typename dst_t>
|
| 623 |
+
static void dequantize_row_q3_K_cuda(const void * vx, dst_t * y, const int64_t k, cudaStream_t stream) {{
|
| 624 |
+
const int nb = k / QK_K;
|
| 625 |
+
int64_t b0 = 0; uint8_t enc = 0;
|
| 626 |
+
const uint8_t * d_packed = hpcq_cuda_get_dev_packed(vx, (int64_t) sizeof(block_q3_K), &b0, &enc);
|
| 627 |
+
dequantize_block_q3_K<<<nb, 64, 0, stream>>>(vx, y, d_packed, b0, enc);
|
| 628 |
+
}}"""
|
| 629 |
+
|
| 630 |
+
CUDA_MULMAT_OLD = """ if (ggml_cuda_should_use_mmvq(src0->type, cc, ne11)) {
|
| 631 |
+
ggml_cuda_mul_mat_vec_q(ctx, src0, src1, nullptr, dst);
|
| 632 |
+
return;
|
| 633 |
+
}
|
| 634 |
+
if (ggml_cuda_should_use_mmq(src0->type, cc, ne11, /*n_experts =*/ 0)) {
|
| 635 |
+
ggml_cuda_mul_mat_q(ctx, src0, src1, nullptr, dst);
|
| 636 |
+
return;
|
| 637 |
+
}
|
| 638 |
+
ggml_cuda_mul_mat_cublas(ctx, src0, src1, dst);"""
|
| 639 |
+
|
| 640 |
+
CUDA_MULMAT_NEW = f""" // {BEGIN}: route segmented Q2_K/Q3_K to pooled-scratch cublas dequant path
|
| 641 |
+
if ((src0->type == GGML_TYPE_Q2_K || src0->type == GGML_TYPE_Q3_K) &&
|
| 642 |
+
ggml_hpcq_seg_find(src0->data, (int64_t) ggml_type_size(src0->type), nullptr) != nullptr) {{
|
| 643 |
+
ggml_cuda_mul_mat_cublas(ctx, src0, src1, dst);
|
| 644 |
+
return;
|
| 645 |
+
}}
|
| 646 |
+
// {END}
|
| 647 |
+
if (ggml_cuda_should_use_mmvq(src0->type, cc, ne11)) {{
|
| 648 |
+
ggml_cuda_mul_mat_vec_q(ctx, src0, src1, nullptr, dst);
|
| 649 |
+
return;
|
| 650 |
+
}}
|
| 651 |
+
if (ggml_cuda_should_use_mmq(src0->type, cc, ne11, /*n_experts =*/ 0)) {{
|
| 652 |
+
ggml_cuda_mul_mat_q(ctx, src0, src1, nullptr, dst);
|
| 653 |
+
return;
|
| 654 |
+
}}
|
| 655 |
+
ggml_cuda_mul_mat_cublas(ctx, src0, src1, dst);"""
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
def _read(p: Path) -> str:
|
| 659 |
+
return p.read_text(encoding="utf-8")
|
| 660 |
+
|
| 661 |
+
|
| 662 |
+
def _write(p: Path, s: str) -> None:
|
| 663 |
+
p.write_text(s, encoding="utf-8")
|
| 664 |
+
|
| 665 |
+
|
| 666 |
+
def _backup(p: Path) -> None:
|
| 667 |
+
bak = p.with_suffix(p.suffix + ".hpcq-bak")
|
| 668 |
+
if not bak.exists():
|
| 669 |
+
shutil.copy2(p, bak)
|
| 670 |
+
|
| 671 |
+
|
| 672 |
+
def _require_once(text: str, needle: str, what: str) -> None:
|
| 673 |
+
n = text.count(needle)
|
| 674 |
+
if n != 1:
|
| 675 |
+
raise SystemExit(f"anchor for {what}: found {n} occurrence(s), expected 1")
|
| 676 |
+
|
| 677 |
+
|
| 678 |
+
def _insert_after(text: str, anchor: str, block: str, what: str) -> str:
|
| 679 |
+
_require_once(text, anchor, what)
|
| 680 |
+
i = text.index(anchor) + len(anchor)
|
| 681 |
+
return text[:i] + block + text[i:]
|
| 682 |
+
|
| 683 |
+
|
| 684 |
+
def _replace_block(text: str, old: str, new: str, what: str) -> str:
|
| 685 |
+
_require_once(text, old, what)
|
| 686 |
+
return text.replace(old, new, 1)
|
| 687 |
+
|
| 688 |
+
|
| 689 |
+
# --------------------------------------------------------------------------
|
| 690 |
+
# Patch steps
|
| 691 |
+
# --------------------------------------------------------------------------
|
| 692 |
+
|
| 693 |
+
def step_header(root: Path) -> None:
|
| 694 |
+
_write(root / HEADER_REL, HEADER)
|
| 695 |
+
old_src_h = root / "ggml" / "src" / "hpcq-seg.h"
|
| 696 |
+
if old_src_h.exists():
|
| 697 |
+
old_src_h.unlink()
|
| 698 |
+
|
| 699 |
+
|
| 700 |
+
def step_ggml_c(root: Path) -> None:
|
| 701 |
+
p = root / "ggml" / "src" / "ggml.c"
|
| 702 |
+
s = _read(p)
|
| 703 |
+
if BEGIN in s:
|
| 704 |
+
return
|
| 705 |
+
_backup(p)
|
| 706 |
+
anchor = '#include "ggml-impl.h"'
|
| 707 |
+
s = _insert_after(s, anchor, "\n" + GGML_C_INCLUDE, "ggml.c include")
|
| 708 |
+
marker = "////////////////////////////////////////////////////////////////////////////////"
|
| 709 |
+
i = s.rindex(marker)
|
| 710 |
+
s = s[:i] + GGML_C_API + "\n\n" + s[i:]
|
| 711 |
+
_write(p, s)
|
| 712 |
+
|
| 713 |
+
|
| 714 |
+
def step_ggml_quants(root: Path) -> None:
|
| 715 |
+
p = root / "ggml" / "src" / "ggml-quants.c"
|
| 716 |
+
s = _read(p)
|
| 717 |
+
if BEGIN in s:
|
| 718 |
+
return
|
| 719 |
+
_backup(p)
|
| 720 |
+
anchor = '#include "ggml-quants.h"'
|
| 721 |
+
s = _insert_after(s, anchor, '\n#include "hpcq-seg.h"\n', "ggml-quants.c include")
|
| 722 |
+
s = _replace_block(s, Q2K_DEQ_OLD, Q2K_DEQ_NEW, "dequantize_row_q2_K")
|
| 723 |
+
s = _replace_block(s, Q3K_DEQ_OLD, Q3K_DEQ_NEW, "dequantize_row_q3_K")
|
| 724 |
+
_write(p, s)
|
| 725 |
+
|
| 726 |
+
|
| 727 |
+
def step_ggml_cpu(root: Path) -> None:
|
| 728 |
+
p = root / "ggml" / "src" / "ggml-cpu" / "ggml-cpu.c"
|
| 729 |
+
s = _read(p)
|
| 730 |
+
if BEGIN in s:
|
| 731 |
+
return
|
| 732 |
+
_backup(p)
|
| 733 |
+
anchor = "static const struct ggml_type_traits_cpu type_traits_cpu[GGML_TYPE_COUNT] = {"
|
| 734 |
+
_require_once(s, anchor, "ggml-cpu.c type_traits_cpu")
|
| 735 |
+
s = s.replace(anchor, CPU_VECDOT_WRAPPERS + "\n" + anchor, 1)
|
| 736 |
+
s = _replace_block(s, CPU_TRAITS_OLD, CPU_TRAITS_NEW, "ggml-cpu.c Q2_K/Q3_K traits")
|
| 737 |
+
_write(p, s)
|
| 738 |
+
|
| 739 |
+
|
| 740 |
+
def step_ggml_cuda(root: Path) -> None:
|
| 741 |
+
conv = root / "ggml" / "src" / "ggml-cuda" / "convert.cu"
|
| 742 |
+
s = _read(conv)
|
| 743 |
+
if BEGIN not in s:
|
| 744 |
+
_backup(conv)
|
| 745 |
+
s = _replace_block(s, CUDA_CONVERT_OLD_KERNELS, CUDA_CONVERT_NEW_KERNELS, "convert.cu kernels")
|
| 746 |
+
s = _replace_block(s, CUDA_CONVERT_OLD_LAUNCH, CUDA_CONVERT_NEW_LAUNCH, "convert.cu launch")
|
| 747 |
+
_write(conv, s)
|
| 748 |
+
|
| 749 |
+
cu = root / "ggml" / "src" / "ggml-cuda" / "ggml-cuda.cu"
|
| 750 |
+
s2 = _read(cu)
|
| 751 |
+
if BEGIN not in s2:
|
| 752 |
+
_backup(cu)
|
| 753 |
+
anchor = '#include "ggml-cuda.h"'
|
| 754 |
+
s2 = _insert_after(s2, anchor, '\n#include "hpcq-seg.h"', "ggml-cuda.cu include")
|
| 755 |
+
s2 = _replace_block(s2, CUDA_MULMAT_OLD, CUDA_MULMAT_NEW, "ggml-cuda.cu mul_mat")
|
| 756 |
+
_write(cu, s2)
|
| 757 |
+
|
| 758 |
+
|
| 759 |
+
def step_loader(root: Path) -> None:
|
| 760 |
+
cpp = root / "src" / "llama-model-loader.cpp"
|
| 761 |
+
s = _read(cpp)
|
| 762 |
+
if BEGIN in s:
|
| 763 |
+
return
|
| 764 |
+
_backup(cpp)
|
| 765 |
+
|
| 766 |
+
anchor = '#include "llama-model-loader.h"'
|
| 767 |
+
s = _insert_after(s, anchor, '\n#include "hpcq-seg.h"', "loader include")
|
| 768 |
+
|
| 769 |
+
# prevent CPU repack buffer selection on segmented tensors so they stay in
|
| 770 |
+
# native block_q2_K / block_q3_K layout for hpcq_vec_dot_q2_K_q8_K
|
| 771 |
+
anchor_buft = """ if (!buft) {
|
| 772 |
+
buft = select_weight_buft(hparams, t_meta, op, info.src1_noncont, buft_list);
|
| 773 |
+
if (!buft) {
|
| 774 |
+
throw std::runtime_error(format("failed to find a compatible buffer type for tensor %s", tn.str().c_str()));
|
| 775 |
+
}
|
| 776 |
+
}"""
|
| 777 |
+
new_buft = anchor_buft + f"""
|
| 778 |
+
// {BEGIN}: keep segmented CPU tensors in standard host/mmap buffer (no 8x8 interleave repack)
|
| 779 |
+
if (buft && metadata) {{
|
| 780 |
+
const std::string seg_key = std::string(HPCQ_SEG_PREFIX) + tn.str();
|
| 781 |
+
if (gguf_find_key(metadata, seg_key.c_str()) >= 0) {{
|
| 782 |
+
auto * bdev = ggml_backend_buft_get_device(buft);
|
| 783 |
+
if (bdev && ggml_backend_dev_type(bdev) == GGML_BACKEND_DEVICE_TYPE_CPU &&
|
| 784 |
+
buft != ggml_backend_cpu_buffer_type()) {{
|
| 785 |
+
buft = ggml_backend_cpu_buffer_type();
|
| 786 |
+
}}
|
| 787 |
+
}}
|
| 788 |
+
}}
|
| 789 |
+
// {END}"""
|
| 790 |
+
s = _replace_block(s, anchor_buft, new_buft, "loader select_weight_buft")
|
| 791 |
+
|
| 792 |
+
# bind compact HQS1 nibble stream directly to the tensor's payload pointer
|
| 793 |
+
anchor_tail = " size_done += n_size;\n }"
|
| 794 |
+
new_tail = f""" // {BEGIN}: bind compact HQS1 nibble stream to payload range (no weight/order expansion)
|
| 795 |
+
if (metadata && cur->data != NULL && (cur->type == GGML_TYPE_Q2_K || cur->type == GGML_TYPE_Q3_K)) {{
|
| 796 |
+
const std::string seg_key = std::string(HPCQ_SEG_PREFIX) + ggml_get_name(cur);
|
| 797 |
+
const int64_t seg_ki = gguf_find_key(metadata, seg_key.c_str());
|
| 798 |
+
if (seg_ki >= 0 && gguf_get_kv_type(metadata, seg_ki) == GGUF_TYPE_ARRAY &&
|
| 799 |
+
gguf_get_arr_type(metadata, seg_ki) == GGUF_TYPE_UINT8) {{
|
| 800 |
+
ggml_hpcq_seg_bind_raw(
|
| 801 |
+
cur->data,
|
| 802 |
+
(int64_t) ggml_nbytes(cur),
|
| 803 |
+
(const uint8_t *) gguf_get_arr_data(metadata, seg_ki),
|
| 804 |
+
gguf_get_arr_n(metadata, seg_ki),
|
| 805 |
+
(int64_t) ggml_type_size(cur->type));
|
| 806 |
+
}}
|
| 807 |
+
}}
|
| 808 |
+
// {END}
|
| 809 |
+
size_done += n_size;
|
| 810 |
+
}}"""
|
| 811 |
+
s = _replace_block(s, anchor_tail, new_tail, "loader load_all_data tail")
|
| 812 |
+
_write(cpp, s)
|
| 813 |
+
|
| 814 |
+
|
| 815 |
+
STEPS = [
|
| 816 |
+
("header", step_header),
|
| 817 |
+
("ggml.c", step_ggml_c),
|
| 818 |
+
("ggml-quants.c", step_ggml_quants),
|
| 819 |
+
("ggml-cpu.c", step_ggml_cpu),
|
| 820 |
+
("ggml-cuda", step_ggml_cuda),
|
| 821 |
+
("loader", step_loader),
|
| 822 |
+
]
|
| 823 |
+
|
| 824 |
+
TOUCHED_FILES = (
|
| 825 |
+
"ggml/src/ggml.c",
|
| 826 |
+
"ggml/src/ggml-quants.c",
|
| 827 |
+
"ggml/src/ggml-cpu/ggml-cpu.c",
|
| 828 |
+
"ggml/src/ggml-cuda/convert.cu",
|
| 829 |
+
"ggml/src/ggml-cuda/ggml-cuda.cu",
|
| 830 |
+
"src/llama-model-loader.cpp",
|
| 831 |
+
"src/llama-model-loader.h",
|
| 832 |
+
)
|
| 833 |
+
|
| 834 |
+
|
| 835 |
+
def check(root: Path) -> int:
|
| 836 |
+
ok = True
|
| 837 |
+
checks = [
|
| 838 |
+
("ggml.c", root / "ggml/src/ggml.c", ['#include "ggml-impl.h"']),
|
| 839 |
+
("ggml-quants.c", root / "ggml/src/ggml-quants.c", [Q2K_DEQ_OLD, Q3K_DEQ_OLD]),
|
| 840 |
+
("ggml-cpu.c", root / "ggml/src/ggml-cpu/ggml-cpu.c", [CPU_TRAITS_OLD]),
|
| 841 |
+
("convert.cu", root / "ggml/src/ggml-cuda/convert.cu", [CUDA_CONVERT_OLD_KERNELS, CUDA_CONVERT_OLD_LAUNCH]),
|
| 842 |
+
("ggml-cuda.cu", root / "ggml/src/ggml-cuda/ggml-cuda.cu", [CUDA_MULMAT_OLD]),
|
| 843 |
+
("loader.cpp", root / "src/llama-model-loader.cpp", [" size_done += n_size;\n }"]),
|
| 844 |
+
]
|
| 845 |
+
for label, p, needles in checks:
|
| 846 |
+
s = _read(p)
|
| 847 |
+
if BEGIN in s:
|
| 848 |
+
print(f"{label:15s}: already patched")
|
| 849 |
+
else:
|
| 850 |
+
present = all(n in s for n in needles)
|
| 851 |
+
print(f"{label:15s}: anchors {'ok' if present else 'MISSING'}")
|
| 852 |
+
ok &= present
|
| 853 |
+
return 0 if ok else 1
|
| 854 |
+
|
| 855 |
+
|
| 856 |
+
def apply(root: Path) -> int:
|
| 857 |
+
for name, fn in STEPS:
|
| 858 |
+
fn(root)
|
| 859 |
+
print(f"patched {name}")
|
| 860 |
+
print("done.")
|
| 861 |
+
return 0
|
| 862 |
+
|
| 863 |
+
|
| 864 |
+
def revert(root: Path) -> int:
|
| 865 |
+
for rel in TOUCHED_FILES:
|
| 866 |
+
p = root / rel
|
| 867 |
+
bak = p.with_suffix(p.suffix + ".hpcq-bak")
|
| 868 |
+
if bak.exists():
|
| 869 |
+
shutil.copy2(bak, p)
|
| 870 |
+
print(f"restored {rel}")
|
| 871 |
+
for hrel in (HEADER_REL, "ggml/src/hpcq-seg.h"):
|
| 872 |
+
h = root / hrel
|
| 873 |
+
if h.exists():
|
| 874 |
+
h.unlink()
|
| 875 |
+
print(f"removed {hrel}")
|
| 876 |
+
return 0
|
| 877 |
+
|
| 878 |
+
|
| 879 |
+
SELFTEST_CPP = r"""
|
| 880 |
+
#include <cstdio>
|
| 881 |
+
#include <cstdlib>
|
| 882 |
+
#include <cstring>
|
| 883 |
+
#include <vector>
|
| 884 |
+
|
| 885 |
+
#define GGML_API
|
| 886 |
+
#include "hpcq-seg.h"
|
| 887 |
+
|
| 888 |
+
int main() {
|
| 889 |
+
// Verify that hpcq_seg_make_order_block produces the exact stable argsort
|
| 890 |
+
// (slot -> original_position) for both nibble (enc=0) and byte (enc=1) streams,
|
| 891 |
+
// and that gathering y_perm by ord[s] matches the scattered dot product.
|
| 892 |
+
uint8_t labels[256];
|
| 893 |
+
uint8_t nibbles[128];
|
| 894 |
+
for (int p = 0; p < 256; ++p) {
|
| 895 |
+
labels[p] = (uint8_t) ((p * 7 + 3) % 16);
|
| 896 |
+
}
|
| 897 |
+
for (int i = 0; i < 128; ++i) {
|
| 898 |
+
nibbles[i] = (uint8_t) ((labels[2 * i] & 0x0F) | ((labels[2 * i + 1] & 0x0F) << 4));
|
| 899 |
+
}
|
| 900 |
+
uint16_t ord0[256], ord1[256];
|
| 901 |
+
hpcq_seg_make_order_block(nibbles, 0, ord0);
|
| 902 |
+
hpcq_seg_make_order_block(labels, 1, ord1);
|
| 903 |
+
for (int s = 0; s < 256; ++s) {
|
| 904 |
+
if (ord0[s] != ord1[s]) return 1;
|
| 905 |
+
if (s > 0) {
|
| 906 |
+
uint8_t l_prev = labels[ord0[s - 1]];
|
| 907 |
+
uint8_t l_curr = labels[ord0[s]];
|
| 908 |
+
if (l_prev > l_curr) return 2;
|
| 909 |
+
if (l_prev == l_curr && ord0[s - 1] >= ord0[s]) return 3;
|
| 910 |
+
}
|
| 911 |
+
}
|
| 912 |
+
// Check dot-product identity: sum_s x_slot[s] * y_orig[ord[s]] == sum_p x_orig[p] * y_orig[p]
|
| 913 |
+
int x_orig[256], x_slot[256], y_orig[256], y_perm[256];
|
| 914 |
+
for (int p = 0; p < 256; ++p) {
|
| 915 |
+
x_orig[p] = (p * 13 - 97);
|
| 916 |
+
y_orig[p] = (p * 5 - 41);
|
| 917 |
+
}
|
| 918 |
+
for (int s = 0; s < 256; ++s) {
|
| 919 |
+
x_slot[s] = x_orig[ord0[s]];
|
| 920 |
+
y_perm[s] = y_orig[ord0[s]];
|
| 921 |
+
}
|
| 922 |
+
long dot_orig = 0, dot_perm = 0;
|
| 923 |
+
for (int i = 0; i < 256; ++i) {
|
| 924 |
+
dot_orig += (long) x_orig[i] * (long) y_orig[i];
|
| 925 |
+
dot_perm += (long) x_slot[i] * (long) y_perm[i];
|
| 926 |
+
}
|
| 927 |
+
if (dot_orig != dot_perm) return 4;
|
| 928 |
+
std::printf("selftest ok (dot=%ld)\n", dot_perm);
|
| 929 |
+
return 0;
|
| 930 |
+
}
|
| 931 |
+
"""
|
| 932 |
+
|
| 933 |
+
|
| 934 |
+
def selftest() -> int:
|
| 935 |
+
with tempfile.TemporaryDirectory() as td:
|
| 936 |
+
td = Path(td)
|
| 937 |
+
(td / "ggml.h").write_text("#pragma once\n", encoding="utf-8")
|
| 938 |
+
(td / "hpcq-seg.h").write_text(HEADER, encoding="utf-8")
|
| 939 |
+
src = td / "selftest.cpp"
|
| 940 |
+
src.write_text(SELFTEST_CPP, encoding="utf-8")
|
| 941 |
+
exe = td / "selftest"
|
| 942 |
+
for cmd in (
|
| 943 |
+
["g++", "-O2", "-std=c++11", "-I", str(td), str(src), "-o", str(exe)],
|
| 944 |
+
[str(exe)],
|
| 945 |
+
):
|
| 946 |
+
r = subprocess.run(cmd, capture_output=True, text=True)
|
| 947 |
+
if r.returncode != 0:
|
| 948 |
+
print(r.stderr, file=sys.stderr)
|
| 949 |
+
return 1
|
| 950 |
+
if r.stdout:
|
| 951 |
+
print(r.stdout.strip())
|
| 952 |
+
return 0
|
| 953 |
+
|
| 954 |
+
|
| 955 |
+
def main() -> int:
|
| 956 |
+
ap = argparse.ArgumentParser()
|
| 957 |
+
ap.add_argument("--llama", default="/home/node/Desktop/Dev/llama.cpp")
|
| 958 |
+
g = ap.add_mutually_exclusive_group(required=True)
|
| 959 |
+
g.add_argument("--check", action="store_true")
|
| 960 |
+
g.add_argument("--apply", action="store_true")
|
| 961 |
+
g.add_argument("--revert", action="store_true")
|
| 962 |
+
g.add_argument("--selftest", action="store_true")
|
| 963 |
+
a = ap.parse_args()
|
| 964 |
+
if a.selftest:
|
| 965 |
+
return selftest()
|
| 966 |
+
root = Path(a.llama)
|
| 967 |
+
if not (root / "ggml" / "src" / "ggml-quants.c").exists():
|
| 968 |
+
raise SystemExit(f"not a llama.cpp tree: {root}")
|
| 969 |
+
if a.check:
|
| 970 |
+
return check(root)
|
| 971 |
+
if a.apply:
|
| 972 |
+
return apply(root)
|
| 973 |
+
return revert(root)
|
| 974 |
+
|
| 975 |
+
|
| 976 |
+
if __name__ == "__main__":
|
| 977 |
+
sys.exit(main())
|