docs / stdlib / xpu

Stdlib index
  1. Overview
  1. Captured-borrow migration worklist (3.3.3)
  2. Owned-bind migration worklist (8.2.7)
  3. Return-side title audit — the ride-through enumeration
  4. stdlib ownership audit
  5. stdlib ownership dispositions (plan 1.3.1 / 4.3.1)

aot

  1. Components
  2. Scope
  3. Scoped

codec

  1. Base32
  2. Base64

codec / csv

  1. Csv

codec / json

  1. Json

collection

  1. ArrayList
  2. BPlusTree
  3. Cache
  4. Collectors
  5. HashMap
  6. HashSet
  7. Heap
  8. ImmutableList
  9. ImmutableMap
  10. ImmutableSet
  11. LinkedList
  12. RedBlackTree
  13. Sort

collection / ltm

  1. LtmBPlusTree

concurrent

  1. AtomicInt32
  2. AtomicInt64
  3. Channel
  4. Fiber
  5. FiberLocal
  6. Lock
  7. Mutex
  8. RwLock
  9. Semaphore
  10. Tasks

error

  1. Exception
  2. NoOptionalValueException
  3. NotProvidedException
  4. RecoverableException
  5. ScopedBuildFailedException
  6. ScopeNotActiveException
  7. Throwable
  8. UnrecoverableException

gfx

  1. Sampler
  2. Texture2D

hash

  1. DefaultHasher
  2. Hash
  3. SipHash
  4. XXHash3

ifx

  1. BackendRegistry
  2. Window

io

  1. Buffer

io / file

  1. File
  2. FileInfo
  3. FileReader
  4. FileWriter
  5. Path
  6. Watcher

io / net

  1. BufferPool
  2. ByteBuffer
  3. IpAddress
  4. Server
  5. ServerBuilder
  6. SocketAddress
  7. TcpListener
  8. TcpStream
  9. UdpSocket

io / net / dns

  1. Dns

io / net / uri

  1. Uri
  2. UriBuilder

lang

  1. Guid
  2. Math
  3. Optional
  4. Pair
  5. Slice
  6. String
  7. StringBuilder

lang / stream

  1. ArrayStream
  2. Stream

math

  1. Camera
  2. Color
  3. DType
  4. Ray
  5. Rotation
  6. Tensor
  7. Transform

math / fft

  1. Fft

math / linalg

  1. LinAlg

math / npio

  1. Npy

math / poly

  1. Poly

math / random

  1. Generator

math / stats

  1. Stats

nucleo

  1. Columns — the Arrow-laid-out substrate
  2. Fused tensor expressions — Fuse
  3. Table — the lazy, typed dataframe
  4. Tape — define-by-run autograd
  5. Transform intrinsics — Grad, Vmap, Jit

process

  1. Command
  2. Process

reflect

  1. Class

search / distance

  1. Distance

search / fuzzy

  1. Matcher

search / ngram

  1. Index

session

  1. PackageInstallException
  2. Packages

time

  1. Clock
  2. DateTimeFormatter
  3. Duration
  4. Instant
  5. LocalDate
  6. LocalDateTime
  7. LocalTime
  8. Period
  9. ZonedDateTime
  10. ZoneId
  11. ZoneOffset

wire

  1. Compressor
  2. CompressStream
  3. DecompressionLimitException
  4. Decompressor
  5. Encoder
  6. Schema
  7. SchemaEncoder

xpu

  1. Device
  2. KernelBuffer
  3. KernelStream
  4. KernelTimer

xpu / mesh

  1. MeshSimplifier

KernelTimer

cajeta.xpu.KernelTimer — a per-kernel timer whose number can be stood behind. It brackets a KernelStream with two Events and reads the DEVICE’s own elapsed time between them (cuEventElapsedTime / hipEventElapsedTime), which ships with the driver: no profiler, no CUPTI, no toolkit. Every number comes with a tier that says what it means, and a timer that cannot measure answers -1 rather than guessing.

KernelStream s #= KernelStream.current();
KernelTimer t #= KernelTimer.create();
t.begin(s);
kernel.launch(s, grid: [g], block: [b])(args);
t.end(s);
int64 ns = t.elapsedNanos();                     // waits for the end event; -1 = refused
System.stdout.println(ns + " ns at tier " + KernelTimer.tierName());
if (!KernelTimer.withinPeak(ns, bytesMoved, Device.peakBandwidthGBps(), flops, peakFlops)) {
    // the measurement implies more than the hardware can do: do not report it
}
t.destroy();

Tiers

ConstanttierName()Meaning
TIER_DEVICE (2)deviceThe device measured it between two of its own events (CUDA, HIP; ~0.5 µs resolution). The bracket includes whatever the stream did between the records, launch latency included, so bracket several back-to-back launches when that matters.
TIER_HOST (1)hostThe stream is synchronous (CPU), so a host timestamp at each record is the stream’s tail exactly. Exact, but the host’s clock.
TIER_UNAVAILABLE (0)unavailableNo clock the timer can read (Vulkan). elapsedNanos() answers -1.

Methods

Signature
static #KernelTimer create()Two fresh events; the caller owns the timer and must destroy() it
void begin(KernelStream s)Record the start at the stream’s tail; re-arms the timer
void end(KernelStream s)Record the end at the stream’s tail
int64 elapsedNanos()Nanoseconds between the records on the backend’s clock, waiting for the end; -1 when begin or end was not recorded, the tier is unavailable, or the driver refused
void destroy()Release both events
static int32 tier()What a number means on the active backend
static String tierName()The tier as the word to print beside the number
static float64 clockScale()The factor the backend’s event clock runs fast by against the host clock, already divided out of elapsedNanos(); 1.0 for a correct driver, 0.0 when no usable clock
static float64 impliedGBps(int64 ns, int64 bytes)Bytes per nanosecond, which is GB/s
static float64 impliedOpsPerSecond(int64 ns, float64 ops)Operations per second
static boolean withinPeak(int64 ns, int64 bytes, float64 peakGBps, float64 ops, float64 peakOpsPerSecond)The standing assertion: ns positive and each declared work amount at or under its ceiling. A work amount with a zero ceiling is REFUSED, never waved through

The event clock’s scale

The driver’s conversion of device ticks to milliseconds has been measured wrong: on a WSL2 RTX 4090 (driver 610.62) two events around a 2 s host sleep with no kernel between them read 2.091 s, 4.56% fast. The timer’s first use on CUDA or HIP spends about 300 ms measuring that scale against the host clock around a BUSY bracket (device-to-device copies between the two records, the host clock spanning the same submissions to the synchronize) and divides it out of every figure; clockScale() reports it. Busy, because the earlier idle sleep-slope measurement read 1.046 in one process and 1.086 in the next on the same box and day (2026-09-24), a spread larger than the effect it corrects, and the timer is used around busy brackets; the busy bracket reads 1.045. A scale outside [0.5, 2] is refused and the tier reads unavailable.

Calibration

XpuKernelTimerTests spins a kernel on KernelThread.clock() for a stated number of SM cycles and checks the timer against Device.clockKHz(), the driver’s maximum clock: the spin cannot finish faster than that clock allows, and doubling the cycles must double the time within 10%. A second test checks the device timer against the host clock around a synchronised 20 ms launch. Read the RESULT lines of those tests on your part before quoting a figure.

See also

Source: docs/stdlib/xpu/KernelTimer.md · 3 min read · 649 words