TFLiteElixir.LiteRT.CompiledModel.Isolated (tflite_elixir v1.0.1)

Copy Markdown View Source

A compiled model on a node of its own, so that a crash inside the runtime costs one node instead of yours.

Everything under this binding is native code, and native code that segfaults takes the whole VM with it regardless of how carefully the Elixir above it is written. Where that is unacceptable, this puts the model on a separate BEAM node and forwards calls to it:

{:ok, model} = TFLiteElixir.LiteRT.CompiledModel.Isolated.start_link(
                 model_path: path, accelerators: [:cpu, :gpu])
{:ok, outputs} = TFLiteElixir.LiteRT.CompiledModel.Isolated.run(model, inputs)

The far side is an ordinary TFLiteElixir.LiteRT.CompiledModel.Server, so the calls are the same ones; only the wire is different. When the node dies the calls answer {:error, "the isolated model is no longer there"} rather than hanging or taking the caller down.

What it costs

Every input and every output crosses the distribution link, which for image sized tensors is not free, and the node takes a moment to start. Reach for it when a crash must not be fatal, not by default.

Distribution is started if it is not already up, because a library should not insist the caller arranged that in advance.

Summary

Functions

Whether the accelerator took the whole graph.

As fully_accelerated/1, answering false rather than an error.

The byte size of each input and output tensor, as {inputs, outputs}.

Raising version of io_sizes/1.

The node the model is running on.

Raising version of node_of/1.

How many profiling events are waiting, without reading them.

Every profiling event recorded so far.

The most recent limit profiling events, or all of them when zero.

Raising version of profile/1.

Raising version of profile/2.

Forget the events recorded so far and keep recording.

Run the model over a list of input binaries.

Run the model, waiting at most timeout.

Raising version of run/2.

Raising version of run/3.

Run the model and collect whatever counters the accelerator reports.

Start one outside a supervision tree.

As start/1, with options for the gen_server itself.

Start a model on a node of its own, linked to the caller.

As start_link/1, with options for the gen_server itself.

Stop the model and the node it is on.

Per-operator totals over every run since the last reset, slowest first.

Run a function against the compiled model, on the node that owns it.

As with/2, waiting at most timeout.

Types

opts()

@type opts() :: [
  model_path: String.t(),
  runtime_library_dir: String.t(),
  accelerators: [TFLiteElixir.LiteRT.CompiledModel.accelerator()],
  precision: TFLiteElixir.LiteRT.CompiledModel.precision(),
  profile: boolean(),
  signature: non_neg_integer() | String.t(),
  max_model_bytes: non_neg_integer(),
  max_queue: non_neg_integer(),
  peer_args: [String.t()]
]

Functions

fully_accelerated(model)

@spec fully_accelerated(pid()) :: {:ok, boolean()} | {:error, String.t()}

Whether the accelerator took the whole graph.

fully_accelerated!(model)

Raising version of fully_accelerated/1.

fully_accelerated?(model)

@spec fully_accelerated?(pid()) :: boolean()

As fully_accelerated/1, answering false rather than an error.

io_sizes(model)

@spec io_sizes(pid()) ::
  {:ok, {[non_neg_integer()], [non_neg_integer()]}} | {:error, String.t()}

The byte size of each input and output tensor, as {inputs, outputs}.

io_sizes!(model)

Raising version of io_sizes/1.

node_of(model)

@spec node_of(pid()) :: {:ok, node()} | {:error, String.t()}

The node the model is running on.

node_of!(model)

Raising version of node_of/1.

pending_events(model)

@spec pending_events(pid()) :: {:ok, non_neg_integer()} | {:error, String.t()}

How many profiling events are waiting, without reading them.

pending_events!(model)

Raising version of pending_events/1.

profile(model)

@spec profile(pid()) ::
  {:ok, [TFLiteElixir.LiteRT.CompiledModel.event()]} | {:error, String.t()}

Every profiling event recorded so far.

profile(model, limit)

