### Example of adapt function usage Source: https://github.com/juliagpu/adapt.jl/blob/master/README.md Demonstrates how `adapt` can convert a wrapper type like `Adjoint` to a GPU-compatible type while preserving the wrapper. ```julia adapt(CuArray, ::Adjoint{Array})::Adjoint{CuArray} ``` -------------------------------- ### Adapt structure for ScaledArray Source: https://context7.com/juliagpu/adapt.jl/llms.txt This example shows how to preserve wrapper types like ScaledArray when adapting the inner storage. The scale factor remains on the CPU while the parent array is moved to the GPU. ```julia Adapt.adapt_structure(to, x::ScaledArray) = ScaledArray(adapt(to, x.parent), x.scale) ``` ```julia struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Base.size(x::MyGPUArray, d...) = size(x.data, d...) Base.getindex(x::MyGPUArray, i...) = getindex(x.data, i...) Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) ``` ```julia cpu = ScaledArray([1.0, 2.0, 3.0], 2.5) gpu = adapt(MyGPUArray, cpu) # => ScaledArray{Float64,1}(MyGPUArray{Float64,1}([1.0,2.0,3.0]), 2.5) # The scale factor is untouched; the inner array is on the GPU. ``` -------------------------------- ### Define Leaf-Level Conversion with `adapt_storage` Source: https://context7.com/juliagpu/adapt.jl/llms.txt Illustrates how to override `adapt_storage` to define custom conversion rules for the innermost data types. This is the primary extension point for library authors. Examples include adapting scalars and specific array types. ```julia using Adapt # Adaptor that converts all integers to floats struct FloatAdaptor end Adapt.adapt_storage(::FloatAdaptor, x::Int64) = Float64(x) # Scalars adapt(FloatAdaptor(), 42) # => 42.0 # Works recursively through known structures (tuples) adapt(FloatAdaptor(), (1, 2, 3)) # => (1.0, 2.0, 3.0) # Type-based adaptor for converting to plain Array Adapt.adapt_storage(::Type{Array}, xs::AbstractArray) = convert(Array, xs) Adapt.adapt_storage(::Type{<:Array{T}}, xs::AbstractArray) where {T} = convert(Array{T}, xs) using SparseArrays sv = sparsevec([1,3], [1.0, 2.0], 5) adapt(Array, sv) # => sparse vector unchanged (special rule) adapt(Array{Float32}, sv) # => SparseVector{Float32,Int64}(...) ``` -------------------------------- ### `adapt(to, x)` — Convert a value to a target format Source: https://context7.com/juliagpu/adapt.jl/llms.txt The primary entry point for adapting values. It calls `adapt_structure` which, by default, calls `adapt_storage`. If no matching method is found, the original value is returned unchanged. The `to` argument can be a type or an adaptor object. ```APIDOC ## `adapt(to, x)` — Convert a value to a target format The primary entry point. Calls `adapt_structure(to, x)`, which by default calls `adapt_storage(to, x)`. If no matching method exists, `adapt_storage` is a no-op and `x` is returned unchanged. `to` can be a type (e.g., `Array`, `CuArray`) or an adaptor object (e.g., a singleton struct). ```julia using Adapt # --- 1. Converting to a plain Array (built-in storage adaptor) --- using LinearAlgebra gpu_like = [1.0 2.0; 3.0 4.0] # pretend this is on a GPU wrapped = Adjoint(gpu_like) # Adjoint{Float64, Matrix{Float64}} result = adapt(Array, wrapped) # => Adjoint{Float64, Matrix{Float64}} — wrapper preserved, storage converted # --- 2. Custom array adaptor --- struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Base.size(x::MyGPUArray, d...) = size(x.data, d...) Base.getindex(x::MyGPUArray, i...) = getindex(x.data, i...) Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) cpu_matrix = [1.0 2.0; 3.0 4.0] gpu_matrix = adapt(MyGPUArray, cpu_matrix) # => MyGPUArray{Float64,2}([1.0 2.0; 3.0 4.0]) # Wrap in Adjoint and adapt — wrapper is preserved result = adapt(MyGPUArray, Adjoint(cpu_matrix)) # => Adjoint{Float64, MyGPUArray{Float64,2}}(...) # --- 3. Type-parameterized element conversion --- result_f32 = adapt(Array{Float32}, cpu_matrix) # => Matrix{Float32} — converts element type as well ``` ``` -------------------------------- ### Convert to Plain Array with Wrapper Preservation Source: https://context7.com/juliagpu/adapt.jl/llms.txt Demonstrates converting a wrapped array (Adjoint) to a plain Array, preserving the Adjoint wrapper while converting the inner storage. Also shows custom array adaptors and element type conversion. ```julia using Adapt # --- 1. Converting to a plain Array (built-in storage adaptor) --- using LinearAlgebra gpu_like = [1.0 2.0; 3.0 4.0] # pretend this is on a GPU wrapped = Adjoint(gpu_like) # Adjoint{Float64, Matrix{Float64}} result = adapt(Array, wrapped) # => Adjoint{Float64, Matrix{Float64}} — wrapper preserved, storage converted # --- 2. Custom array adaptor --- struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Base.size(x::MyGPUArray, d...) = size(x.data, d...) Base.getindex(x::MyGPUArray, i...) = getindex(x.data, i...) Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) cpu_matrix = [1.0 2.0; 3.0 4.0] gpu_matrix = adapt(MyGPUArray, cpu_matrix) # => MyGPUArray{Float64,2}([1.0 2.0; 3.0 4.0]) # Wrap in Adjoint and adapt — wrapper is preserved result = adapt(MyGPUArray, Adjoint(cpu_matrix)) # => Adjoint{Float64, MyGPUArray{Float64,2}}(...) # --- 3. Type-parameterized element conversion --- result_f32 = adapt(Array{Float32}, cpu_matrix) # => Matrix{Float32} — converts element type as well ``` -------------------------------- ### Overloading adapt_structure for wrapper types Source: https://github.com/juliagpu/adapt.jl/blob/master/README.md Shows how to implement `adapt_structure` for new wrapper types to ensure compatibility with Adapt.jl. This typically involves forwarding the call to `adapt` on the parent object. ```julia Adapt.adapt_structure(to, x::Adjoint) = Adjoint(adapt(to, parent(x))) ``` -------------------------------- ### Defining conversion behavior with adapt_storage Source: https://github.com/juliagpu/adapt.jl/blob/master/README.md Illustrates how `adapt_storage` is used to define conversion behavior for the innermost storage types. This is often implemented by libraries that use Adapt.jl. ```julia adapt_storage(::Type{<:CuArray}, xs::AbstractArray) = convert(CuArray, xs) ``` -------------------------------- ### Curried `adapt(to)` for Higher-Order Functions Source: https://context7.com/juliagpu/adapt.jl/llms.txt Shows how to use the curried form of `adapt(to)` to create a function suitable for `map` or `broadcast`. This is useful for applying adaptation within pipelines or other functional constructs. ```julia using Adapt struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) arrays = [[1,2,3], [4,5,6], [7,8,9]] gpu_arrays = map(adapt(MyGPUArray), arrays) # => [MyGPUArray([1,2,3]), MyGPUArray([4,5,6]), MyGPUArray([7,8,9])] # Works inside a pipeline result = arrays |> map(adapt(MyGPUArray)) |> first # => MyGPUArray{Int64,1}([1, 2, 3]) ``` -------------------------------- ### StaticArrays Extension for Adapt.jl Source: https://context7.com/juliagpu/adapt.jl/llms.txt Illustrates Adapt.jl's extensions for `StaticArrays`, enabling storage conversions between `Array` and `SArray`, and recursive adaptation of elements within an `SArray`. ```julia using Adapt, StaticArrays # Convert a plain Vector to a statically-sized SArray adapt(SArray{Tuple{3}}, [1, 2, 3]) # => SArray{Tuple{3}, Int64, 1, 3}([1, 2, 3]) # Without explicit shape — inferred from size adapt(SArray, [1, 2, 3]) # => SVector{3, Int64}([1, 2, 3]) # Recursively adapt elements inside an SArray struct ToFloat32 end Adapt.adapt_storage(::ToFloat32, x::Float64) = Float32(x) v = SVector{2}(1.0, 2.0) # SVector{2, Float64} adapt(ToFloat32(), v) # => SVector{2, Float32}(1.0f0, 2.0f0) ``` -------------------------------- ### SparseArrays Extension for Adapt.jl Source: https://context7.com/juliagpu/adapt.jl/llms.txt Shows how Adapt.jl extends `adapt_storage` for `SparseVector` and `SparseMatrixCSC`. Adapting to `Array` is a no-op, while adapting to `Array{T}` changes the element type while preserving sparsity. ```julia using Adapt, SparseArrays m = sparse([1, 2], [2, 1], [1.0, 2.0]) # SparseMatrixCSC{Float64,Int64} v = sparsevec([1, 3], [1.0, 2.0], 5) # SparseVector{Float64,Int64} # Keep sparse, identity conversion adapt(Array, m) === m # => true adapt(Array, v) === v # => true # Convert element type, stay sparse adapt(Array{Float32}, m) # => SparseMatrixCSC{Float32, Int64} adapt(Array{Float32}, v) # => SparseVector{Float32, Int64} ``` -------------------------------- ### Adapt Closures with Custom Array Type Source: https://context7.com/juliagpu/adapt.jl/llms.txt Demonstrates adapting a closure that captures CPU arrays to capture GPU arrays using a custom `MyGPUArray` type. This allows GPU kernels to capture adapted closures. ```julia using Adapt struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Base.size(x::MyGPUArray, d...) = size(x.data, d...) Base.getindex(x::MyGPUArray, i...) = getindex(x.data, i...) Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) cpu_weights = rand(Float32, 4, 4) cpu_bias = rand(Float32, 4) # Closure captures CPU arrays predict = let W = cpu_weights, b = cpu_bias x -> W * x .+ b end # Adapt the closure — captured arrays become GPU arrays gpu_predict = adapt(MyGPUArray, predict) # gpu_predict now closes over MyGPUArray instances input = rand(Float32, 4) # gpu_predict(input) # would run on GPU in a real setup ``` -------------------------------- ### Auto-generate adapt_structure with @adapt_structure Source: https://context7.com/juliagpu/adapt.jl/llms.txt Use the `@adapt_structure` macro to automatically generate `adapt_structure` methods for plain structs. It adapts each field individually and reconstructs the object using its default constructor. Non-array fields are passed through unchanged. ```julia using Adapt struct ModelConfig{W, B} weights::W bias::B lr::Float64 # not an array — will be passed through unchanged end Adapt.@adapt_structure ModelConfig ``` ```julia struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Base.size(x::MyGPUArray, d...) = size(x.data, d...) Base.getindex(x::MyGPUArray, i...) = getindex(x.data, i...) Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) ``` ```julia cpu_cfg = ModelConfig(ones(3,3), zeros(3), 0.01) gpu_cfg = adapt(MyGPUArray, cpu_cfg) # => ModelConfig{MyGPUArray{Float64,2}, MyGPUArray{Float64,1}, Float64}( # MyGPUArray(ones(3,3)), MyGPUArray(zeros(3)), 0.01) # Non-array fields are left intact @assert gpu_cfg.lr == 0.01 ``` -------------------------------- ### `adapt(to)` — Curried single-argument form Source: https://context7.com/juliagpu/adapt.jl/llms.txt A curried version of `adapt` that returns a function `x -> adapt(to, x)`. This is useful for passing to higher-order functions like `map` or `broadcast`. ```APIDOC ## `adapt(to)` — Curried single-argument form Returns a function `x -> adapt(to, x)` via `Base.Fix1`. Useful for passing to `map`, `broadcast`, or any higher-order function. ```julia using Adapt struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) arrays = [[1,2,3], [4,5,6], [7,8,9]] gpu_arrays = map(adapt(MyGPUArray), arrays) # => [MyGPUArray([1,2,3]), MyGPUArray([4,5,6]), MyGPUArray([7,8,9])] # Works inside a pipeline result = arrays |> map(adapt(MyGPUArray)) |> first # => MyGPUArray{Int64,1}([1, 2, 3]) ``` ``` -------------------------------- ### `adapt_storage(to, x)` — Define leaf-level conversion Source: https://context7.com/juliagpu/adapt.jl/llms.txt This function is intended to be overridden to define how the innermost storage type is converted. It's the primary extension point for library authors integrating with Adapt.jl. The default implementation is a no-op. ```APIDOC ## `adapt_storage(to, x)` — Define leaf-level conversion Override this function to specify how the innermost storage type is converted. This is the primary extension point for library authors integrating with Adapt.jl. The default implementation is a no-op that returns `x` unchanged. ```julia using Adapt # Adaptor that converts all integers to floats struct FloatAdaptor end Adapt.adapt_storage(::FloatAdaptor, x::Int64) = Float64(x) # Scalars adapt(FloatAdaptor(), 42) # => 42.0 # Works recursively through known structures (tuples) adapt(FloatAdaptor(), (1, 2, 3)) # => (1.0, 2.0, 3.0) # Type-based adaptor for converting to plain Array Adapt.adapt_storage(::Type{Array}, xs::AbstractArray) = convert(Array, xs) Adapt.adapt_storage(::Type{<:Array{T}}, xs::AbstractArray) where {T} = convert(Array{T}, xs) using SparseArrays sv = sparsevec([1,3], [1.0, 2.0], 5) adapt(Array, sv) # => sparse vector unchanged (special rule) adapt(Array{Float32}, sv) # => SparseVector{Float32,Int64}(...) ``` ``` -------------------------------- ### Define Recursive Structure Traversal with `adapt_structure` Source: https://context7.com/juliagpu/adapt.jl/llms.txt Shows how to override `adapt_structure` to control how composite types are recursively adapted. This allows for custom traversal logic, ensuring that `adapt` calls are propagated to specific fields while maintaining the wrapper type. ```julia using Adapt # Custom wrapper that must survive adaptation struct ScaledArray{T,N} parent::AbstractArray{T,N} scale::Float64 end ``` -------------------------------- ### `adapt_structure(to, x)` — Define recursive structure traversal Source: https://context7.com/juliagpu/adapt.jl/llms.txt Override this function to control how a composite type is recursively adapted. Implement it to propagate `adapt` calls to all relevant fields, returning a new instance of the same wrapper type. Without this, `adapt_structure` falls through to `adapt_storage`. ```APIDOC ## `adapt_structure(to, x)` — Define recursive structure traversal Override this to control how a composite type is recursively adapted. Implement it to propagate `adapt` calls to all relevant fields, returning a new instance of the same wrapper type. Without this, `adapt_structure` falls through to `adapt_storage`. ```julia using Adapt # Custom wrapper that must survive adaptation struct ScaledArray{T,N} parent::AbstractArray{T,N} scale::Float64 end ``` ``` -------------------------------- ### Dispatch on wrapped arrays with Union type Source: https://context7.com/juliagpu/adapt.jl/llms.txt Define a Union type alias to dispatch on any array wrapper type known to Adapt.jl, including custom ones like `MyGPUArray`. This allows functions to accept various wrapped array types and their underlying storage. ```julia using Adapt, LinearAlgebra struct MyGPUArray{T,N} <: AbstractArray{T,N} data::Array{T,N} end Base.size(x::MyGPUArray, d...) = size(x.data, d...) Base.getindex(x::MyGPUArray, i...) = getindex(x.data, i...) # Alias: accept raw MyGPUArray OR any standard wrapper around one const AnyMyGPUArray{T,N} = Union{ MyGPUArray{T,N}, WrappedArray{T,N,MyGPUArray,MyGPUArray{T,N}} } # Dispatch on any GPU-backed array, including wrapped ones function gpu_kernel(A::AnyMyGPUArray) println("Running GPU kernel on: ", typeof(A)) end Adapt.adapt_storage(::Type{<:MyGPUArray}, xs::Array) = MyGPUArray(xs) ``` ```julia mat = adapt(MyGPUArray, rand(3,3)) gpu_kernel(mat) # => Running GPU kernel on: MyGPUArray{Float64,2} gpu_kernel(transpose(mat)) # => Running GPU kernel on: Transpose{Float64, MyGPUArray{Float64,2}} gpu_kernel(view(mat, 1:2, :)) # => Running GPU kernel on: SubArray{...} ``` -------------------------------- ### Retrieve immediate parent type with parent_type Source: https://context7.com/juliagpu/adapt.jl/llms.txt The `parent_type` function returns the immediate parent type of a `WrappedArray`, without recursing. This is useful for type-level inspection in metaprogramming and dispatch, especially when you need to know the direct wrapper. ```julia using Adapt, LinearAlgebra parent_type(Transpose{Int, Array{Int,1}}) # => Array{Int64, 1} parent_type(Transpose{Int, Transpose{Int, Array{Int,1}}}) # => Transpose{Int64, Array{Int64, 1}} (one level only) # Useful in generated functions or where clauses: function requires_plain_parent(::Type{W}) where {W <: WrappedArray} P = parent_type(W) P <: Array || error("Expected plain Array as parent, got $P") end ``` -------------------------------- ### Fully unwrap nested wrapper types with unwrap_type Source: https://context7.com/juliagpu/adapt.jl/llms.txt The `unwrap_type` function recursively calls `parent_type` to return the innermost concrete array type, regardless of nesting depth. This is useful for inspecting the underlying storage's element type, memory layout, or device affinity. ```julia using Adapt, LinearAlgebra unwrap_type(Transpose{Int, Array{Int,1}}) # => Array{Int64, 1} unwrap_type(Transpose{Int, Transpose{Int, Array{Int,1}}}) # => Array{Int64, 1} (fully unwrapped through two layers) # Check device of the innermost storage regardless of wrapping function on_gpu(::Type{W}) where {W} return unwrap_type(W) <: AbstractGPUArray # hypothetical GPU type end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.