Skip to content

Commit 4c1443c

Browse files
committed
Improve error messages for tensor size errors (#7453)
Summary: Print expected and actual tensor sizes when attempting to resize a static tensor. This commonly comes up when a user provides an incorrectly-shaped input tensor and can be confusing. Adding the expected and actual sizes should make this situation more intuitive. This change also includes ET_UNUSED in several places where the variable is used only when logging is enabled, as unused variable warnings cause build failures in some build modes when logging is disabled. Differential Revision: D67665846
1 parent 9a884a8 commit 4c1443c

File tree

4 files changed

+64
-9
lines changed

4 files changed

+64
-9
lines changed

runtime/core/exec_aten/util/dim_order_util.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#pragma once
1010

1111
#include <cstdint>
12+
#include <cstdio>
13+
#include <cstring>
1214

1315
#include <executorch/runtime/core/error.h>
1416
#include <executorch/runtime/platform/assert.h>
@@ -257,6 +259,36 @@ ET_NODISCARD inline Error stride_to_dim_order(
257259
}
258260
return Error::Ok;
259261
}
262+
263+
/**
264+
* Print a string representation of an ArrayRef of tensor sizes into a
265+
* user-provided string buffer. If the user buffer is too small, the string
266+
* will be truncated. The output is of the format (1,2,3,4).
267+
*
268+
* Note that we cannot use ArrayRef here due to a circular dependency (see
269+
* above comments).
270+
*/
271+
template <class SizesType>
272+
inline void sizes_to_string(
273+
char* output,
274+
size_t output_size,
275+
SizesType* sizes,
276+
size_t rank) {
277+
auto remaining_size = output_size;
278+
for (auto i = 0; remaining_size > 0 && i < rank; i++) {
279+
snprintf(
280+
output,
281+
remaining_size,
282+
"%s%zd",
283+
i == 0 ? "(" : ",",
284+
static_cast<size_t>(sizes[i]));
285+
auto len = strlen(output);
286+
output += len;
287+
remaining_size -= len;
288+
}
289+
snprintf(output, remaining_size, ")");
290+
}
291+
260292
} // namespace runtime
261293
} // namespace executorch
262294

runtime/core/portable_type/tensor_impl.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,24 +90,46 @@ Error TensorImpl::internal_resize_contiguous(ArrayRef<SizesType> new_sizes) {
9090
if (dim_ == 0) {
9191
return Error::Ok;
9292
}
93+
9394
switch (shape_dynamism_) {
9495
case TensorShapeDynamism::STATIC:
95-
ET_CHECK_OR_RETURN_ERROR(
96-
std::equal(sizes_, sizes_ + dim_, new_sizes.begin()),
97-
NotSupported,
98-
"Attempted to resize a static tensor");
96+
if (!std::equal(sizes_, sizes_ + dim_, new_sizes.begin())) {
97+
#ifdef ET_LOG_ENABLED
98+
std::array<char, 5> old_sizes_str, new_sizes_str;
99+
100+
executorch::runtime::sizes_to_string(
101+
old_sizes_str.data(),
102+
old_sizes_str.size(),
103+
sizes().data(),
104+
sizes().size());
105+
executorch::runtime::sizes_to_string(
106+
new_sizes_str.data(),
107+
new_sizes_str.size(),
108+
new_sizes.data(),
109+
new_sizes.size());
110+
#endif
111+
112+
ET_CHECK_OR_RETURN_ERROR(
113+
false,
114+
NotSupported,
115+
"Attempted to resize a static tensor. Expected shape %s, but received %s.",
116+
old_sizes_str.data(),
117+
new_sizes_str.data())
118+
}
119+
99120
break;
100121
case TensorShapeDynamism::DYNAMIC_BOUND:
101122
// TODO(T175194371): Unbounded dynamic tensor resizing is not yet
102123
// supported: treat them as upper-bounded.
103124
case TensorShapeDynamism::DYNAMIC_UNBOUND: {
104125
const auto new_numel = compute_numel(new_sizes.data(), dim_);
126+
105127
ET_CHECK_OR_RETURN_ERROR(
106128
new_numel <= numel_bound_,
107129
NotSupported,
108-
"Attempted to resize a bounded tensor with capacity of %zu elements to %zu elements.",
109-
new_numel,
110-
numel_bound_);
130+
"Attempted to resize a bounded tensor with a maximum capacity of %zu elements to %zu elements.",
131+
numel_bound_,
132+
new_numel);
111133

112134
if (strides_ && dim_order_) {
113135
auto error =

runtime/executor/method.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ Error Method::execute_instruction() {
10611061
// We know that instr_args_as_KernelCall is non-null because it was
10621062
// checked at init time.
10631063
auto op_index = instruction->instr_args_as_KernelCall()->op_index();
1064-
auto op = serialization_plan_->operators()->Get(op_index);
1064+
ET_UNUSED auto op = serialization_plan_->operators()->Get(op_index);
10651065
ET_LOG(
10661066
Error,
10671067
"KernelCall failed at instruction %zu:%zu in operator %s.%s: 0x%x",

runtime/kernel/operator_registry.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ Error register_kernels_internal(const Span<const Kernel> kernels) {
7474
return Error::Internal;
7575
}
7676
// for debugging purpose
77-
const char* lib_name = et_pal_get_shared_library_name(kernels.data());
77+
ET_UNUSED const char* lib_name =
78+
et_pal_get_shared_library_name(kernels.data());
7879

7980
for (const auto& kernel : kernels) {
8081
// Linear search. This is fine if the number of kernels is small.

0 commit comments

Comments
 (0)