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
Implement qml.breakpoint()
and initial integration with Pdb
#5600
base: master
Are you sure you want to change the base?
Conversation
Hello. You may have forgotten to update the changelog!
|
[sc-62243] |
Open Questions:
|
qml.breakpoint()
and initial integration with Pdb
qml.breakpoint()
and initial integration with Pdb
Args: | ||
dev (Union[Device, "qml.devices.Device"]): The active device | ||
""" | ||
cls.__active_dev.append(dev) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So devices are add-only, not not selectively removed --- as in, we expect them to be appended, and reset the entire list to remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes exactly! In fact, instead of appending, we could probably just override the 1st entry in the list each time, since there shouldn't be more than one "active device" at a time.
PLDB.valid_context() # Ensure its being executed in a valid context | ||
|
||
debugger = PLDB() | ||
debugger.set_trace(sys._getframe().f_back) # pylint: disable=protected-access |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this always guaranteed to work? What happens if I do this from the CLI versus a Jupyter notebook cell --- is the correct frame used in both cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it works for the CLI and from within a Jupyter-notebook cell. Not sure if it will work with other interactive python sessions.
if PLDB.is_active_dev(): | ||
PLDB.reset_active_dev() | ||
|
||
PLDB.add_device(self.device) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a quick check, but this setup shouldn't have any problem with concurrent execution, right? If we in parallel create 2 qnodes with 2 devices, what happens here if they try to modify the class at the same time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They will most definitely clash! I definitely think this feature should not be used with concurrent execution, I don't know if a user would ever want to actually debug the circuit for 2 qnodes concurrently?
I based this implementation on how the Queuing manger is structured, how does that correspond with concurrent execution
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #5600 +/- ##
==========================================
- Coverage 99.68% 99.68% -0.01%
==========================================
Files 412 412
Lines 38666 38447 -219
==========================================
- Hits 38545 38325 -220
- Misses 121 122 +1 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Jaybsoni!
class PLDB(pdb.Pdb): | ||
"""Custom debugging class integrated with Pdb.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To confirm, this isn't something users would typically interact with?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes exactly! We don't want the user calling the PLDB class at all. In the same way we wouldn't want them to interact with the QueuingManager
class for example.
|
||
|
||
def breakpoint(): | ||
"""Launch the custom PennyLane debugger.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the plan with docs here - normally PRs should have detailed docs, especially for major user-facing functions like this. Though if we have a story to track a subsequent docs revisit and polish, I'm fine with that too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a story to revisit the docs and polish. I will add a little more detail to the breakpoint docs in this PR, but once all of the functionality (measuring states, queuing gates in debug mode, etc.) are added in the subsequent PRs, then we can finalize its docstring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor point that we can discuss in a docs PR:
We don't have a quickstart (.rst) for debugging
yet. And it doesn't seem like we make quickstarts for any of the high level files in the pennylane
folder. Maybe there's a question here about whether debugging functionality should go in pennylane/debugging.py
or in pennylane/debugging/debugging.py
Context:
Part of the effort to add more tools for algorithmic debugging of quantum circuits with PennyLane. In this PR we introduce the
qml.breakpoint()
function which allows users to insert breakpoints into their quantum workflow and enter a debugging context (via Pdb) to step through their quantum functions.Description of the Change: