AI Infra Interviews logo
Coding for Infra / 03
easy★ EssentialNewOpenAICoreWeave

Given per-GPU idle intervals, compute when any GPU was idle and when every GPU was idle. Write both.

The union is a sort and a scan. The intersection is the same sweep with a counter, and it is the one that goes wrong, because a single GPU reporting overlapping intervals will be counted twice and produce an answer that looks plausible. Both implementations, the trap, and the tests that catch it.

Updated Sep 2026 · Grounded in real AI infrastructure interview loops and written to a senior-engineer editorial bar, with every number worked and every diagram hand-built.

TL;DR: The union, meaning any GPU idle, is the classic merge: sort by start, and extend the current interval whenever the next one starts at or before the current end. The intersection, meaning every GPU idle, is a sweep line: emit a plus-one event at each interval start and a minus-one at each end, sort, walk them keeping a running count, and record the spans where the count equals the number of GPUs. The trap is that a single GPU can report overlapping intervals, and each one contributes its own plus-one, so that GPU alone can push the counter to the threshold and the answer will include times when only one GPU was idle. The fix is one line: merge each GPU's own intervals before generating events. The other decision to make explicitly is whether touching intervals, where one ends exactly as the next begins, count as continuous, and the answer depends on whether the endpoints are inclusive, which is a question to ask rather than assume.

How to approach it

Do the union first because it is short and it establishes the sorting idea. Then the intersection as a sweep, and immediately name the double-counting trap, because it is the whole difficulty and an implementation that ignores it produces wrong answers that look right. State the touching-interval question as a question. Close with the tests, which are all boundary cases.

A strong answer

A typical situation: a capacity report says the fleet had two hours a day when every GPU was simultaneously idle, and a proposal to run batch work in those windows is built on it. The intervals came from a monitoring system that emits an interval per sample window, so consecutive samples produce adjacent and sometimes overlapping intervals for the same GPU, and the counter was reaching the threshold on one GPU's samples alone.

The union:

def merge(intervals):
    """Union: the times when at least one interval covers the point."""
    if not intervals:
        return []
    xs = sorted(intervals)                 # by start, then end
    out = [list(xs[0])]
    for s, e in xs[1:]:
        if s <= out[-1][1]:                # <= treats touching as continuous
            out[-1][1] = max(out[-1][1], e)
        else:
            out.append([s, e])
    return [tuple(x) for x in out]

The intersection:

def intersect_all(per_gpu):
    """Times when EVERY GPU is idle. per_gpu is a list of interval lists, one per GPU."""
    n = len(per_gpu)
    if n == 0:
        return []
    events = []
    for gpu in per_gpu:
        for s, e in merge(gpu):            # <- merge each GPU first, or it double-counts
            events.append((s, 1))
            events.append((e, -1))
    events.sort(key=lambda x: (x[0], -x[1]))   # at equal time, starts before ends
    out, active, start = [], 0, None
    for t, d in events:
        prev = active
        active += d
        if prev < n <= active:             # count reached all GPUs
            start = t
        elif prev >= n > active:           # count dropped below
            if start is not None and t > start:
                out.append((start, t))
            start = None
    return out

Running both on a three-GPU example with a deliberate overlap inside one GPU:

per-GPU idle
  GPU 0: [(0, 10), (20, 30)]
  GPU 1: [(5, 25)]
  GPU 2: [(0, 8), (7, 12), (22, 40)]     <- overlapping intervals from one source

GPU 2's own intervals merge first: [(0, 12), (22, 40)]
ANY idle (union):        [(0, 40)]
ALL idle (intersection): [(5, 10), (22, 25)]

checking by hand
  [0,10] and [5,25] and [0,12]  ->  [5,10]
  [20,30] and [5,25] and [22,40] ->  [22,25]
touching intervals [(0,5),(5,10)] merge to: [(0, 10)]
one GPU with no idle intervals at all:      []

Without the per-source merge, GPU 2's overlapping pair at (0,8) and (7,12) both contribute a plus-one, so between 7 and 8 the counter reads 4 rather than 3 on a three-GPU fleet. With a threshold of 3, that interval is emitted even when GPU 0 or GPU 1 is busy. The bug produces extra intervals rather than missing ones, so the result looks generous and plausible, which is why it survives review.

Interval Merging and Utilization Logs covers the wider pattern, including how allocation events become intervals in the first place.

rendering diagram…

The three decisions to make explicitly:

1. are endpoints inclusive?
   with inclusive endpoints, [0,5] and [5,10] touch and should merge into [0,10]
   with half-open [0,5) and [5,10), they are adjacent and merging them is still correct for
     a union but the boundary handling differs
   the code above uses <= in the merge and sorts starts before ends, which treats touching as
     continuous. That is a choice, and it should be stated rather than discovered

2. what does a zero-length interval mean?
   the intersection guard `t > start` drops them, which is right for "when was everything
     idle" and wrong if a zero-length event is meaningful in the data model

3. what if a GPU has no intervals at all?
   it was never idle, so the intersection is empty. The code gets this right because that GPU
     contributes no events and the counter never reaches n. Worth a test, because an
     implementation that iterates only over GPUs with events silently drops the constraint

Complexity and scale:

union         O(m log m) for m intervals, dominated by the sort
intersection  O(m log m) likewise, one sort of 2m events
memory        O(m) for the events

