UnsafeArrays.jl

Stack-allocated pointer-based array views
Author JuliaArrays
Popularity
31 Stars
Updated Last
4 Months Ago
Started In
February 2018

UnsafeArrays.jl

License Build Status Codecov

UnsafeArrays provides stack-allocated pointer-based array views for Julia.

This package is mainly intended as a workaround for Julia issue #14955 (non-allocating array views). This issue is solved in Julia v1.5 and higher.

In Julia versions 1.4 and below, the Julia compiler is sometimes able to elide heap-allocation of views in some, but cannot always do so. If the view can't be elided, the relative cost of allocation and garbage collection of a views is usually still small, in single-threaded applications. But in in multi-threaded applications that use a large number of views, this cost can quickly become prohibitive and views must either be avoided (resulting in more lengthy and less readable code), or some form stack-allocated views must be used for decent scalability. UnsafeArrays provides such a solution. With Julia v1.5 and higher, using UnsafeArrays should not be necessary and is not likely to result in significant performance gains.

Starting with v1.5, Julia can allocate immutable objects that contain heap references on the stack, making UnsafeArrays.jl largely unnecessary. It may still be useful as a lightweight wrapper for memory allocated outside of Julia's memory management.

Example:

using Base.Threads, LinearAlgebra

function colnorms!(dest::AbstractVector, A::AbstractMatrix)
    @threads for i in axes(A, 2)
        dest[i] = norm(view(A, :, i))
    end
    dest
end

A = rand(50, 100000);
dest = similar(A, size(A, 2));

colnorms!(dest, A)

The above will run fine on a single thread, but scales badly on multiple threads. Use the @uviews macro provided by UnsafeArrays to replace A with an UnsafeArray within the scope of the macro. An UnsafeArray is stack-allocated, and so are all views of it, e.g. within colnorms!:

using UnsafeArrays

@uviews A begin
    colnorms!(dest, A)
end

@uviews protects the original array A from GC, so the above is safe as long as the original array is not reallocated (via resize!, etc.) while the scope of @uviews is active.

UnsafeArrays only supports bits types. If the element type of an array is not compatible, @uviews will simply use the original array.

UnsafeArrays also provides:

  • A non macro-variant uviews()

  • A function uview() to directly get an unsafe view (with optional sub-indexing) of an array.

  • The type UnsafeArray itself, instances can be constructed from a data pointer and array size. The data type must be a bits type.

When using uview() and UnsafeArray directly, the user is responsible for preserving the memory accessed from garbage collection.