Repository navigation
Add validate_tensor_layout to check a tensor layout without aborting, and document the raw-bytes overloads - #24772
shoumikhin wants to merge 3 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24772
Note: Links to docs will display an error until the docs builds have been completed. ❌ 1 New FailureAs of commit d6e6f75 with merge base e0015e1 ( NEW FAILURE - The following job has failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@claude /pr-review |
|
Claude finished @shoumikhin's task in 19m 38s —— View job Request changes: removing the Detailed reviewPR Review: #24772SummaryThe PR makes a Two issues block:
The other findings are minor. All four changed files were covered. The findings come from reading the code; nothing was built or run. Code Quality
Testing
API Design
Backward Compatibility
RecommendationRequest Changes Two things block:
The remaining items are minor. |
d5432ac to
df9f4bb
Compare
|
@claude /pr-review |
|
Claude finished @shoumikhin's task in 19m 55s —— View job Request changes: Detailed reviewPR Review: #24772SummaryThe PR documents that the One issue should be fixed before merge: the new check accepts layouts whose strides overflow, and it overflows a signed integer while computing them. The other three findings are minor: the docs, the wasm error messages and a boundary test. All five changed files were covered. The findings come from reading the code; nothing was built or run. Code Quality
Testing
API Design
RecommendationRequest Changes The stride overflow should be fixed before merge. |
df9f4bb to
a6fe4b4
Compare
|
Thanks for the careful review. Changes in this push:
|
|
@claude /pr-review |
|
Claude finished @shoumikhin's task in 32m 39s —— View job PR Review: #24772Request changes: Android Detailed reviewSummaryThe PR adds
Backward Compatibility
API Design
Code Quality
Testing
RecommendationRequest Changes
|
make_tensor_ptr has typed vector overloads and raw-bytes vector overloads.
The templates take typed data and deduce the scalar type from the element
type. The overloads that take sizes and a std::vector<uint8_t> take raw
memory plus the scalar type to read it as, the owning counterpart of passing
a void* to from_blob. Like from_blob, their type defaults to Float.
The docs called these bytes raw data, but did not mention the Float default.
So a reader can expect a uint8 vector to become a Byte tensor, as a vector of
any other element type does, and get an abort from the size check instead:
auto t = make_tensor_ptr({128}, std::vector<uint8_t>(128));
// Data size (128) does not match tensor size (512).
Say in the header and in the tensor guide that these bytes are raw memory
read as the given type, defaulting to Float, and show how to get a Byte
tensor by passing ScalarType::Byte. The typed pointer overload's doc said it
deduces the type the same way the vector overload does; it now names uint8_t
as the exception. No behavior changes.
make_tensor_ptr checks sizes, dim order and strides with ET_CHECK, so an
invalid layout aborts the process:
std::vector<float> data(16);
auto t = make_tensor_ptr({2, 2}, data.data(), {}, {8, 2});
// invalid strides for dim 0: 8!= 2 while its size is 2 != 1
That is fine for a layout the program builds itself. But a program that gets
the layout from outside, for example from a file or over the network, has no
ExecuTorch function to reject a bad one and keep running. ExecuTorch has no
exceptions, so it needs a check that returns an Error. (PyTorch accepts these
strides, because its tensors do not have to be dense.)
Add validate_tensor_layout(sizes, dim_order, strides):
if (validate_tensor_layout(sizes, {}, strides) != Error::Ok) {
return Error::InvalidArgument;
}
It returns Error::InvalidArgument for every layout that the make_tensor_ptr
overloads taking sizes and data abort on. It also rejects sizes that are
negative or whose product overflows, and dense strides that do not fit
StridesType. It does not look at the data, so the caller still has to check
that the data size matches the sizes. The tensor guide shows both checks.
The layout checks move into one internal function that make_tensor_ptr and
validate_tensor_layout both call. make_tensor_ptr accepts and rejects the same
layouts as before, with the same strides. Only its abort message changes, to
"Invalid tensor layout.", with the reason logged at Error level on the line
before it.
That includes dense strides that do not fit StridesType. For example, in
portable mode make_tensor_ptr({0, 65536, 65536}, std::vector<float>{}) builds
a tensor with strides {0, 65536, 1}, where the first stride wrapped around.
make_tensor_ptr keeps accepting these layouts, because existing code depends
on it: the program loader builds such tensors too (an output with sizes
{1, 65536, 32768} gets a wrapped stride in its size-1 dim), and apps clone or
wrap them. The shared function computes the strides with c10::mul_overflows
instead of a plain signed multiply, whose overflow is undefined behavior. On
GCC and Clang that is a compiler builtin, which gives the same wrapped value.
The runtime's dim_order_to_stride, which the program loader and resize use,
keeps its plain multiply; fixing it is a separate runtime change.
validate_tensor_layout rejects these layouts, the way PyTorch throws
"Stride calculation overflowed" when its own strides overflow. The header now
says that make_tensor_ptr accepts them.
The WebAssembly bindings kept their own copy of these checks, so that
Tensor.fromArray and Tensor.fromIter throw a JS error instead of aborting.
They now call validate_tensor_layout, so an empty tensor whose strides
overflow, such as sizes [0, 65536, 65536], now throws instead of being built.
Every layout error now throws "Invalid tensor layout." instead of the copy's
own message, such as "strides size must match sizes or be empty.", or for
negative or overflowing sizes
"Invalid tensor sizes: numel computation failed". The reason is logged only in
builds with logging enabled, which in CMake are Debug builds by default. The
helper is renamed to assert_layout_valid, since it now checks the sizes too.
…need Tensor.fromArray and Tensor.fromIter check the data length before they call make_tensor_ptr, so that a wrong length throws a JS error. The check accepted extra elements. But make_tensor_ptr needs exactly as many elements as the sizes describe, so this call aborted the whole module: et.Tensor.fromArray([2], [1, 2, 3]); Require an exact match, so that it throws "Required 2 elements, given 3" instead.
a6fe4b4 to
d6e6f75
Compare
|
Changes in this push:
|
|
@claude /pr-review |
|
Claude finished @shoumikhin's task in 25m 55s —— View job PR Review: #24772Approve: nothing blocks; the remaining findings are minor, chiefly that Detailed reviewSummaryThe PR adds
Code Quality
Testing
API Design
RecommendationApprove Nothing blocks. Every item is minor and can land here or as a follow-up. Loosening the size-1 rule later accepts strictly more layouts, so existing callers would not break. |
Title: Add validate_tensor_layout to check a tensor layout without aborting, and document the raw-bytes overloads
What is wrong today
A bad layout aborts.
make_tensor_ptraborts when the strides do not match the sizes:No ExecuTorch function lets an app reject a bad layout and continue.
Some strides overflow. Portable strides are 32-bit, so for sizes like
{0, 65536, 65536}computing them is undefined behavior (signed overflow).The raw-bytes overloads are easy to misread. With sizes, a
std::vector<uint8_t>is raw memory read as the given type, like avoid*infrom_blob. The docs never said the type defaults toFloat.Tensor.fromArraywith extra data aborts the WebAssembly module.What this change does
Commit 1 is docs only: raw bytes, the
Floatdefault,ScalarType::Byte.Commit 2 adds
validate_tensor_layout(sizes, dim_order, strides). It returnsError::InvalidArgumentfor every layout that themake_tensor_ptroverloads taking sizes and data abort on. It also rejects negative sizes, sizes whose product overflows, and dense strides that do not fitStridesType. It does not check the data.make_tensor_ptruses the same internal check. It accepts and rejects the same layouts as before, with the same strides; only its abort message changes. It still accepts overflowing strides, which the program loader builds too, but computes them withc10::mul_overflowsinstead of a plain signed multiply.The WebAssembly
Tensor.fromArrayandTensor.fromIternow use this check, so overflowing strides throw too, and every layout error says "Invalid tensor layout." rather than a specific message.Commit 3 makes both throw when they get more data than the sizes need.
InvalidArgumentInvalidArgumentWhat was tested
extension_tensor_testpasses in portable and ATen mode, and fails if any check breaks.make_tensor_ptrmatches main, and a signed-overflow sanitizer ontensor_ptr.cppflags none (main: thousands).lintrunneris clean.