Indexing, Sorting & Utilities
Indexing and slices
1D and 2D arrays support slicing with :, unit ranges (2:4) and integers. A slice is a view: writing to it changes the original array.
A = cuNumeric.rand(Float32, 100, 100)
B = cuNumeric.rand(Float32, 2, 100)
top = A[1:10, :] # view, no copy
A[2:3, :] = B # copy B into rows 2–3
A[:, 5] .= 0f0 # fill a column
A[2:3, :] .= A[1:2, :] .+ 1f0 # broadcast into a sliceDifferences from Base:
A slice with an integer index keeps that dimension:
A[:, 2]isn×1andA[2, :]is1×n, not a vector.Assign a scalar to a slice with
.=.A[1:2, :] = 0f0errors.Not supported: step ranges (
1:2:n), index or Boolean arrays, and slicing arrays with 3 or more dimensions.Single elements (
A[2, 3]) need@allowscalar.
Sorting and searching
sort, sort!, unique, searchsortedfirst, searchsortedlast and searchsorted are not Base's: call them with the cuNumeric. prefix.
v = cuNumeric.rand(Float32, 1000)
s = cuNumeric.sort(v) # cuNumeric.sort!(v) sorts in place
i = cuNumeric.searchsortedfirst(s, 0.5f0) # 0D NDArray; fetch(i) for an Int
u = cuNumeric.unique(NDArray([3, 1, 3])) # [1, 3], sortedN-d arrays need dims. Sorts are unstable unless stable=true.
cuNumeric.NDArray Method
NDArray{T}(undef, dims::Int...)
NDArray{T}(undef, dims::Dims)Allocate an NDArray{T}. Storage is zero-initialized so it can be read immediately.
Base.:== Method
==(arr::NDArray, julia_arr::Array)
==(julia_arr::Array, arr::NDArray)Compare an NDArray and a Julia Array for element-wise equality.
Returns true if both arrays have the same shape and all corresponding elements are equal. Returns false otherwise (including if sizes differ, with a warning).
Warning
This function uses scalar indexing and should not be used in production code. This is meant for testing.
Examples
arr = cuNumeric.ones(2, 2)
julia_arr = ones(2, 2)
arr == julia_arr
julia_arr == arr
julia_arr2 = zeros(2, 2)
arr == julia_arr2Base.:== Method
==(arr1::NDArray, arr2::NDArray)
!=(arr1::NDArray, arr2::NDArray)Element-wise equality reduced to a 0-d NDArray{Bool} (not a Julia Bool). Same shape and values yields true; mismatched shape or rank yields false. Mixed dtypes follow Julia == (promote, then compare). Use fetch or A[] (with allowscalar) for a host value. Broadcast .== / .!= stay elementwise.
Examples
a = cuNumeric.ones(2, 2)
b = cuNumeric.ones(2, 2)
a == b
c = cuNumeric.zeros(2, 2)
a == cBase.copy Method
Base.copy(arr::NDArray)Create and return a deep copy of the given NDArray.
Examples
a = cuNumeric.ones(2, 2)
b = copy(a)
b === a
b[1,1] == a[1,1]Base.copyto! Method
copyto!(arr::NDArray, other::NDArray)
copyto!(arr::NDArray, other::Array)Overwrite arr with the values of other, which may be another NDArray or a Julia host Array of the same element type and shape. A host copy returns once the data is on the device, so other can be reused right away.
Examples
a = cuNumeric.zeros(2, 2)
b = cuNumeric.ones(2, 2)
copyto!(a, b);
copyto!(a, Float32[1 2; 3 4]);Base.firstindex Method
Base.firstindex(arr::NDArray, dim::Integer)
Base.lastindex(arr::NDArray, dim::Integer)
Base.lastindex(arr::NDArray)Provide the first and last valid indices along a given dimension dim for NDArray.
Examples
arr = cuNumeric.rand(4, 5);
firstindex(arr, 2)
lastindex(arr, 2)
lastindex(arr)Base.isapprox Method
isapprox(arr1::NDArray, arr2::NDArray; atol=0, rtol=0)
isapprox(arr::NDArray, julia_array::AbstractArray; atol=0, rtol=0)
isapprox(julia_array::AbstractArray, arr::NDArray; atol=0, rtol=0)Approximate equality comparison between two NDArrays or between an NDArray and a Julia AbstractArray.
Returns true if the arrays have the same shape and all corresponding elements are approximately equal within the given absolute tolerance atol and relative tolerance rtol.
The second and third methods handle comparisons between NDArray and Julia arrays by forwarding to a common comparison function.
Warning
This function uses scalar indexing and should not be used in production code. This is meant for testing.
Examples
arr1 = cuNumeric.ones(2, 2)
arr2 = cuNumeric.ones(2, 2)
julia_arr = ones(2, 2)
isapprox(arr1, arr2)
isapprox(arr1, julia_arr)
isapprox(julia_arr, arr2)Base.permutedims Method
Base.permutedims(arr::NDArray, perm)Permute the dimensions of arr according to perm, a 1-based permutation of 1:ndims(arr). Rank is preserved. See also transpose.
Base.size Method
Base.size(arr::NDArray)
Base.size(arr::NDArray, dim::Integer)Return the size of the given NDArray.
Base.size(arr)returns a tuple of dimensions of the array.Base.size(arr, dim)returns the size of the array along the specified dimensiondim.
Examples
arr = cuNumeric.rand(3, 4, 5);
size(arr)
size(arr, 2)cuNumeric.as_type Method
as_type(arr::NDArray, t::Type{T}) where {T}Convert the element type of arr to type T, returning a new NDArray with elements cast to T.
Arguments
arr::NDArray: Input array.t::Type{T}: Target element type.
Returns
A new NDArray with the same shape as arr but with elements of type T.
Examples
arr = cuNumeric.rand(4, 5);
as_type(arr, Float32)cuNumeric.h5read Method
h5read(path::String, dataset::String; layout::Symbol=:row) -> NDArrayRead a dataset from an HDF5 file into an NDArray.
Arguments
path: Path to the HDF5 file.dataset: Name of the dataset to read.
Keywords
layout: On-disk memory order, either:row(default) or:col.
cuNumeric.h5write Method
h5write(path::String, dataset::String, arr::NDArray)Write an NDArray directly to an HDF5 dataset without a host copy or dimension flip.
A leftover empty or truncated .h5 from a crashed write is removed first. A valid HDF5 file is left in place so Legate can overwrite it. The *_legate_vds sidecar is not touched: it holds the payload of a VDS write.
Arguments
path: Path to the HDF5 file.dataset: Name of the dataset to write.arr: The array to write.
cuNumeric.ravel Method
cuNumeric.ravel(arr::NDArray)Return a flattened 1D view of the input NDArray.
cuNumeric.squeeze Method
squeeze(arr::NDArray)
squeeze(arr::NDArray, dims)Drop size-1 dimensions of arr. With no dims, every size-1 axis is removed. With dims (a 1-based integer or collection), only those axes are removed and each must have size 1.
See also Base.dropdims.
cuNumeric.transpose Method
cuNumeric.transpose(arr::NDArray)Return a new NDArray that is the transpose of the input arr.
cuNumeric.searchsorted Method
cuNumeric.searchsorted(a::NDArray{T,1}, x::Number)searchsortedfirst(a, x):searchsortedlast(a, x) as a UnitRange, matching Base's scalar search. Materializes two 0-d index arrays via fetch. Not Base.searchsorted.
cuNumeric.searchsortedfirst Method
cuNumeric.searchsortedfirst(a::NDArray{T,1}, x)
cuNumeric.searchsortedlast(a::NDArray{T,1}, x)Insertion indices into a 1-d sorted a. x may be a Number or an NDArray of needles.
Scalar queries return a 0-d NDArray{Int64} (not a Julia Int); use fetch for an Int. Array queries return an NDArray{Int64} with the shape of the needles. Indices are 1-based.
Not Base.searchsortedfirst / searchsortedlast. a must already be sorted ascending. lt / by / rev are not accepted. Complex arrays are not supported.
cuNumeric.sort! Method
cuNumeric.sort!(v::NDArray{T,1}; stable::Bool=false)
cuNumeric.sort!(A::NDArray; dims::Integer, stable::Bool=false)Sort A in place. Same kwargs as cuNumeric.sort. Not Base.sort!.
cuNumeric.sort Method
cuNumeric.sort(v::NDArray{T,1}; stable::Bool=false)
cuNumeric.sort(A::NDArray; dims::Integer, stable::Bool=false)Return a copy of A sorted in ascending order.
This is not Base.sort. Call it as cuNumeric.sort. alg, lt, by, rev, and order are not accepted.
For rank greater than 1, dims is required (Julia 1-based). stable=true sets the cupynumeric stable-sort flag (kind="stable"); the default is unstable (kind="quicksort"). These names do not run Julia's QuickSort or MergeSort. Complex values are ordered lexicographically by (real, imag).
cuNumeric.unique Method
cuNumeric.unique(A::NDArray) -> NDArray{T,1}Sorted unique elements of A, flattened to 1-d.
This is not Base.unique, which keeps first-occurrence order and does not sort. dims, return_index, return_inverse, and return_counts are not accepted; cupynumeric does not implement them.
cuNumeric._scalar_indexing_stdlib_caller Method
Best-effort: outermost Base or LinearAlgebra frame above cuNumeric scalar-index frames. Walk innermost-first, skip cuNumeric/Core (and frames with unknown module), indexing/iteration plumbing, keyword-call wrappers (kwcall), and Base loader frames (include_string, IncludeInto on Julia 1.12+, etc.). Keep updating the candidate while still in Base/LinearAlgebra (last one wins) so attribution names the user-facing API (LinearAlgebra.svd) rather than an inner helper (Base.lt) or a loader (Base.include_string). Stop at the first user/other-package frame and return that candidate, or nothing for the plain message (e.g. user Main). Check LinearAlgebra before Base — stdlibs often parent to Base.
cuNumeric.allowpromotion Function
allowpromotion([true])
allowpromotion([true]) do
...
endUse this function to allow or disallow promotion to double precision, either globally or for the duration of the do block.
See also: @allowpromotion.
cuNumeric.allowscalar Function
allowscalar([true])
allowscalar([true]) do
...
endUse this function to allow or disallow scalar indexing, either globall or for the duration of the do block.
See also: @allowscalar.
cuNumeric.assertpromotion Method
assertpromotion(op)Assert that a certain operation op performs promotion to a wider type. If this is not allowed, an error will be thrown (assertpromotion).
cuNumeric.assertscalar Method
assertscalar(op::String)Assert that a certain operation op performs scalar indexing. If this is not allowed, an error will be thrown (allowscalar).
cuNumeric.@allowpromotion Macro
@allowpromotion() begin
# code that can use scalar indexing
endDenote which operations can use scalar indexing.
See also: allowpromotion.
cuNumeric.@allowscalar Macro
@allowscalar() begin
# code that can use scalar indexing
endDenote which operations can use scalar indexing.
See also: allowscalar.
cuNumeric.get_time_microseconds Method
Returns the timestamp in microseconds. Blocks on all Legate operations preceding the call to this function.
sourcecuNumeric.get_time_nanoseconds Method
Returns the timestamp in nanoseconds. Blocks on all Legate operations preceding the call to this function.
sourcecuNumeric.issue_execution_fence Method
issue_execution_fence(; block::Bool=false)Insert a Legate execution fence. block=true waits until prior ops finish; block=false only inserts a DAG node (Julia can keep submitting).
cuNumeric.issue_mapping_fence Method
issue_mapping_fence()Insert a Legate mapping fence (DAG-only; does not block the Julia caller).
sourcecuNumeric.map_cuda_type Method
map_cuda_type(::Type{T})::TypeRecursively rewrite cuNumeric broadcast-related types for fused-broadcast PTX (e.g. mapping NDArray{...} to CuStridedDeviceArray{...}). Dense @cuda_task uses ndarray_cuda_type → CUDA.jl CuDeviceArray instead.
cuNumeric.disable_gc! Method
disable_gc!()Disables the automatic garbage collection heuristics. This gives the user full control over memory management.
sourcecuNumeric.drain_pending_frees! Method
drain_pending_frees!()Destroy NDArray handles queued by finalizers. No-op off the launch thread. Called automatically from the op/allocation path, so user code rarely needs it.
sourcecuNumeric.init_gc! Method
init_gc!()Initializes the cuNumeric garbage collector by querying the available device memory and enabling the automatic GC heuristics.
sourcecuNumeric.insert_finalizers Method
insert_finalizers(block::Expr)Apply finalizer insertion to a begin ... end or :block expression.
cuNumeric.insert_finalizers Method
insert_finalizers(stmts::Vector)Insert cuNumeric.maybe_insert_delete(var) after the last use of each temporary variable.
cuNumeric.@accelerate Macro
@accelerate function f(args...) ... end
@accelerate begin ... end
@accelerate let ... end
@accelerate exprOptimize straight-line array code by coordinating CUDA broadcast fusion within expressions, fusion across broadcast statements, and scope-aware cleanup of materialized temporaries. Control flow and nested/anonymous functions are rejected.
Single-use producers may fuse across intervening read-only calculations when their inputs are unchanged. Unknown calls remain barriers. Function-form fusion across writes to other array arguments checks storage overlap at runtime and retains materialized intermediates when those arguments overlap.
Four forms determine which values must remain valid:
function (preferred): arguments and returned values are protected; non-returned locals may fuse into consumers or be freed after their last use.
begin: creates no new Julia scope, so every named binding stays live; eligible GPU chains may use one multi-output kernel that materializes them.let: creates a local scope; only the result escapes, so other locals may fuse away or be freed after their last use.expression: materializes and returns one expression; eligible operations fuse within it and transient temporaries are released.
@accelerate function step(u, v) # c may fuse away; the result is returned
c = u .* v
return c .^ 2
end
a, b = @accelerate begin # a and b both stay live, one GPU launch
a = x .* y
b = a .+ 1
(a, b)
end
result = @accelerate (x .+ y .* z)cuNumeric.@show_lifetimes Macro
@show_lifetimes function f(args...) ... end
@show_lifetimes begin ... end
@show_lifetimes let ... endPrint the exact expansion @accelerate produces for the same input (all forms), without running it; inserted frees are highlighted. Pure AST work.