@@ -112,67 +112,96 @@ at::Tensor cat(const at::TensorList& tensors, int64_t dim) {
112112 out_shape_vec[dim] = cat_dim_size;
113113 at::Tensor out = at::empty (out_shape_vec, ref_tensor->options ().dtype (out_dtype));
114114
115- std::vector<int64_t > storage_offsets;
116- int64_t current_storage_offset = 0 ;
117- storage_offsets.push_back (current_storage_offset);
118- int64_t out_stride_for_dim = out.stride (dim);
119- for (size_t i = 0 ; i < tensors.size () - 1 ; ++i) {
120- current_storage_offset += cat_dim_size_of (tensors[i], dim) * out_stride_for_dim;
121- storage_offsets.push_back (current_storage_offset);
115+ int64_t dim_prod_post = 1 ;
116+ for (int64_t d = dim + 1 ; d < ndim; ++d) {
117+ dim_prod_post *= out_shape_vec[d];
122118 }
119+ int64_t dim_size_out = out_shape_vec[dim];
123120
124- const TritonJITFunction& copy_kernel_func =
125- TritonJITFunction::get_instance (std::string (utils::get_triton_src_path () / " cat_copy .py" ),
126- " strided_copy_kernel " );
121+ const TritonJITFunction& kernel =
122+ TritonJITFunction::get_instance (std::string (utils::get_flag_gems_src_path () / " ops " / " cat .py" ),
123+ " cat_copy_func_kernel_4 " );
127124 c10::DeviceGuard guard (out.device ());
128125 backend::StreamType stream = backend::getCurrentStream ();
129126 backend::RawStreamType raw_stream = backend::getRawStream (stream);
130127
131- for (size_t i = 0 ; i < tensors.size (); ++i) {
132- const auto & input_tensor = tensors[i];
133- if (input_tensor.numel () == 0 ) continue ;
128+ constexpr int BLOCK = 1024 ;
129+ constexpr int NUM_WARPS = 4 ;
130+ constexpr int NUM_STAGES = 1 ;
131+
132+ int64_t dim_offset = 0 ;
133+ size_t ti = 0 ;
134+ while (ti < tensors.size ()) {
135+ at::Tensor batch_tensors[4 ];
136+ int64_t dim_sizes[4 ] = {0 , 0 , 0 , 0 };
137+ int64_t dim_offsets[4 ] = {0 , 0 , 0 , 0 };
138+ int64_t total_elements[4 ] = {0 , 0 , 0 , 0 };
139+ int num_in_batch = 0 ;
140+
141+ while (ti < tensors.size () && num_in_batch < 4 ) {
142+ const auto & t = tensors[ti];
143+ int64_t dim_size = cat_dim_size_of (t, dim);
144+
145+ if (!is_unconstrained_empty (t) && t.numel () > 0 ) {
146+ at::Tensor src = t;
147+ if (src.scalar_type () != out_dtype) {
148+ src = src.to (out_dtype);
149+ }
150+ src = src.contiguous ();
151+ batch_tensors[num_in_batch] = src;
152+ dim_sizes[num_in_batch] = dim_size;
153+ dim_offsets[num_in_batch] = dim_offset;
154+ total_elements[num_in_batch] = src.numel ();
155+ num_in_batch++;
156+ }
157+
158+ dim_offset += dim_size;
159+ ti++;
160+ }
161+
162+ if (num_in_batch == 0 ) continue ;
163+
164+ for (int j = num_in_batch; j < 4 ; ++j) {
165+ batch_tensors[j] = batch_tensors[0 ];
166+ dim_sizes[j] = 0 ;
167+ dim_offsets[j] = 0 ;
168+ total_elements[j] = 0 ;
169+ }
134170
135- at::Tensor src_tensor = input_tensor ;
136- if (input_tensor. scalar_type () != out_dtype ) {
137- src_tensor = input_tensor. to (out_dtype );
171+ int64_t max_elements = 0 ;
172+ for ( int j = 0 ; j < num_in_batch; ++j ) {
173+ max_elements = std::max (max_elements, total_elements[j] );
138174 }
139175
140- at::Tensor output_view = at::as_strided (out, src_tensor.sizes (), out.strides (), storage_offsets[i]);
141-
142- auto options = torch::TensorOptions ().device (src_tensor.device ()).dtype (torch::kInt64 );
143- at::Tensor in_strides = torch::tensor (src_tensor.strides (), options);
144- at::Tensor out_strides = torch::tensor (output_view.strides (), options);
145- at::Tensor shapes = torch::tensor (src_tensor.sizes (), options);
146-
147- int64_t ndim_val = src_tensor.dim ();
148- int64_t num_elements = src_tensor.numel ();
149-
150- constexpr int BLOCK_SIZE = 256 ;
151- constexpr int MAX_DIMS = 8 ;
152- TORCH_CHECK (ndim_val <= MAX_DIMS ,
153- " Tensor dimension " ,
154- ndim_val,
155- " exceeds the maximum supported by the kernel (" ,
156- MAX_DIMS ,
157- " )" );
158-
159- unsigned int grid_x = (num_elements + BLOCK_SIZE - 1 ) / BLOCK_SIZE ;
160-
161- copy_kernel_func (raw_stream,
162- grid_x,
163- 1 ,
164- 1 ,
165- 4 ,
166- 2 ,
167- src_tensor,
168- output_view,
169- in_strides,
170- out_strides,
171- shapes,
172- ndim_val,
173- num_elements,
174- BLOCK_SIZE ,
175- MAX_DIMS );
176+ unsigned int grid_x = (max_elements + BLOCK - 1 ) / BLOCK ;
177+ unsigned int grid_y = num_in_batch;
178+
179+ kernel (raw_stream,
180+ grid_x,
181+ grid_y,
182+ 1 ,
183+ NUM_WARPS ,
184+ NUM_STAGES ,
185+ out,
186+ batch_tensors[0 ],
187+ batch_tensors[1 ],
188+ batch_tensors[2 ],
189+ batch_tensors[3 ],
190+ dim_sizes[0 ],
191+ dim_sizes[1 ],
192+ dim_sizes[2 ],
193+ dim_sizes[3 ],
194+ dim_size_out,
195+ dim_prod_post,
196+ dim_offsets[0 ],
197+ dim_offsets[1 ],
198+ dim_offsets[2 ],
199+ dim_offsets[3 ],
200+ total_elements[0 ],
201+ total_elements[1 ],
202+ total_elements[2 ],
203+ total_elements[3 ],
204+ BLOCK );
176205 }
177206 return out;
178207}
0 commit comments