Skip to content

Commit 594238d

Browse files
bhimrazyclaude
andcommitted
Write a placeholder for repro inputs that have no source form
Accepting a FakeScriptObject as its own example-input metadata let a graph taking a DeviceMesh reach the reproducer writer, where arg_like raised TypeError: it only knew how to write tensors, numbers and sequences. A DeviceMesh has no source form to write down -- it needs a live process group -- so there is nothing arg_like could emit that would run. Write None for it, and for an input that could not be inferred, which is what the warning above the input list already promises. The script is then one the reader can finish rather than one that cannot be generated at all. That warning was being built and then dropped: the non-serialized branch assigned over input_str instead of appending to it, so the holes arrived unexplained. Append, and raise the warning for a FakeScriptObject too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 101ca06 commit 594238d

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

thunder/dynamo/report.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import shutil
1414

1515
import torch
16+
from torch._library.fake_class_registry import FakeScriptObject
1617
from thunder.core.pytree import tree_flatten
1718
from thunder.core.utils import sequencify, create_python_callable_from_bsym
1819
from thunder.dynamo.compiler import thunderfx, ThunderCompiler
@@ -210,7 +211,12 @@ class FXGraphReport:
210211
reproduction and benchmarking scripts for various executors.
211212
"""
212213

213-
def __init__(self, graph: torch.fx.GraphModule, graph_name: str, example_input_meta: list[ExampleInputMetaData]):
214+
def __init__(
215+
self,
216+
graph: torch.fx.GraphModule,
217+
graph_name: str,
218+
example_input_meta: list[ExampleInputMetaData | FakeScriptObject],
219+
):
214220
if LooseVersion(torch.__version__) < LooseVersion("2.6.0"):
215221
# NOTE: PyTorch 2.6 changes the structure of GraphModule for higher order ops.
216222
# In newer torch version the higher order ops are nested as submodules within the module that uses them,
@@ -293,15 +299,15 @@ def write_inductor_repro(self, folder, use_benchmark: bool = False, serialize_in
293299

294300
def _get_input_str(self, folder, inputs, serialize_inputs):
295301
input_str = ""
296-
if any(arg is None for arg in inputs):
302+
if any(arg is None or isinstance(arg, FakeScriptObject) for arg in inputs):
297303
input_str += "# Warning: The inputs that cannot be inferred are set to None, requiring the user to manually give inputs according to the code\n"
298304
if serialize_inputs:
299305
example_inputs = self.make_example_inputs()
300306
input_file_name = folder / f"{self.graph_name}_inputs.pt"
301307
torch.save(example_inputs, input_file_name)
302308
input_str += f"{INPUTS_NAME} = torch.load('{input_file_name}')\n"
303309
else:
304-
input_str = f"{INPUTS_NAME} = [\n"
310+
input_str += f"{INPUTS_NAME} = [\n"
305311
input_str += textwrap.indent("\n".join(arg_like(a) for a in inputs), " ")
306312
input_str += "\n]"
307313
return input_str

thunder/dynamo/utils.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class SubgraphInfo:
148148
original_split_graph_module: torch.fx.GraphModule | None
149149
split_graph_module: torch.fx.GraphModule | None
150150
thunder_compiled_fns: list[Callable] | None
151-
thunder_compiled_fns_example_inputs: list[list[ExampleInputMetaData]] | None
151+
thunder_compiled_fns_example_inputs: list[list[ExampleInputMetaData | FakeScriptObject]] | None
152152
submodule_to_compiled_functions: dict[torch.fx.GraphModule, CompiledFunction]
153153
split_reasons: list | None = None
154154

@@ -875,6 +875,11 @@ def arg_like(arg: Any):
875875
return "[" + "".join(arg_like(a) for a in arg) + "],"
876876
elif isinstance(arg, (int, bool, float)):
877877
return f"{arg},"
878+
elif arg is None or isinstance(arg, FakeScriptObject):
879+
# Nothing here has a source form to write down: a DeviceMesh needs a live process group,
880+
# and a placeholder we could not infer is already None. Leave a hole for the reader to
881+
# fill, which is what the warning _get_input_str puts above the inputs promises.
882+
return "None,"
878883
else:
879884
raise TypeError(f"Unsupported input type: {type(arg)}")
880885

0 commit comments

Comments
 (0)