-
Notifications
You must be signed in to change notification settings - Fork 220
Standardize docs across nx, exla, torchx #1770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Chapaman
wants to merge
6
commits into
elixir-nx:main
Choose a base branch
from
Chapaman:backend-docs-standard
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
05d66a1
Document backend behaviour with markdown guides instead of ghost modules
Chapaman c04e09f
fix formatting
Chapaman e21b41f
implement josevalim and paulovalente feedback
Chapaman dd75511
Apply suggestions from code review
Chapaman d2630d6
remove exla&torchx mentions from linalg
Chapaman 7a37a57
update according to feedback
Chapaman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Backend documentation | ||
|
|
||
| EXLA-specific documentation for Nx backend behaviour. | ||
|
|
||
| These guides document divergent behaviour, backend-specific options, and | ||
| limitations for Nx operations. They mirror the structure of the Nx API — see | ||
| the [backend documentation convention](https://hexdocs.pm/nx/backend_documentation-convention.html). | ||
|
|
||
| ## Guides | ||
|
|
||
| * [Nx](backend_documentation-nx.html) — top-level `Nx` blocks, transfers, and `defn` integration | ||
| * [Nx.LinAlg](backend_documentation-nx_lin_alg.html) — linear algebra blocks | ||
|
|
||
| Implementation code lives in `EXLA.Defn`, `EXLA.CustomCall`, and related modules. | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| # Nx (EXLA) | ||
|
|
||
| EXLA-specific notes for top-level `Nx` operations where behaviour diverges from | ||
| the portable Nx API or from other backends. | ||
|
|
||
| Linear algebra is documented separately in [Nx.LinAlg](backend_documentation-nx_lin_alg.html). | ||
|
|
||
| ## runtime_call/4 | ||
|
|
||
| Runtime Elixir callback from `defn` (`runtime_call` expression). | ||
|
|
||
| ### Platforms | ||
|
|
||
| * **Host / CUDA** — supported via a device-side callback bridged through | ||
| `EXLA.MLIR.Value.runtime_call/3` | ||
| * **ROCm / TPU** — raises with a message to use `:host` or `:cuda` | ||
|
|
||
| ### Outside `defn` | ||
|
|
||
| Executes the callback directly on the input backend without compilation. | ||
|
|
||
| ### Warnings | ||
|
|
||
| Avoid `Nx.backend_transfer/2` on callback tensors inside the function when | ||
| using `Nx.Defn.Evaluator`. Avoid running other Nx computations on the same GPU | ||
| device from within the callback (deadlock risk). | ||
|
|
||
| ## backend_copy/2 | ||
|
|
||
| Copy tensor data to another backend (`EXLA.Backend.backend_copy/3`). | ||
|
|
||
| ### Behaviour | ||
|
|
||
| Copying to `EXLA.Backend` on the same client and device returns the tensor | ||
| unchanged. Cross-device copies use `EXLA.DeviceBuffer.copy_to_device/3`. | ||
| Copying out reads device memory via `EXLA.DeviceBuffer.read/1` and delegates | ||
| to the target backend's `from_binary/3`. | ||
|
|
||
| ### Options | ||
|
|
||
| * `:client`, `:device_id` — select the EXLA client and device | ||
|
|
||
| ## backend_transfer/2 | ||
|
|
||
| Transfer tensor data to another backend (`EXLA.Backend.backend_transfer/3`). | ||
|
|
||
| ### Behaviour | ||
|
|
||
| Same as `backend_copy/2` followed by deallocation of the source device buffer | ||
| when leaving `EXLA.Backend`. | ||
|
|
||
| ### Options | ||
|
|
||
| * `:client`, `:device_id` — select the EXLA client and device | ||
|
|
||
| ## to_pointer/2 | ||
|
|
||
| Export device memory as a pointer (`EXLA.Backend.to_pointer/2`). | ||
|
|
||
| ### Modes | ||
|
|
||
| * `:local` — supported on **host** and **CUDA** clients; returns a local | ||
| address integer | ||
| * `:ipc` — supported on **host** (`shm_open` handle) and **CUDA** (IPC | ||
| handle plus device id) | ||
|
|
||
| ### Options | ||
|
|
||
| * `:permissions` — octal file mode for host IPC shared memory (default | ||
| `0o400`) | ||
|
|
||
| ### Limitations | ||
|
|
||
| Not supported for ROCm, TPU, or non-device buffers. | ||
|
|
||
| ## from_pointer/5 | ||
|
|
||
| Import device memory from a pointer (`EXLA.Backend.from_pointer/5`). | ||
|
|
||
| ### Behaviour | ||
|
|
||
| Creates an `EXLA.DeviceBuffer` from a local address or IPC handle on **host** | ||
| or **CUDA** clients. Pointer `data_size` must match the tensor byte size. | ||
|
|
||
| ### Options | ||
|
|
||
| * `:client`, `:device_id` — destination device | ||
| * `:names` — tensor names for the result template | ||
|
|
||
| ### Limitations | ||
|
|
||
| Not supported for ROCm or TPU. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Nx.LinAlg (EXLA) | ||
|
|
||
| EXLA-specific notes for `Nx.LinAlg` where behaviour diverges from the portable | ||
| Nx API or from other backends. | ||
|
|
||
| On GPU and TPU clients, the `:precision` option passed to `Nx.Defn.jit/2` | ||
| affects accumulator precision for many composed linear algebra graphs compiled | ||
| from the default callbacks. For decomposition verification tests, prefer | ||
| `precision: :highest`. | ||
|
|
||
| ## qr/2 | ||
|
|
||
| QR decomposition (`%Nx.Block.LinAlg.QR{}`). | ||
|
|
||
| ### Supported platforms | ||
|
|
||
| * **Host** — native CPU custom call for supported **real** dtypes (`f16`, | ||
| `bf16`, `f32`, `f64`, and integer types cast to `f32`); default callback for | ||
| complex inputs and unsupported types | ||
| * **CUDA / ROCm / TPU** — default callback only (no native QR custom call) | ||
|
|
||
| ### Options | ||
|
|
||
| * `:mode` — honored by whichever implementation is selected (`:reduced` or | ||
| `:complete`) | ||
| * `:eps` — used by the default callback only; ignored by the native custom call | ||
|
|
||
| ### Numerical notes | ||
|
|
||
| Native and default implementations may differ slightly in orthogonality of `q` | ||
| and triangular structure of `r` within floating-point tolerance. | ||
| For example, for an eigenpair `(lambda, v)`, `(-lambda, -v)` is | ||
| an equally valid eigenpair that would lead to radically different | ||
| `q` and `r` matrices. Reconstruction of `q · r` should match the | ||
| input within reasonable tolerances for the dtype. | ||
|
|
||
| ## eigh/2 | ||
|
|
||
| Hermitian eigendecomposition (`%Nx.Block.LinAlg.Eigh{}`). | ||
|
|
||
| ### Supported platforms | ||
|
|
||
| * **Host** — native CPU custom call for supported **real** dtypes (`f32`, | ||
| `f64`, and integer types cast to `f32`); default callback for complex inputs and | ||
| unsupported types | ||
| * **CUDA / ROCm / TPU** — default callback only | ||
|
|
||
| ### Options | ||
|
|
||
| * `:max_iter` and `:eps` — honored by the default callback; ignored by the | ||
| native custom call | ||
|
|
||
| ### Numerical notes | ||
|
|
||
| Eigenvectors are not unique (sign and degenerate subspaces). Compare results | ||
| using reconstruction `v · diag(λ) · vᵀ` rather than direct eigenvector equality | ||
| across backends. | ||
|
|
||
| ## svd/2 | ||
|
|
||
| Singular value decomposition (`%Nx.Block.LinAlg.SVD{}`). | ||
|
|
||
| ### Options | ||
|
|
||
| * `:max_iter` — honored (default iterative algorithm in Nx) | ||
| * `:full_matrices?` — honored | ||
|
|
||
| ### Numerical notes | ||
|
|
||
| SVD is iterative; results may vary across devices and precision settings. | ||
| Singular values are the most stable quantity to compare across backends. | ||
| Use `precision: :highest` on GPU when verifying decompositions. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -82,6 +82,13 @@ defmodule EXLA do | |||||
| your block tag struct; see `EXLA.CustomCall` for the `call/4` contract, | ||||||
| including returning `:skip` to fall back to the block's default Elixir callback. | ||||||
|
|
||||||
| Backend-specific behaviour, options, and limitations for Nx functions are | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| documented in the [Backend documentation](backend_documentation.html) guides | ||||||
| (for example [Nx](backend_documentation-nx.html) and | ||||||
| [Nx.LinAlg](backend_documentation-nx_lin_alg.html)). See also the | ||||||
| [backend documentation convention](https://hexdocs.pm/nx/backend_documentation-convention.html) | ||||||
| in the Nx package. | ||||||
|
|
||||||
| ## Clients | ||||||
|
|
||||||
| The `EXLA` library uses a client for compiling and executing code. | ||||||
|
|
||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| defmodule EXLA.BackendDocumentationTest do | ||
| use ExUnit.Case, async: true | ||
|
|
||
| doctest_file("guides/backend_documentation/index.md") | ||
| doctest_file("guides/backend_documentation/nx.md") | ||
| doctest_file("guides/backend_documentation/nx_lin_alg.md") | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Backend documentation convention | ||
|
|
||
| Nx exposes a stable public API (`Nx`, `Nx.LinAlg`, and so on) while individual | ||
| backends implement the underlying callbacks and optional `Nx.block/4` lowerings. | ||
| Users who need to know how a specific backend differs from the portable API should | ||
| not have to read backend source code. | ||
|
|
||
| ## Documentation guides | ||
|
|
||
| Each backend may publish **backend documentation guides** that mirror the Nx | ||
| module structure. The naming convention is: | ||
|
|
||
| guides/backend_documentation/nx.md # mirrors top-level `Nx` | ||
| guides/backend_documentation/nx_lin_alg.md # mirrors `Nx.LinAlg` | ||
|
|
||
| For example, EXLA documents operations in its [Backend documentation](https://hexdocs.pm/exla/backend_documentation.html) | ||
| guides, and Torchx in its [Backend documentation](https://hexdocs.pm/torchx/backend_documentation.html) | ||
| guides. | ||
|
|
||
| ## What to document | ||
|
|
||
| Document an operation only when a backend has **divergent behaviour**, **backend-specific | ||
| options**, or **trade-offs and limitations** worth calling out relative to the | ||
| portable Nx API or to other backends. Examples: | ||
|
|
||
| * an option that a backend honours, ignores, or overrides | ||
| * platform or device support gaps (for example an operation unavailable on MPS) | ||
| * numerical or performance trade-offs that affect how you use the API | ||
| * warnings about deadlock, unsupported pointer modes, and similar constraints | ||
|
|
||
| Do not document routine lowerings (for example which StableHLO op or LibTorch | ||
| kernel is used) when behaviour matches the reference Nx implementation. If you | ||
| are implementing or overriding custom blocks, the backend source remains the best | ||
| source of truth. | ||
|
|
||
| Cross-link from the Nx function doc when a backend guide has relevant notes for | ||
| that operation. | ||
|
|
||
| ## Relation to `Nx.Backend` | ||
|
|
||
| Most tensor operations go through `Nx.Backend` callbacks. Operations that need | ||
| a portable default with optional native acceleration use `Nx.block/4` and the | ||
| `Nx.Block.*` tags — see `Nx.Backend.block/4`. Backend documentation guides | ||
| should cover divergent behaviour for both callback implementations and block | ||
| lowerings. | ||
|
|
||
| ## Example | ||
|
|
||
| ```elixir | ||
| iex> Nx.take(Nx.tensor([10, 20, 30]), Nx.tensor([0, 2])) | ||
| #Nx.Tensor< | ||
| s32[2] | ||
| [10, 30] | ||
| > | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is exactly the kind of documentation that this PR let's shine through!