"bool" everywhere."AnvlArray"s the dispatcher wraps its outputs in no longer carry a
$device field; read the device off $data.as_array_async() is removed; use as_array(x, await = FALSE), which
returns an R array whose values materialize when first read instead of a
PJRTArrayPromise. value() is removed, use the array directly or
await() it.pjrt_compile() gains xla_options, XLA compiler options for that
compilation only.register_tree_node() makes the objects of a class nodes of a tree, with aux
data and a printer, which flatten() and the dispatcher recurse into.flatten() and build_tree() take an is_leaf predicate, whose values are
leaves rather than nodes, as with JAX's tree_flatten(is_leaf = ).dispatcher()'s compile callback can return
uses_default_device = FALSE to have an entry that fixes its own device
served under any default device, instead of recompiled when it changes.pjrt_register_custom_call() accepts the NativeSymbol objects returned by
getNativeSymbolInfo(), so a handler needs no C glue to pass its address.dispatcher() compile callback can declare implicit_inputs and
implicit_outputs, values the program takes and returns beyond the call's
arguments and result, and an on_success function that receives the implicit
outputs and the call's arguments after every successful run. An implicit
input's get() returns the buffer to pass on.PJRTBuffers can now be serialized, e.g. with saveRDS(); they load onto
the default device.PJRTBuffer supports the "bf16" (bfloat16) element type.PJRTBuffer supports the "f16" (IEEE 754 binary16) element type.lu custom call factorises a singular matrix instead of
failing with getrf failed with info = <k>.potrf custom call: a batched Cholesky factorisation through
LAPACK on the host and cuSOLVER on CUDA, reporting each matrix's info
instead of failing on one that is not positive definite.trsm custom call: a batched triangular solve through BLAS on
the host, standing in for stablehlo.triangular_solve, which XLA's CPU
backend expands into much slower HLO.print_tensor_ordered: print_tensor that takes and returns
a !stablehlo.token, so that a chain of prints runs in order.build_tree(), flatten() and dispatch() raise an error for a
value nested more than 1000 levels deep instead of crashing R.tree_concat() rejects names that are not a character vector
instead of leaking memory.gesdd, syevd, geqrf and orgqr custom calls raise an error
for a matrix whose LAPACK workspace exceeds the int range, instead of
passing LAPACK a garbage workspace size.as_array() reads f64, i32, i64 and ui64 buffers straight into the
result vector instead of through a host-side copy.log1p().DataType now come from xlamisc, which absorbed
tengen; pjrt now depends on xlamisc instead of tengen.rdata objects.
This enables the improved precision semantics in anvl.as_array()'s check argument is now "warn" (the default), "err" or
FALSE, and a value R's type cannot hold is reported instead of returned
silently. Write check = "err" where you wrote check = TRUE.pjrt_buffer() and pjrt_scalar() no longer take a check argument; what
happens to an NA is fixed by the dtype.platform_support() lists which backends are available on which
operating system and architecture.dispatcher() gained a context resolver: a function called on every
dispatch whose character() result is part of the cache key and reaches the
compile callback as info$context. anvl uses it to key compiled programs on
the backend's default dtypes.RTree objects can be compared with == and !=, which apply
tree_equal() structural comparison.pjrt_buffer() reads its source vector through R's read-only accessors
(DATAPTR_RO, INTEGER_RO, REAL_RO, LOGICAL_RO) instead of the writable
RAW(), INTEGER(), REAL() and LOGICAL(). A writable pointer forces
copy-on-write materialization of ALTREP vectors (for example shared-memory
mappings), so every upload from such a source paid for a private duplicate of
the payload before the device copy. The source is now read in place on every
upload path.bit64::integer64 NA is no longer silent. At dtype "i64"
it warns, like an NA_integer_ at "i32" does, since INT64_MIN travels
zero-copy and materializes as NA again. At dtype "ui64" it is now an
error: the same bits read unsigned are the ordinary value 2^63.NA at dtype "pred" is now an error. It previously became
TRUE, silently.as_array() on a donated buffer with two or more axes now errors instead
of crashing R.PJRTBuffer now memoizes its immutable metadata (dtype, shape, and
device) on first access, so repeated element_type() / dimensions()
reads no longer issue a PJRT C API call each time.check_err() (C++) no longer leaks the underlying PJRT_Error when
converting a plugin error into an R exception.mhlo.layout_mode — is
reordered correctly instead of being returned transposed. A layout the
readback cannot faithfully reorder (strided, tiled, or rank-mismatched)
now raises a clear error rather than silently returning wrong data.pjrt_buffer(), pjrt_scalar(), and pjrt_execute() now call R's
garbage collector and retry once when the plugin reports
RESOURCE_EXHAUSTED. Unreferenced PJRTBuffer external pointers are
finalized between attempts so their device memory is released before the
retry.torch).
Non-interactive sessions no longer download automatically. The
PJRT_INSTALL environment variable overrides this: set it to "1" to
always download without asking, or "0" to never download.install_pjrt() function which is a slight convenience wrapper
for downloading the plugins. When it installs the CUDA plugin, it also
installs the R package providing the CUDA libraries (cuda12.8).build_tree(), flatten(), unflatten(), etc..dispatcher() and dispatch(), a native (C++) eager-dispatch engine:
an executable cache keyed on the inputs' structure and abstract values, which
calls back into R to compile only on a cache miss. Its default
backend = "pjrt" runs a compiled PJRT executable natively; any other backend
runs through a compiled R closure. It is intended to be used in {anvl}.
Ideally this would live in a library of its own, but we have included it here
for convenience.inspect_hlo() returns the HLO intermediate representations the XLA
compiler produces for a program -- the input (before_optimizations) and
optimized (after_optimizations) HLO -- to help debug compilation (#194).
Enable it by setting the dump flags in XLA_FLAGS (e.g.
--xla_dump_to=<dir> --xla_dump_hlo_as_text) at the start of the session,
before the first compilation; inspect_hlo() errors with instructions if
they are not set.PJRT_TEST environment variable is
set to "1", so it is skipped on CRAN (where the required PJRT plugin
cannot be downloaded). CI sets PJRT_TEST=1.bit64 package to better support long integers.pjrt_buffer(), pjrt_scalar(), and as_array() gain a check
argument (default FALSE). When TRUE, the call errors instead of
silently losing information: on input if data contains NAs, on
output if the materialized R vector contains a value that's
indistinguishable from NA or that has wrapped through the integer
container.as_array() on a ui32 buffer now returns a bit64::integer64
instead of a base integer, so values >= 2^31 round-trip losslessly
rather than wrapping to negative.buffer_copy() function to copy buffer between devices.pjrt_register_custom_call() allows external packages to register C/C++
XLA FFI handlers with the PJRT plugin. Registration is deferred until the
plugin loads, so handlers can be registered during .onLoad().pjrt_device() now returns cached PJRTDevice instances, so repeated calls
for the same device yield objects with stable identity (useful for hashing
and caching, e.g. in {anvl}'s JIT).protoc compiler from the same installation
as the linked protobuf library, preventing version mismatches when multiple
protobuf versions are installed.cpu:1) now targets
that device instead of silently falling back to cpu:0.Operations such as host <-> device transfers and program execution were previously only synchronous. Now, they are asynchronous which has considerable performance benefits, especially on GPU. Specifically:
pjrt_buffer() and pjrt_execute() return immediately, but the returned buffer is not
necessarily ready. To await a transfer or computation of a buffer, use
await(). However, this is handled within PJRT, so this function never has to
be called by a user.as_array() is still synchronous, but there is now the asynchronous version
as_array_async() but this is rarely needed.
If used, it returns a PJRTArrayPromise object which can be converted to
an R array/vector via value().PJRTBuffer or PJRTArrayPromise is ready, use
is_ready().dtype support for PJRTBuffers via the tengen::dtype S3 generic. "bool" is now accepted as an alias for "i1"/"pred".DataType objects in the dtype parameter of pjrt_buffer().device argument in pjrt_compile().pjrt_execute().cuda12.8 package, which now only
requires compatible drivers to be installed.PJRTBuffer now uses "bool" instead of "pred" to avoid
discrepancies with {anvl}.