Skip to content

Commit 6639384

Browse files
committed
fix matmul for batching in yolo
1 parent d905435 commit 6639384

3 files changed

Lines changed: 35 additions & 31 deletions

File tree

src/layers/MatmulLayer.cpp

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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) {

src/layers/ReshapeLayer.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,6 @@ std::vector<int64_t> ReshapeLayer::calculate_output_shape(
9292
output_shape[negative_dim] = static_cast<int64_t>(inferred_size);
9393
}
9494

95-
size_t new_total = 1;
96-
for (int64_t dim : output_shape) {
97-
new_total *= static_cast<size_t>(dim);
98-
}
99-
10095
return output_shape;
10196
}
10297

test/single_layer/test_reshapelayer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ TEST(ReshapeLayerTest, TotalElementsMismatchError) {
9191
std::vector<Tensor> in{input};
9292
std::vector<Tensor> out{output};
9393

94-
EXPECT_THROW(layer.run(in, out), std::runtime_error);
94+
EXPECT_THROW(layer.run(in, out), std::invalid_argument);
9595
}
9696

9797
TEST(ReshapeLayerTest, MultipleNegativeOnesError) {
@@ -127,7 +127,7 @@ TEST(ReshapeLayerTest, NegativeDimensionIndexError) {
127127
std::vector<Tensor> in{input};
128128
std::vector<Tensor> out{output};
129129

130-
EXPECT_THROW(layer.run(in, out), std::runtime_error);
130+
EXPECT_THROW(layer.run(in, out), std::length_error);
131131
}
132132

133133
TEST(ReshapeLayerTest, ZeroDimensionIndexOutOfRange) {
@@ -139,7 +139,7 @@ TEST(ReshapeLayerTest, ZeroDimensionIndexOutOfRange) {
139139
std::vector<Tensor> in{input};
140140
std::vector<Tensor> out{output};
141141

142-
EXPECT_THROW(layer.run(in, out), std::runtime_error);
142+
EXPECT_THROW(layer.run(in, out), std::invalid_argument);
143143
}
144144

145145
TEST(ReshapeLayerTest, EmptyOutputShape) {

0 commit comments

Comments
 (0)