From baee56163ea18e96f015fc86c86db784dc5a0b40 Mon Sep 17 00:00:00 2001 From: shukebeta Date: Wed, 4 Nov 2026 18:09:34 +1300 Subject: [PATCH 1/2] Document backend-only Adapt targets Adapt.adapt takes the backing array type of the target backend, such as Array, CuArray or ROCArray, without element-type parameters; the element type is chosen when the operator is constructed. Add a section to the GPU guide that contrasts the Adapt target with the parameterized storage type S, and state the same in the GradientOp docstring. Co-Authored-By: Claude Opus 5.5 --- docs/src/literate/howtos/gpu.jl | 21 ++++++++++++++++++++- src/GradientOp.jl | 17 ++++++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/src/literate/howtos/gpu.jl b/docs/src/literate/howtos/gpu.jl index d4f8985..955fa96 100644 --- a/docs/src/literate/howtos/gpu.jl +++ b/docs/src/literate/howtos/gpu.jl @@ -16,4 +16,23 @@ storage = Complex.(similar(image_gpu, 0)) fop = FFTOp(eltype(image_gpu), shape = (N, N), S = typeof(storage)) LinearOperators.storage_type(fop) == typeof(storage) -# GPU operators can be used just like the other operators. Note however, that a GPU operator does not necessarily work with a CPU vector. \ No newline at end of file +# GPU operators can be used just like the other operators. Note however, that a GPU operator does not necessarily work with a CPU vector. + +# ## Moving an Operator to Another Backend +# Operators that implement [Adapt.jl](https://github.com/JuliaGPU/Adapt.jl) support can be moved to another array backend with `Adapt.adapt(target, op)`. +# Which backends are supported depends on the operator and the target, and not every operator in LinearOperatorCollection implements Adapt. + +# The target is the backing array type without element-type parameters, such as `Array`, `CuArray` or `ROCArray`. +# LinearOperatorCollection does not support element-typed targets such as `Array{ComplexF64}` or `CuArray{Float32}`, even when the element type matches the operator. +# Adapting moves an operator to another backend; it is not the way to change the operator's precision. Choose the element type when you construct the operator. + +# This differs from the `S` keyword above, which takes a parameterized storage type such as `CuArray{T, 1}`: +# ```julia +# using LinearOperatorCollection, Adapt +# op = GradientOp(Float32; shape = (32, 32)) +# op_cpu = Adapt.adapt(Array, op) # not Array{Float32} +# +# using CUDA # requires CUDA.jl and a supported NVIDIA GPU +# op_gpu = Adapt.adapt(CuArray, op) # not CuArray{Float32} +# ``` +# GPU targets require the corresponding backend package, such as CUDA.jl or AMDGPU.jl, and supported hardware. diff --git a/src/GradientOp.jl b/src/GradientOp.jl index 85c3d3c..2010c36 100644 --- a/src/GradientOp.jl +++ b/src/GradientOp.jl @@ -17,13 +17,16 @@ directional gradient operator along the dimensions `dims` for an array of size ` Adapt.adapt(CuArray, op) -returns a new gradient operator for the target array type (e.g. `Array`, `JLArray`, `CuArray` -or `ROCArray`), and `copy(op)` returns a new one with the same storage type. Both rebuild the -operator and its temporary storage from `shape` and the directions taken from `dims` at -construction; a later change of the vector passed as `dims`, or an iterator consumed by the -construction, has no effect. `op` itself is not modified. The directions stay on the host. -The adapted storage must have the element type of `op`: an element-typed target such as -`CuArray{Float32}` for a `Float64` operator throws an `ArgumentError`. An operator built with +returns a new gradient operator for the target backend, and `copy(op)` returns a new one with +the same storage type. The target is the backing array type without element-type parameters +(e.g. `Array`, `JLArray`, `CuArray` or `ROCArray`). Unlike `S`, which takes a parameterized type +such as `CuArray{T, 1}`, an element-typed target such as `Array{Float64}` is not supported, even +when its element type matches `op`. Adapting does not change the precision: choose `T` at +construction. Both rebuild the operator and its temporary storage from `shape` and the +directions taken from `dims` at construction; a later change of the vector passed as `dims`, or +an iterator consumed by the construction, has no effect. `op` itself is not modified. The +directions stay on the host. An element-typed target whose element type differs from `op`, such +as `CuArray{Float32}` for a `Float64` operator, throws an `ArgumentError`. An operator built with an `S` of another element type cannot be adapted to any target and throws an `ArgumentError`; `copy` keeps it as it is. """ From c14b05c3d27e89533666786354854e79f6f93b96 Mon Sep 17 00:00:00 2001 From: shukebeta Date: Wed, 4 Nov 2026 18:16:35 +1300 Subject: [PATCH 2/2] Reword the Adapt support sentence in the GPU guide Co-Authored-By: Claude Opus 5.5 --- docs/src/literate/howtos/gpu.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/literate/howtos/gpu.jl b/docs/src/literate/howtos/gpu.jl index 955fa96..3d153fc 100644 --- a/docs/src/literate/howtos/gpu.jl +++ b/docs/src/literate/howtos/gpu.jl @@ -19,7 +19,7 @@ LinearOperators.storage_type(fop) == typeof(storage) # GPU operators can be used just like the other operators. Note however, that a GPU operator does not necessarily work with a CPU vector. # ## Moving an Operator to Another Backend -# Operators that implement [Adapt.jl](https://github.com/JuliaGPU/Adapt.jl) support can be moved to another array backend with `Adapt.adapt(target, op)`. +# Operators that support [Adapt.jl](https://github.com/JuliaGPU/Adapt.jl) can be moved to another array backend with `Adapt.adapt(target, op)`. # Which backends are supported depends on the operator and the target, and not every operator in LinearOperatorCollection implements Adapt. # The target is the backing array type without element-type parameters, such as `Array`, `CuArray` or `ROCArray`.