@@ -351,6 +351,12 @@ enum vk_conv_shapes {
351351 CONV_SHAPE_COUNT,
352352};
353353
354+ uint32_t conv_shapes_wg_denoms[][3] = {
355+ { 128, 128, 1 },
356+ { 64, 32, 1 },
357+ { 32, 256, 1 },
358+ };
359+
354360enum dmmv_wg_sizes {
355361 DMMV_WG_SIZE_SUBGROUP,
356362 DMMV_WG_SIZE_LARGE,
@@ -379,6 +385,18 @@ struct vk_fa_pipeline_state {
379385 }
380386};
381387
388+ struct vk_conv2d_pipeline_state {
389+ vk_conv2d_pipeline_state(uint32_t s0, uint32_t s1, uint32_t p0, uint32_t p1, uint32_t d0, uint32_t d1, uint32_t KW, uint32_t KH)
390+ : s0(s0), s1(s1), p0(p0), p1(p1), d0(d0), d1(d1), KW(KW), KH(KH) {}
391+
392+ uint32_t s0, s1, p0, p1, d0, d1, KW, KH;
393+
394+ bool operator<(const vk_conv2d_pipeline_state &b) const {
395+ return std::tie(s0, s1, p0, p1, d0, d1, KW, KH) <
396+ std::tie(b.s0, b.s1, b.p0, b.p1, b.d0, b.d1, b.KW, b.KH);
397+ }
398+ };
399+
382400enum shader_reduction_mode {
383401 SHADER_REDUCTION_MODE_SHMEM,
384402 SHADER_REDUCTION_MODE_HYBRID,
@@ -675,10 +693,10 @@ struct vk_device_struct {
675693 vk_pipeline pipeline_ssm_conv_f32;
676694 vk_pipeline pipeline_opt_step_adamw_f32;
677695 vk_pipeline pipeline_opt_step_sgd_f32;
678- vk_pipeline pipeline_conv2d_f32[CONV_SHAPE_COUNT];
679- vk_pipeline pipeline_conv2d_f16_f32[CONV_SHAPE_COUNT];
680- vk_pipeline pipeline_conv_transpose_2d_f32[CONV_SHAPE_COUNT];
681- vk_pipeline pipeline_conv_transpose_2d_f16_f32[CONV_SHAPE_COUNT];
696+ std::map<vk_conv2d_pipeline_state, vk_pipeline> pipeline_conv2d_f32[CONV_SHAPE_COUNT];
697+ std::map<vk_conv2d_pipeline_state, vk_pipeline> pipeline_conv2d_f16_f32[CONV_SHAPE_COUNT];
698+ std::map<vk_conv2d_pipeline_state, vk_pipeline> pipeline_conv_transpose_2d_f32[CONV_SHAPE_COUNT];
699+ std::map<vk_conv2d_pipeline_state, vk_pipeline> pipeline_conv_transpose_2d_f16_f32[CONV_SHAPE_COUNT];
682700 vk_pipeline pipeline_conv2d_dw_whcn_f32, pipeline_conv2d_dw_whcn_f16_f32;
683701 vk_pipeline pipeline_conv2d_dw_cwhn_f32, pipeline_conv2d_dw_cwhn_f16_f32;
684702
@@ -1258,17 +1276,13 @@ struct vk_op_conv2d_push_constants {
12581276 uint32_t nb2;
12591277 uint32_t nb3;
12601278
1261- // init_fastdiv_values constants for dividing by KW, KW*KH, OW, OW*OH
1262- uint32_t KWmp; uint32_t KWL;
1263- uint32_t KWKHmp; uint32_t KWKHL;
1279+ // init_fastdiv_values constants for dividing by OW, OW*OH
12641280 uint32_t OWmp; uint32_t OWL;
12651281 uint32_t OWOHmp; uint32_t OWOHL;
12661282};
12671283
12681284template <> void init_pushconst_fastdiv(vk_op_conv2d_push_constants &p) {
1269- // Compute magic values to divide by KW, KW*KH, OW, OW*OH
1270- init_fastdiv_values(p.KW, p.KWmp, p.KWL);
1271- init_fastdiv_values(p.KW*p.KH, p.KWKHmp, p.KWKHL);
1285+ // Compute magic values to divide by OW, OW*OH
12721286 init_fastdiv_values(p.OW, p.OWmp, p.OWL);
12731287 init_fastdiv_values(p.OW*p.OH, p.OWOHmp, p.OWOHL);
12741288}
@@ -1304,23 +1318,15 @@ struct vk_op_conv_transpose_2d_push_constants {
13041318 uint32_t nb2;
13051319 uint32_t nb3;
13061320
1307- // init_fastdiv_values constants for dividing by KW, KW*KH, OW, OW*OH, s0, s1
1308- uint32_t KWmp; uint32_t KWL;
1309- uint32_t KWKHmp; uint32_t KWKHL;
1321+ // init_fastdiv_values constants for dividing by OW, OW*OH
13101322 uint32_t OWmp; uint32_t OWL;
13111323 uint32_t OWOHmp; uint32_t OWOHL;
1312- uint32_t s0mp; uint32_t s0L;
1313- uint32_t s1mp; uint32_t s1L;
13141324};
13151325
13161326template <> void init_pushconst_fastdiv(vk_op_conv_transpose_2d_push_constants &p) {
1317- // Compute magic values to divide by KW, KW*KH, OW, OW*OH, s0, s1
1318- init_fastdiv_values(p.KW, p.KWmp, p.KWL);
1319- init_fastdiv_values(p.KW*p.KH, p.KWKHmp, p.KWKHL);
1327+ // Compute magic values to divide by OW, OW*OH
13201328 init_fastdiv_values(p.OW, p.OWmp, p.OWL);
13211329 init_fastdiv_values(p.OW*p.OH, p.OWOHmp, p.OWOHL);
1322- init_fastdiv_values(p.s0, p.s0mp, p.s0L);
1323- init_fastdiv_values(p.s1, p.s1mp, p.s1L);
13241330}
13251331
13261332struct vk_op_conv2d_dw_push_constants {
@@ -3858,22 +3864,22 @@ static void ggml_vk_load_shaders(vk_device& device) {
38583864 switch (s) {
38593865 default:
38603866 case CONV_SHAPE_128x128:
3861- conv2d_BS_K = 128 ;
3862- conv2d_BS_NPQ = 128 ;
3867+ conv2d_BS_K = conv_shapes_wg_denoms[CONV_SHAPE_128x128][0] ;
3868+ conv2d_BS_NPQ = conv_shapes_wg_denoms[CONV_SHAPE_128x128][1] ;
38633869 conv2d_BS_CRS = 16;
38643870 if (device->vendor_id == VK_VENDOR_ID_AMD && device->architecture != vk_device_architecture::AMD_GCN) {
38653871 conv2d_UNROLL = false;
38663872 }
38673873 break;
38683874 case CONV_SHAPE_64x32:
3869- conv2d_BS_K = 64 ;
3870- conv2d_BS_NPQ = 32 ;
3875+ conv2d_BS_K = conv_shapes_wg_denoms[CONV_SHAPE_64x32][0] ;
3876+ conv2d_BS_NPQ = conv_shapes_wg_denoms[CONV_SHAPE_64x32][1] ;
38713877 conv2d_BS_CRS = 32;
38723878 conv2d_TS_K = 4;
38733879 break;
38743880 case CONV_SHAPE_32x256:
3875- conv2d_BS_K = 32 ;
3876- conv2d_BS_NPQ = 256 ;
3881+ conv2d_BS_K = conv_shapes_wg_denoms[CONV_SHAPE_32x256][0] ;
3882+ conv2d_BS_NPQ = conv_shapes_wg_denoms[CONV_SHAPE_32x256][1] ;
38773883 conv2d_BS_CRS = 16;
38783884 break;
38793885 }
@@ -3907,10 +3913,22 @@ static void ggml_vk_load_shaders(vk_device& device) {
39073913 std::vector<uint32_t> spec_constants = { conv2d_WG_SIZE, conv2d_BS_K, conv2d_BS_CRS, conv2d_BS_NPQ, conv2d_TS_K, use_collectives, conv2d_SHMEM_PAD };
39083914
39093915#define CREATE_CONV(name, type_suffix, spv_suffix) \
3910- ggml_vk_create_pipeline( \
3911- device, device->pipeline_##name##type_suffix[s], #name #type_suffix, \
3912- name##type_suffix##spv_suffix##_len, name##type_suffix##spv_suffix##_data, "main", 3, \
3913- sizeof(vk_op_##name##_push_constants), wg_denoms, spec_constants, 1, true, use_collectives);
3916+ for (auto &c : device->pipeline_##name##type_suffix[s]) { \
3917+ const vk_conv2d_pipeline_state &state = c.first; \
3918+ std::vector<uint32_t> spec_constants_cpy = spec_constants; \
3919+ spec_constants_cpy.push_back(state.s0); \
3920+ spec_constants_cpy.push_back(state.s1); \
3921+ spec_constants_cpy.push_back(state.p0); \
3922+ spec_constants_cpy.push_back(state.p1); \
3923+ spec_constants_cpy.push_back(state.d0); \
3924+ spec_constants_cpy.push_back(state.d1); \
3925+ spec_constants_cpy.push_back(state.KW); \
3926+ spec_constants_cpy.push_back(state.KH); \
3927+ ggml_vk_create_pipeline( \
3928+ device, c.second, #name #type_suffix, \
3929+ name##type_suffix##spv_suffix##_len, name##type_suffix##spv_suffix##_data, "main", 3, \
3930+ sizeof(vk_op_##name##_push_constants), wg_denoms, spec_constants_cpy, 1, true, use_collectives); \
3931+ }
39143932#define CREATE_CONVS(spv_suffix) \
39153933 CREATE_CONV(conv2d, _f32, spv_suffix) \
39163934 CREATE_CONV(conv2d, _f16_f32, spv_suffix) \
@@ -8536,7 +8554,7 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
85368554
85378555 uint32_t tiles[CONV_SHAPE_COUNT];
85388556 for (uint32_t i = 0; i < CONV_SHAPE_COUNT; ++i) {
8539- tiles[i] = CEIL_DIV(elements[0], ctx->device->pipeline_conv2d_f32 [i]->wg_denoms [0]) * CEIL_DIV(elements[1], ctx->device->pipeline_conv2d_f32 [i]->wg_denoms [1]);
8557+ tiles[i] = CEIL_DIV(elements[0], conv_shapes_wg_denoms [i][0]) * CEIL_DIV(elements[1], conv_shapes_wg_denoms [i][1]);
85408558 }
85418559
85428560 // We can't query number of shader cores on Intel, use 32 as a placeholder
@@ -8551,19 +8569,45 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
85518569 shape = CONV_SHAPE_64x32;
85528570 }
85538571
8572+ uint32_t KW = static_cast<uint32_t>(src0->ne[0]);
8573+ uint32_t KH = static_cast<uint32_t>(src0->ne[1]);
8574+ uint32_t s0 = static_cast<uint32_t>(dst->op_params[0]);
8575+ uint32_t s1 = op == GGML_OP_CONV_2D ? static_cast<uint32_t>(dst->op_params[1]) : static_cast<uint32_t>(dst->op_params[0]);
8576+ uint32_t p0 = op == GGML_OP_CONV_2D ? static_cast<uint32_t>(dst->op_params[2]) : 0;
8577+ uint32_t p1 = op == GGML_OP_CONV_2D ? static_cast<uint32_t>(dst->op_params[3]) : 0;
8578+ uint32_t d0 = op == GGML_OP_CONV_2D ? static_cast<uint32_t>(dst->op_params[4]) : 1;
8579+ uint32_t d1 = op == GGML_OP_CONV_2D ? static_cast<uint32_t>(dst->op_params[5]) : 1;
8580+
8581+ vk_conv2d_pipeline_state conv2d_pipeline_state(s0, s1, p0, p1, d0, d1, KW, KH);
8582+
8583+ std::map<vk_conv2d_pipeline_state, vk_pipeline> *pipelines = nullptr;
85548584 if (op == GGML_OP_CONV_2D) {
85558585 if (src0->type == GGML_TYPE_F32) {
8556- return ctx->device->pipeline_conv2d_f32[shape];
8586+ pipelines = & ctx->device->pipeline_conv2d_f32[shape];
85578587 } else if (src0->type == GGML_TYPE_F16) {
8558- return ctx->device->pipeline_conv2d_f16_f32[shape];
8588+ pipelines = & ctx->device->pipeline_conv2d_f16_f32[shape];
85598589 }
85608590 } else if (op == GGML_OP_CONV_TRANSPOSE_2D) {
85618591 if (src0->type == GGML_TYPE_F32) {
8562- return ctx->device->pipeline_conv_transpose_2d_f32[shape];
8592+ pipelines = & ctx->device->pipeline_conv_transpose_2d_f32[shape];
85638593 } else if (src0->type == GGML_TYPE_F16) {
8564- return ctx->device->pipeline_conv_transpose_2d_f16_f32[shape];
8594+ pipelines = &ctx->device->pipeline_conv_transpose_2d_f16_f32[shape];
8595+ }
8596+ }
8597+
8598+ vk_pipeline pipeline = nullptr;
8599+
8600+ {
8601+ std::lock_guard<std::recursive_mutex> guard(ctx->device->mutex);
8602+ auto it = pipelines->find(conv2d_pipeline_state);
8603+ if (it != pipelines->end()) {
8604+ pipeline = it->second;
8605+ } else {
8606+ (*pipelines)[conv2d_pipeline_state] = pipeline = std::make_shared<vk_pipeline_struct>();
85658607 }
85668608 }
8609+
8610+ return pipeline;
85678611 }
85688612 return nullptr;
85698613 case GGML_OP_CONV_2D_DW:
0 commit comments