EMLX.Application (emlx v0.3.0)

Copy Markdown View Source

OTP Application for EMLX.

Allocates the application-default EMLX.CommandQueue (one per device: :cpu and :gpu) at boot and stashes the NIF resource references in :persistent_term. These are the workers used by EMLX.eval/1 and EMLX.to_blob/1 for any process that has not bound its own queue via EMLX.CommandQueue.with_queue/2.

See clean-room-import/01-worker-thread-dispatch.md for the rationale behind :persistent_term instead of a GenServer + Registry.

Idempotency

start/2 is safe to call more than once (e.g. from an umbrella where :emlx is referenced by several apps). The first call to allocate a worker for a given device wins; subsequent calls observe the existing :persistent_term entry and skip. This matters because every :persistent_term.put/2 triggers a global GC scan across every process heap on the node — we do exactly two puts (CPU + GPU) over the BEAM's lifetime.

GPU absence

On platforms where MLX cannot allocate a GPU stream (e.g. Linux without Metal), EMLX.NIF.command_queue_new(:gpu) returns {:error, _} and this module silently skips the GPU worker. Subsequent EMLX.eval/1 calls on a GPU tensor will raise at use time with the underlying :persistent_term ArgumentError.

Summary

Functions

Returns the application-default EMLX.CommandQueue NIF resource for the given device.

Functions

default_worker(device)

@spec default_worker(:cpu | :gpu) :: reference()

Returns the application-default EMLX.CommandQueue NIF resource for the given device.

Raises ArgumentError if no worker has been allocated for the device (e.g. asking for :gpu on a system without Metal).

Never call :persistent_term.put/2 on the underlying key ({EMLX, :default_worker, device}) — overwriting a :persistent_term value triggers a node-wide GC.