mirror of
https://github.com/ggerganov/llama.cpp.git
synced 2024-12-25 02:44:36 +00:00
ggml : add SOTA 2,3,4,5,6 bit k-quantizations (#1684)
* Starting to add k-quantization to ggml I think it is better to have quantization separate from ggml. For now just adding the k-quants there, but it would be better to also factor out the existing ggml quantizations. * Adding Q3_K and Q8_K (de)-quantization * Q3_K now working on CUDA and AVX2/scalar CUDA is not ideal - ~50% slower than Q4_0 for single token prediction, about the same in batch mode (perplexity). CPU single token is ~55 ms (on Ryzen 7950X). * Some improvement for Q3_K on CUDA It is now ~22.5 ms/token on my GPU, so ~30% slower than Q4_0. * Some more CUDA optimizations for Q3_K Single token is now 20.5 ms/token (~20% slower than Q4_0). Perplexity is on par with Q4_0. * Adding Q4_K - scalar, AVX2, CUDA Performance is the same or perhaps very slightly better than Q4_0 on the CPU. On the GPU, single token prediction is ~10% better than Q4_0, batch mode (perplexity is about the same). * Adding Q6_K - scalar, AVX2, CUDA Performance is ~40% lower compared to Q4_K on the CPU. This is to be expected, considering that we are memory bound on the CPU and the 6-bit model is ~44% larger than the 4-bit. On the GPU, single token prediction is ~6% lower than Q4_0, batch mode (perplexity) is even closer (but still slower). * Adding Q5_K - scalar, AVX2, CUDA Performance is ~20% lower compared to Q4_K on the CPU. This is to be expected, considering that we are memory bound on the CPU and the 5-bit model is ~22% larger than the 4-bit. On the GPU, single token prediction is about the same as Q4_0 for both, single token and batch prediction. * Per convention, all QX_K quantizations use Q5_K for output.weight * Adding quantization mixes * Quantization mixes: didn't quite get what I wanted in the last commit * Q4_K dot product for ARM_NEON * Q6_K dot product for ARM_NEON * Q5_K dot product for ARM_NEON * Adding Q3_K dot for ARM_NEON It is 22% slower than Q4_K, despite the smaller model size. On x86_64, where we are memory bound, the Q3_K model is quite a bit faster than Q4_K. * A very slightly faster ARM_NEON Q3_K dot * Adding Q2_K - just CUDA for now Token prediction is pretty good - about 15.5 ms on a RTX 4080. Perplexity is about the same as Q4_K. * Adding scalar and AVX2 Q2_K dot * Adding ARM_NEON Q2_K dot About the same performance as Q4_K. * A slightly faster ARM_NEON Q2_K dot Single token prediction is now ~36 ms on M2 Max. The code is much simpler too. * Fixed bug in Q2_K CUDA dot product kernel Stranegly enough, for the few prompts I tried with the 7B model the responses looked perfectly reasonable. Only realized something is not quite right when I tried the larger models and started getting nonse back. In any case, Q2_K single token evaluation time on an RTX 4080 in a Ryzen7950X box iusing CUDA and model fully loaded on the GPU are ~15.5 ms for 7B, ~25.4 ms for 13B, and ~55.8 ms for 30B. The max number of layers that fit in VRAM for The 65B is 32. With that, we get ~330 ms per token, which is not that much faster than just running on the CPU (~470 ms per token). * Don't print zeros/NaNs when no count histogram has been collected * A 10% faster CUDA vector dot kernel for Q3_K Q3_K is now running at ~18.5 ms / token on CUDA, so the gap to Q4_0 is only 10%. It seems memory acccess pattern is more important for performance than the amount of computation the kernel does. * A slightly daster Q4_K AVX2 dot product For perplexity, where we are less memory bound, time per pass drops by ~5%. Barely measurable difference for single token prediction. * A slightly faster ARM_NEON A4_K dot product * Minor * Fix quantization error test We cannot possibly be expecting rmse < 0.002 for 2- and 3-bit quantization variants. * Fix docker build I have been sloppy with vector reinterpret casts on ARM_NEON. It seems clang is very forgiving in that regard. * Added forgotten ggml.o dependence on k_quants.h to the Makefile * Had unintentionally committed the Makefile with -Ofast enabled * ggml : rename k_quants -> ggml-quants-k, use lowercase in code --------- Co-authored-by: Iwan Kawrakow <iwan.kawrakow@gmail.com> Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>
This commit is contained in:
parent
5220a991a5
commit
99009e72f8
@ -396,6 +396,8 @@ endif()
|
|||||||
add_library(ggml OBJECT
|
add_library(ggml OBJECT
|
||||||
ggml.c
|
ggml.c
|
||||||
ggml.h
|
ggml.h
|
||||||
|
ggml-quants-k.h
|
||||||
|
ggml-quants-k.c
|
||||||
${GGML_SOURCES_CUDA}
|
${GGML_SOURCES_CUDA}
|
||||||
${GGML_SOURCES_OPENCL}
|
${GGML_SOURCES_OPENCL}
|
||||||
${GGML_SOURCES_METAL}
|
${GGML_SOURCES_METAL}
|
||||||
|
26
Makefile
26
Makefile
@ -40,8 +40,11 @@ endif
|
|||||||
#
|
#
|
||||||
|
|
||||||
# keep standard at C11 and C++11
|
# keep standard at C11 and C++11
|
||||||
CFLAGS = -I. -O3 -std=c11 -fPIC
|
# -Ofast tends to produce faster code, but may not be available for some compilers.
|
||||||
CXXFLAGS = -I. -I./examples -O3 -std=c++11 -fPIC
|
#OPT = -Ofast
|
||||||
|
OPT = -O3
|
||||||
|
CFLAGS = -I. $(OPT) -std=c11 -fPIC
|
||||||
|
CXXFLAGS = -I. -I./examples $(OPT) -std=c++11 -fPIC
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
|
|
||||||
ifdef LLAMA_DEBUG
|
ifdef LLAMA_DEBUG
|
||||||
@ -228,7 +231,10 @@ $(info )
|
|||||||
# Build library
|
# Build library
|
||||||
#
|
#
|
||||||
|
|
||||||
ggml.o: ggml.c ggml.h ggml-cuda.h
|
ggml.o: ggml.c ggml.h ggml-cuda.h ggml-quants-k.h
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
ggml-quants-k.o: ggml-quants-k.c ggml-quants-k.h ggml.h ggml-cuda.h
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
llama.o: llama.cpp ggml.h ggml-cuda.h llama.h llama-util.h
|
llama.o: llama.cpp ggml.h ggml-cuda.h llama.h llama-util.h
|
||||||
@ -247,25 +253,25 @@ clean:
|
|||||||
# Examples
|
# Examples
|
||||||
#
|
#
|
||||||
|
|
||||||
main: examples/main/main.cpp build-info.h ggml.o llama.o common.o $(OBJS)
|
main: examples/main/main.cpp build-info.h ggml.o ggml-quants-k.o llama.o common.o $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
||||||
@echo
|
@echo
|
||||||
@echo '==== Run ./main -h for help. ===='
|
@echo '==== Run ./main -h for help. ===='
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
quantize: examples/quantize/quantize.cpp build-info.h ggml.o llama.o $(OBJS)
|
quantize: examples/quantize/quantize.cpp build-info.h ggml.o llama.o ggml-quants-k.o $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
quantize-stats: examples/quantize-stats/quantize-stats.cpp build-info.h ggml.o llama.o $(OBJS)
|
quantize-stats: examples/quantize-stats/quantize-stats.cpp build-info.h ggml.o llama.o ggml-quants-k.o $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
perplexity: examples/perplexity/perplexity.cpp build-info.h ggml.o llama.o common.o $(OBJS)
|
perplexity: examples/perplexity/perplexity.cpp build-info.h ggml.o llama.o common.o ggml-quants-k.o $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
embedding: examples/embedding/embedding.cpp build-info.h ggml.o llama.o common.o $(OBJS)
|
embedding: examples/embedding/embedding.cpp build-info.h ggml.o llama.o common.o ggml-quants-k.o $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
save-load-state: examples/save-load-state/save-load-state.cpp build-info.h ggml.o llama.o common.o $(OBJS)
|
save-load-state: examples/save-load-state/save-load-state.cpp build-info.h ggml.o llama.o common.o ggml-quants-k.o $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
server: examples/server/server.cpp examples/server/httplib.h examples/server/json.hpp build-info.h ggml.o llama.o common.o $(OBJS)
|
server: examples/server/server.cpp examples/server/httplib.h examples/server/json.hpp build-info.h ggml.o llama.o common.o $(OBJS)
|
||||||
@ -287,7 +293,7 @@ benchmark-matmult: examples/benchmark/benchmark-matmult.cpp build-info.h ggml.o
|
|||||||
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS)
|
||||||
./$@
|
./$@
|
||||||
|
|
||||||
vdot: pocs/vdot/vdot.cpp ggml.o $(OBJS)
|
vdot: pocs/vdot/vdot.cpp ggml.o ggml-quants-k.o $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
.PHONY: tests clean
|
.PHONY: tests clean
|
||||||
|
@ -282,8 +282,9 @@ int main(int argc, char ** argv) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; j < GGML_TYPE_COUNT && strcmp(argv[i], ggml_type_name((ggml_type) j)) != 0; j++) {
|
for (j = 0; j < GGML_TYPE_COUNT; ++j) {
|
||||||
// find match
|
const auto * name = ggml_type_name((ggml_type) j);
|
||||||
|
if (name && strcmp(argv[i], name) == 0) break;
|
||||||
}
|
}
|
||||||
if (j < GGML_TYPE_COUNT) {
|
if (j < GGML_TYPE_COUNT) {
|
||||||
params.include_types.push_back((ggml_type) j);
|
params.include_types.push_back((ggml_type) j);
|
||||||
|
@ -7,11 +7,23 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
static const std::map<std::string, llama_ftype> LLAMA_FTYPE_MAP = {
|
static const std::map<std::string, llama_ftype> LLAMA_FTYPE_MAP = {
|
||||||
{"q4_0", LLAMA_FTYPE_MOSTLY_Q4_0},
|
{"q4_0", LLAMA_FTYPE_MOSTLY_Q4_0},
|
||||||
{"q4_1", LLAMA_FTYPE_MOSTLY_Q4_1},
|
{"q4_1", LLAMA_FTYPE_MOSTLY_Q4_1},
|
||||||
{"q5_0", LLAMA_FTYPE_MOSTLY_Q5_0},
|
{"q5_0", LLAMA_FTYPE_MOSTLY_Q5_0},
|
||||||
{"q5_1", LLAMA_FTYPE_MOSTLY_Q5_1},
|
{"q5_1", LLAMA_FTYPE_MOSTLY_Q5_1},
|
||||||
{"q8_0", LLAMA_FTYPE_MOSTLY_Q8_0},
|
{"q8_0", LLAMA_FTYPE_MOSTLY_Q8_0},
|
||||||
|
{"q2_K", LLAMA_FTYPE_MOSTLY_Q2_K},
|
||||||
|
{"q3_K", LLAMA_FTYPE_MOSTLY_Q3_K_M},
|
||||||
|
{"q3_K_S", LLAMA_FTYPE_MOSTLY_Q3_K_S},
|
||||||
|
{"q3_K_M", LLAMA_FTYPE_MOSTLY_Q3_K_M},
|
||||||
|
{"q3_K_L", LLAMA_FTYPE_MOSTLY_Q3_K_L},
|
||||||
|
{"q4_K", LLAMA_FTYPE_MOSTLY_Q4_K_M},
|
||||||
|
{"q4_K_S", LLAMA_FTYPE_MOSTLY_Q4_K_S},
|
||||||
|
{"q4_K_M", LLAMA_FTYPE_MOSTLY_Q4_K_M},
|
||||||
|
{"q5_K", LLAMA_FTYPE_MOSTLY_Q5_K_M},
|
||||||
|
{"q5_K_S", LLAMA_FTYPE_MOSTLY_Q5_K_S},
|
||||||
|
{"q5_K_M", LLAMA_FTYPE_MOSTLY_Q5_K_M},
|
||||||
|
{"q6_K", LLAMA_FTYPE_MOSTLY_Q6_K},
|
||||||
};
|
};
|
||||||
|
|
||||||
bool try_parse_ftype(const std::string & ftype_str, llama_ftype & ftype, std::string & ftype_str_out) {
|
bool try_parse_ftype(const std::string & ftype_str, llama_ftype & ftype, std::string & ftype_str_out) {
|
||||||
|
491
ggml-cuda.cu
491
ggml-cuda.cu
@ -3,6 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <cuda_runtime.h>
|
#include <cuda_runtime.h>
|
||||||
#include <cublas_v2.h>
|
#include <cublas_v2.h>
|
||||||
@ -35,6 +36,7 @@ static_assert(sizeof(half) == sizeof(ggml_fp16_t), "wrong fp16 size");
|
|||||||
typedef void (*dequantize_kernel_t)(const void * vx, const int ib, const int iqs, float & v0, float & v1);
|
typedef void (*dequantize_kernel_t)(const void * vx, const int ib, const int iqs, float & v0, float & v1);
|
||||||
typedef void (*to_fp32_cuda_t)(const void * x, float * y, int k, cudaStream_t stream);
|
typedef void (*to_fp32_cuda_t)(const void * x, float * y, int k, cudaStream_t stream);
|
||||||
typedef void (*dequantize_mul_mat_vec_cuda_t)(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream);
|
typedef void (*dequantize_mul_mat_vec_cuda_t)(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream);
|
||||||
|
typedef void (*dot_kernel_k_t)(const void * vx, const int ib, const int iqs, const float * y, float & v);
|
||||||
|
|
||||||
// QK = number of values after dequantization
|
// QK = number of values after dequantization
|
||||||
// QR = QK / number of values before dequantization
|
// QR = QK / number of values before dequantization
|
||||||
@ -83,6 +85,51 @@ typedef struct {
|
|||||||
} block_q8_0;
|
} block_q8_0;
|
||||||
static_assert(sizeof(block_q8_0) == sizeof(ggml_fp16_t) + QK8_0, "wrong q8_0 block size/padding");
|
static_assert(sizeof(block_q8_0) == sizeof(ggml_fp16_t) + QK8_0, "wrong q8_0 block size/padding");
|
||||||
|
|
||||||
|
//================================= k-quants
|
||||||
|
|
||||||
|
#define QK_K 256
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t scales[QK_K/16]; // scales and mins, quantized with 4 bits
|
||||||
|
uint8_t qs[QK_K/4]; // quants
|
||||||
|
half d; // super-block scale for quantized scales
|
||||||
|
half dmin; // super-block scale for quantized mins
|
||||||
|
} block_q2_k;
|
||||||
|
static_assert(sizeof(block_q2_k) == 2*sizeof(ggml_fp16_t) + QK_K/16 + QK_K/4, "wrong q2_k block size/padding");
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t hmask[QK_K/8];
|
||||||
|
uint8_t qs[QK_K/4]; // nibbles / quants
|
||||||
|
uint8_t scales[3*QK_K/64];
|
||||||
|
half d;
|
||||||
|
} block_q3_k;
|
||||||
|
static_assert(sizeof(block_q3_k) == sizeof(ggml_fp16_t) + QK_K / 4 + 11 * QK_K / 64, "wrong q3_k block size/padding");
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
half d; // super-block scale for quantized scales
|
||||||
|
half dmin; // super-block scale for quantized mins
|
||||||
|
uint8_t scales[3*QK_K/64]; // scales, quantized with 6 bits
|
||||||
|
uint8_t qs[QK_K/2]; // 4--bit quants
|
||||||
|
} block_q4_k;
|
||||||
|
static_assert(sizeof(block_q4_k) == 2*sizeof(ggml_fp16_t) + 3*QK_K/64 + QK_K/2, "wrong q4_k block size/padding");
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
half d; // super-block scale for quantized scales
|
||||||
|
half dmin; // super-block scale for quantized mins
|
||||||
|
uint8_t scales[3*QK_K/64]; // scales, quantized with 6 bits
|
||||||
|
uint8_t qh[QK_K/8]; // quants, high bit
|
||||||
|
uint8_t qs[QK_K/2]; // quants, low 4 bits
|
||||||
|
} block_q5_k;
|
||||||
|
static_assert(sizeof(block_q5_k) == 2*sizeof(ggml_fp16_t) + 3*QK_K/64 + QK_K/2 + QK_K/8, "wrong q5_k block size/padding");
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ql[QK_K/2]; // quants, lower 4 bits
|
||||||
|
uint8_t qh[QK_K/4]; // quants, upper 2 bits
|
||||||
|
int8_t scales[QK_K/16]; // scales
|
||||||
|
half d; // delta
|
||||||
|
} block_q6_k;
|
||||||
|
static_assert(sizeof(block_q6_k) == sizeof(ggml_fp16_t) + 13*QK_K/16, "wrong q6_k block size/padding");
|
||||||
|
|
||||||
#define WARP_SIZE 32
|
#define WARP_SIZE 32
|
||||||
|
|
||||||
#define CUDA_MUL_BLOCK_SIZE 256
|
#define CUDA_MUL_BLOCK_SIZE 256
|
||||||
@ -184,6 +231,337 @@ static __device__ void dequantize_q8_0(const void * vx, const int ib, const int
|
|||||||
v1 = vi1*d;
|
v1 = vi1*d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//================================== k-quants
|
||||||
|
|
||||||
|
static __global__ void dequantize_block_q2_k(const void * vx, float * yy) {
|
||||||
|
|
||||||
|
const int i = blockIdx.x;
|
||||||
|
const int tid = threadIdx.x;
|
||||||
|
const int n = tid/32;
|
||||||
|
const int l = tid - 32*n;
|
||||||
|
const int is = 8*n + l/16;
|
||||||
|
|
||||||
|
const block_q2_k * x = (const block_q2_k *) vx;
|
||||||
|
|
||||||
|
const uint8_t q = x[i].qs[32*n + l];
|
||||||
|
float * y = yy + i*QK_K + 128*n;
|
||||||
|
|
||||||
|
float dall = x[i].d;
|
||||||
|
float dmin = x[i].dmin;
|
||||||
|
y[l+ 0] = dall * (x[i].scales[is+0] & 0xF) * ((q >> 0) & 3) - dmin * (x[i].scales[is+0] >> 4);
|
||||||
|
y[l+32] = dall * (x[i].scales[is+2] & 0xF) * ((q >> 2) & 3) - dmin * (x[i].scales[is+2] >> 4);
|
||||||
|
y[l+64] = dall * (x[i].scales[is+4] & 0xF) * ((q >> 4) & 3) - dmin * (x[i].scales[is+4] >> 4);
|
||||||
|
y[l+96] = dall * (x[i].scales[is+6] & 0xF) * ((q >> 6) & 3) - dmin * (x[i].scales[is+6] >> 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static __device__ void vec_dot_q2_k(const void * vx, const int ib, const int iqs, const float * yy, float & result) {
|
||||||
|
|
||||||
|
const block_q2_k * x = (const block_q2_k *) vx;
|
||||||
|
|
||||||
|
// if n is 0, we want to do the lower 128, else the upper 128,
|
||||||
|
// covering y[l+0], y[l+32], y[l+64], y[l+96] and
|
||||||
|
// y[l+16], y[l+48], y[l+80], y[l+112]
|
||||||
|
int n = iqs/128; // 0 or 1
|
||||||
|
int r = iqs - 128*n; // 0...120 in steps of 8
|
||||||
|
int l = r/8; // 0...15 in steps of 1
|
||||||
|
|
||||||
|
const float * y = yy + 128*n + l;
|
||||||
|
const uint8_t * q = x[ib].qs + 32*n + l;
|
||||||
|
const uint8_t * s = x[ib].scales + 8*n;
|
||||||
|
|
||||||
|
const float dall = x[ib].d;
|
||||||
|
const float dmin = x[ib].dmin;
|
||||||
|
|
||||||
|
float sum = y[ 0] * (dall * ((s[0] & 0xF) * ((q[ 0] >> 0) & 3)) - dmin * (s[0] >> 4))
|
||||||
|
+ y[ 32] * (dall * ((s[2] & 0xF) * ((q[ 0] >> 2) & 3)) - dmin * (s[2] >> 4))
|
||||||
|
+ y[ 64] * (dall * ((s[4] & 0xF) * ((q[ 0] >> 4) & 3)) - dmin * (s[4] >> 4))
|
||||||
|
+ y[ 96] * (dall * ((s[6] & 0xF) * ((q[ 0] >> 6) & 3)) - dmin * (s[6] >> 4))
|
||||||
|
+ y[ 16] * (dall * ((s[1] & 0xF) * ((q[16] >> 0) & 3)) - dmin * (s[1] >> 4))
|
||||||
|
+ y[ 48] * (dall * ((s[3] & 0xF) * ((q[16] >> 2) & 3)) - dmin * (s[3] >> 4))
|
||||||
|
+ y[ 80] * (dall * ((s[5] & 0xF) * ((q[16] >> 4) & 3)) - dmin * (s[5] >> 4))
|
||||||
|
+ y[112] * (dall * ((s[7] & 0xF) * ((q[16] >> 6) & 3)) - dmin * (s[7] >> 4));
|
||||||
|
|
||||||
|
result = sum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static __global__ void dequantize_block_q3_k(const void * vx, float * yy) {
|
||||||
|
|
||||||
|
int r = threadIdx.x/4;
|
||||||
|
int i = blockIdx.x;
|
||||||
|
int tid = r/2;
|
||||||
|
int is0 = r%2;
|
||||||
|
int l0 = 16*is0 + 4*(threadIdx.x%4);
|
||||||
|
int n = tid / 4;
|
||||||
|
int j = tid - 4*n;
|
||||||
|
|
||||||
|
const block_q3_k * x = (const block_q3_k *) vx;
|
||||||
|
|
||||||
|
uint8_t m = 1 << (4*n + j);
|
||||||
|
int is = 8*n + 2*j + is0;
|
||||||
|
int shift = 2*j;
|
||||||
|
|
||||||
|
int8_t us = is < 4 ? (x[i].scales[is-0] & 0xF) | (((x[i].scales[is+8] >> 0) & 3) << 4) :
|
||||||
|
is < 8 ? (x[i].scales[is-0] & 0xF) | (((x[i].scales[is+4] >> 2) & 3) << 4) :
|
||||||
|
is < 12 ? (x[i].scales[is-8] >> 4) | (((x[i].scales[is+0] >> 4) & 3) << 4) :
|
||||||
|
(x[i].scales[is-8] >> 4) | (((x[i].scales[is-4] >> 6) & 3) << 4);
|
||||||
|
float d_all = x[i].d;
|
||||||
|
float dl = d_all * (us - 32);
|
||||||
|
|
||||||
|
float * y = yy + i*QK_K + 128*n + 32*j;
|
||||||
|
const uint8_t * q = x[i].qs + 32*n;
|
||||||
|
const uint8_t * hm = x[i].hmask;
|
||||||
|
|
||||||
|
for (int l = l0; l < l0+4; ++l) y[l] = dl * ((int8_t)((q[l] >> shift) & 3) - ((hm[l] & m) ? 0 : 4));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static __device__ void vec_dot_q3_k(const void * vx, const int ib, const int iqs, const float * yy, float & result) {
|
||||||
|
|
||||||
|
const block_q3_k * x = (const block_q3_k *) vx;
|
||||||
|
|
||||||
|
const uint32_t kmask1 = 0x03030303;
|
||||||
|
const uint32_t kmask2 = 0x0f0f0f0f;
|
||||||
|
|
||||||
|
uint32_t aux[3];
|
||||||
|
uint32_t utmp[4];
|
||||||
|
|
||||||
|
// if n is 0, we want to do the lower 128, else the upper 128,
|
||||||
|
// covering y[l+0], y[l+32], y[l+64], y[l+96] and
|
||||||
|
// y[l+16], y[l+48], y[l+80], y[l+112]
|
||||||
|
int n = iqs/128; // 0 or 1
|
||||||
|
int r = iqs - 128*n; // 0...120 in steps of 8
|
||||||
|
int l = r/8; // 0...15 in steps of 1
|
||||||
|
|
||||||
|
const float * y = yy + 128*n + l;
|
||||||
|
const uint8_t * q = x[ib].qs + 32*n + l;
|
||||||
|
const uint8_t * hm = x[ib].hmask + l;
|
||||||
|
const int8_t * s = (const int8_t *)utmp + 8*n;
|
||||||
|
|
||||||
|
memcpy(aux, x[ib].scales, 12);
|
||||||
|
utmp[3] = ((aux[1] >> 4) & kmask2) | (((aux[2] >> 6) & kmask1) << 4);
|
||||||
|
utmp[2] = ((aux[0] >> 4) & kmask2) | (((aux[2] >> 4) & kmask1) << 4);
|
||||||
|
utmp[1] = (aux[1] & kmask2) | (((aux[2] >> 2) & kmask1) << 4);
|
||||||
|
utmp[0] = (aux[0] & kmask2) | (((aux[2] >> 0) & kmask1) << 4);
|
||||||
|
|
||||||
|
const float dall = x[ib].d;
|
||||||
|
|
||||||
|
const uint8_t m = 1 << (4*n);
|
||||||
|
|
||||||
|
float sum = y[ 0] * (s[0] - 32) * (((q[ 0] >> 0) & 3) - (hm[ 0] & (m << 0) ? 0 : 4))
|
||||||
|
+ y[ 32] * (s[2] - 32) * (((q[ 0] >> 2) & 3) - (hm[ 0] & (m << 1) ? 0 : 4))
|
||||||
|
+ y[ 64] * (s[4] - 32) * (((q[ 0] >> 4) & 3) - (hm[ 0] & (m << 2) ? 0 : 4))
|
||||||
|
+ y[ 96] * (s[6] - 32) * (((q[ 0] >> 6) & 3) - (hm[ 0] & (m << 3) ? 0 : 4))
|
||||||
|
+ y[ 16] * (s[1] - 32) * (((q[16] >> 0) & 3) - (hm[16] & (m << 0) ? 0 : 4))
|
||||||
|
+ y[ 48] * (s[3] - 32) * (((q[16] >> 2) & 3) - (hm[16] & (m << 1) ? 0 : 4))
|
||||||
|
+ y[ 80] * (s[5] - 32) * (((q[16] >> 4) & 3) - (hm[16] & (m << 2) ? 0 : 4))
|
||||||
|
+ y[112] * (s[7] - 32) * (((q[16] >> 6) & 3) - (hm[16] & (m << 3) ? 0 : 4));
|
||||||
|
|
||||||
|
result = sum * dall;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __device__ void get_scale_min_k4(int j, const uint8_t * q, uint8_t & d, uint8_t & m) {
|
||||||
|
if (j < 4) {
|
||||||
|
d = q[j] & 63; m = q[j + 4] & 63;
|
||||||
|
} else {
|
||||||
|
d = (q[j+4] & 0xF) | ((q[j-4] >> 6) << 4);
|
||||||
|
m = (q[j+4] >> 4) | ((q[j-0] >> 6) << 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static __global__ void dequantize_block_q4_k(const void * vx, float * yy) {
|
||||||
|
const block_q4_k * x = (const block_q4_k *) vx;
|
||||||
|
|
||||||
|
const int i = blockIdx.x;
|
||||||
|
|
||||||
|
//// assume 64 threads - this is very slightly better than the one below
|
||||||
|
//const int tid = threadIdx.x;
|
||||||
|
//const int il = tid/16;
|
||||||
|
//const int ir = tid%16;
|
||||||
|
//const int is = 2*il;
|
||||||
|
//const int n = 2;
|
||||||
|
|
||||||
|
// assume 32 threads
|
||||||
|
const int tid = threadIdx.x;
|
||||||
|
const int il = tid/8;
|
||||||
|
const int ir = tid%8;
|
||||||
|
const int is = 2*il;
|
||||||
|
const int n = 4;
|
||||||
|
|
||||||
|
float * y = yy + i*QK_K + 64*il + n*ir;
|
||||||
|
|
||||||
|
const float dall = x[i].d;
|
||||||
|
const float dmin = x[i].dmin;
|
||||||
|
|
||||||
|
const uint8_t * q = x[i].qs + 32*il + n*ir;
|
||||||
|
|
||||||
|
uint8_t sc, m;
|
||||||
|
get_scale_min_k4(is + 0, x[i].scales, sc, m);
|
||||||
|
const float d1 = dall * sc; const float m1 = dmin * m;
|
||||||
|
get_scale_min_k4(is + 1, x[i].scales, sc, m);
|
||||||
|
const float d2 = dall * sc; const float m2 = dmin * m;
|
||||||
|
for (int l = 0; l < n; ++l) {
|
||||||
|
y[l + 0] = d1 * (q[l] & 0xF) - m1;
|
||||||
|
y[l +32] = d2 * (q[l] >> 4) - m2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static __device__ void vec_dot_q4_k(const void * vx, const int ib, const int iqs, const float * yy, float & result) {
|
||||||
|
|
||||||
|
const block_q4_k * x = (const block_q4_k *) vx;
|
||||||
|
|
||||||
|
// iqs is in 0...248 in steps of 8 =>
|
||||||
|
const int j = iqs / 64; // j is in 0...3
|
||||||
|
const int ir = (iqs - 64*j)/2; // ir is in 0...28 in steps of 4
|
||||||
|
const int is = 2*j; // is is in 0...6 in steps of 2
|
||||||
|
|
||||||
|
const float * y = yy + 64*j + ir;
|
||||||
|
const uint8_t * q = x[ib].qs + 32*j + ir;
|
||||||
|
|
||||||
|
const float dall = x[ib].d;
|
||||||
|
const float dmin = x[ib].dmin;
|
||||||
|
|
||||||
|
uint8_t sc, m;
|
||||||
|
get_scale_min_k4(is + 0, x[ib].scales, sc, m);
|
||||||
|
const float d1 = dall * sc;
|
||||||
|
const float m1 = dmin * m;
|
||||||
|
get_scale_min_k4(is + 1, x[ib].scales, sc, m);
|
||||||
|
const float d2 = dall * sc;
|
||||||
|
const float m2 = dmin * m;
|
||||||
|
|
||||||
|
float sum = 0;
|
||||||
|
for (int k = 0; k < 4; ++k) {
|
||||||
|
sum += y[k + 0] * (d1 * (q[k] & 0xF) - m1);
|
||||||
|
sum += y[k + 32] * (d2 * (q[k] >> 4) - m2);
|
||||||
|
}
|
||||||
|
result = sum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static __global__ void dequantize_block_q5_k(const void * vx, float * yy) {
|
||||||
|
const block_q5_k * x = (const block_q5_k *) vx;
|
||||||
|
|
||||||
|
const int i = blockIdx.x;
|
||||||
|
|
||||||
|
// assume 64 threads - this is very slightly better than the one below
|
||||||
|
const int tid = threadIdx.x;
|
||||||
|
const int il = tid/16; // il is in 0...3
|
||||||
|
const int ir = tid%16; // ir is in 0...15
|
||||||
|
const int is = 2*il; // is is in 0...6
|
||||||
|
|
||||||
|
float * y = yy + i*QK_K + 64*il + 2*ir;
|
||||||
|
|
||||||
|
const float dall = x[i].d;
|
||||||
|
const float dmin = x[i].dmin;
|
||||||
|
|
||||||
|
const uint8_t * ql = x[i].qs + 32*il + 2*ir;
|
||||||
|
const uint8_t * qh = x[i].qh + 2*ir;
|
||||||
|
|
||||||
|
uint8_t sc, m;
|
||||||
|
get_scale_min_k4(is + 0, x[i].scales, sc, m);
|
||||||
|
const float d1 = dall * sc; const float m1 = dmin * m;
|
||||||
|
get_scale_min_k4(is + 1, x[i].scales, sc, m);
|
||||||
|
const float d2 = dall * sc; const float m2 = dmin * m;
|
||||||
|
|
||||||
|
uint8_t hm = 1 << (2*il);
|
||||||
|
y[ 0] = d1 * ((ql[ 0] & 0xF) + (qh[ 0] & hm ? 16 : 0)) - m1;
|
||||||
|
y[ 1] = d1 * ((ql[ 1] & 0xF) + (qh[ 1] & hm ? 16 : 0)) - m1;
|
||||||
|
hm <<= 1;
|
||||||
|
y[32] = d2 * ((ql[ 0] >> 4) + (qh[ 0] & hm ? 16 : 0)) - m2;
|
||||||
|
y[33] = d2 * ((ql[ 1] >> 4) + (qh[ 1] & hm ? 16 : 0)) - m2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __device__ void vec_dot_q5_k(const void * vx, const int ib, const int iqs, const float * yy, float & result) {
|
||||||
|
|
||||||
|
const block_q5_k * x = (const block_q5_k *) vx;
|
||||||
|
|
||||||
|
// iqs is in 0...248 in steps of 8 =>
|
||||||
|
const int j = iqs / 64; // j is in 0...3
|
||||||
|
const int ir = (iqs - 64*j)/2; // ir is in 0...28 in steps of 4
|
||||||
|
const int is = 2*j; // is is in 0...6 in steps of 2
|
||||||
|
|
||||||
|
const float * y = yy + 64*j + ir;
|
||||||
|
const uint8_t * ql = x[ib].qs + 32*j + ir;
|
||||||
|
const uint8_t * qh = x[ib].qh + ir;
|
||||||
|
|
||||||
|
const float dall = x[ib].d;
|
||||||
|
const float dmin = x[ib].dmin;
|
||||||
|
|
||||||
|
uint8_t sc, m;
|
||||||
|
get_scale_min_k4(is + 0, x[ib].scales, sc, m);
|
||||||
|
const float d1 = dall * sc;
|
||||||
|
const float m1 = dmin * m;
|
||||||
|
get_scale_min_k4(is + 1, x[ib].scales, sc, m);
|
||||||
|
const float d2 = dall * sc;
|
||||||
|
const float m2 = dmin * m;
|
||||||
|
|
||||||
|
uint8_t hm = 1 << is;
|
||||||
|
float sum = 0;
|
||||||
|
for (int k = 0; k < 4; ++k) {
|
||||||
|
sum += y[k + 0] * (d1 * ((ql[k] & 0xF) + (qh[k] & hm ? 16 : 0)) - m1);
|
||||||
|
}
|
||||||
|
hm <<= 1;
|
||||||
|
for (int k = 0; k < 4; ++k) {
|
||||||
|
sum += y[k + 32] * (d2 * ((ql[k] >> 4) + (qh[k] & hm ? 16 : 0)) - m2);
|
||||||
|
}
|
||||||
|
result = sum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static __global__ void dequantize_block_q6_k(const void * vx, float * yy) {
|
||||||
|
const block_q6_k * x = (const block_q6_k *) vx;
|
||||||
|
|
||||||
|
const int i = blockIdx.x;
|
||||||
|
|
||||||
|
// assume 64 threads - this is very slightly better than the one below
|
||||||
|
const int tid = threadIdx.x;
|
||||||
|
const int ip = tid/32; // ip is 0 or 1
|
||||||
|
const int il = tid - 32*ip; // 0...32
|
||||||
|
const int is = 8*ip + il/16;
|
||||||
|
|
||||||
|
float * y = yy + i*QK_K + 128*ip + il;
|
||||||
|
|
||||||
|
const float d = x[i].d;
|
||||||
|
|
||||||
|
const uint8_t * ql = x[i].ql + 64*ip + il;
|
||||||
|
const uint8_t qh = x[i].qh[32*ip + il];
|
||||||
|
const int8_t * sc = x[i].scales + is;
|
||||||
|
|
||||||
|
y[ 0] = d * sc[0] * ((int8_t)((ql[ 0] & 0xF) | (((qh >> 0) & 3) << 4)) - 32);
|
||||||
|
y[32] = d * sc[2] * ((int8_t)((ql[32] & 0xF) | (((qh >> 2) & 3) << 4)) - 32);
|
||||||
|
y[64] = d * sc[4] * ((int8_t)((ql[ 0] >> 4) | (((qh >> 4) & 3) << 4)) - 32);
|
||||||
|
y[96] = d * sc[6] * ((int8_t)((ql[32] >> 4) | (((qh >> 6) & 3) << 4)) - 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __device__ void vec_dot_q6_k(const void * vx, const int ib, const int iqs, const float * yy, float & result) {
|
||||||
|
|
||||||
|
const block_q6_k * x = (const block_q6_k *) vx;
|
||||||
|
|
||||||
|
const int ip = iqs / 128; // 0 or 1
|
||||||
|
const int il = (iqs - 128*ip)/8; // 0...15
|
||||||
|
const int is = 8*ip;
|
||||||
|
|
||||||
|
const float * y = yy + 128*ip + il;
|
||||||
|
|
||||||
|
const float d = x[ib].d;
|
||||||
|
|
||||||
|
const uint8_t * ql = x[ib].ql + 64*ip + il;
|
||||||
|
const uint8_t * qh = x[ib].qh + 32*ip + il;
|
||||||
|
const int8_t * sc = x[ib].scales + is;
|
||||||
|
|
||||||
|
result = y[ 0] * d * sc[0] * ((int8_t)((ql[ 0] & 0xF) | (((qh[ 0] >> 0) & 3) << 4)) - 32)
|
||||||
|
+ y[ 32] * d * sc[2] * ((int8_t)((ql[32] & 0xF) | (((qh[ 0] >> 2) & 3) << 4)) - 32)
|
||||||
|
+ y[ 64] * d * sc[4] * ((int8_t)((ql[ 0] >> 4) | (((qh[ 0] >> 4) & 3) << 4)) - 32)
|
||||||
|
+ y[ 96] * d * sc[6] * ((int8_t)((ql[32] >> 4) | (((qh[ 0] >> 6) & 3) << 4)) - 32)
|
||||||
|
+ y[ 16] * d * sc[1] * ((int8_t)((ql[16] & 0xF) | (((qh[16] >> 0) & 3) << 4)) - 32)
|
||||||
|
+ y[ 48] * d * sc[3] * ((int8_t)((ql[48] & 0xF) | (((qh[16] >> 2) & 3) << 4)) - 32)
|
||||||
|
+ y[ 80] * d * sc[5] * ((int8_t)((ql[16] >> 4) | (((qh[16] >> 4) & 3) << 4)) - 32)
|
||||||
|
+ y[112] * d * sc[7] * ((int8_t)((ql[48] >> 4) | (((qh[16] >> 6) & 3) << 4)) - 32);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static __device__ void convert_f16(const void * vx, const int ib, const int iqs, float & v0, float & v1){
|
static __device__ void convert_f16(const void * vx, const int ib, const int iqs, float & v0, float & v1){
|
||||||
const half * x = (const half *) vx;
|
const half * x = (const half *) vx;
|
||||||
|
|
||||||
@ -258,6 +636,41 @@ static __global__ void dequantize_mul_mat_vec(const void * vx, const float * y,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <int n_thread, dot_kernel_k_t dot_kernel>
|
||||||
|
static __global__ void dequantize_mul_mat_vec_k(const void * vx, const float * y, float * dst, const int ncols) {
|
||||||
|
const int row = blockIdx.x*blockDim.y + threadIdx.y;
|
||||||
|
const int tid = threadIdx.x;
|
||||||
|
|
||||||
|
const int iter_stride = QK_K;
|
||||||
|
const int vals_per_iter = iter_stride / n_thread;
|
||||||
|
const int num_blocks_per_row = ncols / QK_K;
|
||||||
|
const int ib0 = row*num_blocks_per_row;
|
||||||
|
|
||||||
|
float tmp = 0; // partial sum for thread in warp
|
||||||
|
|
||||||
|
for (int i = 0; i < ncols; i += iter_stride) {
|
||||||
|
const int col = i + vals_per_iter*tid;
|
||||||
|
const int ib = ib0 + col/QK_K; // x block index
|
||||||
|
const int iqs = col%QK_K; // x quant index
|
||||||
|
const int iybs = col - col%QK_K; // y block start index
|
||||||
|
|
||||||
|
float v;
|
||||||
|
dot_kernel(vx, ib, iqs, y + iybs, v);
|
||||||
|
tmp += v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sum up partial sums and write back result
|
||||||
|
__syncthreads();
|
||||||
|
#pragma unroll
|
||||||
|
for (int mask = 16; mask > 0; mask >>= 1) {
|
||||||
|
tmp += __shfl_xor_sync(0xffffffff, tmp, mask, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tid == 0) {
|
||||||
|
dst[row] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void mul_f32_cuda(const float * x, const float * y, float * dst, const int kx, const int ky, cudaStream_t stream) {
|
static void mul_f32_cuda(const float * x, const float * y, float * dst, const int kx, const int ky, cudaStream_t stream) {
|
||||||
const int num_blocks = (kx + CUDA_MUL_BLOCK_SIZE - 1) / CUDA_MUL_BLOCK_SIZE;
|
const int num_blocks = (kx + CUDA_MUL_BLOCK_SIZE - 1) / CUDA_MUL_BLOCK_SIZE;
|
||||||
mul_f32<<<num_blocks, CUDA_MUL_BLOCK_SIZE, 0, stream>>>(x, y, dst, kx, ky);
|
mul_f32<<<num_blocks, CUDA_MUL_BLOCK_SIZE, 0, stream>>>(x, y, dst, kx, ky);
|
||||||
@ -288,6 +701,31 @@ static void dequantize_row_q8_0_cuda(const void * vx, float * y, const int k, cu
|
|||||||
dequantize_block<QK8_0, QR8_0, dequantize_q8_0><<<num_blocks, CUDA_DEQUANTIZE_BLOCK_SIZE, 0, stream>>>(vx, y, k);
|
dequantize_block<QK8_0, QR8_0, dequantize_q8_0><<<num_blocks, CUDA_DEQUANTIZE_BLOCK_SIZE, 0, stream>>>(vx, y, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dequantize_row_q2_k_cuda(const void * vx, float * y, const int k, cudaStream_t stream) {
|
||||||
|
const int nb = k / QK_K;
|
||||||
|
dequantize_block_q2_k<<<nb, 64, 0, stream>>>(vx, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_row_q3_k_cuda(const void * vx, float * y, const int k, cudaStream_t stream) {
|
||||||
|
const int nb = k / QK_K;
|
||||||
|
dequantize_block_q3_k<<<nb, 64, 0, stream>>>(vx, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_row_q4_k_cuda(const void * vx, float * y, const int k, cudaStream_t stream) {
|
||||||
|
const int nb = k / QK_K;
|
||||||
|
dequantize_block_q4_k<<<nb, 32, 0, stream>>>(vx, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_row_q5_k_cuda(const void * vx, float * y, const int k, cudaStream_t stream) {
|
||||||
|
const int nb = k / QK_K;
|
||||||
|
dequantize_block_q5_k<<<nb, 64, 0, stream>>>(vx, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_row_q6_k_cuda(const void * vx, float * y, const int k, cudaStream_t stream) {
|
||||||
|
const int nb = k / QK_K;
|
||||||
|
dequantize_block_q6_k<<<nb, 64, 0, stream>>>(vx, y);
|
||||||
|
}
|
||||||
|
|
||||||
static void dequantize_mul_mat_vec_q4_0_cuda(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
static void dequantize_mul_mat_vec_q4_0_cuda(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
GGML_ASSERT(ncols % GGML_CUDA_DMMV_X == 0);
|
GGML_ASSERT(ncols % GGML_CUDA_DMMV_X == 0);
|
||||||
GGML_ASSERT(nrows % GGML_CUDA_DMMV_Y == 0);
|
GGML_ASSERT(nrows % GGML_CUDA_DMMV_Y == 0);
|
||||||
@ -328,6 +766,37 @@ static void dequantize_mul_mat_vec_q8_0_cuda(const void * vx, const float * y, f
|
|||||||
<<<nrows/GGML_CUDA_DMMV_Y, block_dims, 0, stream>>>(vx, y, dst, ncols);
|
<<<nrows/GGML_CUDA_DMMV_Y, block_dims, 0, stream>>>(vx, y, dst, ncols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dequantize_mul_mat_vec_q2_k_cuda(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
|
GGML_ASSERT(ncols % QK_K == 0);
|
||||||
|
const int ny = 2;
|
||||||
|
const dim3 block_dims(32, ny, 1);
|
||||||
|
dequantize_mul_mat_vec_k<32, vec_dot_q2_k><<<(nrows + ny - 1)/ny, block_dims, 0, stream>>>(vx, y, dst, ncols);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_mul_mat_vec_q3_k_cuda(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
|
GGML_ASSERT(ncols % QK_K == 0);
|
||||||
|
const dim3 block_dims(32, 2, 1);
|
||||||
|
dequantize_mul_mat_vec_k<32, vec_dot_q3_k><<<nrows/2, block_dims, 0, stream>>>(vx, y, dst, ncols);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_mul_mat_vec_q4_k_cuda(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
|
GGML_ASSERT(ncols % QK_K == 0);
|
||||||
|
const dim3 block_dims(32, 2, 1);
|
||||||
|
dequantize_mul_mat_vec_k<32, vec_dot_q4_k><<<nrows/2, block_dims, 0, stream>>>(vx, y, dst, ncols);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_mul_mat_vec_q5_k_cuda(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
|
GGML_ASSERT(ncols % QK_K == 0);
|
||||||
|
const dim3 block_dims(32, 2, 1);
|
||||||
|
dequantize_mul_mat_vec_k<32, vec_dot_q5_k><<<nrows/2, block_dims, 0, stream>>>(vx, y, dst, ncols);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dequantize_mul_mat_vec_q6_k_cuda(const void * vx, const float * y, float * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
|
GGML_ASSERT(ncols % QK_K == 0);
|
||||||
|
const dim3 block_dims(32, 2, 1);
|
||||||
|
dequantize_mul_mat_vec_k<32, vec_dot_q6_k><<<nrows/2, block_dims, 0, stream>>>(vx, y, dst, ncols);
|
||||||
|
}
|
||||||
|
|
||||||
static void convert_fp16_to_fp32_cuda(const void * vx, float * y, const int k, cudaStream_t stream) {
|
static void convert_fp16_to_fp32_cuda(const void * vx, float * y, const int k, cudaStream_t stream) {
|
||||||
const int num_blocks = (k + CUDA_DEQUANTIZE_BLOCK_SIZE - 1) / CUDA_DEQUANTIZE_BLOCK_SIZE;
|
const int num_blocks = (k + CUDA_DEQUANTIZE_BLOCK_SIZE - 1) / CUDA_DEQUANTIZE_BLOCK_SIZE;
|
||||||
dequantize_block<32, 1, convert_f16><<<num_blocks, CUDA_DEQUANTIZE_BLOCK_SIZE, 0, stream>>>(vx, y, k);
|
dequantize_block<32, 1, convert_f16><<<num_blocks, CUDA_DEQUANTIZE_BLOCK_SIZE, 0, stream>>>(vx, y, k);
|
||||||
@ -353,6 +822,16 @@ static to_fp32_cuda_t ggml_get_to_fp32_cuda(ggml_type type) {
|
|||||||
return dequantize_row_q5_1_cuda;
|
return dequantize_row_q5_1_cuda;
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
return dequantize_row_q8_0_cuda;
|
return dequantize_row_q8_0_cuda;
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
return dequantize_row_q2_k_cuda;
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
return dequantize_row_q3_k_cuda;
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
return dequantize_row_q4_k_cuda;
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
return dequantize_row_q5_k_cuda;
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
|
return dequantize_row_q6_k_cuda;
|
||||||
case GGML_TYPE_F16:
|
case GGML_TYPE_F16:
|
||||||
return convert_fp16_to_fp32_cuda;
|
return convert_fp16_to_fp32_cuda;
|
||||||
default:
|
default:
|
||||||
@ -372,6 +851,16 @@ static dequantize_mul_mat_vec_cuda_t ggml_get_dequantize_mul_mat_vec_cuda(ggml_t
|
|||||||
return dequantize_mul_mat_vec_q5_1_cuda;
|
return dequantize_mul_mat_vec_q5_1_cuda;
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
return dequantize_mul_mat_vec_q8_0_cuda;
|
return dequantize_mul_mat_vec_q8_0_cuda;
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
return dequantize_mul_mat_vec_q2_k_cuda;
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
return dequantize_mul_mat_vec_q3_k_cuda;
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
return dequantize_mul_mat_vec_q4_k_cuda;
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
return dequantize_mul_mat_vec_q5_k_cuda;
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
|
return dequantize_mul_mat_vec_q6_k_cuda;
|
||||||
case GGML_TYPE_F16:
|
case GGML_TYPE_F16:
|
||||||
return convert_mul_mat_vec_f16_cuda;
|
return convert_mul_mat_vec_f16_cuda;
|
||||||
default:
|
default:
|
||||||
@ -790,12 +1279,14 @@ static void ggml_cuda_mul_mat_q_f32(const ggml_tensor * src0, const ggml_tensor
|
|||||||
CUDA_CHECK(cudaStreamWaitEvent(cudaStream, cudaEvent, 0));
|
CUDA_CHECK(cudaStreamWaitEvent(cudaStream, cudaEvent, 0));
|
||||||
|
|
||||||
// compute
|
// compute
|
||||||
|
//printf("Calling dmmv\n");
|
||||||
dmmv(c_Q, c_Y, c_D, ne00, ne01, cudaStream);
|
dmmv(c_Q, c_Y, c_D, ne00, ne01, cudaStream);
|
||||||
CUDA_CHECK(cudaGetLastError());
|
CUDA_CHECK(cudaGetLastError());
|
||||||
|
|
||||||
} else { // general dequantization kernel + cuBLAS matrix matrix multiplication
|
} else { // general dequantization kernel + cuBLAS matrix matrix multiplication
|
||||||
float * c_X = d_X + i * x_ne;
|
float * c_X = d_X + i * x_ne;
|
||||||
|
|
||||||
|
//typedef void (*to_fp32_cuda_t)(const void * x, float * y, int k, cudaStream_t stream);
|
||||||
// convert src0 to fp32 on device
|
// convert src0 to fp32 on device
|
||||||
to_fp32_cuda(c_Q, c_X, x_ne, cudaStream2);
|
to_fp32_cuda(c_Q, c_X, x_ne, cudaStream2);
|
||||||
CUDA_CHECK(cudaGetLastError());
|
CUDA_CHECK(cudaGetLastError());
|
||||||
|
2246
ggml-quants-k.c
Normal file
2246
ggml-quants-k.c
Normal file
File diff suppressed because it is too large
Load Diff
122
ggml-quants-k.h
Normal file
122
ggml-quants-k.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ggml.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// Super-block size
|
||||||
|
#define QK_K 256
|
||||||
|
|
||||||
|
//
|
||||||
|
// Super-block quantization structures
|
||||||
|
//
|
||||||
|
|
||||||
|
// 2-bit quantization
|
||||||
|
// weight is represented as x = a * q + b
|
||||||
|
// 16 blocks of 16 elemenets each
|
||||||
|
// Effectively 2.5625 bits per weight
|
||||||
|
typedef struct {
|
||||||
|
uint8_t scales[QK_K/16]; // scales and mins, quantized with 4 bits
|
||||||
|
uint8_t qs[QK_K/4]; // quants
|
||||||
|
ggml_fp16_t d; // super-block scale for quantized scales
|
||||||
|
ggml_fp16_t dmin; // super-block scale for quantized mins
|
||||||
|
} block_q2_k;
|
||||||
|
static_assert(sizeof(block_q2_k) == 2*sizeof(ggml_fp16_t) + QK_K/16 + QK_K/4, "wrong q2_k block size/padding");
|
||||||
|
|
||||||
|
// 3-bit quantization
|
||||||
|
// weight is represented as x = a * q
|
||||||
|
// 16 blocks of 16 elemenets each
|
||||||
|
// Effectively 3.4375 bits per weight
|
||||||
|
typedef struct {
|
||||||
|
uint8_t hmask[QK_K/8]; // quants - high bit
|
||||||
|
uint8_t qs[QK_K/4]; // quants - low 2 bits
|
||||||
|
uint8_t scales[3*QK_K/64]; // scales, quantized with 6 bits
|
||||||
|
ggml_fp16_t d; // super-block scale
|
||||||
|
} block_q3_k;
|
||||||
|
static_assert(sizeof(block_q3_k) == sizeof(ggml_fp16_t) + QK_K / 4 + 11 * QK_K / 64, "wrong q3_k block size/padding");
|
||||||
|
|
||||||
|
// 4-bit quantization
|
||||||
|
// 16 blocks of 32 elements each
|
||||||
|
// weight is represented as x = a * q + b
|
||||||
|
// Effectively 4.5 bits per weight
|
||||||
|
typedef struct {
|
||||||
|
ggml_fp16_t d; // super-block scale for quantized scales
|
||||||
|
ggml_fp16_t dmin; // super-block scale for quantized mins
|
||||||
|
uint8_t scales[3*QK_K/64]; // scales and mins, quantized with 6 bits
|
||||||
|
uint8_t qs[QK_K/2]; // 4--bit quants
|
||||||
|
} block_q4_k;
|
||||||
|
static_assert(sizeof(block_q4_k) == 2*sizeof(ggml_fp16_t) + 3*QK_K/64 + QK_K/2, "wrong q4_k block size/padding");
|
||||||
|
|
||||||
|
// 5-bit quantization
|
||||||
|
// 16 blocks of 32 elements each
|
||||||
|
// weight is represented as x = a * q + b
|
||||||
|
// Effectively 5.5 bits per weight
|
||||||
|
typedef struct {
|
||||||
|
ggml_fp16_t d; // super-block scale for quantized scales
|
||||||
|
ggml_fp16_t dmin; // super-block scale for quantized mins
|
||||||
|
uint8_t scales[3*QK_K/64]; // scales and mins, quantized with 6 bits
|
||||||
|
uint8_t qh[QK_K/8]; // quants, high bit
|
||||||
|
uint8_t qs[QK_K/2]; // quants, low 4 bits
|
||||||
|
} block_q5_k;
|
||||||
|
static_assert(sizeof(block_q5_k) == 2*sizeof(ggml_fp16_t) + 3*QK_K/64 + QK_K/2 + QK_K/8, "wrong q5_k block size/padding");
|
||||||
|
|
||||||
|
// 6-bit quantization
|
||||||
|
// weight is represented as x = a * q
|
||||||
|
// 16 blocks of 16 elemenets each
|
||||||
|
// Effectively 6.5625 bits per weight
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ql[QK_K/2]; // quants, lower 4 bits
|
||||||
|
uint8_t qh[QK_K/4]; // quants, upper 2 bits
|
||||||
|
int8_t scales[QK_K/16]; // scales, quantized with 8 bits
|
||||||
|
ggml_fp16_t d; // super-block scale
|
||||||
|
} block_q6_k;
|
||||||
|
static_assert(sizeof(block_q6_k) == sizeof(ggml_fp16_t) + QK_K / 16 + 3*QK_K/4, "wrong q6_k block size/padding");
|
||||||
|
|
||||||
|
// This is only used for intermediate quantization and dot products
|
||||||
|
typedef struct {
|
||||||
|
float d; // delta
|
||||||
|
int8_t qs[QK_K]; // quants
|
||||||
|
int16_t bsums[QK_K/16]; // sum of quants in groups of 16
|
||||||
|
} block_q8_k;
|
||||||
|
static_assert(sizeof(block_q8_k) == sizeof(float) + QK_K + QK_K/16*sizeof(int16_t), "wrong q8_k block size/padding");
|
||||||
|
|
||||||
|
|
||||||
|
// Quantization
|
||||||
|
void quantize_row_q2_k_reference(const float * restrict x, block_q2_k * restrict y, int k);
|
||||||
|
void quantize_row_q3_k_reference(const float * restrict x, block_q3_k * restrict y, int k);
|
||||||
|
void quantize_row_q4_k_reference(const float * restrict x, block_q4_k * restrict y, int k);
|
||||||
|
void quantize_row_q5_k_reference(const float * restrict x, block_q5_k * restrict y, int k);
|
||||||
|
void quantize_row_q6_k_reference(const float * restrict x, block_q6_k * restrict y, int k);
|
||||||
|
void quantize_row_q8_k_reference(const float * restrict x, block_q8_k * restrict y, int k);
|
||||||
|
|
||||||
|
void quantize_row_q2_k(const float * restrict x, void * restrict y, int k);
|
||||||
|
void quantize_row_q3_k(const float * restrict x, void * restrict y, int k);
|
||||||
|
void quantize_row_q4_k(const float * restrict x, void * restrict y, int k);
|
||||||
|
void quantize_row_q5_k(const float * restrict x, void * restrict y, int k);
|
||||||
|
void quantize_row_q6_k(const float * restrict x, void * restrict y, int k);
|
||||||
|
void quantize_row_q8_k(const float * restrict x, void * restrict y, int k);
|
||||||
|
|
||||||
|
// Dequantization
|
||||||
|
void dequantize_row_q2_k(const block_q2_k * restrict x, float * restrict y, int k);
|
||||||
|
void dequantize_row_q3_k(const block_q3_k * restrict x, float * restrict y, int k);
|
||||||
|
void dequantize_row_q4_k(const block_q4_k * restrict x, float * restrict y, int k);
|
||||||
|
void dequantize_row_q5_k(const block_q5_k * restrict x, float * restrict y, int k);
|
||||||
|
void dequantize_row_q6_k(const block_q6_k * restrict x, float * restrict y, int k);
|
||||||
|
void dequantize_row_q8_k(const block_q8_k * restrict x, float * restrict y, int k);
|
||||||
|
|
||||||
|
// Dot product
|
||||||
|
void ggml_vec_dot_q2_k_q8_k(int n, float * restrict s, const void * restrict vx, const void * restrict vy);
|
||||||
|
void ggml_vec_dot_q3_k_q8_k(int n, float * restrict s, const void * restrict vx, const void * restrict vy);
|
||||||
|
void ggml_vec_dot_q4_k_q8_k(int n, float * restrict s, const void * restrict vx, const void * restrict vy);
|
||||||
|
void ggml_vec_dot_q5_k_q8_k(int n, float * restrict s, const void * restrict vx, const void * restrict vy);
|
||||||
|
void ggml_vec_dot_q6_k_q8_k(int n, float * restrict s, const void * restrict vx, const void * restrict vy);
|
||||||
|
|
||||||
|
// Quantization with histogram collection
|
||||||
|
size_t ggml_quantize_q2_k(const float * src, void * dst, int n, int k, int64_t * hist);
|
||||||
|
size_t ggml_quantize_q3_k(const float * src, void * dst, int n, int k, int64_t * hist);
|
||||||
|
size_t ggml_quantize_q4_k(const float * src, void * dst, int n, int k, int64_t * hist);
|
||||||
|
size_t ggml_quantize_q5_k(const float * src, void * dst, int n, int k, int64_t * hist);
|
||||||
|
size_t ggml_quantize_q6_k(const float * src, void * dst, int n, int k, int64_t * hist);
|
||||||
|
|
150
ggml.c
150
ggml.c
@ -2,6 +2,7 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "ggml.h"
|
#include "ggml.h"
|
||||||
|
#include "ggml-quants-k.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#include <malloc.h> // using malloc.h with MSC/MINGW
|
#include <malloc.h> // using malloc.h with MSC/MINGW
|
||||||
@ -1565,6 +1566,46 @@ static const quantize_fns_t quantize_fns[GGML_TYPE_COUNT] = {
|
|||||||
.vec_dot_q = NULL, // TODO
|
.vec_dot_q = NULL, // TODO
|
||||||
.vec_dot_type = GGML_TYPE_Q8_1,
|
.vec_dot_type = GGML_TYPE_Q8_1,
|
||||||
},
|
},
|
||||||
|
[GGML_TYPE_Q2_K] = {
|
||||||
|
.dequantize_row_q = (dequantize_row_q_t) dequantize_row_q2_k,
|
||||||
|
.quantize_row_q = quantize_row_q2_k,
|
||||||
|
.quantize_row_q_reference = (quantize_row_q_t) quantize_row_q2_k_reference,
|
||||||
|
.quantize_row_q_dot = quantize_row_q8_k,
|
||||||
|
.vec_dot_q = ggml_vec_dot_q2_k_q8_k,
|
||||||
|
.vec_dot_type = GGML_TYPE_Q8_K,
|
||||||
|
},
|
||||||
|
[GGML_TYPE_Q3_K] = {
|
||||||
|
.dequantize_row_q = (dequantize_row_q_t) dequantize_row_q3_k,
|
||||||
|
.quantize_row_q = quantize_row_q3_k,
|
||||||
|
.quantize_row_q_reference = (quantize_row_q_t) quantize_row_q3_k_reference,
|
||||||
|
.quantize_row_q_dot = quantize_row_q8_k,
|
||||||
|
.vec_dot_q = ggml_vec_dot_q3_k_q8_k,
|
||||||
|
.vec_dot_type = GGML_TYPE_Q8_K,
|
||||||
|
},
|
||||||
|
[GGML_TYPE_Q4_K] = {
|
||||||
|
.dequantize_row_q = (dequantize_row_q_t) dequantize_row_q4_k,
|
||||||
|
.quantize_row_q = quantize_row_q4_k,
|
||||||
|
.quantize_row_q_reference = (quantize_row_q_t) quantize_row_q4_k_reference,
|
||||||
|
.quantize_row_q_dot = quantize_row_q8_k,
|
||||||
|
.vec_dot_q = ggml_vec_dot_q4_k_q8_k,
|
||||||
|
.vec_dot_type = GGML_TYPE_Q8_K,
|
||||||
|
},
|
||||||
|
[GGML_TYPE_Q5_K] = {
|
||||||
|
.dequantize_row_q = (dequantize_row_q_t) dequantize_row_q5_k,
|
||||||
|
.quantize_row_q = quantize_row_q5_k,
|
||||||
|
.quantize_row_q_reference = (quantize_row_q_t) quantize_row_q5_k_reference,
|
||||||
|
.quantize_row_q_dot = quantize_row_q8_k,
|
||||||
|
.vec_dot_q = ggml_vec_dot_q5_k_q8_k,
|
||||||
|
.vec_dot_type = GGML_TYPE_Q8_K,
|
||||||
|
},
|
||||||
|
[GGML_TYPE_Q6_K] = {
|
||||||
|
.dequantize_row_q = (dequantize_row_q_t) dequantize_row_q6_k,
|
||||||
|
.quantize_row_q = quantize_row_q6_k,
|
||||||
|
.quantize_row_q_reference = (quantize_row_q_t) quantize_row_q6_k_reference,
|
||||||
|
.quantize_row_q_dot = quantize_row_q8_k,
|
||||||
|
.vec_dot_q = ggml_vec_dot_q6_k_q8_k,
|
||||||
|
.vec_dot_type = GGML_TYPE_Q8_K,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// For internal test use
|
// For internal test use
|
||||||
@ -3444,11 +3485,17 @@ static const int GGML_BLCK_SIZE[GGML_TYPE_COUNT] = {
|
|||||||
[GGML_TYPE_Q5_1] = QK5_1,
|
[GGML_TYPE_Q5_1] = QK5_1,
|
||||||
[GGML_TYPE_Q8_0] = QK8_0,
|
[GGML_TYPE_Q8_0] = QK8_0,
|
||||||
[GGML_TYPE_Q8_1] = QK8_1,
|
[GGML_TYPE_Q8_1] = QK8_1,
|
||||||
|
[GGML_TYPE_Q2_K] = QK_K,
|
||||||
|
[GGML_TYPE_Q3_K] = QK_K,
|
||||||
|
[GGML_TYPE_Q4_K] = QK_K,
|
||||||
|
[GGML_TYPE_Q5_K] = QK_K,
|
||||||
|
[GGML_TYPE_Q6_K] = QK_K,
|
||||||
|
[GGML_TYPE_Q8_K] = QK_K,
|
||||||
[GGML_TYPE_I8] = 1,
|
[GGML_TYPE_I8] = 1,
|
||||||
[GGML_TYPE_I16] = 1,
|
[GGML_TYPE_I16] = 1,
|
||||||
[GGML_TYPE_I32] = 1,
|
[GGML_TYPE_I32] = 1,
|
||||||
};
|
};
|
||||||
static_assert(GGML_TYPE_COUNT == 13, "GGML_BLCK_SIZE is outdated");
|
static_assert(GGML_TYPE_COUNT == 19, "GGML_BLCK_SIZE is outdated");
|
||||||
|
|
||||||
static const size_t GGML_TYPE_SIZE[GGML_TYPE_COUNT] = {
|
static const size_t GGML_TYPE_SIZE[GGML_TYPE_COUNT] = {
|
||||||
[GGML_TYPE_F32] = sizeof(float),
|
[GGML_TYPE_F32] = sizeof(float),
|
||||||
@ -3459,11 +3506,17 @@ static const size_t GGML_TYPE_SIZE[GGML_TYPE_COUNT] = {
|
|||||||
[GGML_TYPE_Q5_1] = sizeof(block_q5_1),
|
[GGML_TYPE_Q5_1] = sizeof(block_q5_1),
|
||||||
[GGML_TYPE_Q8_0] = sizeof(block_q8_0),
|
[GGML_TYPE_Q8_0] = sizeof(block_q8_0),
|
||||||
[GGML_TYPE_Q8_1] = sizeof(block_q8_1),
|
[GGML_TYPE_Q8_1] = sizeof(block_q8_1),
|
||||||
|
[GGML_TYPE_Q2_K] = sizeof(block_q2_k),
|
||||||
|
[GGML_TYPE_Q3_K] = sizeof(block_q3_k),
|
||||||
|
[GGML_TYPE_Q4_K] = sizeof(block_q4_k),
|
||||||
|
[GGML_TYPE_Q5_K] = sizeof(block_q5_k),
|
||||||
|
[GGML_TYPE_Q6_K] = sizeof(block_q6_k),
|
||||||
|
[GGML_TYPE_Q8_K] = sizeof(block_q8_k),
|
||||||
[GGML_TYPE_I8] = sizeof(int8_t),
|
[GGML_TYPE_I8] = sizeof(int8_t),
|
||||||
[GGML_TYPE_I16] = sizeof(int16_t),
|
[GGML_TYPE_I16] = sizeof(int16_t),
|
||||||
[GGML_TYPE_I32] = sizeof(int32_t),
|
[GGML_TYPE_I32] = sizeof(int32_t),
|
||||||
};
|
};
|
||||||
static_assert(GGML_TYPE_COUNT == 13, "GGML_TYPE_SIZE is outdated");
|
static_assert(GGML_TYPE_COUNT == 19, "GGML_TYPE_SIZE is outdated");
|
||||||
|
|
||||||
|
|
||||||
static const char * GGML_TYPE_NAME[GGML_TYPE_COUNT] = {
|
static const char * GGML_TYPE_NAME[GGML_TYPE_COUNT] = {
|
||||||
@ -3475,11 +3528,17 @@ static const char * GGML_TYPE_NAME[GGML_TYPE_COUNT] = {
|
|||||||
[GGML_TYPE_Q5_1] = "q5_1",
|
[GGML_TYPE_Q5_1] = "q5_1",
|
||||||
[GGML_TYPE_Q8_0] = "q8_0",
|
[GGML_TYPE_Q8_0] = "q8_0",
|
||||||
[GGML_TYPE_Q8_1] = "q8_1",
|
[GGML_TYPE_Q8_1] = "q8_1",
|
||||||
|
[GGML_TYPE_Q2_K] = "q2_k",
|
||||||
|
[GGML_TYPE_Q3_K] = "q3_k",
|
||||||
|
[GGML_TYPE_Q4_K] = "q4_k",
|
||||||
|
[GGML_TYPE_Q5_K] = "q5_k",
|
||||||
|
[GGML_TYPE_Q6_K] = "q6_k",
|
||||||
|
[GGML_TYPE_Q8_K] = "q8_k",
|
||||||
[GGML_TYPE_I8] = "i8",
|
[GGML_TYPE_I8] = "i8",
|
||||||
[GGML_TYPE_I16] = "i16",
|
[GGML_TYPE_I16] = "i16",
|
||||||
[GGML_TYPE_I32] = "i32",
|
[GGML_TYPE_I32] = "i32",
|
||||||
};
|
};
|
||||||
static_assert(GGML_TYPE_COUNT == 13, "GGML_TYPE_NAME is outdated");
|
static_assert(GGML_TYPE_COUNT == 19, "GGML_TYPE_NAME is outdated");
|
||||||
|
|
||||||
static bool GGML_IS_QUANTIZED[GGML_TYPE_COUNT] = {
|
static bool GGML_IS_QUANTIZED[GGML_TYPE_COUNT] = {
|
||||||
[GGML_TYPE_F32] = false,
|
[GGML_TYPE_F32] = false,
|
||||||
@ -3490,11 +3549,17 @@ static bool GGML_IS_QUANTIZED[GGML_TYPE_COUNT] = {
|
|||||||
[GGML_TYPE_Q5_1] = true,
|
[GGML_TYPE_Q5_1] = true,
|
||||||
[GGML_TYPE_Q8_0] = true,
|
[GGML_TYPE_Q8_0] = true,
|
||||||
[GGML_TYPE_Q8_1] = true,
|
[GGML_TYPE_Q8_1] = true,
|
||||||
|
[GGML_TYPE_Q2_K] = true,
|
||||||
|
[GGML_TYPE_Q3_K] = true,
|
||||||
|
[GGML_TYPE_Q4_K] = true,
|
||||||
|
[GGML_TYPE_Q5_K] = true,
|
||||||
|
[GGML_TYPE_Q6_K] = true,
|
||||||
|
[GGML_TYPE_Q8_K] = true,
|
||||||
[GGML_TYPE_I8] = false,
|
[GGML_TYPE_I8] = false,
|
||||||
[GGML_TYPE_I16] = false,
|
[GGML_TYPE_I16] = false,
|
||||||
[GGML_TYPE_I32] = false,
|
[GGML_TYPE_I32] = false,
|
||||||
};
|
};
|
||||||
static_assert(GGML_TYPE_COUNT == 13, "GGML_IS_QUANTIZED is outdated");
|
static_assert(GGML_TYPE_COUNT == 19, "GGML_IS_QUANTIZED is outdated");
|
||||||
|
|
||||||
static const char * GGML_OP_NAME[GGML_OP_COUNT] = {
|
static const char * GGML_OP_NAME[GGML_OP_COUNT] = {
|
||||||
"NONE",
|
"NONE",
|
||||||
@ -3808,6 +3873,11 @@ enum ggml_type ggml_ftype_to_ggml_type(enum ggml_ftype ftype) {
|
|||||||
case GGML_FTYPE_MOSTLY_Q5_0: wtype = GGML_TYPE_Q5_0; break;
|
case GGML_FTYPE_MOSTLY_Q5_0: wtype = GGML_TYPE_Q5_0; break;
|
||||||
case GGML_FTYPE_MOSTLY_Q5_1: wtype = GGML_TYPE_Q5_1; break;
|
case GGML_FTYPE_MOSTLY_Q5_1: wtype = GGML_TYPE_Q5_1; break;
|
||||||
case GGML_FTYPE_MOSTLY_Q8_0: wtype = GGML_TYPE_Q8_0; break;
|
case GGML_FTYPE_MOSTLY_Q8_0: wtype = GGML_TYPE_Q8_0; break;
|
||||||
|
case GGML_FTYPE_MOSTLY_Q2_K: wtype = GGML_TYPE_Q2_K; break;
|
||||||
|
case GGML_FTYPE_MOSTLY_Q3_K: wtype = GGML_TYPE_Q3_K; break;
|
||||||
|
case GGML_FTYPE_MOSTLY_Q4_K: wtype = GGML_TYPE_Q4_K; break;
|
||||||
|
case GGML_FTYPE_MOSTLY_Q5_K: wtype = GGML_TYPE_Q5_K; break;
|
||||||
|
case GGML_FTYPE_MOSTLY_Q6_K: wtype = GGML_TYPE_Q6_K; break;
|
||||||
case GGML_FTYPE_UNKNOWN: wtype = GGML_TYPE_COUNT; break;
|
case GGML_FTYPE_UNKNOWN: wtype = GGML_TYPE_COUNT; break;
|
||||||
case GGML_FTYPE_MOSTLY_Q4_1_SOME_F16: wtype = GGML_TYPE_COUNT; break;
|
case GGML_FTYPE_MOSTLY_Q4_1_SOME_F16: wtype = GGML_TYPE_COUNT; break;
|
||||||
}
|
}
|
||||||
@ -7623,6 +7693,11 @@ static void ggml_compute_forward_add(
|
|||||||
case GGML_TYPE_Q5_0:
|
case GGML_TYPE_Q5_0:
|
||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
{
|
{
|
||||||
ggml_compute_forward_add_q_f32(params, src0, src1, dst);
|
ggml_compute_forward_add_q_f32(params, src0, src1, dst);
|
||||||
} break;
|
} break;
|
||||||
@ -7926,6 +8001,11 @@ static void ggml_compute_forward_add1(
|
|||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
case GGML_TYPE_Q8_1:
|
case GGML_TYPE_Q8_1:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
{
|
{
|
||||||
ggml_compute_forward_add1_q_f32(params, src0, src1, dst);
|
ggml_compute_forward_add1_q_f32(params, src0, src1, dst);
|
||||||
} break;
|
} break;
|
||||||
@ -8048,6 +8128,11 @@ static void ggml_compute_forward_acc(
|
|||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
case GGML_TYPE_Q8_1:
|
case GGML_TYPE_Q8_1:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
GGML_ASSERT(false);
|
GGML_ASSERT(false);
|
||||||
@ -10148,6 +10233,11 @@ static void ggml_compute_forward_mul_mat(
|
|||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
case GGML_TYPE_Q8_1:
|
case GGML_TYPE_Q8_1:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
{
|
{
|
||||||
ggml_compute_forward_mul_mat_q_f32(params, src0, src1, dst);
|
ggml_compute_forward_mul_mat_q_f32(params, src0, src1, dst);
|
||||||
} break;
|
} break;
|
||||||
@ -10331,6 +10421,11 @@ static void ggml_compute_forward_set(
|
|||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
case GGML_TYPE_Q8_1:
|
case GGML_TYPE_Q8_1:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
GGML_ASSERT(false);
|
GGML_ASSERT(false);
|
||||||
@ -10496,6 +10591,11 @@ static void ggml_compute_forward_get_rows(
|
|||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
case GGML_TYPE_Q8_1:
|
case GGML_TYPE_Q8_1:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
{
|
{
|
||||||
ggml_compute_forward_get_rows_q(params, src0, src1, dst);
|
ggml_compute_forward_get_rows_q(params, src0, src1, dst);
|
||||||
} break;
|
} break;
|
||||||
@ -11042,6 +11142,12 @@ static void ggml_compute_forward_alibi(
|
|||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
case GGML_TYPE_Q8_1:
|
case GGML_TYPE_Q8_1:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
|
case GGML_TYPE_Q8_K:
|
||||||
case GGML_TYPE_I8:
|
case GGML_TYPE_I8:
|
||||||
case GGML_TYPE_I16:
|
case GGML_TYPE_I16:
|
||||||
case GGML_TYPE_I32:
|
case GGML_TYPE_I32:
|
||||||
@ -11113,6 +11219,12 @@ static void ggml_compute_forward_clamp(
|
|||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
case GGML_TYPE_Q8_1:
|
case GGML_TYPE_Q8_1:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
|
case GGML_TYPE_Q8_K:
|
||||||
case GGML_TYPE_I8:
|
case GGML_TYPE_I8:
|
||||||
case GGML_TYPE_I16:
|
case GGML_TYPE_I16:
|
||||||
case GGML_TYPE_I32:
|
case GGML_TYPE_I32:
|
||||||
@ -16152,6 +16264,36 @@ size_t ggml_quantize_chunk(enum ggml_type type, const float * src, void * dst, i
|
|||||||
block_q8_0 * block = (block_q8_0*)dst + start / QK8_0;
|
block_q8_0 * block = (block_q8_0*)dst + start / QK8_0;
|
||||||
result = ggml_quantize_q8_0(src + start, block, n, n, hist);
|
result = ggml_quantize_q8_0(src + start, block, n, n, hist);
|
||||||
} break;
|
} break;
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
{
|
||||||
|
GGML_ASSERT(start % QK_K == 0);
|
||||||
|
block_q2_k * block = (block_q2_k*)dst + start / QK_K;
|
||||||
|
result = ggml_quantize_q2_k(src + start, block, n, n, hist);
|
||||||
|
} break;
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
{
|
||||||
|
GGML_ASSERT(start % QK_K == 0);
|
||||||
|
block_q3_k * block = (block_q3_k*)dst + start / QK_K;
|
||||||
|
result = ggml_quantize_q3_k(src + start, block, n, n, hist);
|
||||||
|
} break;
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
{
|
||||||
|
GGML_ASSERT(start % QK_K == 0);
|
||||||
|
block_q4_k * block = (block_q4_k*)dst + start / QK_K;
|
||||||
|
result = ggml_quantize_q4_k(src + start, block, n, n, hist);
|
||||||
|
} break;
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
{
|
||||||
|
GGML_ASSERT(start % QK_K == 0);
|
||||||
|
block_q5_k * block = (block_q5_k*)dst + start / QK_K;
|
||||||
|
result = ggml_quantize_q5_k(src + start, block, n, n, hist);
|
||||||
|
} break;
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
|
{
|
||||||
|
GGML_ASSERT(start % QK_K == 0);
|
||||||
|
block_q6_k * block = (block_q6_k*)dst + start / QK_K;
|
||||||
|
result = ggml_quantize_q6_k(src + start, block, n, n, hist);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
12
ggml.h
12
ggml.h
@ -241,6 +241,13 @@ extern "C" {
|
|||||||
GGML_TYPE_Q5_1 = 7,
|
GGML_TYPE_Q5_1 = 7,
|
||||||
GGML_TYPE_Q8_0 = 8,
|
GGML_TYPE_Q8_0 = 8,
|
||||||
GGML_TYPE_Q8_1 = 9,
|
GGML_TYPE_Q8_1 = 9,
|
||||||
|
// k-quantizations
|
||||||
|
GGML_TYPE_Q2_K = 10,
|
||||||
|
GGML_TYPE_Q3_K = 11,
|
||||||
|
GGML_TYPE_Q4_K = 12,
|
||||||
|
GGML_TYPE_Q5_K = 13,
|
||||||
|
GGML_TYPE_Q6_K = 14,
|
||||||
|
GGML_TYPE_Q8_K = 15,
|
||||||
GGML_TYPE_I8,
|
GGML_TYPE_I8,
|
||||||
GGML_TYPE_I16,
|
GGML_TYPE_I16,
|
||||||
GGML_TYPE_I32,
|
GGML_TYPE_I32,
|
||||||
@ -264,6 +271,11 @@ extern "C" {
|
|||||||
GGML_FTYPE_MOSTLY_Q8_0 = 7, // except 1d tensors
|
GGML_FTYPE_MOSTLY_Q8_0 = 7, // except 1d tensors
|
||||||
GGML_FTYPE_MOSTLY_Q5_0 = 8, // except 1d tensors
|
GGML_FTYPE_MOSTLY_Q5_0 = 8, // except 1d tensors
|
||||||
GGML_FTYPE_MOSTLY_Q5_1 = 9, // except 1d tensors
|
GGML_FTYPE_MOSTLY_Q5_1 = 9, // except 1d tensors
|
||||||
|
GGML_FTYPE_MOSTLY_Q2_K = 10, // except 1d tensors
|
||||||
|
GGML_FTYPE_MOSTLY_Q3_K = 11, // except 1d tensors
|
||||||
|
GGML_FTYPE_MOSTLY_Q4_K = 12, // except 1d tensors
|
||||||
|
GGML_FTYPE_MOSTLY_Q5_K = 13, // except 1d tensors
|
||||||
|
GGML_FTYPE_MOSTLY_Q6_K = 14, // except 1d tensors
|
||||||
};
|
};
|
||||||
|
|
||||||
// available tensor operations:
|
// available tensor operations:
|
||||||
|
85
llama.cpp
85
llama.cpp
@ -515,6 +515,11 @@ struct llama_file_loader {
|
|||||||
case GGML_TYPE_Q5_0:
|
case GGML_TYPE_Q5_0:
|
||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
throw format("unrecognized tensor type %u\n", shard.type);
|
throw format("unrecognized tensor type %u\n", shard.type);
|
||||||
@ -590,6 +595,11 @@ struct llama_file_saver {
|
|||||||
case GGML_TYPE_Q5_0:
|
case GGML_TYPE_Q5_0:
|
||||||
case GGML_TYPE_Q5_1:
|
case GGML_TYPE_Q5_1:
|
||||||
case GGML_TYPE_Q8_0:
|
case GGML_TYPE_Q8_0:
|
||||||
|
case GGML_TYPE_Q2_K:
|
||||||
|
case GGML_TYPE_Q3_K:
|
||||||
|
case GGML_TYPE_Q4_K:
|
||||||
|
case GGML_TYPE_Q5_K:
|
||||||
|
case GGML_TYPE_Q6_K:
|
||||||
break;
|
break;
|
||||||
default: LLAMA_ASSERT(false);
|
default: LLAMA_ASSERT(false);
|
||||||
}
|
}
|
||||||
@ -906,6 +916,16 @@ static const char *llama_ftype_name(enum llama_ftype ftype) {
|
|||||||
case LLAMA_FTYPE_MOSTLY_Q5_0: return "mostly Q5_0";
|
case LLAMA_FTYPE_MOSTLY_Q5_0: return "mostly Q5_0";
|
||||||
case LLAMA_FTYPE_MOSTLY_Q5_1: return "mostly Q5_1";
|
case LLAMA_FTYPE_MOSTLY_Q5_1: return "mostly Q5_1";
|
||||||
case LLAMA_FTYPE_MOSTLY_Q8_0: return "mostly Q8_0";
|
case LLAMA_FTYPE_MOSTLY_Q8_0: return "mostly Q8_0";
|
||||||
|
// K-quants
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q2_K: return "mostly Q2_K";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q3_K_S: return "mostly Q3_K - Small";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q3_K_M: return "mostly Q3_K - Medium";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q3_K_L: return "mostly Q3_K - Large";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q4_K_S: return "mostly Q4_K - Small";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q4_K_M: return "mostly Q4_K - Medium";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q5_K_S: return "mostly Q5_K - Small";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q5_K_M: return "mostly Q5_K - Medium";
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q6_K: return "mostly Q6_K";
|
||||||
default: return "unknown, may not work";
|
default: return "unknown, may not work";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2113,8 +2133,18 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s
|
|||||||
case LLAMA_FTYPE_MOSTLY_Q5_0: quantized_type = GGML_TYPE_Q5_0; break;
|
case LLAMA_FTYPE_MOSTLY_Q5_0: quantized_type = GGML_TYPE_Q5_0; break;
|
||||||
case LLAMA_FTYPE_MOSTLY_Q5_1: quantized_type = GGML_TYPE_Q5_1; break;
|
case LLAMA_FTYPE_MOSTLY_Q5_1: quantized_type = GGML_TYPE_Q5_1; break;
|
||||||
case LLAMA_FTYPE_MOSTLY_Q8_0: quantized_type = GGML_TYPE_Q8_0; break;
|
case LLAMA_FTYPE_MOSTLY_Q8_0: quantized_type = GGML_TYPE_Q8_0; break;
|
||||||
|
// K-quants
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q2_K: quantized_type = GGML_TYPE_Q2_K; break;
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q3_K_S:
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q3_K_M:
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q3_K_L: quantized_type = GGML_TYPE_Q3_K; break;
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q4_K_S:
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q4_K_M: quantized_type = GGML_TYPE_Q4_K; break;
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q5_K_S:
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q5_K_M: quantized_type = GGML_TYPE_Q5_K; break;
|
||||||
|
case LLAMA_FTYPE_MOSTLY_Q6_K: quantized_type = GGML_TYPE_Q6_K; break;
|
||||||
default: throw format("invalid output file type %d\n", ftype);
|
default: throw format("invalid output file type %d\n", ftype);
|
||||||
};
|
}
|
||||||
|
|
||||||
if (nthread <= 0) {
|
if (nthread <= 0) {
|
||||||
nthread = std::thread::hardware_concurrency();
|
nthread = std::thread::hardware_concurrency();
|
||||||
@ -2124,6 +2154,20 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s
|
|||||||
/*vocab_only*/ false));
|
/*vocab_only*/ false));
|
||||||
llama_file_saver file_saver(fname_out.c_str(), model_loader->file_loaders.at(0).get(), ftype);
|
llama_file_saver file_saver(fname_out.c_str(), model_loader->file_loaders.at(0).get(), ftype);
|
||||||
|
|
||||||
|
int n_attention_wv = 0;
|
||||||
|
int n_feed_forward_w2 = 0;
|
||||||
|
for (auto& tensor : model_loader->tensors_map.tensors) {
|
||||||
|
if (tensor.name.find("attention.wv.weight") != std::string::npos) {
|
||||||
|
++n_attention_wv;
|
||||||
|
}
|
||||||
|
else if (tensor.name.find("feed_forward.w2.weight") != std::string::npos) {
|
||||||
|
++n_feed_forward_w2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i_attention_wv = 0;
|
||||||
|
int i_feed_forward_w2 = 0;
|
||||||
|
|
||||||
size_t total_size_org = 0;
|
size_t total_size_org = 0;
|
||||||
size_t total_size_new = 0;
|
size_t total_size_new = 0;
|
||||||
std::vector<int64_t> hist_all(1 << 4, 0);
|
std::vector<int64_t> hist_all(1 << 4, 0);
|
||||||
@ -2166,6 +2210,27 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s
|
|||||||
printf("size = %8.3f MB\n", tensor.size/1024.0/1024.0);
|
printf("size = %8.3f MB\n", tensor.size/1024.0/1024.0);
|
||||||
} else {
|
} else {
|
||||||
new_type = quantized_type;
|
new_type = quantized_type;
|
||||||
|
if (tensor.name == "output.weight") new_type = GGML_TYPE_Q6_K;
|
||||||
|
else if (tensor.name.find("attention.wv.weight") != std::string::npos) {
|
||||||
|
if (ftype == LLAMA_FTYPE_MOSTLY_Q3_K_M || ftype == LLAMA_FTYPE_MOSTLY_Q2_K) new_type = GGML_TYPE_Q4_K;
|
||||||
|
else if (ftype == LLAMA_FTYPE_MOSTLY_Q3_K_L) new_type = GGML_TYPE_Q5_K;
|
||||||
|
else if ((ftype == LLAMA_FTYPE_MOSTLY_Q4_K_M || ftype == LLAMA_FTYPE_MOSTLY_Q5_K_M) &&
|
||||||
|
(i_attention_wv < n_attention_wv/8 || i_attention_wv >= 7*n_attention_wv/8 ||
|
||||||
|
(i_attention_wv - n_attention_wv/8)%3 == 2)) new_type = GGML_TYPE_Q6_K;
|
||||||
|
++i_attention_wv;
|
||||||
|
}
|
||||||
|
else if (tensor.name.find("feed_forward.w2.weight") != std::string::npos) {
|
||||||
|
if (ftype == LLAMA_FTYPE_MOSTLY_Q3_K_M || ftype == LLAMA_FTYPE_MOSTLY_Q2_K) new_type = GGML_TYPE_Q4_K;
|
||||||
|
else if (ftype == LLAMA_FTYPE_MOSTLY_Q3_K_L) new_type = GGML_TYPE_Q5_K;
|
||||||
|
else if ((ftype == LLAMA_FTYPE_MOSTLY_Q4_K_M || ftype == LLAMA_FTYPE_MOSTLY_Q5_K_M) &&
|
||||||
|
(i_feed_forward_w2 < n_feed_forward_w2/8 || i_feed_forward_w2 >= 7*n_feed_forward_w2/8 ||
|
||||||
|
(i_feed_forward_w2 - n_feed_forward_w2/8)%3 == 2)) new_type = GGML_TYPE_Q6_K;
|
||||||
|
++i_feed_forward_w2;
|
||||||
|
}
|
||||||
|
else if (tensor.name.find("attention.wo.weight") != std::string::npos) {
|
||||||
|
if (ftype == LLAMA_FTYPE_MOSTLY_Q3_K_M || ftype == LLAMA_FTYPE_MOSTLY_Q2_K) new_type = GGML_TYPE_Q4_K;
|
||||||
|
else if (ftype == LLAMA_FTYPE_MOSTLY_Q3_K_L) new_type = GGML_TYPE_Q5_K;
|
||||||
|
}
|
||||||
float * f32_data;
|
float * f32_data;
|
||||||
size_t nelements = tensor.ne.at(0) * tensor.ne.at(1);
|
size_t nelements = tensor.ne.at(0) * tensor.ne.at(1);
|
||||||
llama_buffer f32_conv_buf;
|
llama_buffer f32_conv_buf;
|
||||||
@ -2233,12 +2298,16 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("size = %8.2f MB -> %8.2f MB | hist: ", tensor.size/1024.0/1024.0, new_size/1024.0/1024.0);
|
printf("size = %8.2f MB -> %8.2f MB | hist: ", tensor.size/1024.0/1024.0, new_size/1024.0/1024.0);
|
||||||
|
int64_t tot_count = 0;
|
||||||
for (size_t i = 0; i < hist_cur.size(); i++) {
|
for (size_t i = 0; i < hist_cur.size(); i++) {
|
||||||
hist_all[i] += hist_cur[i];
|
hist_all[i] += hist_cur[i];
|
||||||
|
tot_count += hist_cur[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < hist_cur.size(); i++) {
|
if (tot_count > 0) {
|
||||||
printf("%5.3f ", hist_cur[i] / float(nelements));
|
for (size_t i = 0; i < hist_cur.size(); i++) {
|
||||||
|
printf("%5.3f ", hist_cur[i] / float(nelements));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@ -2256,11 +2325,13 @@ static void llama_model_quantize_internal(const std::string & fname_inp, const s
|
|||||||
sum_all += hist_all[i];
|
sum_all += hist_all[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s: hist: ", __func__);
|
if (sum_all > 0) {
|
||||||
for (size_t i = 0; i < hist_all.size(); i++) {
|
printf("%s: hist: ", __func__);
|
||||||
printf("%5.3f ", hist_all[i] / float(sum_all));
|
for (size_t i = 0; i < hist_all.size(); i++) {
|
||||||
|
printf("%5.3f ", hist_all[i] / float(sum_all));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
llama.h
9
llama.h
@ -94,6 +94,15 @@ extern "C" {
|
|||||||
LLAMA_FTYPE_MOSTLY_Q8_0 = 7, // except 1d tensors
|
LLAMA_FTYPE_MOSTLY_Q8_0 = 7, // except 1d tensors
|
||||||
LLAMA_FTYPE_MOSTLY_Q5_0 = 8, // except 1d tensors
|
LLAMA_FTYPE_MOSTLY_Q5_0 = 8, // except 1d tensors
|
||||||
LLAMA_FTYPE_MOSTLY_Q5_1 = 9, // except 1d tensors
|
LLAMA_FTYPE_MOSTLY_Q5_1 = 9, // except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q2_K = 10,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q3_K_S = 11,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q3_K_M = 12,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q3_K_L = 13,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q4_K_S = 14,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q4_K_M = 15,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q5_K_S = 16,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q5_K_M = 17,// except 1d tensors
|
||||||
|
LLAMA_FTYPE_MOSTLY_Q6_K = 18,// except 1d tensors
|
||||||
};
|
};
|
||||||
|
|
||||||
LLAMA_API struct llama_context_params llama_context_default_params();
|
LLAMA_API struct llama_context_params llama_context_default_params();
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
const float MAX_QUANTIZATION_REFERENCE_ERROR = 0.0001;
|
const float MAX_QUANTIZATION_REFERENCE_ERROR = 0.0001;
|
||||||
const float MAX_QUANTIZATION_TOTAL_ERROR = 0.002;
|
const float MAX_QUANTIZATION_TOTAL_ERROR = 0.002;
|
||||||
|
const float MAX_QUANTIZATION_TOTAL_ERROR_2BITS = 0.0075;
|
||||||
|
const float MAX_QUANTIZATION_TOTAL_ERROR_3BITS = 0.0040;
|
||||||
const float MAX_DOT_PRODUCT_ERROR = 0.02;
|
const float MAX_DOT_PRODUCT_ERROR = 0.02;
|
||||||
|
|
||||||
const char* RESULT_STR[] = {"ok", "FAILED"};
|
const char* RESULT_STR[] = {"ok", "FAILED"};
|
||||||
@ -122,7 +124,10 @@ int main(int argc, char * argv[]) {
|
|||||||
|
|
||||||
if (qfns.quantize_row_q && qfns.dequantize_row_q) {
|
if (qfns.quantize_row_q && qfns.dequantize_row_q) {
|
||||||
const float total_error = total_quantization_error(qfns, test_size, test_data.data());
|
const float total_error = total_quantization_error(qfns, test_size, test_data.data());
|
||||||
failed = !(total_error < MAX_QUANTIZATION_TOTAL_ERROR);
|
const float max_quantization_error =
|
||||||
|
type == GGML_TYPE_Q2_K ? MAX_QUANTIZATION_TOTAL_ERROR_2BITS :
|
||||||
|
type == GGML_TYPE_Q3_K ? MAX_QUANTIZATION_TOTAL_ERROR_3BITS : MAX_QUANTIZATION_TOTAL_ERROR;
|
||||||
|
failed = !(total_error < max_quantization_error);
|
||||||
num_failed += failed;
|
num_failed += failed;
|
||||||
if (failed || verbose) {
|
if (failed || verbose) {
|
||||||
printf("%5s absolute quantization error: %s (%f)\n", ggml_type_name(type), RESULT_STR[failed], total_error);
|
printf("%5s absolute quantization error: %s (%f)\n", ggml_type_name(type), RESULT_STR[failed], total_error);
|
||||||
|
Loading…
Reference in New Issue
Block a user