Implement Time-Aware GPU Credit Ledger
OpenAISoftware Engineer · Technical ScreenLast updated
Design an in-memory credit ledger that tracks GPU compute grants with expiration timestamps, consumes credits greedily by earliest expiration, and supports atomic deductions.
Problem Statement
AI compute platforms often issue GPU credits with varying expiration dates (e.g., promotional grants, monthly subscription allowances, and reserved instance buffers). When a user runs a workload, credits should be deducted from grants that expire the earliest to prevent premature expiration waste.
Implement the CreditLedger class to manage time-aware GPU credit balances:
__init__(): Initializes the ledger with no credits.add_grant(grant_id: str, amount: int, expire_at: int) -> None: Adds a grant ofamountcredits that remains valid for timestampst bool: Attempts to consumeamountcredits attimestamp. Credits must be drawn from valid (unexpired) grants prioritizing the ones with the earliestexpire_at. If the total valid credits attimestampis less thanamount, the transaction fails atomically (no credits are deducted) and returnsFalse. Otherwise, credits are deducted and it returnsTrue.get_balance(timestamp: int) -> int: Returns the total amount of unexpired credits available attimestamp.
Note: Calls to consume and get_balance are guaranteed to have monotonically non-decreasing timestamps (timestamp_{i} >= timestamp_{i-1}).
Interface
class CreditLedger:
def __init__(self):
pass
def add_grant(self, grant_id: str, amount: int, expire_at: int) -> None:
pass
def consume(self, timestamp: int, amount: int) -> bool:
pass
def get_balance(self, timestamp: int) -> int:
pass
Examples
Example 1
ledger = CreditLedger()
ledger.add_grant("g1", 100, 50) # 100 credits expiring at t=50
ledger.add_grant("g2", 50, 30) # 50 credits expiring at t=30
# At t=10, consume 80 credits.
# Priority goes to g2 (expires at 30). Takes 50 from g2 and 30 from g1.
assert ledger.consume(10, 80) == True
# Remaining: 70 credits in g1 expiring at 50.
assert ledger.get_balance(20) == 70
# At t=40, g1 is still valid (40 < 50).
assert ledger.consume(40, 70) == True
assert ledger.get_balance(45) == 0
Example 2
ledger = CreditLedger()
ledger.add_grant("g1", 50, 20)
# At t=20, g1 has expired (valid only for t < 20).
assert ledger.get_balance(20) == 0
assert ledger.consume(20, 10) == False
Constraints
1 <= amount <= 10^91 <= timestamp, expire_at <= 10^14grant_idis a unique non-empty alphanumeric string.- Timestamps in
consumeandget_balanceare monotonically non-decreasing. - Up to
2 * 10^5calls across all methods.
Edge Cases
- Grants added with
expire_at <= current_time. - A
consumerequest exceeding available balance should not alter any grant balances. - Multiple grants having identical
expire_attimestamps.
Hints
Hint 1
Because query timestamps are non-decreasing, expired grants can be pruned lazily using a min-heap ordered by expiration timestamp.
Hint 2
Maintain a running sum of active credits so that `get_balance` and the sufficiency check in `consume` can run in O(1) time after pruning expired grants.
Hint 3
For atomic deductions, verify that `total_active_credits >= amount` before mutating or popping grants from your active heap.
Follow-up questions
- How would your design change if queries could arrive out-of-order with arbitrary timestamps instead of monotonically non-decreasing timestamps?
- How would you support concurrent readers and writers while maintaining atomicity and thread safety?
- If grants also supported an `effective_from` timestamp (where credits cannot be used before `effective_from`), what data structure would you use?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.