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: Support for Braket Direct Reservations #87

Merged
merged 19 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/device.jl
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,70 @@ function get_devices(; arns::Vector{String}=String[], names::Vector{String}=Stri
end
return sort(collect(values(device_map)), by=(x->getproperty(x, Symbol("_"*order_by))))
end

"""
DirectReservation(device::Union{Device, String, Nothing}, reservation_arn::Union{String, Nothing})

A context manager that adjusts AwsQuantumTasks generated within the context to utilize a reservation ARN
Copy link
Member

Choose a reason for hiding this comment

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

Why no doc link here for AwsQuantumTask?

for all tasks targeting the designated device. Notably, this manager permits only one reservation
at a time.

[Reservations](https://docs.aws.amazon.com/braket/latest/developerguide/braket-reservations.html)
are specific to AWS accounts and devices. Only the AWS account that initiated the reservation
can utilize the reservation ARN. Moreover, the reservation ARN is solely valid on the
reserved device within the specified start and end times.

Arguments:
- device (Device | String | Nothing): The Braket device for which you possess a reservation ARN, or
Copy link
Member

Choose a reason for hiding this comment

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

Device here can also use a doc link

alternatively, the device ARN.
- reservation_arn (String | Nothing): The Braket Direct reservation ARN to be implemented for all
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't match the actual struct field types

quantum tasks executed within the context.
"""
mutable struct DirectReservation
device_arn::String
reservation_arn::String
is_active::Bool
end

DirectReservation(device_arn::String, reservation_arn::String) = DirectReservation(device_arn, reservation_arn, false)

# Start reservation function
function start_reservation!(state::DirectReservation)
if state.is_active
error("Another reservation is already active.")
Copy link
Member

Choose a reason for hiding this comment

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

Why not include the reservation_arn in this error message?

end
state.is_active = true
ENV["AMZN_BRAKET_RESERVATION_DEVICE_ARN"] = state.device_arn
ENV["AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN"] = state.reservation_arn
end

# Stop reservation function
function stop_reservation!(state::DirectReservation)
if !state.is_active
@warn "Reservation is not active."
end
state.is_active = false
if haskey(ENV, "AMZN_BRAKET_RESERVATION_DEVICE_ARN")
delete!(ENV, "AMZN_BRAKET_RESERVATION_DEVICE_ARN")
end
if haskey(ENV, "AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN")
delete!(ENV, "AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN")
end
end

function direct_reservation(reservation::DirectReservation, func::Function)
env_vars = Dict(
"AMZN_BRAKET_RESERVATION_DEVICE_ARN" => reservation.device_arn,
"AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN" => reservation.reservation_arn
)
withenv(pairs(env_vars)...) do
start_reservation!(reservation)
try
func()
Fe-r-oz marked this conversation as resolved.
Show resolved Hide resolved
catch e
error("Error during reservation with device ARN $(reservation.device_arn): $(e)")
Copy link
Member

Choose a reason for hiding this comment

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

Why not show the reservation ARN in this error message as well?

finally
stop_reservation!(reservation)
end
end
end
54 changes: 54 additions & 0 deletions test/integ_tests/direct_reservations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Braket, Test, Mocking, JSON3, Dates, Graphs
using Braket: status
Mocking.activate()

# Constants
RESERVATION_ARN = "arn:aws:braket:us-east-1:123456789:reservation/uuid"
DEVICE_ARN = "arn:aws:braket:us-east-1:123456789:device/qpu/ionq/Forte-1"

@testset "DirectReservation Tests" begin
# Creating a DirectReservation
@testset "Creating DirectReservation" begin
reservation = Braket.DirectReservation(DEVICE_ARN, RESERVATION_ARN)
@test reservation.device_arn == DEVICE_ARN
@test reservation.reservation_arn == RESERVATION_ARN
@test reservation.is_active == false
end

# Starting and stopping a reservation
@testset "Starting and Stopping Reservation" begin
reservation = Braket.DirectReservation(DEVICE_ARN, RESERVATION_ARN)

# Start reservation
Braket.start_reservation!(reservation)
@test reservation.is_active == true
@test ENV["AMZN_BRAKET_RESERVATION_DEVICE_ARN"] == DEVICE_ARN
@test ENV["AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN"] == RESERVATION_ARN

# Stop reservation
Braket.stop_reservation!(reservation)
@test reservation.is_active == false
@test !haskey(ENV, "AMZN_BRAKET_RESERVATION_DEVICE_ARN")
@test !haskey(ENV, "AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN")

end

function test_func()
println("Executing within reservation context")
return 5
# Add actions as needed
@test ENV["AMZN_BRAKET_RESERVATION_DEVICE_ARN"] == DEVICE_ARN
@test ENV["AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN"] == RESERVATION_ARN
end

@testset "Direct Reservation Function" begin
reservation = Braket.DirectReservation(DEVICE_ARN, RESERVATION_ARN)
@test Braket.direct_reservation(reservation, test_func) == 5
end

@testset "Invalid Device Type" begin
invalid_device = 12345 # Not a valid device type
@test_throws UndefVarError DirectReservation(invalid_device, RESERVATION_ARN)
end

end
1 change: 1 addition & 0 deletions test/integ_tests/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ s3_destination_folder = Braket.default_task_bucket()
include("adjoint_gradient.jl")
include("create_local_quantum_job.jl")
include("create_quantum_job.jl")
include("direct_reservations.jl")
include("job_macro.jl")
include("measure.jl")
include("cost_tracking.jl")
Expand Down