Skip to content

Commit 305dc66

Browse files
committed
vulkan: support copy from q4_0/q4_1/q5_0/q5_1/q8_0/iq4_nl to f32
1 parent 924bccc commit 305dc66

File tree

6 files changed

+155
-1
lines changed

6 files changed

+155
-1
lines changed

ggml/src/ggml-cpu/ggml-cpu.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3967,6 +3967,52 @@ static void ggml_compute_forward_dup_bytes(
39673967
}
39683968
}
39693969

3970+
static void ggml_compute_forward_dup_q(
3971+
const struct ggml_compute_params * params,
3972+
struct ggml_tensor * dst) {
3973+
3974+
const struct ggml_tensor * src0 = dst->src[0];
3975+
const struct ggml_tensor * src1 = dst->src[1];
3976+
3977+
GGML_TENSOR_BINARY_OP_LOCALS
3978+
3979+
const enum ggml_type type = src0->type;
3980+
ggml_to_float_t const dequantize_row_q = ggml_get_type_traits(type)->to_float;
3981+
3982+
size_t qk = ggml_blck_size(type);
3983+
const int64_t nr = ggml_nelements(src1) / qk;
3984+
3985+
const int ith = params->ith;
3986+
const int nth = params->nth;
3987+
3988+
const int dr = (nr + nth - 1)/nth;
3989+
3990+
// row range for this thread
3991+
const int ir0 = dr*ith;
3992+
const int ir1 = MIN(ir0 + dr, nr);
3993+
3994+
for (int64_t ir = ir0; ir < ir1; ++ir) {
3995+
3996+
uint32_t i = ir * qk;
3997+
3998+
const int64_t i03 = i/(ne00 * ne01 * ne02);
3999+
const int64_t i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01);
4000+
const int64_t i01 = (i - i03*ne00*ne01*ne02 - i02*ne01*ne00) / ne00;
4001+
const int64_t i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00;
4002+
const int64_t x_offset = (i00/qk)*nb00 + i01*nb01 + i02*nb02 + i03 * nb03;
4003+
4004+
const int64_t i13 = i/(ne10 * ne11 * ne12);
4005+
const int64_t i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11);
4006+
const int64_t i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10;
4007+
const int64_t i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10;
4008+
const int64_t dst_offset = i10*nb10 + i11*nb11 + i12*nb12 + i13*nb13;
4009+
4010+
dequantize_row_q(
4011+
(const void *) ((char *) src0->data + x_offset),
4012+
(float *) ((char *) dst->data + dst_offset), qk);
4013+
}
4014+
}
4015+
39704016
static void ggml_compute_forward_dup(
39714017
const struct ggml_compute_params * params,
39724018
struct ggml_tensor * dst) {
@@ -3993,6 +4039,10 @@ static void ggml_compute_forward_dup(
39934039
} break;
39944040
default:
39954041
{
4042+
if (ggml_is_quantized(src0->type) && dst->type == GGML_TYPE_F32) {
4043+
ggml_compute_forward_dup_q(params, dst);
4044+
break;
4045+
}
39964046
GGML_ABORT("fatal error");
39974047
}
39984048
}

ggml/src/ggml-vulkan/ggml-vulkan.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ struct vk_device_struct {
229229
vk_pipeline pipeline_cpy_f32_f32, pipeline_cpy_f32_f16, pipeline_cpy_f16_f16;
230230
vk_pipeline pipeline_contig_cpy_f32_f32, pipeline_contig_cpy_f32_f16, pipeline_contig_cpy_f16_f16;
231231
vk_pipeline pipeline_cpy_f32_quant[GGML_TYPE_COUNT];
232+
vk_pipeline pipeline_cpy_quant_f32[GGML_TYPE_COUNT];
232233
vk_pipeline pipeline_norm_f32;
233234
vk_pipeline pipeline_group_norm_f32;
234235
vk_pipeline pipeline_rms_norm_f32;
@@ -1973,6 +1974,13 @@ static void ggml_vk_load_shaders(vk_device& device) {
19731974
ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_len, cpy_f32_q8_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q8_0), 1, 1}, {}, 1);
19741975
ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_len, cpy_f32_iq4_nl_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_IQ4_NL), 1, 1}, {}, 1);
19751976