@spec profile(pid(), non_neg_integer()) ::
  {:ok, [TFLiteElixir.LiteRT.CompiledModel.event()]} | {:error, String.t()}

The most recent limit profiling events, or all of them when zero.

profile!(model)

Raising version of profile/1.

profile!(model, limit)

Raising version of profile/2.

reset_profile(model)

@spec reset_profile(pid()) :: :ok | {:error, String.t()}

Forget the events recorded so far and keep recording.

reset_profile!(model)

Raising version of reset_profile/1.

run(model, inputs)

@spec run(pid(), [binary()]) :: {:ok, [binary()]} | {:error, String.t()}

Run the model over a list of input binaries.

run(model, inputs, timeout)

@spec run(pid(), [binary()], timeout()) :: {:ok, [binary()]} | {:error, String.t()}

Run the model, waiting at most timeout.

run!(model, inputs)

Raising version of run/2.

run!(model, inputs, timeout)

Raising version of run/3.

run_with_metrics(model, inputs)

@spec run_with_metrics(pid(), [binary()]) ::
  {:ok,
   {[binary()], [{binary(), TFLiteElixir.LiteRT.CompiledModel.metric_value()}]}}
  | {:error, String.t()}

Run the model and collect whatever counters the accelerator reports.

run_with_metrics(model, inputs, detail_level)

@spec run_with_metrics(pid(), [binary()], non_neg_integer()) ::
  {:ok,
   {[binary()], [{binary(), TFLiteElixir.LiteRT.CompiledModel.metric_value()}]}}
  | {:error, String.t()}

As run_with_metrics/2, at a given detail level.

run_with_metrics(model, inputs, detail_level, timeout)

@spec run_with_metrics(pid(), [binary()], non_neg_integer(), timeout()) ::
  {:ok,
   {[binary()], [{binary(), TFLiteElixir.LiteRT.CompiledModel.metric_value()}]}}
  | {:error, String.t()}

As run_with_metrics/3, waiting at most timeout.

run_with_metrics!(model, inputs)

Raising version of run_with_metrics/2.

run_with_metrics!(model, inputs, detail_level)

Raising version of run_with_metrics/3.

run_with_metrics!(model, inputs, detail_level, timeout)

Raising version of run_with_metrics/4.

start(opts)

@spec start(opts()) :: {:ok, pid()} | :ignore | {:error, term()}

Start one outside a supervision tree.

start(opts, gen_opts)

@spec start(opts(), list()) :: {:ok, pid()} | :ignore | {:error, term()}

As start/1, with options for the gen_server itself.

start_link(opts)

@spec start_link(opts()) :: {:ok, pid()} | :ignore | {:error, term()}

Start a model on a node of its own, linked to the caller.

:model_path is required. The rest are what TFLiteElixir.LiteRT.CompiledModel.new/3 and TFLiteElixir.LiteRT.CompiledModel.Server.start_link/3 take, plus:

  • :peer_args. Extra arguments for the node itself, e.g. ["+sbwt", "none"].

start_link(opts, gen_opts)

@spec start_link(opts(), list()) :: {:ok, pid()} | :ignore | {:error, term()}

As start_link/1, with options for the gen_server itself.

stop(model)

@spec stop(pid()) :: :ok

Stop the model and the node it is on.

summarise_profile(model)

@spec summarise_profile(pid()) ::
  {:ok, [TFLiteElixir.LiteRT.CompiledModel.summary_entry()]}
  | {:error, String.t()}

Per-operator totals over every run since the last reset, slowest first.

summarise_profile!(model)

Raising version of summarise_profile/1.

with(model, fun)

@spec with(pid(), (reference() -> result)) :: result | {:error, String.t()}
when result: term()

Run a function against the compiled model, on the node that owns it.

The callback is sent to that node and applied there, so it must return something worth sending back: a value, not a handle to something local to it.

with(model, fun, timeout)

@spec with(pid(), (reference() -> result), timeout()) :: result | {:error, String.t()}
when result: term()

As with/2, waiting at most timeout.