Swift · Arenas

Arenas

import UForm 4.0.0-rc.1 · 3ee5e534

Every output whose length scales with the call - pooled embeddings, per-token states and their offsets - lands in an Arena you pass, and the verb answers views over it without copying. There is one verb per operation: no allocating twin, no caller buffers, and no default arena. Arena(on: executor) places it where that executor computes, decided once, and Arena() makes host pages for the calling thread. Each call rewinds its arena, so the previous call’s views die and a steady loop allocates once it reaches its high-water mark. Reading a stale view traps, as an out-of-bounds index does; to keep a result past the next call, pass that call another arena. An arena serves one call at a time, so each deferred call needs its own, and a call naming an arena another call holds finishes contended. An arena from a VRAM executor holds device memory, which host accessors refuse with a trap.

let arena = try Arena(on: executor)
for batch in batches {
    let encoded = try model.on(executor).textEncode(batch, arena: arena) // rewinds: the last batch's rows are gone
    index.add(encoded.embeddings!)
}
let calls = try zip(shards, arenas).map { shard, arena in
    try model.deferred(executor).imageEncode(shard, arena: arena)        // one arena per submitted call
}
for call in calls { consume(try await call.value) }                      // or: try call.wait()

A result keeps the arena it reads alive, so it outlives the model and the caller’s reference alike.

API

ClassArenaMemory the library writes every output whose length scales with a call into, reused across calls so a steady loop allocates once.1
Types.swift:740 ↗
final class Arena

Every output verb requires one and answers views reading it in place. Each call given the arena rewinds it, so the views an earlier call answered stop reading: any read of them traps, as an out-of-bounds index does. To keep a result past the next call, give that call another arena. An arena serves one call at a time, deferred ones included, and a call naming it while another holds it is refused with contended.

initMakes an arena where executor computes, host pages or its GPU's memory, decided once; nil makes host pages for calls on the calling thread.
Types.swift:750 ↗
init(on executor: Executor? = nil) throws(UFormError)

Calls uform_arena_init.