Skip to content

complex_graph_rewrite: AttributeError 'float' object has no attribute 'name' when graph contains scalar literals near view_as_complex #4378

Description

@robbysun

Bug description

torch_tensorrt.dynamo.compile crashes with AttributeError: 'float' object has no attribute 'name' when the exported graph contains both view_as_complex/view_as_real ops and a scalar constant (e.g. from x * 1.0 / math.sqrt(dim)) nearby.

The complex_graph_detection lowering pass's match_complex_mul filter iterates over match.nodes_map.values(), assuming every value is an fx.Node. However, torch.fx.subgraph_rewriter can include Python scalar literals (floats) in nodes_map, causing the crash.

Minimal reproducer

import math
import torch
import torch.nn as nn
import torch_tensorrt

class ComplexRoPEWithScale(nn.Module):
    def __init__(self, dim: int, seq_len: int):
        super().__init__()
        freqs = torch.polar(
            torch.ones(seq_len, dim // 2),
            torch.arange(seq_len * dim // 2, dtype=torch.float).reshape(seq_len, dim // 2),
        )
        self.register_buffer("freqs_cis", freqs)
        self.scale = 1.0 / math.sqrt(dim)  # becomes a float literal in the fx graph

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # view_as_complex -> mul -> view_as_real  (triggers complex_graph_detection)
        xc = torch.view_as_complex(x.float().reshape(*x.shape[:-1], -1, 2))
        out = torch.view_as_real(xc * self.freqs_cis).flatten(-2)
        # scalar multiply — introduces a Python float constant near the complex subgraph
        return (out * self.scale).to(x.dtype)

B, L, D = 2, 16, 32
x = torch.randn(B, L, D, device="cuda", dtype=torch.bfloat16)
model = ComplexRoPEWithScale(dim=D, seq_len=L).cuda().bfloat16().eval()

with torch.no_grad():
    ep = torch.export.export(model, (x,))

trt_ep = torch_tensorrt.dynamo.compile(
    ep,
    inputs=[x],
    enabled_precisions={torch.bfloat16},
    use_explicit_typing=False,
    device=torch_tensorrt.Device(gpu_id=0),
)

Full traceback

Traceback (most recent call last):
  File "repro.py", line 34, in <module>
  File ".../torch_tensorrt/dynamo/_compiler.py", line 764, in compile
    gm = post_lowering(gm, settings)
  File ".../torch_tensorrt/dynamo/lowering/passes/_aten_lowering_pass.py", line 137, in post_lowering
    gm = ATEN_POST_LOWERING_PASSES(gm, settings)
  File ".../torch_tensorrt/dynamo/lowering/passes/pass_manager.py", line 135, in __call__
    out = _pass(out, settings)
  File ".../torch_tensorrt/dynamo/lowering/passes/complex_graph_rewrite.py", line 360, in complex_graph_detection
    complex_graph_rewriter.rewrite_subgraph_nodes(complex_subgraphs)
  File ".../torch_tensorrt/dynamo/lowering/passes/complex_graph_rewrite.py", line 221, in rewrite_subgraph_nodes
    nodes = torch.fx.subgraph_rewriter.replace_pattern_with_filters(...)
  File ".../torch/fx/subgraph_rewriter.py", line 310, in <genexpr>
    match_filter(m, original_graph, pattern_graph)
  File ".../torch_tensorrt/dynamo/lowering/passes/complex_graph_rewrite.py", line 217, in match_complex_mul
    if original_node.name == node.name:
       ^^^^^^^^^^^^^^^^^^
AttributeError: 'float' object has no attribute 'name'

Root cause

In complex_graph_rewrite.py, rewrite_subgraph_nodes (line ~216) defines match_complex_mul as:

def match_complex_mul(match, original_graph, pattern_graph) -> bool:
    for original_node in match.nodes_map.values():
        if original_node.name == node.name:   # ← crashes if value is a float
            return True
    return False

torch.fx.subgraph_rewriter.replace_pattern_with_filters passes ignore_literals=True, but match.nodes_map can still contain Python scalar values (floats, ints) that were captured as constants in the pattern. Accessing .name on a Python float raises AttributeError.

Fix

Guard the attribute access:

def match_complex_mul(match, original_graph, pattern_graph) -> bool:
    for original_node in match.nodes_map.values():
        if isinstance(original_node, torch.fx.Node) and original_node.name == node.name:
            return True
    return False

Environment

torch-tensorrt 2.10.0
torch 2.10.0+cu128
tensorrt 10.14.1.48.post1
CUDA 13.0
GPU NVIDIA GeForce RTX 4080
Python 3.12

Context

Encountered while compiling a SAM3 ViT image encoder (rotary position encoding uses view_as_complex; the attention scaling factor 1/sqrt(head_dim) introduces the float literal). The _patch_vit_rope_real workaround (replacing complex RoPE with equivalent real arithmetic) avoids this path entirely, but the crash should be fixed in the library.

Discovered and diagnosed by @robbysun with assistance from Claude Code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions