Skip to content

[Vulkan] Partitioner raises AttributeError on an op returning a one-element Tensor[], aborting the whole lowering#22306

Description

@msluszniak

馃悰 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    module: vulkanIssues related to the Vulkan delegate and code under backends/vulkan/

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions