In-place mutation with Referenceables.jl

using CUDA
using Folds
using FoldsCUDA
using Referenceables: referenceable

Simple mutation

function increment_folds!(xs)
    Folds.foreach(referenceable(xs)) do x
        x[] += 1
    end
    return xs
end

if has_cuda_gpu()
    xs = CuArray(1:5)
else
    xs = Array(1:5)
end

collect(increment_folds!(xs))
5-element Vector{Int64}:
 2
 3
 4
 5
 6

This can also be written with FLoops.jl:

using FLoops

function increment_floops!(xs, ex = nothing)
    @floop ex for x in referenceable(xs)
        x[] += 1
    end
    return xs
end

collect(increment_floops!(xs))
5-element Vector{Int64}:
 3
 4
 5
 6
 7

Fusing reduction and mutationg

Computing sum(f, xs) and f.(xs) in one go:

function mutation_with_folds(f, xs)
    ys = similar(xs)
    s = Folds.sum(zip(referenceable(ys), xs)) do (r, x)
        r[] = y = f(x)
        return y
    end
    return s, ys
end
if has_cuda_gpu()
    xs = CuArray(1:5)
else
    xs = Array(1:5)
end

s, ys = mutation_with_folds(x -> x^2, xs)
s
55
collect(ys)
5-element Vector{Int64}:
  1
  4
  9
 16
 25

An equilvalent computaton with FLoops.jl:

using FLoops

function mutation_with_floop(f, xs)
    ys = similar(xs)
    z = zero(eltype(ys))
    @floop for (r, x) in zip(referenceable(ys), xs)
        r[] = y = f(x)
        @reduce(s = z + y)
    end
    return s, ys
end
@assert mutation_with_folds(x -> x^2, xs) == (s, ys)

This page was generated using Literate.jl.