1977+
ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q4_0], "cpy_q4_0_f32", cpy_q4_0_f32_len, cpy_q4_0_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_0), 1, 1}, {}, 1);
1978+
ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q4_1], "cpy_q4_1_f32", cpy_q4_1_f32_len, cpy_q4_1_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q4_1), 1, 1}, {}, 1);
1979+
ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q5_0], "cpy_q5_0_f32", cpy_q5_0_f32_len, cpy_q5_0_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_0), 1, 1}, {}, 1);
1980+
ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q5_1], "cpy_q5_1_f32", cpy_q5_1_f32_len, cpy_q5_1_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q5_1), 1, 1}, {}, 1);
1981+
ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_Q8_0], "cpy_q8_0_f32", cpy_q8_0_f32_len, cpy_q8_0_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_Q8_0), 1, 1}, {}, 1);
1982+
ggml_vk_create_pipeline(device, device->pipeline_cpy_quant_f32[GGML_TYPE_IQ4_NL], "cpy_iq4_nl_f32", cpy_iq4_nl_f32_len, cpy_iq4_nl_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {(uint32_t)ggml_blck_size(GGML_TYPE_IQ4_NL), 1, 1}, {}, 1);
1983+
19761984
ggml_vk_create_pipeline(device, device->pipeline_add_f32, "add_f32", add_f32_len, add_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {0}, 1);
19771985
ggml_vk_create_pipeline(device, device->pipeline_add_f32_norepeat, "add_f32_norepeat", add_f32_len, add_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {1}, 1);
19781986
ggml_vk_create_pipeline(device, device->pipeline_add_f16_f32_f16, "add_f16_f32_f16", add_f16_f32_f16_len, add_f16_f32_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {0}, 1);
@@ -3711,6 +3719,20 @@ static vk_pipeline ggml_vk_get_cpy_pipeline(ggml_backend_vk_context * ctx, const
37113719
}
37123720
}
37133721

