Packages

Production ML model serving on the BEAM. Serve PyTorch models faster than Python with pre-compiled graph execution, AOTI compiled inference, and OTP fault tolerance.

Current section

Files

Jump to
extorch lib extorch.ex
Raw

lib/extorch.ex

defmodule ExTorch do
@moduledoc """
The ``ExTorch`` namespace contains data structures for multi-dimensional tensors and mathematical operations over these are defined.
Additionally, it provides many utilities for efficient serializing of Tensors and arbitrary types, and other useful utilities.
It has a CUDA counterpart, that enables you to run your tensor computations on an NVIDIA GPU with compute capability >= 3.0
"""
use ExTorch.DelegateWithDocs
import ExTorch.ModuleMixin
# Native operations
extends(ExTorch.Native.Tensor.Creation)
extends(ExTorch.Native.Tensor.Ops.Manipulation)
extends(ExTorch.Native.Tensor.Ops.Indexing)
extends(ExTorch.Native.Tensor.Ops.PointWise)
extends(ExTorch.Native.Tensor.Ops.Comparison)
extends(ExTorch.Native.Tensor.Ops.Reduction)
extends(ExTorch.Native.Tensor.Ops.Other)
extends(ExTorch.Registry.DType)
extends(ExTorch.Registry.Device)
# extends(ExTorch.Native.Tensor.Info)
@doc """
Enable or disable autograd tracking process-wide.
Equivalent to `torch.set_grad_enabled(enabled)` in Python. When disabled,
tensor operations skip building the autograd graph and dispatch to faster
inference-mode kernels in the underlying libtorch backends (notably
oneDNN/MKLDNN). For pure inference workloads, disable grad once at startup.
Returns `:ok`.
"""
@spec set_grad_enabled(boolean()) :: :ok
def set_grad_enabled(enabled) when is_boolean(enabled) do
_ = ExTorch.Native.aten_set_grad_enabled(enabled)
:ok
end
@doc """
Returns whether autograd tracking is currently enabled process-wide.
"""
@spec grad_enabled?() :: boolean()
def grad_enabled?() do
ExTorch.Native.aten_is_grad_enabled()
end
@doc """
Temporarily disable autograd tracking around the given zero-arity function
and restore the previous setting afterward. Mirrors `torch.no_grad()` as a
Python context manager.
## Example
ExTorch.no_grad(fn ->
ExTorch.Export.forward(model, [input])
end)
"""
@spec no_grad((-> result)) :: result when result: any()
def no_grad(fun) when is_function(fun, 0) do
prev = grad_enabled?()
:ok = set_grad_enabled(false)
try do
fun.()
after
:ok = set_grad_enabled(prev)
end
end
@doc """
Clear the current OS thread's CPU affinity mask so libtorch's OpenMP
worker threads can run on all available cores.
NIF calls run on BEAM scheduler threads which are typically bound to
individual CPUs. OpenMP workers spawned by libtorch inherit that mask,
so all intra-op parallelism happens on a single core. This resets the
mask to include every online CPU, letting libtorch parallelize freely.
Call once per BEAM process that will dispatch tensor ops. Returns `true`
on Linux if the syscall succeeded, `false` on other platforms.
"""
@spec clear_cpu_affinity() :: boolean()
def clear_cpu_affinity() do
ExTorch.Native.aten_clear_cpu_affinity()
end
@doc """
Block until all queued CUDA kernels on the current device have finished.
CUDA operations are asynchronous — `at::conv2d` on a CUDA tensor queues
the kernel and returns immediately. `:timer.tc` / `:erlang.monotonic_time`
measurements around CUDA work will undercount unless they're bracketed
by a sync. Call this once before starting a benchmark interval (to drain
the queue) and once after (to wait for the measured work).
No-op on CPU-only libtorch builds.
"""
@spec cuda_synchronize() :: :ok
def cuda_synchronize() do
_ = ExTorch.Native.aten_cuda_synchronize()
:ok
end
end