馃悰 Describe the bug
VulkanPartitioner raises AttributeError instead of reporting a node unsupported when an op declared to return Tensor[] happens to produce exactly one tensor. The exception propagates out of to_edge_transform_and_lower, so a single such node aborts partitioning for the entire model.
num_tensors_in_node() counts the tensors associated with a node rather than the nesting of meta["val"]:
if isinstance(node.meta["val"], list) or isinstance(node.meta["val"], tuple):
if all(isinstance(x, FakeTensor) for x in node.meta["val"]):
return len(node.meta["val"])
so it returns 1 both for a bare FakeTensor and for a one-element list. OpRepSets.__init__ reads that count as proof of the former and passes meta["val"] straight through:
if num_tensors_in_node(op_node) == 1:
common_out_repset = filter_invalid_reprs(
op_node.meta["val"], outputs_repsets[0], texture_limits
)
filter_invalid_reprs is annotated tensor_val: FakeTensor and immediately does tensor_val.shape.
Repro, using the existing test helpers in backends/vulkan/test/test_vulkan_tensor_repr.py:
arg = _make_tensor_arg_node((1, 3, 8, 8))
node = _make_op_node(
target=torch.ops.aten.split_with_sizes_copy.default,
args=(arg, [3]),
output_val=[_make_fake_tensor((1, 3, 8, 8))], # one-element list
)
OpRepSets(
TensorRepSetList(ANY_STORAGE),
TensorRepSetList(ANY_STORAGE),
node,
DEFAULT_TEXTURE_LIMITS,
)
File "backends/vulkan/utils.py", line 1445, in __init__
common_out_repset = filter_invalid_reprs(
File "backends/vulkan/utils.py", line 1203, in filter_invalid_reprs
extents = required_image_extents(tensor_val.shape, memory_layout)
AttributeError: 'list' object has no attribute 'shape'
Seen in the wild lowering RF-DETR nano, where aten.split_with_sizes_copy.default is emitted with a single split size.
Expected behavior
Either handle the node or report it unsupported so it stays on host. A partitioner should not be able to abort the whole lowering because one node's output nesting differs.
Fix
Unwrap the single element before filtering, matching what the multiple-output branch immediately below already does per element.
PR: #22308
Versions
ExecuTorch main @ c27baa8 (also reproduces on the v1.4.1 branch). Python 3.10, torch 2.13.0, macOS 15.5 / arm64.
馃悰 Describe the bug
VulkanPartitionerraisesAttributeErrorinstead of reporting a node unsupported when an op declared to returnTensor[]happens to produce exactly one tensor. The exception propagates out ofto_edge_transform_and_lower, so a single such node aborts partitioning for the entire model.num_tensors_in_node()counts the tensors associated with a node rather than the nesting ofmeta["val"]:so it returns
1both for a bareFakeTensorand for a one-element list.OpRepSets.__init__reads that count as proof of the former and passesmeta["val"]straight through:filter_invalid_reprsis annotatedtensor_val: FakeTensorand immediately doestensor_val.shape.Repro, using the existing test helpers in
backends/vulkan/test/test_vulkan_tensor_repr.py:Seen in the wild lowering RF-DETR nano, where
aten.split_with_sizes_copy.defaultis emitted with a single split size.Expected behavior
Either handle the node or report it unsupported so it stays on host. A partitioner should not be able to abort the whole lowering because one node's output nesting differs.
Fix
Unwrap the single element before filtering, matching what the multiple-output branch immediately below already does per element.
PR: #22308
Versions
ExecuTorch
main@ c27baa8 (also reproduces on the v1.4.1 branch). Python 3.10, torch 2.13.0, macOS 15.5 / arm64.