3722+
if (to == GGML_TYPE_F32) {
3723+
switch (src->type) {
3724+
case GGML_TYPE_Q4_0:
3725+
case GGML_TYPE_Q4_1:
3726+
case GGML_TYPE_Q5_0:
3727+
case GGML_TYPE_Q5_1:
3728+
case GGML_TYPE_Q8_0:
3729+
case GGML_TYPE_IQ4_NL:
3730+
return ctx->device->pipeline_cpy_quant_f32[src->type];
3731+
default:
3732+
break;
3733+
}
3734+
}
3735+
37143736
std::cerr << "Missing CPY op for types: " << ggml_type_name(src->type) << " " << ggml_type_name(to) << std::endl;
37153737
GGML_ABORT("fatal error");
37163738
}
@@ -5181,7 +5203,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co
51815203
}
51825204
std::cerr << "), (" << dst << ", name=" << dst->name << ", type=" << dst->type << ", ne0=" << dst->ne[0] << ", ne1=" << dst->ne[1] << ", ne2=" << dst->ne[2] << ", ne3=" << dst->ne[3] << ", nb0=" << dst->nb[0] << ", nb1=" << dst->nb[1] << ", nb2=" << dst->nb[2] << ", nb3=" << dst->nb[3];
51835205
std::cerr << "), " << ggml_op_name(op) << ", " << (dryrun ? "dryrun" : "") << ")");
5184-
GGML_ASSERT(op == GGML_OP_GET_ROWS || (!ggml_is_quantized(src0->type) && (src1 == nullptr || !ggml_is_quantized(src1->type)))); // NOLINT
5206+
GGML_ASSERT(op == GGML_OP_GET_ROWS || op == GGML_OP_CPY || (!ggml_is_quantized(src0->type) && (src1 == nullptr || !ggml_is_quantized(src1->type)))); // NOLINT
51855207
GGML_ASSERT(ggml_vk_op_supports_incontiguous(op) || ggml_vk_dim01_contiguous(src0)); // NOLINT
51865208
GGML_ASSERT(dst->buffer != nullptr);
51875209
const uint64_t ne00 = src0->ne[0];
@@ -7942,6 +7964,20 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
79427964
break;
79437965
}
79447966
}
7967+
if (src1_type == GGML_TYPE_F32) {
7968+
switch (src0_type) {
7969+
case GGML_TYPE_Q4_0:
7970+
case GGML_TYPE_Q4_1:
7971+
case GGML_TYPE_Q5_0:
7972+
case GGML_TYPE_Q5_1:
7973+
case GGML_TYPE_Q8_0:
7974+
case GGML_TYPE_IQ4_NL:
7975+
return true;
7976+
default:
7977+
break;
7978+
}
7979+
}
7980+
79457981
if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) {
79467982
return true;
79477983
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#version 450
2+
3+
#include "types.comp"
4+
#include "generic_unary_head.comp"
5+
#include "dequant_funcs.comp"
6+
7+
#if defined(DATA_A_IQ4_NL)
8+
// 16 invocations needed for init_iq4nl_shmem
9+
layout(local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
10+
#else
11+
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12+
#endif
13+
14+
void main() {
15+
#if defined(DATA_A_IQ4_NL)
16+
init_iq4nl_shmem();
17+
if (gl_LocalInvocationIndex.x != 0) {
18+
return;
19+
}
20+
#endif
21+
22+
const uint idx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * QUANT_K;
23+
24+
if (idx >= p.ne) {
25+
return;
26+
}
27+
28+
uint dst_idx = get_doffset() + dst_idx(idx);
29+
uint src_idx = src0_idx_quant(idx, QUANT_K);
30+
31+
const uint a_offset = 0;
32+
const uint ib = src_idx;
33+
const vec2 dm = get_dm(ib, a_offset);
34+
35+
[[unroll]] for (int j = 0; j < QUANT_K; j += 4) {
36+
vec4 v = dequantize4(ib, j / QUANT_R, a_offset);
37+
v = v * dm.x + vec4(dm.y);
38+
39+
#if QUANT_R == 2
40+
data_d[dst_idx + j/2 + 0] = v[0];
41+
data_d[dst_idx + j/2 + QUANT_K/2 + 0] = v[1];
42+
data_d[dst_idx + j/2 + 1] = v[2];
43+
data_d[dst_idx + j/2 + QUANT_K/2 + 1] = v[3];
44+
#else
45+
data_d[dst_idx + j + 0] = v[0];
46+
data_d[dst_idx + j + 1] = v[1];
47+
data_d[dst_idx + j + 2] = v[2];
48+
data_d[dst_idx + j + 3] = v[3];
49+
#endif
50+
}
51+
}

ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.comp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ uint dst_idx(uint idx) {
5555
return i13*p.nb13 + i12*p.nb12 + i11*p.nb11 + i10*p.nb10;
5656
}
5757

58+
uint src0_idx_quant(uint idx, uint qk) {
59+
const uint i03 = fastdiv(idx, p.ne0_012mp, p.ne0_012L);
60+
const uint i03_offset = i03 * p.ne02*p.ne01*p.ne00;
61+
const uint i02 = fastdiv(idx - i03_offset, p.ne0_01mp, p.ne0_01L);
62+
const uint i02_offset = i02*p.ne01*p.ne00;
63+
const uint i01 = fastdiv(idx - i03_offset - i02_offset, p.ne0_0mp, p.ne0_0L);
64+
const uint i00 = idx - i03_offset - i02_offset - i01*p.ne00;
65+
return i03*p.nb03 + i02*p.nb02 + i01*p.nb01 + (i00/qk)*p.nb00;
66+
}
67+
5868
uint dst_idx_quant(uint idx, uint qk) {
5969
const uint i13 = fastdiv(idx, p.ne1_012mp, p.ne1_012L);
6070
const uint i13_offset = i13 * p.ne12*p.ne11*p.ne10;

ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ void process_shaders() {
421421

422422
for (std::string t : {"q4_0", "q4_1", "q5_0", "q5_1", "q8_0", "iq4_nl"}) {
423423
string_to_spv("cpy_f32_" + t, "copy_to_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
424+
string_to_spv("cpy_" + t + "_f32", "copy_from_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
424425
}
425426

426427
string_to_spv("add_f32", "add.comp", {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});

tests/test-backend-ops.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,6 +3553,12 @@ static std::vector<std::unique_ptr<test_case>> make_test_cases_eval() {
35533553
test_cases.emplace_back(new test_cpy(type_src, type_dst, {256, 2, 3, 4}, {0, 2, 1, 3})); // cpy by rows
35543554
}
35553555
}
3556+
for (ggml_type type_dst : {GGML_TYPE_F32}) {
3557+
for (ggml_type type_src : all_types) {
3558+
test_cases.emplace_back(new test_cpy(type_src, type_dst, {256, 4, 4, 4}));
3559+
test_cases.emplace_back(new test_cpy(type_src, type_dst, {256, 2, 3, 4}, {0, 2, 1, 3})); // cpy by rows
3560+
}
3561+
}
35563562
for (ggml_type type_src : {GGML_TYPE_F16, GGML_TYPE_F32}) {
35573563
for (ggml_type type_dst : {GGML_TYPE_F16, GGML_TYPE_F32}) {
35583564
test_cases.emplace_back(new test_cpy(type_src, type_dst, {256, 2, 3, 4}, {1, 0, 2, 3})); // cpy not-contiguous

0 commit comments

Comments
 (0)