GPUArrays.jl icon indicating copy to clipboard operation
GPUArrays.jl copied to clipboard

`Base.any` has different semantics from base implementation

Open ssz66666 opened this issue 7 years ago • 1 comments

The Base.mapreduce based implementation of Base.any and Base.all

Base.any(A::GPUArray{Bool}) = mapreduce(identity, |, A; init = false)

currently has slightly different semantics from the implementation in Base, in two ways:

  1. The base implementation specifies that any and all are short-circuiting reductions. Their semantics can differ if the predicate applied is side-effecting (note any(p, itr) which is implemented in #148 ). Would retaining the difference and clarifying it in documentation be reasonable?

  2. The base implementation implements three-valued logic if the input iterable contains missing values. We might well implement it with something like:

function any(p, itr::GPUArray)
    v, m = mapreduce(
        x -> begin
            b = p(x)
            ismissing(b) ? (false, true) : (b::Bool, false)
        end,
        ((v1, m1), (v2, m2)) ->
            (v1 || v2, m1 || m2),
        itr,
        init = (false, false)
    )
    v || (m ? missing : false)
end

function all(p, itr::GPUArray)
    v, m = mapreduce(
        x -> begin
            b = p(x)
            ismissing(b) ? (true, true) : (b::Bool, false)
        end,
        ((v1, m1), (v2, m2)) ->
            (v1 && v2, m1 || m2),
        itr,
        init = (true, false)
    )
    v && (m ? missing : true)
end

However, currently CuArrays doesn't handle missing values correctly yet (~~~I'll write an issue there as well~~~ see issue here). I don't know if it makes sense to implement this in GPUArrays and make CuArrays fail the test.

ssz66666 avatar Aug 28 '18 16:08 ssz66666

Revisiting this, I don't think we can provide the short-circuiting behavior without completely sacrificing performance. Documenting the difference would seem like a good thing to do.

maleadt avatar Feb 24 '20 13:02 maleadt