@@ -13,6 +13,7 @@ void MatmulLayer::run(const std::vector<Tensor>& input,
1313 }
1414 const auto & a = input[0 ];
1515 const auto & b = input[1 ];
16+
1617 try {
1718 bool should_swap = false ;
1819
@@ -232,14 +233,19 @@ void MatmulLayer::matmul_nd_nd(const Tensor& a, const Tensor& b,
232233 for (size_t i = 0 ; i < batch_dims_b; ++i) {
233234 batch_shape_b[i] = b_shape[i];
234235 }
235- for (size_t i = 0 ; i < max_batch_dims; ++i) {
236- size_t a_dim = (i < batch_dims_a) ? batch_shape_a[i] : 1 ;
237- size_t b_dim = (i < batch_dims_b) ? batch_shape_b[i] : 1 ;
238236
239- if (a_dim != b_dim && a_dim != 1 && b_dim != 1 ) {
240- throw std::runtime_error (
241- " MatMul: Incompatible batch dimensions for broadcasting" );
242- }
237+ size_t a_matrix_size = a_shape[a_dims - 2 ] * a_shape[a_dims - 1 ];
238+ size_t b_matrix_size = b_shape[b_dims - 2 ] * b_shape[b_dims - 1 ];
239+ size_t out_matrix_size = a_shape[a_dims - 2 ] * b_shape[b_dims - 1 ];
240+
241+ std::vector<size_t > a_batch_strides (max_batch_dims, a_matrix_size);
242+ std::vector<size_t > b_batch_strides (max_batch_dims, b_matrix_size);
243+ std::vector<size_t > out_batch_strides (max_batch_dims, out_matrix_size);
244+
245+ for (int i = static_cast <int >(max_batch_dims) - 2 ; i >= 0 ; --i) {
246+ size_t idx = static_cast <size_t >(i);
247+ a_batch_strides[idx] = a_batch_strides[idx + 1 ] * batch_shape_a[idx + 1 ];
248+ b_batch_strides[idx] = b_batch_strides[idx + 1 ] * batch_shape_b[idx + 1 ];
243249 }
244250
245251 std::vector<size_t > output_batch_shape (max_batch_dims);
@@ -252,6 +258,12 @@ void MatmulLayer::matmul_nd_nd(const Tensor& a, const Tensor& b,
252258 output_batch_shape[i] = std::max (batch_shape_a[i], batch_shape_b[i]);
253259 }
254260
261+ for (int i = static_cast <int >(max_batch_dims) - 2 ; i >= 0 ; --i) {
262+ size_t idx = static_cast <size_t >(i);
263+ out_batch_strides[idx] =
264+ out_batch_strides[idx + 1 ] * output_batch_shape[idx + 1 ];
265+ }
266+
255267 std::vector<size_t > output_shape = output_batch_shape;
256268 output_shape.push_back (a_shape[a_dims - 2 ]);
257269 output_shape.push_back (b_shape[b_dims - 1 ]);
@@ -270,30 +282,27 @@ void MatmulLayer::matmul_nd_nd(const Tensor& a, const Tensor& b,
270282 for (size_t batch = 0 ; batch < total_batch; ++batch) {
271283 size_t a_batch_idx = 0 ;
272284 size_t b_batch_idx = 0 ;
285+ size_t out_batch_idx = 0 ;
273286 size_t temp_batch = batch;
274287
275- for (size_t dim_index = 0 ; dim_index < max_batch_dims; ++dim_index ) {
276- size_t i = max_batch_dims - dim_index - 1 ;
277- size_t dim_size = output_batch_shape[i ];
278- size_t idx = temp_batch % dim_size;
288+ for (int i = static_cast < int >(max_batch_dims) - 1 ; i >= 0 ; --i ) {
289+ size_t idx = static_cast < size_t >(i) ;
290+ size_t dim_size = output_batch_shape[idx ];
291+ size_t batch_idx = temp_batch % dim_size;
279292 temp_batch /= dim_size;
280293
281- if (batch_shape_a[i] > 1 ) {
282- a_batch_idx = a_batch_idx * batch_shape_a[i] + (idx % batch_shape_a[i]);
283- } else {
284- a_batch_idx = a_batch_idx * batch_shape_a[i];
294+ if (batch_shape_a[idx] > 1 ) {
295+ a_batch_idx += batch_idx * a_batch_strides[idx];
285296 }
286-
287- if (batch_shape_b[i] > 1 ) {
288- b_batch_idx = b_batch_idx * batch_shape_b[i] + (idx % batch_shape_b[i]);
289- } else {
290- b_batch_idx = b_batch_idx * batch_shape_b[i];
297+ if (batch_shape_b[idx] > 1 ) {
298+ b_batch_idx += batch_idx * b_batch_strides[idx];
291299 }
300+ out_batch_idx += batch_idx * out_batch_strides[idx];
292301 }
293302
294- size_t a_offset = a_batch_idx * m * k ;
295- size_t b_offset = b_batch_idx * k * n ;
296- size_t out_offset = batch * m * n ;
303+ size_t a_offset = a_batch_idx;
304+ size_t b_offset = b_batch_idx;
305+ size_t out_offset = out_batch_idx ;
297306
298307 for (size_t i = 0 ; i < m; ++i) {
299308 for (size_t j = 0 ; j < n; ++j) {
0 commit comments