at fleet scale
  16,384 GPUs sampled every minute over a day = 16,384 x 1,440 = 23.6 million intervals
  merging each GPU's own first reduces this substantially, since consecutive idle samples
    collapse into one interval
  if the raw stream is too large for memory, the same sweep works streaming, since events can
    be produced in time order per source and merged with a heap
sanity: a day of per-minute samples across a large fleet is tens of millions of intervals,
        which sorts in seconds and does not need anything cleverer than this

The reversal condition: the intersection over every GPU is rarely the question anyone actually wants. "When was the whole fleet idle" is almost never true on a busy cluster and is not useful when it is. The questions that get asked are "when were at least k GPUs idle", which is the same sweep with the threshold changed from n to k, and "how many GPU-hours were idle in total", which is a simpler sum over merged per-GPU intervals. Both fall out of the same code, and asking which one is wanted before writing is worth more than the implementation, which is the habit The Practical Coding Screen Playbook is built around.

What interviewers probe next

  • "Change it to at least k idle." One character: compare the count against k rather than n. That generality is why the sweep is the right structure.
  • "What if intervals arrive unsorted and streaming?" Sort per source, then merge the per-source event streams with a heap, which keeps memory bounded by the number of sources rather than by the number of intervals.
  • "How do you handle open-ended intervals?" A GPU idle at the end of the window has no end event; substitute the window's end so the sweep terminates, and document that the last interval is truncated.
  • "What about float timestamps?" Comparisons are exact enough for ordering, but equality at boundaries becomes fragile; integers, typically epoch milliseconds, avoid it entirely.

Common mistakes

  • Not merging each source's intervals first, which double-counts and produces extra intersections that look plausible.
  • Sorting ends before starts at equal times, which closes an interval a moment before reopening it and produces spurious splits.
  • Ignoring GPUs with no intervals, which drops a constraint and over-reports.
  • Assuming touching intervals should or should not merge without asking which the data model means.

Key takeaways

  • Union: sort by start and extend while the next start is at or before the current end.
  • Intersection: sweep plus-one and minus-one events with a counter, and record spans where the count equals the number of sources.
  • Merge each source's own intervals before generating events, or one source's overlapping samples reach the threshold alone.
  • Both are O(m log m); 23.6 million intervals from a day of per-minute samples across 16,384 GPUs sorts in seconds.
That one was free — and so are 10 answers per topic without an account. Signing in doubles that to 20, opens the Plus lessons in the courses, and remembers which topics you keep getting wrong.no card · Google sign-in · nothing to cancel
HOW DID IT GO?
0
READING SIGNED OUT

Signing in doubles your free answers, from 10 to 20 per topic, and the site starts remembering you: mastery per topic, bookmarks, and a next-focus recommendation. Free, no card.

Sign in free

The concepts behind this question

Ranked by how closely each one overlaps this question's topic, so the first card is the thing to read if the answer above moved too fast.

Advanced
💻 Coding for Infra🔒 Premium
Interval Merging and Utilization LogsGiven busy intervals per GPU, when was the whole cluster idle? What was the utilization per hour from a log of start and stop events? Which jobs overlapped? These are the interval problems of the infrastructure coding screen, and they share one tool: sort the endpoints and sweep. The sweep line turns every variant into a single pass with a counter, the sort is the only thing that costs more than linear time, and the edge cases (touching intervals, zero-length events, an unterminated start) are where candidates lose the round. This page works the standard problem and its relatives with code, tests and the complexity derivation.
Advanced
💻 Coding for Infra🔒 Premium
Batching Queues and BackpressureWrite a request batcher is the coding round's version of the serving engine's scheduler: requests arrive one at a time, the GPU wants them in groups, and the batcher decides when a group is full enough to send without holding anyone too long or accepting more than it can hold. The two knobs are the maximum batch size and the maximum wait, the invariant is a bounded queue, and the follow-ups (priorities, cost-aware batching, cancellation, bounded in-flight batches) are the ideas the real engines carry. This page implements the batcher in asyncio, derives what each knob buys, and walks the follow-ups.
Foundational
💻 Coding for Infra
The GPU Credit Scheduler PatternThe most widely reported coding problem in AI infrastructure loops is a small scheduler: accounts hold credits, jobs arrive with a cost and a priority, and you must decide which jobs run, in what order, without letting any account overspend, then extend it under follow-ups (refunds, reservations, concurrency limits, fairness). It is not a trick question; it is a test of whether you can model state cleanly, pick the right data structures, keep invariants under mutation, and talk about complexity while typing. This page works the problem from the first line to the fourth follow-up, with the code, the invariants, and the derivations.
Core
💻 Coding for InfraSign in
Retry, Backoff and IdempotencyA retry is a second request that the system did not budget for, and a thousand clients retrying at the same moment is a second outage that the first one caused. The craft is small and specific: retry only what is safe to retry, wait an exponentially growing random interval so the retries spread out, cap the total retries with a budget, and make every retried operation idempotent so a duplicate does not double-charge or double-train. This page derives why synchronized retries double the load, works the jitter arithmetic, implements the client correctly, and covers idempotency keys for the operations an AI platform exposes.
UP NEXT ON YOUR JOURNEY
FEDITOR'S NOTE

Scored on the sweep-line with a counter for the intersection, on merging each source's own intervals first to avoid double counting, and on the touching-versus-overlapping boundary decision.

DISCUSSION · 0

No comments yet — be the first to share your approach.