Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make exceptions from user code more readable #1460

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

apaz-cli
Copy link
Contributor

Code:

import thunder

def f1():
    raise ValueError

def f2():
    f1()

def f3():
    f2()

jfn = thunder.jit(f3)

jfn()

After:

⚡ ap-readable_exceptions ~/lightning-thunder python ti.py                       
Traceback (most recent call last):
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 14, in <module>
    jfn()
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/__init__.py", line 849, in _thunder_unwrap_inner_exception
    raise exc
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 10, in f3
    f2()
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 7, in f2
    f1()
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 4, in f1
    raise ValueError
ValueError

Before:

⚡ main ~/lightning-thunder python ti.py
Traceback (most recent call last):
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 14, in <module>
    jfn()
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/__init__.py", line 774, in wrapped
    return fn(*args, **kwargs)
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/__init__.py", line 824, in fn_
    cache_entry, inps, pro_to_epi = get_computation_and_inputs(*args, **kwargs)
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/__init__.py", line 756, in wrapped
    cache_entry, inps, pro_to_epi = get_computation_and_inputs_fn(*args, **kwargs)
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/core/langctxs.py", line 136, in _fn
    result = fn(*args, **kwargs)
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/__init__.py", line 236, in cache_info_wrapper
    res = fn(*args, **kwargs)
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/__init__.py", line 529, in get_computation_and_inputs
    jit_results: TraceResults = thunder_general_jit(
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/core/jit_ext.py", line 1744, in thunder_general_jit
    result = jfn(*args, **kwargs)
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/core/interpreter.py", line 7231, in fn_
    raise e
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/core/interpreter.py", line 7191, in fn_2
    return fn(*args, **kwargs)
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 10, in f3
    f2()
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 7, in f2
    f1()
  File "/teamspace/studios/this_studio/lightning-thunder/ti.py", line 4, in f1
    raise ValueError
ValueError

Copy link
Collaborator

@t-vi t-vi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @apaz-cli , the general idea seems OK, but we would

  • need a flag that gives the full traceback (register DebugOptions.interpreter_traceback),
  • need a test for both full traceback and reduced..
    Could you add these please?
    Also the code comments.

thunder/__init__.py Outdated Show resolved Hide resolved
Comment on lines +828 to +830
return co.co_filename.endswith("thunder" + os.sep + "core" + os.sep + "interpreter.py") and (
co.co_name in ("fn_", "fn_2")
)
Copy link
Collaborator

@t-vi t-vi Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Why just fn_ and fn_2 and not all of the methods in the interpreter?
  • Please don't use the filename/code object here. Instead check whether that is in f_globals of the frame has __name__ == 'thunder.core.interpreter'.

If we drop all interpreter methods, we likely want to keep internal frames at the top of the stacktrace.

Copy link
Contributor Author

@apaz-cli apaz-cli Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excluding everything in thunder.core.interpreter sounds good. I was trying to be conservative by default.

But using f_globals to do that instead of co_name doesn't work, because not every function has a f_globals with a __name__ in it. Certainly it would not work with some uses of the exec() lookaside. It also depends on how exactly the module is imported. There are a bunch of reasons why it doesn't work.

As for the functions filtered out by code object, those live outside of interpreter.py, in files that I don't want to exclude because some of their functions could be called by user code. And using the code objects is very convenient because it exactly matches the functions to exclude, and we wouldn't want to exclude all of thunder.__init__.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which functions we want to filter does not have an f_globals with __name__?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thunder_general_jit() does not. When I add an assertion that f_globals has a __name__, it fails.

ap-readable_exceptions ~/lightning-thunder python exctest.py 
Traceback (most recent call last):
  File "/teamspace/studios/this_studio/lightning-thunder/exctest.py", line 14, in <module>
    jfn()
  File "/teamspace/studios/this_studio/lightning-thunder/thunder/__init__.py", line 836, in _thunder_unwrap_inner_exception
    assert hasattr(tb.tb_frame.f_globals, "__name__"), tb.tb_frame.f_code.co_name
AssertionError: thunder_general_jit

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because f_globals is a mapping, so it's members, not attributes.

@@ -814,7 +814,50 @@ def maybe_call_epilogue(cache_entry, result, pro_to_epi):

return result

def unwrap_inner_exception(c: Callable) -> Callable:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this could live in the interpreter instead.

Copy link
Contributor Author

@apaz-cli apaz-cli Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function can. The unwrapping actually can't, tried that already. Traceback frames are pushed as the stack unwinds, not when the exception is thrown.

@apaz-cli
Copy link
Contributor Author

apaz-cli commented Nov 21, 2024

@t-vi I can't think of any situation where I would want to see the full traceback. This change is only triggered in situations where the exception comes from user code inside the interpreter.

If there's an interpreter bug where the path is relevant, this is not triggered. If there's a bug, then the bug is in their code, and not the interpreter, so the path through the interpreter is known to be irrelevant.

@t-vi
Copy link
Collaborator

t-vi commented Nov 22, 2024

Can you please add the flag to get the full traceback? Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants