2424#include " ck/tensor_operation/gpu/device/impl/device_grouped_conv_utils.hpp"
2525#include " ck/tensor_operation/gpu/device/impl/split_k_utils.hpp"
2626#include " ck/tensor_operation/gpu/device/impl/split_k_arg.hpp"
27+ #include " ck/tensor_operation/gpu/device/impl/split_k_offset_utils.hpp"
2728#include " ck/tensor_operation/gpu/element/element_wise_operation.hpp"
2829
2930#include " ck/host_utility/device_prop.hpp"
@@ -60,13 +61,19 @@ __launch_bounds__(CK_MAX_THREAD_PER_BLOCK, MinimumOccupancy)
6061 [[maybe_unused]] const CGridDesc_MBlock_MPerBlock_NBlock_NPerBlock
6162 c_grid_desc_mblock_mperblock_nblock_nperblock,
6263 [[maybe_unused]] const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch,
63- [[maybe_unused]] const index_t num_k_per_block)
64+ [[maybe_unused]] const index_t num_k_per_block,
65+ const long_index_t split_k_stride_a,
66+ const long_index_t split_k_stride_b,
67+ bool split_k_offset_hack)
6468{
6569#if defined(__gfx9__) || defined(__gfx11__) || defined(__gfx12__)
6670 if constexpr (GridwiseGemm::template IsValidCompilationParameter<CGlobalMemoryDataOperation>())
6771 {
6872 const index_t g_idx = __builtin_amdgcn_readfirstlane (blockIdx.z * NumGroupsToMerge);
69- const index_t k_idx = __builtin_amdgcn_readfirstlane (blockIdx.y * num_k_per_block);
73+ const index_t k_idx = __builtin_amdgcn_readfirstlane (blockIdx.y );
74+
75+ const long_index_t split_k_offset_a = split_k_offset_hack ? k_idx * split_k_stride_a : 0 ;
76+ const long_index_t split_k_offset_b = split_k_offset_hack ? k_idx * split_k_stride_b : 0 ;
7077
7178 const long_index_t a_batch_offset = amd_wave_read_first_lane (
7279 static_cast <long_index_t >(compute_ptr_offset_of_batch.GetAPtrOffset (g_idx)));
@@ -77,23 +84,29 @@ __launch_bounds__(CK_MAX_THREAD_PER_BLOCK, MinimumOccupancy)
7784
7885 __shared__ char p_shared[GridwiseGemm::GetSharedMemoryNumberOfByte ()];
7986
80- GridwiseGemm::template Run<AGridDesc_AK0_M_K1,
81- BGridDesc_BK0_N_K1,
82- CGridDesc_MBlock_MPerBlock_NBlock_NPerBlock,
83- HasMainKBlockLoop,
84- CGlobalMemoryDataOperation,
85- TailNum>(karg.p_a_grid + a_batch_offset,
86- karg.p_b_grid + b_batch_offset,
87- karg.p_c_grid + e_batch_offset,
88- p_shared,
89- karg,
90- a_grid_desc_ak0_m_ak1,
91- b_grid_desc_bk0_n_bk1,
92- c_grid_desc_mblock_mperblock_nblock_nperblock,
93- k_idx);
87+ DispatchSplitKHack<GridwiseGemm,
88+ AGridDesc_AK0_M_K1,
89+ BGridDesc_BK0_N_K1,
90+ CGridDesc_MBlock_MPerBlock_NBlock_NPerBlock,
91+ HasMainKBlockLoop,
92+ CGlobalMemoryDataOperation,
93+ TailNum>(karg.p_a_grid + a_batch_offset + split_k_offset_a,
94+ karg.p_b_grid + b_batch_offset + split_k_offset_b,
95+ karg.p_c_grid + e_batch_offset,
96+ p_shared,
97+ karg,
98+ a_grid_desc_ak0_m_ak1,
99+ b_grid_desc_bk0_n_bk1,
100+ c_grid_desc_mblock_mperblock_nblock_nperblock,
101+ k_idx * num_k_per_block,
102+ gridDim.y ,
103+ split_k_offset_hack);
94104 }
95105#else
96106 ignore = karg;
107+ ignore = split_k_stride_a;
108+ ignore = split_k_stride_b;
109+ ignore = split_k_offset_hack;
97110#endif // end of if (defined(__gfx9__))
98111}
99112
@@ -118,14 +131,20 @@ __launch_bounds__(CK_MAX_THREAD_PER_BLOCK, MinimumOccupancy)
118131 [[maybe_unused]] const CGridDesc_MBlock_MPerBlock_NBlock_NPerBlock
119132 c_grid_desc_mblock_mperblock_nblock_nperblock,
120133 [[maybe_unused]] const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch,
121- [[maybe_unused]] const index_t num_k_per_block)
134+ [[maybe_unused]] const index_t num_k_per_block,
135+ const long_index_t split_k_stride_a,
136+ const long_index_t split_k_stride_b,
137+ bool split_k_offset_hack)
122138{
123139#if defined(__gfx9__) || defined(__gfx11__) || defined(__gfx12__)
124140 if constexpr (GridwiseGemm::template IsValidCompilationParameter<CGlobalMemoryDataOperation>())
125141 {
126142 // offset base pointer for each work-group
127143 const index_t g_idx = __builtin_amdgcn_readfirstlane (blockIdx.z * NumGroupsToMerge);
128- const index_t k_idx = __builtin_amdgcn_readfirstlane (blockIdx.y * num_k_per_block);
144+ const index_t k_idx = __builtin_amdgcn_readfirstlane (blockIdx.y );
145+
146+ const long_index_t split_k_offset_a = split_k_offset_hack ? k_idx * split_k_stride_a : 0 ;
147+ const long_index_t split_k_offset_b = split_k_offset_hack ? k_idx * split_k_stride_b : 0 ;
129148
130149 const long_index_t a_batch_offset = amd_wave_read_first_lane (
131150 static_cast <long_index_t >(compute_ptr_offset_of_batch.GetAPtrOffset (g_idx)));
@@ -139,24 +158,30 @@ __launch_bounds__(CK_MAX_THREAD_PER_BLOCK, MinimumOccupancy)
139158 __shared__ char p_shared_0[GridwiseGemm::GetSharedMemoryNumberOfByte ()];
140159 __shared__ char p_shared_1[GridwiseGemm::GetSharedMemoryNumberOfByte ()];
141160
142- GridwiseGemm::template Run_2Lds<AGridDesc_AK0_M_K1,
143- BGridDesc_BK0_N_K1,
144- CGridDesc_MBlock_MPerBlock_NBlock_NPerBlock,
145- HasMainKBlockLoop,
146- CGlobalMemoryDataOperation,
147- TailNum>(karg.p_a_grid + a_batch_offset,
148- karg.p_b_grid + b_batch_offset,
149- karg.p_c_grid + e_batch_offset,
150- p_shared_0,
151- p_shared_1,
152- karg,
153- a_grid_desc_ak0_m_ak1,
154- b_grid_desc_bk0_n_bk1,
155- c_grid_desc_mblock_mperblock_nblock_nperblock,
156- k_idx);
161+ DispatchSplitKHack_2Lds<GridwiseGemm,
162+ AGridDesc_AK0_M_K1,
163+ BGridDesc_BK0_N_K1,
164+ CGridDesc_MBlock_MPerBlock_NBlock_NPerBlock,
165+ HasMainKBlockLoop,
166+ CGlobalMemoryDataOperation,
167+ TailNum>(karg.p_a_grid + a_batch_offset + split_k_offset_a,
168+ karg.p_b_grid + b_batch_offset + split_k_offset_b,
169+ karg.p_c_grid + e_batch_offset,
170+ p_shared_0,
171+ p_shared_1,
172+ karg,
173+ a_grid_desc_ak0_m_ak1,
174+ b_grid_desc_bk0_n_bk1,
175+ c_grid_desc_mblock_mperblock_nblock_nperblock,
176+ k_idx * num_k_per_block,
177+ gridDim.y ,
178+ split_k_offset_hack);
157179 }
158180#else
159181 ignore = karg;
182+ ignore = split_k_offset_hack;
183+ ignore = split_k_stride_a;
184+ ignore = split_k_stride_b;
160185#endif // end of if (defined(__gfx9__))
161186}
162187
@@ -693,7 +718,8 @@ struct DeviceGroupedConvBwdWeightTwoStage_Xdl_CShuffle
693718 k_batch_ = split_k;
694719 }
695720
696- const auto descs =
721+ // Create initial descriptors with hack=false to check compactness
722+ const auto descs_initial =
697723 conv_to_gemm_transformer_v2
698724 .template MakeABCGridDescriptor_A_K0_M_K1_B_K0_N_K1_C_M_N <NDimSpatial>(
699725 Conv_N_,
@@ -709,11 +735,9 @@ struct DeviceGroupedConvBwdWeightTwoStage_Xdl_CShuffle
709735 conv_filter_dilations,
710736 input_left_pads,
711737 input_right_pads,
712- k_batch_);
713-
714- a_grid_desc_k0_m_k1_ = descs[I0 ];
715- b_grid_desc_k0_n_k1_ = descs[I1 ];
716- ce_grid_desc_m_n_ = descs[I2 ];
738+ k_batch_,
739+ false , // hack=false for initial check
740+ true ); // use_full_batch_kindex
717741
718742 ce_elementwise_grid_desc_m_n_ =
719743 conv_to_gemm_transformer_v1
@@ -733,6 +757,67 @@ struct DeviceGroupedConvBwdWeightTwoStage_Xdl_CShuffle
733757 input_right_pads,
734758 k_batch_)[I2 ];
735759
760+ split_k_offset_hack_ =
761+ SplitKHackEligibility<NDimSpatial, InLayout, WeiLayout, OutLayout>::Check (
762+ descs_initial[I0 ],
763+ descs_initial[I1 ],
764+ k_batch_,
765+ Conv_N_,
766+ output_spatial_lengths_,
767+ KPerBlock);
768+
769+ // Create final descriptors with correct hack flag
770+ const auto descs =
771+ conv_to_gemm_transformer_v2
772+ .template MakeABCGridDescriptor_A_K0_M_K1_B_K0_N_K1_C_M_N <NDimSpatial>(
773+ Conv_N_,
774+ Conv_K_,
775+ Conv_C_,
776+ input_spatial_lengths_,
777+ filter_spatial_lengths_,
778+ output_spatial_lengths_,
779+ b_g_n_c_wis_strides_transposed,
780+ e_g_k_c_xs_strides_transposed,
781+ a_g_n_k_wos_strides_transposed,
782+ conv_filter_strides,
783+ conv_filter_dilations,
784+ input_left_pads,
785+ input_right_pads,
786+ k_batch_,
787+ split_k_offset_hack_, // Use determined hack flag
788+ true ); // use_full_batch_kindex
789+
790+ a_grid_desc_k0_m_k1_ = descs[I0 ];
791+ b_grid_desc_k0_n_k1_ = descs[I1 ];
792+ ce_grid_desc_m_n_ = descs[I2 ];
793+
794+ // Step 5: Calculate stride using CalculateOffset on FINAL descriptors
795+ if (split_k_offset_hack_)
796+ {
797+ const index_t k0_per_batch = a_grid_desc_k0_m_k1_.GetLength (I0 ) / k_batch_;
798+ const auto idx_start = make_multi_index (0 , 0 , 0 );
799+ const auto idx_next = make_multi_index (k0_per_batch, 0 , 0 );
800+ split_k_stride_a_ = a_grid_desc_k0_m_k1_.CalculateOffset (idx_next) -
801+ a_grid_desc_k0_m_k1_.CalculateOffset (idx_start);
802+ }
803+ else
804+ {
805+ split_k_stride_a_ = a_grid_desc_k0_m_k1_.GetElementSpaceSize ();
806+ }
807+
808+ if (split_k_offset_hack_)
809+ {
810+ const index_t k0_per_batch = b_grid_desc_k0_n_k1_.GetLength (I0 ) / k_batch_;
811+ const auto idx_start = make_multi_index (0 , 0 , 0 );
812+ const auto idx_next = make_multi_index (k0_per_batch, 0 , 0 );
813+ split_k_stride_b_ = b_grid_desc_k0_n_k1_.CalculateOffset (idx_next) -
814+ b_grid_desc_k0_n_k1_.CalculateOffset (idx_start);
815+ }
816+ else
817+ {
818+ split_k_stride_b_ = b_grid_desc_k0_n_k1_.GetElementSpaceSize ();
819+ }
820+
736821 const index_t GemmM = a_grid_desc_k0_m_k1_.GetLength (I1 );
737822 const index_t GemmN = b_grid_desc_k0_n_k1_.GetLength (I1 );
738823
@@ -869,6 +954,9 @@ struct DeviceGroupedConvBwdWeightTwoStage_Xdl_CShuffle
869954 const std::array<ck::index_t , NDimSpatial>& input_left_pads_;
870955 const std::array<ck::index_t , NDimSpatial>& input_right_pads_;
871956 long_index_t c_space_size_bytes;
957+
958+ bool split_k_offset_hack_;
959+ long_index_t split_k_stride_a_, split_k_stride_b_;
872960 };
873961
874962 // Invoker
@@ -971,7 +1059,10 @@ struct DeviceGroupedConvBwdWeightTwoStage_Xdl_CShuffle
9711059 arg.b_grid_desc_k0_n_k1_ ,
9721060 arg.c_grid_desc_mblock_mperblock_nblock_nperblock_ ,
9731061 arg.compute_ptr_offset_of_batch_ ,
974- num_k_per_block);
1062+ num_k_per_block,
1063+ arg.split_k_stride_a_ ,
1064+ arg.split_k_stride_b_ ,
1065+ arg.split_k_offset_hack_ );
9751066 }
9761067 else
9771068 {
@@ -987,7 +1078,10 @@ struct DeviceGroupedConvBwdWeightTwoStage_Xdl_CShuffle
9871078 arg.b_grid_desc_k0_n_k1_ ,
9881079 arg.c_grid_desc_mblock_mperblock_nblock_nperblock_ ,
9891080 arg.compute_ptr_offset_of_batch_ ,
990- num_k_per_block);
1081+ num_k_per_block,
1082+ arg.split_k_stride_a_ ,
1083+ arg.split_k_stride_b_ ,
1084+ arg.split_k_offset_hack_ );
9911085 }
9921086 };
9931087
@@ -1920,14 +2014,6 @@ struct DeviceGroupedConvBwdWeightTwoStage_Xdl_CShuffle
19202014 }
19212015 }
19222016
1923- constexpr long_index_t TwoGB = (long_index_t {1 } << 31 );
1924- if (!(arg.a_grid_desc_k0_m_k1_ .GetElementSpaceSize () * sizeof (ADataType) <= TwoGB &&
1925- arg.b_grid_desc_k0_n_k1_ .GetElementSpaceSize () * sizeof (BDataType) <= TwoGB &&
1926- arg.ce_grid_desc_m_n_ .GetElementSpaceSize () * sizeof (EDataType) <= TwoGB))
1927- {
1928- return false ;
1929- }
1930-
19312017 return true ;
19322018 }
19332019
0 commit comments