Hello! Working with Metal.jl I have encountered the following issue. When computing the inverse of ComplexF32 numbers, some Float64 numbers seem to sneak in and cause Metal.jl to throw an error.
Here's a minimal example:
using Metal
function mwe(T)
d = mtl(rand(T, 2, 2))
return inv.(d)
end
If T = Float32, everything works fine. If T = ComplexF32 instead, I get the following error:
julia> mwe(ComplexF32)
ERROR: InvalidIRError: compiling MethodInstance for (::Metal.var"#broadcast_2d#_copyto!##2")(::MtlDeviceMatrix{ComplexF32, 1}, ::Base.Broadcast.Broadcasted{Metal.MtlArrayStyle{…}, Tuple{…}, typeof(inv), Tuple{…}}) resulted in invalid LLVM IR
Reason: unsupported use of double value
Stacktrace:
[1] Float64
@ ./float.jl:345
[2] convert
@ ./number.jl:7
[3] Complex
@ ./complex.jl:14
[4] Complex
@ ./complex.jl:43
[5] convert
@ ./number.jl:7
[6] widen
@ ./operators.jl:946
[7] inv
@ ./complex.jl:474
[8] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[9] _broadcast_getindex
@ ./broadcast.jl:672
[10] _getindex
@ ./broadcast.jl:620
[11] getindex
@ ./broadcast.jl:616
[12] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] Float64
@ ./float.jl:345
[2] convert
@ ./number.jl:7
[3] Complex
@ ./complex.jl:14
[4] Complex
@ ./complex.jl:43
[5] convert
@ ./number.jl:7
[6] widen
@ ./operators.jl:946
[7] inv
@ ./complex.jl:474
[8] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[9] _broadcast_getindex
@ ./broadcast.jl:672
[10] _getindex
@ ./broadcast.jl:620
[11] getindex
@ ./broadcast.jl:616
[12] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] abs
@ ./float.jl:699
[2] isinf
@ ./float.jl:724
[3] inv
@ ./complex.jl:475
[4] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[5] _broadcast_getindex
@ ./broadcast.jl:672
[6] _getindex
@ ./broadcast.jl:620
[7] getindex
@ ./broadcast.jl:616
[8] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] isinf
@ ./float.jl:724
[2] inv
@ ./complex.jl:475
[3] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[4] _broadcast_getindex
@ ./broadcast.jl:672
[5] _getindex
@ ./broadcast.jl:620
[6] getindex
@ ./broadcast.jl:616
[7] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] abs
@ ./float.jl:699
[2] isinf
@ ./float.jl:724
[3] inv
@ ./complex.jl:475
[4] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[5] _broadcast_getindex
@ ./broadcast.jl:672
[6] _getindex
@ ./broadcast.jl:620
[7] getindex
@ ./broadcast.jl:616
[8] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] isinf
@ ./float.jl:724
[2] inv
@ ./complex.jl:475
[3] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[4] _broadcast_getindex
@ ./broadcast.jl:672
[5] _getindex
@ ./broadcast.jl:620
[6] getindex
@ ./broadcast.jl:616
[7] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] muladd
@ ./float.jl:500
[2] inv
@ ./complex.jl:476
[3] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[4] _broadcast_getindex
@ ./broadcast.jl:672
[5] _getindex
@ ./broadcast.jl:620
[6] getindex
@ ./broadcast.jl:616
[7] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] *
@ ./float.jl:497
[2] literal_pow
@ ./intfuncs.jl:437
[3] inv
@ ./complex.jl:476
[4] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[5] _broadcast_getindex
@ ./broadcast.jl:672
[6] _getindex
@ ./broadcast.jl:620
[7] getindex
@ ./broadcast.jl:616
[8] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] muladd
@ ./float.jl:500
[2] inv
@ ./complex.jl:476
[3] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[4] _broadcast_getindex
@ ./broadcast.jl:672
[5] _getindex
@ ./broadcast.jl:620
[6] getindex
@ ./broadcast.jl:616
[7] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] /
@ ./float.jl:498
[2] inv
@ ./number.jl:255
[3] inv
@ ./complex.jl:476
[4] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[5] _broadcast_getindex
@ ./broadcast.jl:672
[6] _getindex
@ ./broadcast.jl:620
[7] getindex
@ ./broadcast.jl:616
[8] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] -
@ ./float.jl:493
[2] inv
@ ./complex.jl:477
[3] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[4] _broadcast_getindex
@ ./broadcast.jl:672
[5] _getindex
@ ./broadcast.jl:620
[6] getindex
@ ./broadcast.jl:616
[7] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] *
@ ./float.jl:497
[2] inv
@ ./complex.jl:477
[3] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[4] _broadcast_getindex
@ ./broadcast.jl:672
[5] _getindex
@ ./broadcast.jl:620
[6] getindex
@ ./broadcast.jl:616
[7] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] Float32
@ ./float.jl:342
[2] convert
@ ./number.jl:7
[3] Complex
@ ./complex.jl:14
[4] Complex
@ ./complex.jl:43
[5] convert
@ ./number.jl:7
[6] oftype
@ ./essentials.jl:666
[7] inv
@ ./complex.jl:477
[8] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[9] _broadcast_getindex
@ ./broadcast.jl:672
[10] _getindex
@ ./broadcast.jl:620
[11] getindex
@ ./broadcast.jl:616
[12] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] *
@ ./float.jl:497
[2] inv
@ ./complex.jl:477
[3] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[4] _broadcast_getindex
@ ./broadcast.jl:672
[5] _getindex
@ ./broadcast.jl:620
[6] getindex
@ ./broadcast.jl:616
[7] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Reason: unsupported use of double value
Stacktrace:
[1] Float32
@ ./float.jl:342
[2] convert
@ ./number.jl:7
[3] Complex
@ ./complex.jl:14
[4] Complex
@ ./complex.jl:43
[5] convert
@ ./number.jl:7
[6] oftype
@ ./essentials.jl:666
[7] inv
@ ./complex.jl:477
[8] _broadcast_getindex_evalf
@ ./broadcast.jl:699
[9] _broadcast_getindex
@ ./broadcast.jl:672
[10] _getindex
@ ./broadcast.jl:620
[11] getindex
@ ./broadcast.jl:616
[12] broadcast_2d
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:119
Hint: catch this exception as `err` and call `code_typed(err; interactive = true)` to introspect the erroneous code with Cthulhu.jl
Stacktrace:
[1] check_ir(job::GPUCompiler.CompilerJob{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}, args::LLVM.Module)
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/validation.jl:170
[2] emit_llvm(job::GPUCompiler.CompilerJob; kwargs::@Kwargs{})
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:455
[3] emit_llvm(job::GPUCompiler.CompilerJob)
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:200
[4] compile_unhooked(output::Symbol, job::GPUCompiler.CompilerJob; kwargs::@Kwargs{})
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:101
[5] compile_unhooked
@ ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:80 [inlined]
[6] #compile#118
@ ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:67 [inlined]
[7] compile(target::Symbol, job::GPUCompiler.CompilerJob)
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:55
[8] #invoke_frozen#19
@ ~/.julia/packages/Metal/TF981/src/initialization.jl:15 [inlined]
[9] invoke_frozen
@ ~/.julia/packages/Metal/TF981/src/initialization.jl:13 [inlined]
[10] macro expansion
@ ~/.julia/packages/Metal/TF981/src/compiler/compilation.jl:436 [inlined]
[11] macro expansion
@ ~/.julia/packages/ObjectiveC/ectoz/src/os.jl:264 [inlined]
[12] (::Metal.var"#compile##0#compile##1"{GPUCompiler.CompilerJob{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}})(ctx::LLVM.Context)
@ Metal ~/.julia/packages/Metal/TF981/src/compiler/compilation.jl:435
[13] JuliaContext(f::Metal.var"#compile##0#compile##1"{GPUCompiler.CompilerJob{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}}; kwargs::@Kwargs{})
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:34
[14] JuliaContext(f::Function)
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/driver.jl:25
[15] compile(job::GPUCompiler.CompilerJob)
@ Metal ~/.julia/packages/Metal/TF981/src/compiler/compilation.jl:434
[16] actual_compilation(cache::Dict{…}, src::Core.MethodInstance, world::UInt64, cfg::GPUCompiler.CompilerConfig{…}, compiler::typeof(Metal.compile), linker::typeof(Metal.link))
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/execution.jl:245
[17] cached_compilation(cache::Dict{…}, src::Core.MethodInstance, cfg::GPUCompiler.CompilerConfig{…}, compiler::Function, linker::Function)
@ GPUCompiler ~/.julia/packages/GPUCompiler/QgckP/src/execution.jl:159
[18] macro expansion
@ ~/.julia/packages/Metal/TF981/src/compiler/execution.jl:199 [inlined]
[19] macro expansion
@ ./lock.jl:376 [inlined]
[20] mtlfunction(f::Metal.var"#broadcast_2d#_copyto!##2", tt::Type{Tuple{MtlDeviceMatrix{…}, Base.Broadcast.Broadcasted{…}}}; name::Nothing, kwargs::@Kwargs{})
@ Metal ~/.julia/packages/Metal/TF981/src/compiler/execution.jl:194
[21] mtlfunction
@ ~/.julia/packages/Metal/TF981/src/compiler/execution.jl:192 [inlined]
[22] macro expansion
@ ~/.julia/packages/Metal/TF981/src/compiler/execution.jl:89 [inlined]
[23] _copyto!
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:128 [inlined]
[24] copyto!
@ ~/.julia/packages/Metal/TF981/src/broadcast.jl:52 [inlined]
[25] copy
@ ~/.julia/packages/GPUArrays/VNJ6B/src/host/broadcast.jl:34 [inlined]
[26] materialize(bc::Base.Broadcast.Broadcasted{Metal.MtlArrayStyle{2, Metal.PrivateStorage}, Nothing, typeof(inv), Tuple{MtlMatrix{ComplexF32, Metal.PrivateStorage}}})
@ Base.Broadcast ./broadcast.jl:894
[27] mwe(T::Type)
@ Main ~/Projects/mwe.jl:4
[28] top-level scope
@ REPL[3]:1
[29] top-level scope
@ ~/.julia/packages/Metal/TF981/src/initialization.jl:110
Some type information was truncated. Use `show(err)` to see complete types.
The stacktrace is huge, but “Reason: unsupported use of double value” appears frequently. In this Julia Discourse thread it was suggested that widen is the culprit.
Adding @fastmath before inv.(d) in the function above makes mwe work, but it doesn’t seem like a proper solution. I won’t always be able to do this, for example if inv is called inside a package function.
Hello! Working with Metal.jl I have encountered the following issue. When computing the inverse of
ComplexF32numbers, someFloat64numbers seem to sneak in and cause Metal.jl to throw an error.Here's a minimal example:
If
T = Float32, everything works fine. IfT = ComplexF32instead, I get the following error:The stacktrace is huge, but “Reason: unsupported use of double value” appears frequently. In this Julia Discourse thread it was suggested that
widenis the culprit.Adding
@fastmathbeforeinv.(d)in the function above makesmwework, but it doesn’t seem like a proper solution. I won’t always be able to do this, for example ifinvis called inside a package function.