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

feature: context manager for reservation arns #949

Closed
wants to merge 10 commits into from

Conversation

mbeach-aws
Copy link
Contributor

@mbeach-aws mbeach-aws commented Apr 11, 2024

feature: context manager for reservation arns

Issue #, if available:

Description of changes:
Adds a context manager that temporarily modifies the run method of a device object
to include a specified reservation_arn in all calls within the context. This is useful
for ensuring that all quantum task run within the context are associated with a given
reservation ARN (Amazon Resource Name).

Example usage

with reservation(device, reservation_arn="<my_reservation_arn>"):
    task1 = device.run(circuit, shots)
    task2 = device.run(circuit, shots)

Testing done:

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

General

Tests

  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have checked that my tests are not configured for a specific region or account (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@mbeach-aws mbeach-aws requested a review from a team as a code owner April 11, 2024 18:28
@mbeach-aws mbeach-aws force-pushed the reservation-context branch from ff8c616 to 0ca5c2f Compare April 11, 2024 18:30
Copy link

codecov bot commented Apr 11, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (53aba5e) to head (d3bf64e).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #949   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          134       136    +2     
  Lines         8911      8932   +21     
  Branches      2007      2010    +3     
=========================================
+ Hits          8911      8932   +21     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@mbeach-aws mbeach-aws assigned mbeach-aws and speller26 and unassigned mbeach-aws Apr 11, 2024
src/braket/reservations/reservations.py Outdated Show resolved Hide resolved

Args:
device (Device): The Braket device for which you have a reservation ARN.
reservation_arn (str | None): The Braket Direct reservation ARN to be applied to all
Copy link
Contributor

Choose a reason for hiding this comment

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

What would be the use case of this with no reservation arn?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So that a customer doesn't have to modify their code if they don't have an ARN. Example

def run_tasks(device, circuit, shots, reservation_arn=None):
    with Reservation(device, reservation_arn=reservation_arn) as reservation:
        task1 = device.run(circuit, shots)
        task2 = device.run(circuit, shots)
        return task1, task2

vs

def run_tasks(device, circuit, shots, reservation_arn=None):
    if reservation_arn is None:
        task1 = device.run(circuit, shots)
        task2 = device.run(circuit, shots)
        return task1, task2
    elif reservation_arn:
        with Reservation(device, reservation_arn=reservation_arn) as reservation:
            task1 = device.run(circuit, shots)
            task2 = device.run(circuit, shots)
        return task1, task2

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated to make reservation_arn required now, but its still allowed to be None.

Co-authored-by: Abe Coull <85974725+math411@users.noreply.github.com>
src/braket/reservations/reservations.py Outdated Show resolved Hide resolved


@contextmanager
def Reservation(device: Device, reservation_arn: str | None = None) -> Device | None:
Copy link
Member

Choose a reason for hiding this comment

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

Lower case, since this isn't a class; also just take an AwsDevice instead of Device

Comment on lines 46 to 53
if not isinstance(device, Device):
raise ValueError("The provided device is not a valid Braket device.")

# Local simulators do not accept reservation ARNs
if isinstance(device, LocalSimulator) or device.type == AwsDeviceType.SIMULATOR:
yield device

elif isinstance(device, AwsDevice):
Copy link
Member

Choose a reason for hiding this comment

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

I'd rearrange as

if isinstance(device, AwsDevice):
    ...
elif isinstance(device, Device):
    ...
raise TypeError(...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does the API allow reservation arns for simulators? I'm not sure now

Co-authored-by: Cody Wang <speller26@gmail.com>
modification.

Examples:
>>> with Reservation(device, reservation_arn="<my_reservation_arn>"):
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor nit: can you also add an example of this used as a decorator?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

interesting, I did not know the context could also be a decorator. Why don't we also have Tracker available as a decorator?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would have to ask around for why that was not the case. Could be that the functionality in contextmanager was not known at the time.



@contextmanager
def reservation(device: Device, reservation_arn: str | None) -> Device | None:
Copy link
Contributor

Choose a reason for hiding this comment

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

When customers use reservations, do they only do it for specific portions of their code or would they typically have the entire script using reservation arns? How would that affect the UX we expose here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

do they only do it for specific portions of their code or would they typically have the entire script using reservation arns?

They are only required to pass reservation arns to their quantum tasks. Hence this wrapper makes it easier to add the require kw args to their tasks without manually modifying every single task.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to make this less intrusive and more agnostic?

try:
yield device
finally:
device.run = original_run
Copy link
Contributor Author

Choose a reason for hiding this comment

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

do I need to also modify "run_batch? or is just "run" sufficient?

Comment on lines +24 to +26
@contextmanager
def reservation(device: Device, reservation_arn: str | None) -> Device | None:
"""
Copy link
Contributor Author

Choose a reason for hiding this comment

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

given this takes a Device, I'm not sure how to make it work with a qiskit-braket BraketAwsBackend, or even pennylane qml.device.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is usually an indicator that there might be an opportunity to work at a different abstraction. Would it help if we moved this functionality to a different abstraction?

@mbeach-aws
Copy link
Contributor Author

closing to make sure qiskit/PL is supported

@mbeach-aws mbeach-aws closed this Apr 15, 2024
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.

4 participants