Skip to content

Commit 2eba631

Browse files
authored
vulkan: Add copy_transpose shader (ggml-org#17371)
1 parent 99c53d6 commit 2eba631

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ struct vk_device_struct {
638638
vk_pipeline pipeline_contig_cpy_f32_f32, pipeline_contig_cpy_f32_f16, pipeline_contig_cpy_f16_f16, pipeline_contig_cpy_f16_f32, pipeline_contig_cpy_f32_bf16, pipeline_contig_cpy_f32_i32, pipeline_contig_cpy_i32_f32;
639639
vk_pipeline pipeline_cpy_f32_quant[GGML_TYPE_COUNT];
640640
vk_pipeline pipeline_cpy_quant_f32[GGML_TYPE_COUNT];
641+
vk_pipeline pipeline_cpy_transpose_16, pipeline_cpy_transpose_32;
641642
vk_pipeline pipeline_set_rows_i32[GGML_TYPE_COUNT];
642643
vk_pipeline pipeline_set_rows_i64[GGML_TYPE_COUNT];
643644
vk_pipeline pipeline_norm_f32;
@@ -3697,6 +3698,9 @@ static void ggml_vk_load_shaders(vk_device& device) {
36973698
ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_i32_f32, "contig_cpy_i32_f32", contig_cpy_i32_f32_len, contig_cpy_i32_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
36983699
ggml_vk_create_pipeline(device, device->pipeline_contig_cpy_f32_i32, "contig_cpy_f32_i32", contig_cpy_f32_i32_len, contig_cpy_f32_i32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
36993700

3701+
ggml_vk_create_pipeline(device, device->pipeline_cpy_transpose_32, "cpy_transpose_32", cpy_transpose_32_len, cpy_transpose_32_data, "main", 2, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1);
3702+
ggml_vk_create_pipeline(device, device->pipeline_cpy_transpose_16, "cpy_transpose_16", cpy_transpose_16_len, cpy_transpose_16_data, "main", 2, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1);
3703+
37003704
if (device->float_controls_rte_fp16) {
37013705
ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_0], "cpy_f32_q4_0", cpy_f32_q4_0_rte_len, cpy_f32_q4_0_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1);
37023706
ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q4_1], "cpy_f32_q4_1", cpy_f32_q4_1_rte_len, cpy_f32_q4_1_rte_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1);
@@ -6247,6 +6251,17 @@ static vk_pipeline ggml_vk_get_cpy_pipeline(ggml_backend_vk_context * ctx, const
62476251
// Choose "contiguous copy" shader if src/dst are contiguous
62486252
bool contig = ggml_is_contiguous(src) && (!dst || ggml_is_contiguous(dst));
62496253

6254+
// Use optimized "transpose" shader if src dim1 is the innermost dimension.
6255+
bool transpose = dst && src->nb[1] == ggml_type_size(to) && ggml_are_same_shape(dst, src);
6256+
6257+
if (transpose && src->type == to) {
6258+
if (ggml_type_size(to) == 4) {
6259+
return ctx->device->pipeline_cpy_transpose_32;
6260+
} else if (ggml_type_size(to) == 2) {
6261+
return ctx->device->pipeline_cpy_transpose_16;
6262+
}
6263+
}
6264+
62506265
if (src->type == GGML_TYPE_F32 && to == GGML_TYPE_F32) {
62516266
if (contig) {
62526267
return ctx->device->pipeline_contig_cpy_f32_f32;
@@ -8858,6 +8873,17 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co
88588873
} else {
88598874
elements = { ne, 1, 1 };
88608875
}
8876+
8877+
if (pipeline == ctx->device->pipeline_cpy_transpose_32 ||
8878+
pipeline == ctx->device->pipeline_cpy_transpose_16) {
8879+
// 32x32 tiles
8880+
elements[0] = (uint32_t)CEIL_DIV(dst->ne[0], 32);
8881+
elements[1] = (uint32_t)CEIL_DIV(dst->ne[1], 32);
8882+
elements[2] = (uint32_t)(dst->ne[2]*dst->ne[3]);
8883+
elements[0] = std::min(elements[0], ctx->device->properties.limits.maxComputeWorkGroupCount[0]);
8884+
elements[1] = std::min(elements[1], ctx->device->properties.limits.maxComputeWorkGroupCount[1]);
8885+
elements[2] = std::min(elements[2], ctx->device->properties.limits.maxComputeWorkGroupCount[2]);
8886+
}
88618887
} break;
88628888
case GGML_OP_ADD_ID:
88638889
{
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#version 450
2+
3+
#include "types.glsl"
4+
#include "generic_unary_head.glsl"
5+
6+
// workgroup does 32x32 tile, but uses 32x8 threads
7+
#define TILE_DIM 32
8+
layout(local_size_x = 32, local_size_y = 8, local_size_z = 1) in;
9+
10+
shared uint sh[TILE_DIM][TILE_DIM + 1];
11+
12+
void iter(uvec3 wg_id) {
13+
const uint tile_col = wg_id.x;
14+
const uint tile_row = wg_id.y;
15+
16+
const uint tid_col = gl_LocalInvocationID.x;
17+
const uint tid_row = gl_LocalInvocationID.y;
18+
19+
const uint i2 = wg_id.z % p.ne12;
20+
const uint i3 = wg_id.z / p.ne12;
21+
const uint i02 = i2;
22+
const uint i03 = i3;
23+
24+
// The workgroup does TILE_DIM x TILE_DIM, but swaps the LSBs of the
25+
// src coords to make memory accesses contiguous, dst has tid.x in i0,
26+
// src has tid.x in i01
27+
28+
[[unroll]] for (uint y = 0; y < 4; ++y) {
29+
const uint i00 = tile_col * TILE_DIM + tid_row + 8 * y;
30+
const uint i01 = tile_row * TILE_DIM + tid_col;
31+
if (i00 < p.ne00 && i01 < p.ne01 && i02 < p.ne02 && i03 < p.ne03) {
32+
const uint src_idx = i00 * p.nb00 + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
33+
sh[tid_row + 8 * y][tid_col] = uint(data_a[get_aoffset() + src_idx]);
34+
}
35+
}
36+
37+
barrier();
38+
39+
[[unroll]] for (uint y = 0; y < 4; ++y) {
40+
const uint i0 = tile_col * TILE_DIM + tid_col;
41+
const uint i1 = tile_row * TILE_DIM + tid_row + 8 * y;
42+
if (i0 < p.ne10 && i1 < p.ne11 && i2 < p.ne12 && i3 < p.ne13) {
43+
const uint dst_idx = i0 * p.nb10 + i1 * p.nb11 + i2 * p.nb12 + i3 * p.nb13;
44+
// load transposed
45+
data_d[get_doffset() + dst_idx] = D_TYPE(sh[tid_col][tid_row + 8 * y]);
46+
}
47+
}
48+
}
49+
50+
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
51+
52+
void main() {
53+
uint z = gl_WorkGroupID.z;
54+
uint y = gl_WorkGroupID.y;
55+
bool need_barrier = false;
56+
for (uint z = gl_WorkGroupID.z; z < p.ne12 * p.ne13; z += gl_NumWorkGroups.z) {
57+
for (uint y = gl_WorkGroupID.y; y < CEIL_DIV(p.ne11, TILE_DIM); y += gl_NumWorkGroups.y) {
58+
for (uint x = gl_WorkGroupID.x; x < CEIL_DIV(p.ne10, TILE_DIM); x += gl_NumWorkGroups.x) {
59+
if (need_barrier) {
60+
barrier();
61+
}
62+
need_barrier = true;
63+
iter(uvec3(x, y, z));
64+
}
65+
}
66+
}
67+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,9 @@ void process_shaders() {
734734
string_to_spv("cpy_f32_i32", "copy.comp", {{"A_TYPE", "float"}, {"D_TYPE", "int"}});
735735
string_to_spv("cpy_i32_f32", "copy.comp", {{"A_TYPE", "int"}, {"D_TYPE", "float"}});
736736

737+
string_to_spv("cpy_transpose_16", "copy_transpose.comp", {{"A_TYPE", "uint16_t"}, {"D_TYPE", "uint16_t"}});
738+
string_to_spv("cpy_transpose_32", "copy_transpose.comp", {{"A_TYPE", "uint"}, {"D_TYPE", "uint"}});
739+
737740
for (std::string t : {"q4_0", "q4_1", "q5_0", "q5_1", "q8_0", "iq4_nl"}) {
738741
string_to_spv("cpy_f32_" + t, "copy_to_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
739742
string_to_spv("cpy_f32_" + t + "_rte", "copy_to_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}, {"RTE16", "1"}});

0 commit comments

Comments
 (0)