Skip to content

Broadcast of function with errors results in CPU execution #146

@maleadt

Description

@maleadt

This is a fun one, not sure about the solution but it hurts usability. Take the following MWE:

using CuArrays
import CUDAnative

using ForwardDiff

@inline function CUDAnative.erf(input::ForwardDiff.Dual{T}) where T
    x = ForwardDiff.value(input)
    val = CUDAnative.erf(x)
    deriv = CUDAnative.sqrt(π)
    return deriv
end

a = CuArray{Float32}(1:1)
CUDAnative.erf.(a) # works

b = CuArray(ForwardDiff.Dual.(1f0:1f0, 1f0))
CUDAnative.erf.(b) # crashes

This crashes with FATAL ERROR: Symbol "__nv_erff"not found, indicating CPU execution of the GPU kernel. As it turns out, CUDAnative.erf(input::ForwardDiff.Dual{T}) contains an error: CUDAnative.erf is not defined for Irrational, meaning the call to CUDAnative.sqrt(π) (and the entire method) infers to Bottom. As a result, Broadcast.combine_eltypes works with Union{}, which isn't a concrete type, calling the fallback broadcast operation that uses scalar indexing.

I'm not sure whether we should just classify this under "user error" and move along, or try to catch this. For some reason, it doesn't seem caught by allowscalar(false) either:

julia> b[1]
ERROR: scalar getindex is disabled
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] assertscalar at /home/tbesard/Julia/GPUArrays/src/indexing.jl:6 [inlined]
 [3] getindex(::CuArray{ForwardDiff.Dual{Nothing,Float32,1},1}, ::Int64) at /home/tbesard/Julia/GPUArrays/src/indexing.jl:29
 [4] top-level scope at none:0

julia> CUDAnative.erf.(b)
FATAL ERROR: Symbol "__nv_erff"not found

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions