aboutsummaryrefslogtreecommitdiff
path: root/ggml-opencl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ggml-opencl.cpp')
-rw-r--r--ggml-opencl.cpp493
1 files changed, 489 insertions, 4 deletions
diff --git a/ggml-opencl.cpp b/ggml-opencl.cpp
index 5df922a..1d4db96 100644
--- a/ggml-opencl.cpp
+++ b/ggml-opencl.cpp
@@ -15,7 +15,7 @@
#include "ggml.h"
-#define CL_DMMV_BLOCK_SIZE 32;
+#define CL_DMMV_BLOCK_SIZE 32
#define MULTILINE_QUOTE(...) #__VA_ARGS__
static std::string program_source = MULTILINE_QUOTE(
@@ -59,6 +59,46 @@ struct __attribute__ ((packed)) block_q8_0
int8_t qs[QK8_0];
};
+struct __attribute__((packed)) block_q2_K
+{
+ uint8_t scales[16];
+ uint8_t qs[64];
+ half d;
+ half dmin;
+};
+
+struct __attribute__((packed)) block_q3_K
+{
+ uint8_t hmask[32];
+ uint8_t qs[64];
+ uint8_t scales[12];
+ half d;
+};
+
+struct __attribute__((packed)) block_q4_K
+{
+ half d;
+ half dmin;
+ uint8_t scales[12];
+ uint8_t qs[128];
+};
+
+struct __attribute__((packed)) block_q5_K
+{
+ half d;
+ half dmin;
+ uint8_t scales[12];
+ uint8_t qh[32];
+ uint8_t qs[128];
+};
+
+struct __attribute__((packed)) block_q6_K
+{
+ uint8_t ql[128];
+ uint8_t qh[64];
+ int8_t scales[16];
+ half d;
+};
__kernel void convert_fp16_to_fp32(__global half* x, __global float* y) {
const uint i = get_global_id(0);
@@ -131,8 +171,314 @@ void convert_f16(__global half* x, const int ib, const int iqs, float* v0, float
*v0 = vload_half(0, &x[ib + 0]);
*v1 = vload_half(0, &x[ib + 1]);
}
+
+inline void get_scale_min_k4(int j, const __global 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);
+ }
+}
+
+__kernel void dequantize_block_q2_K(__global const struct block_q2_K *x, __global float *yy)
+{
+ const int i = get_group_id(0);
+ const int tid = get_local_id(0);
+ const int n = tid / 32;
+ const int l = tid - 32 * n;
+ const int is = 8 * n + l / 16;
+
+ const uint8_t q = x[i].qs[32 * n + l];
+ __global float *y = yy + i * 256 + 128 * n;
+
+ const float dall = vload_half(0, &x[i].d);
+ const float dmin = vload_half(0, &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);
+}
+
+__kernel void dequantize_block_q3_K(__global const struct block_q3_K *x, __global float *yy)
+{
+ int r = get_local_id(0) / 4;
+ int i = get_group_id(0);
+ int tid = r / 2;
+ int is0 = r % 2;
+ int l0 = 16 * is0 + 4 * (get_local_id(0) % 4);
+ int n = tid / 4;
+ int j = tid - 4 * n;
+
+ 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 = vload_half(0, &x[i].d);
+ float dl = d_all * (us - 32);
+
+ __global float *y = yy + i * 256 + 128 * n + 32 * j;
+ const __global uint8_t *q = x[i].qs + 32 * n;
+ const __global 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));
+}
+
+__kernel void dequantize_block_q4_K(__global const struct block_q4_K *x, __global float *yy)
+{
+ const int i = get_group_id(0);
+ const int tid = get_local_id(0);
+ const int il = tid / 8;
+ const int ir = tid % 8;
+ const int is = 2 * il;
+ const int n = 4;
+
+ __global float *y = yy + i * 256 + 64 * il + n * ir;
+
+ const float dall = vload_half(0, &x[i].d);
+ const float dmin = vload_half(0, &x[i].dmin);
+
+ __global 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);
+ float d1 = dall * sc;
+ float m1 = dmin * m;
+ get_scale_min_k4(is + 1, x[i].scales, &sc, &m);
+ float d2 = dall * sc;
+ 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;
+ }
+}
+
+__kernel void dequantize_block_q5_K(__global const struct block_q5_K *x, __global float *yy)
+{
+ const int i = get_group_id(0);
+ const int tid = get_local_id(0);
+ const int il = tid / 16;
+ const int ir = tid % 16;
+ const int is = 2 * il;
+
+ __global float *y = yy + i * 256 + 64 * il + 2 * ir;
+
+ const float dall = vload_half(0, &x[i].d);
+ const float dmin = vload_half(0, &x[i].dmin);
+
+ __global const uint8_t *ql = x[i].qs + 32 * il + 2 * ir;
+ __global 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;
+}
+
+__kernel void dequantize_block_q6_K(__global const struct block_q6_K *x, __global float *yy)
+{
+ const int i = get_group_id(0);
+ const int tid = get_local_id(0);
+ const int ip = tid / 32;
+ const int il = tid - 32 * ip;
+ const int is = 8 * ip + il / 16;
+
+ __global float *y = yy + i * 256 + 128 * ip + il;
+
+ const float d = vload_half(0, &x[i].d);
+
+ __global const uint8_t *ql = x[i].ql + 64 * ip + il;
+ const uint8_t qh = x[i].qh[32 * ip + il];
+ __global 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);
+}
+
+
+void vec_dot_q2_K(__global const struct block_q2_K* x, const int ib, const int iqs, const __global float *yy, float *result) {
+
+ int n = iqs / 128;
+ int r = iqs - 128 * n;
+ int l = r / 8;
+
+ __global const float *y = yy + 128 * n + l;
+ __global const uint8_t *q = x[ib].qs + 32 * n + l;
+ __global const uint8_t *s = x[ib].scales + 8 * n;
+
+ const float dall = vload_half(0, &x[ib].d);
+ const float dmin = vload_half(0, &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;
+}
+
+void vec_dot_q3_K(__global const struct block_q3_K* x, const int ib, const int iqs, const __global float *yy, float *result) {
+
+ const uint32_t kmask1 = 0x03030303;
+ const uint32_t kmask2 = 0x0f0f0f0f;
+
+ uint32_t aux[3];
+ uint32_t utmp[4];
+
+ int n = iqs/128;
+ int r = iqs - 128*n;
+ int l = r/8;
+
+ __global const float * y = yy + 128*n + l;
+ __global const uint8_t * q = x[ib].qs + 32*n + l;
+ __global const uint8_t * hm = x[ib].hmask + l;
+ const int8_t * s = (const int8_t *)utmp + 8*n;
+
+ aux[0] = x[ib].scales[0] | x[ib].scales[1] << 8 | x[ib].scales[2] << 16 | x[ib].scales[3] << 24;
+ aux[1] = x[ib].scales[4] | x[ib].scales[5] << 8 | x[ib].scales[6] << 16 | x[ib].scales[7] << 24;
+ aux[2] = x[ib].scales[8] | x[ib].scales[9] << 8 | x[ib].scales[10] << 16 | x[ib].scales[11] << 24;
+
+ 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 = vload_half(0, &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;
+
+}
+
+void vec_dot_q4_K(__global const struct block_q4_K* x, const int ib, const int iqs, const __global float *yy, float *result) {
+
+ 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
+
+ __global const float * y = yy + 64*j + ir;
+ __global const uint8_t * q = x[ib].qs + 32*j + ir;
+
+ const float dall = vload_half(0, &x[ib].d);
+ const float dmin = vload_half(0, &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;
+}
+
+void vec_dot_q5_K(__global const struct block_q5_K* x, const int ib, const int iqs, const __global float *yy, float *result) {
+
+ const int j = iqs / 64;
+ const int ir = (iqs - 64*j)/2;
+ const int is = 2*j;
+
+ __global const float * y = yy + 64*j + ir;
+ __global const uint8_t * ql = x[ib].qs + 32*j + ir;
+ __global const uint8_t * qh = x[ib].qh + ir;
+
+ const float dall = vload_half(0, &x[ib].d);
+ const float dmin = vload_half(0, &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;
+
+}
+
+void vec_dot_q6_K(__global const struct block_q6_K* x, const int ib, const int iqs, const __global float *yy, float *result) {
+
+
+ const int ip = iqs / 128; // 0 or 1
+ const int il = (iqs - 128*ip)/8; // 0...15
+ const int is = 8*ip;
+
+ __global const float * y = yy + 128*ip + il;
+
+ const float d = vload_half(0, &x[ib].d);
+
+ __global const uint8_t * ql = x[ib].ql + 64*ip + il;
+ __global const uint8_t * qh = x[ib].qh + 32*ip + il;
+ __global 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);
+
+}
+
);
+
std::string dequant_template = MULTILINE_QUOTE(
__kernel void KERNEL_NAME(__global X_TYPE* x, __global float* y) {
const int i = get_group_id(0)*get_local_size(0) + get_local_id(0)*2;
@@ -160,7 +506,7 @@ __kernel void KERNEL_NAME(__global X_TYPE* x, __global float* y) {
std::string dequant_mul_mat_vec_template = MULTILINE_QUOTE(
__kernel void KERNEL_NAME(__global X_TYPE* x, __local float* tmp, __global float* y, __global float* dst, const int ncols) {
const int block_size = get_local_size(0);
- const int row = get_global_id(0) / block_size;
+ const int row = get_group_id(0);
const int tid = get_local_id(0);
const uint qk = QUANT_K;
@@ -199,6 +545,45 @@ __kernel void KERNEL_NAME(__global X_TYPE* x, __local float* tmp, __global float
}
);
+std::string dequant_mul_mat_vec_k_template = MULTILINE_QUOTE(
+__kernel void KERNEL_NAME(__global X_TYPE* x, __local float* tmp, __global float* y, __global float* dst, const int ncols) {
+ const int block_size = get_local_size(0);
+ const int row = get_group_id(0);
+ const int tid = get_local_id(0);
+
+ const int iter_stride = 256;
+ const int vals_per_iter = iter_stride / block_size;
+ const int num_blocks_per_row = ncols / 256;
+ const int ib0 = row*num_blocks_per_row;
+
+ tmp[tid] = 0;
+
+ for (int i = 0; i < ncols; i += iter_stride) {
+ const int col = i + vals_per_iter*tid;
+ const int ib = ib0 + col/256; // x block index
+ const int iqs = col%256; // x quant index
+ const int iybs = col - col%256; // y block start index
+
+ // dequantize
+ float v;
+ DOT_KERNEL(x, ib, iqs, y + iybs, &v);
+ tmp[tid] += v;
+ }
+
+ // sum up partial sums and write back result
+ barrier(CLK_LOCAL_MEM_FENCE);
+ for (int s=block_size/2; s>0; s>>=1) {
+ if (tid < s) {
+ tmp[tid] += tmp[tid + s];
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+ }
+ if (tid == 0) {
+ dst[row] = tmp[0];
+ }
+}
+);
+
std::string mul_template = MULTILINE_QUOTE(
__kernel void KERNEL_NAME(__global TYPE* x, const int x_offset, __global TYPE* y, const int y_offset, __global TYPE* dst, const int dst_offset, const int ky) {
const int i = get_group_id(0)*get_local_size(0) + get_local_id(0);
@@ -260,6 +645,18 @@ std::array<std::string, 2> mul_str_values = {
"mul_f32", "float"
};
+std::array<std::string, 3> dmmv_k_str_keys = {
+ "KERNEL_NAME", "X_TYPE", "DOT_KERNEL"
+};
+
+std::array<std::string, 15> dmmv_k_str_values = {
+ "dequantize_mul_mat_vec_q2_K", "struct block_q2_K", "vec_dot_q2_K",
+ "dequantize_mul_mat_vec_q3_K", "struct block_q3_K", "vec_dot_q3_K",
+ "dequantize_mul_mat_vec_q4_K", "struct block_q4_K", "vec_dot_q4_K",
+ "dequantize_mul_mat_vec_q5_K", "struct block_q5_K", "vec_dot_q5_K",
+ "dequantize_mul_mat_vec_q6_K", "struct block_q6_K", "vec_dot_q6_K",
+};
+
std::string& replace(std::string& s, const std::string& from, const std::string& to) {
size_t pos = 0;
while ((pos = s.find(from, pos)) != std::string::npos) {
@@ -289,6 +686,14 @@ std::string generate_kernels() {
}
src << mul_kernel << '\n';
}
+ for (size_t i = 0; i < dmmv_k_str_values.size(); i += dmmv_k_str_keys.size()) {
+ std::string dmmv_k_kernel = dequant_mul_mat_vec_k_template;
+ for (size_t j = 0; j < dmmv_k_str_keys.size(); j++) {
+ replace(dmmv_k_kernel, dmmv_k_str_keys[j], dmmv_k_str_values[i + j]);
+ }
+ src << dmmv_k_kernel << '\n';
+ }
+
return src.str();
}
@@ -300,6 +705,8 @@ static cl_program program;
static cl_kernel convert_row_f16_cl;
static cl_kernel dequantize_row_q4_0_cl, dequantize_row_q4_1_cl, dequantize_row_q5_0_cl, dequantize_row_q5_1_cl, dequantize_row_q8_0_cl;
static cl_kernel dequantize_mul_mat_vec_q4_0_cl, dequantize_mul_mat_vec_q4_1_cl, dequantize_mul_mat_vec_q5_0_cl, dequantize_mul_mat_vec_q5_1_cl, dequantize_mul_mat_vec_q8_0_cl, convert_mul_mat_vec_f16_cl;
+static cl_kernel dequantize_block_q2_k_cl, dequantize_block_q3_k_cl, dequantize_block_q4_k_cl, dequantize_block_q5_k_cl, dequantize_block_q6_k_cl;
+static cl_kernel dequantize_mul_mat_vec_q2_K_cl, dequantize_mul_mat_vec_q3_K_cl, dequantize_mul_mat_vec_q4_K_cl, dequantize_mul_mat_vec_q5_K_cl, dequantize_mul_mat_vec_q6_K_cl;
static cl_kernel mul_f32_cl;
static bool fp16_support;
@@ -529,6 +936,12 @@ void ggml_cl_init(void) {
CL_CHECK((dequantize_row_q5_0_cl = clCreateKernel(program, "dequantize_row_q5_0", &err), err));
CL_CHECK((dequantize_row_q5_1_cl = clCreateKernel(program, "dequantize_row_q5_1", &err), err));
CL_CHECK((dequantize_row_q8_0_cl = clCreateKernel(program, "dequantize_row_q8_0", &err), err));
+ CL_CHECK((dequantize_row_q8_0_cl = clCreateKernel(program, "dequantize_row_q8_0", &err), err));
+ CL_CHECK((dequantize_block_q2_k_cl = clCreateKernel(program, "dequantize_block_q2_K", &err), err));
+ CL_CHECK((dequantize_block_q3_k_cl = clCreateKernel(program, "dequantize_block_q3_K", &err), err));
+ CL_CHECK((dequantize_block_q4_k_cl = clCreateKernel(program, "dequantize_block_q4_K", &err), err));
+ CL_CHECK((dequantize_block_q5_k_cl = clCreateKernel(program, "dequantize_block_q5_K", &err), err));
+ CL_CHECK((dequantize_block_q6_k_cl = clCreateKernel(program, "dequantize_block_q6_K", &err), err));
// dequant mul mat kernel
CL_CHECK((dequantize_mul_mat_vec_q4_0_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q4_0", &err), err));
@@ -537,6 +950,11 @@ void ggml_cl_init(void) {
CL_CHECK((dequantize_mul_mat_vec_q5_1_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q5_1", &err), err));
CL_CHECK((dequantize_mul_mat_vec_q8_0_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q8_0", &err), err));
CL_CHECK((convert_mul_mat_vec_f16_cl = clCreateKernel(program, "convert_mul_mat_vec_f16", &err), err));
+ CL_CHECK((dequantize_mul_mat_vec_q2_K_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q2_K", &err), err));
+ CL_CHECK((dequantize_mul_mat_vec_q3_K_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q3_K", &err), err));
+ CL_CHECK((dequantize_mul_mat_vec_q4_K_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q4_K", &err), err));
+ CL_CHECK((dequantize_mul_mat_vec_q5_K_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q5_K", &err), err));
+ CL_CHECK((dequantize_mul_mat_vec_q6_K_cl = clCreateKernel(program, "dequantize_mul_mat_vec_q6_K", &err), err));
// mul kernel
CL_CHECK((mul_f32_cl = clCreateKernel(program, "mul_f32", &err), err));
@@ -554,6 +972,16 @@ static cl_kernel* ggml_get_to_fp32_cl(ggml_type type) {
return &dequantize_row_q5_1_cl;
case GGML_TYPE_Q8_0:
return &dequantize_row_q8_0_cl;
+ case GGML_TYPE_Q2_K:
+ return &dequantize_block_q2_k_cl;
+ case GGML_TYPE_Q3_K:
+ return &dequantize_block_q3_k_cl;
+ case GGML_TYPE_Q4_K:
+ return &dequantize_block_q4_k_cl;
+ case GGML_TYPE_Q5_K:
+ return &dequantize_block_q5_k_cl;
+ case GGML_TYPE_Q6_K:
+ return &dequantize_block_q6_k_cl;
case GGML_TYPE_F16:
return &convert_row_f16_cl;
default:
@@ -561,6 +989,50 @@ static cl_kernel* ggml_get_to_fp32_cl(ggml_type type) {
}
}
+static size_t ggml_cl_global_denom(ggml_type type) {
+ switch (type) {
+ case GGML_TYPE_Q4_0:
+ case GGML_TYPE_Q4_1:
+ case GGML_TYPE_Q5_0:
+ case GGML_TYPE_Q5_1:
+ case GGML_TYPE_Q8_0:
+ return 1;
+ case GGML_TYPE_Q2_K:
+ case GGML_TYPE_Q3_K:
+ return 4;
+ case GGML_TYPE_Q4_K:
+ return 8;
+ case GGML_TYPE_Q5_K:
+ case GGML_TYPE_Q6_K:
+ return 4;
+ case GGML_TYPE_F16:
+ default:
+ return 1;
+ }
+}
+
+static size_t ggml_cl_local_size(ggml_type type) {
+ switch (type) {
+ case GGML_TYPE_Q4_0:
+ case GGML_TYPE_Q4_1:
+ case GGML_TYPE_Q5_0:
+ case GGML_TYPE_Q5_1:
+ case GGML_TYPE_Q8_0:
+ return 0;
+ case GGML_TYPE_Q2_K:
+ case GGML_TYPE_Q3_K:
+ return 64;
+ case GGML_TYPE_Q4_K:
+ return 32;
+ case GGML_TYPE_Q5_K:
+ case GGML_TYPE_Q6_K:
+ return 64;
+ case GGML_TYPE_F16:
+ default:
+ return 0;
+ }
+}
+
static cl_kernel* ggml_get_dequantize_mul_mat_vec_cl(ggml_type type) {
switch (type) {
case GGML_TYPE_Q4_0:
@@ -575,6 +1047,16 @@ static cl_kernel* ggml_get_dequantize_mul_mat_vec_cl(ggml_type type) {
return &dequantize_mul_mat_vec_q8_0_cl;
case GGML_TYPE_F16:
return &convert_mul_mat_vec_f16_cl;
+ case GGML_TYPE_Q2_K:
+ return &dequantize_mul_mat_vec_q2_K_cl;
+ case GGML_TYPE_Q3_K:
+ return &dequantize_mul_mat_vec_q3_K_cl;
+ case GGML_TYPE_Q4_K:
+ return &dequantize_mul_mat_vec_q4_K_cl;
+ case GGML_TYPE_Q5_K:
+ return &dequantize_mul_mat_vec_q5_K_cl;
+ case GGML_TYPE_Q6_K:
+ return &dequantize_mul_mat_vec_q6_K_cl;
default:
return nullptr;
}
@@ -1017,6 +1499,9 @@ static void ggml_cl_mul_mat_q_f32(const ggml_tensor * src0, const ggml_tensor *
cl_kernel* dmmv = ggml_get_dequantize_mul_mat_vec_cl(type);
GGML_ASSERT(to_fp32_cl != nullptr);
+ const size_t global_denom = ggml_cl_global_denom(type);
+ const size_t local = ggml_cl_local_size(type);
+
size_t ev_idx = 0;
std::vector<cl_event> events;
@@ -1049,10 +1534,10 @@ static void ggml_cl_mul_mat_q_f32(const ggml_tensor * src0, const ggml_tensor *
CL_CHECK(clEnqueueNDRangeKernel(queue, *dmmv, 1, NULL, &global, &local, events.size() - 1, events.data(), events.data() + ev_idx++));
} else { // general dequantization kernel + CLBlast matrix matrix multiplication
// convert src0 to fp32 on device
- const size_t global = x_ne;
+ const size_t global = x_ne / global_denom;
CL_CHECK(clSetKernelArg(*to_fp32_cl, 0, sizeof(cl_mem), &d_Q));
CL_CHECK(clSetKernelArg(*to_fp32_cl, 1, sizeof(cl_mem), &d_X));
- CL_CHECK(clEnqueueNDRangeKernel(queue, *to_fp32_cl, 1, NULL, &global, NULL, events.size(), !events.empty() ? events.data() : NULL, NULL));
+ CL_CHECK(clEnqueueNDRangeKernel(queue, *to_fp32_cl, 1, NULL, &global, local > 0 ? &local : NULL, events.size(), !events.empty() ? events.data() : NULL, NULL));
// copy src1 to device
CL_CHECK(ggml_cl_h2d_tensor_2d(queue, d_Y, 0, src1, i03, i02, NULL));