GPUArrays.jl
GPUArrays.jl copied to clipboard
Broadcast of function with errors results in CPU execution
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