JuliaGPU / Metal.jl

Metal programming in Julia
MIT License
350 stars 38 forks source link

Base._cpow is type unstable #441

Open dominic-chang opened 2 weeks ago

dominic-chang commented 2 weeks ago

Broadcasting over Base._cpow with a MtlArray causes an error due to type promotion in Metalv1.3.0

MWE: ``` Base._cpow.(Metal.rand(Complex{Float32}, 1), 0.5f0) ``` ``` ERROR: InvalidIRError: compiling MethodInstance for (::Metal.var"#broadcast_linear#216")(::MtlDeviceVector{…}, ::Base.Broadcast.Broadcasted{…}) resulted in invalid LLVM IR Reason: unsupported call to an unknown function (call to gpu_malloc) Stacktrace: [1] malloc @ ~/.julia/packages/GPUCompiler/2CW9L/src/runtime.jl:85 [2] macro expansion @ ~/.julia/packages/GPUCompiler/2CW9L/src/runtime.jl:180 [3] macro expansion @ ./none:0 [4] box @ ./none:0 [5] box_float32 @ ~/.julia/packages/GPUCompiler/2CW9L/src/runtime.jl:209 [6] Int64 @ ./float.jl:912 [7] convert @ ./number.jl:7 [8] _cpow @ ./complex.jl:794 [9] _broadcast_getindex_evalf @ ./broadcast.jl:709 [10] _broadcast_getindex @ ./broadcast.jl:682 [11] getindex @ ./broadcast.jl:636 [12] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] Float64 @ ./float.jl:261 [2] < @ ./float.jl:601 [3] _cpow @ ./complex.jl:786 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] < @ ./float.jl:536 [2] < @ ./float.jl:601 [3] _cpow @ ./complex.jl:786 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] Float64 @ ./float.jl:261 [2] convert @ ./number.jl:7 [3] Complex @ ./complex.jl:14 [4] Complex @ ./complex.jl:43 [5] convert @ ./number.jl:7 [6] widen @ ./operators.jl:891 [7] inv @ ./complex.jl:471 [8] _cpow @ ./complex.jl:808 [9] _broadcast_getindex_evalf @ ./broadcast.jl:709 [10] _broadcast_getindex @ ./broadcast.jl:682 [11] getindex @ ./broadcast.jl:636 [12] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] Float64 @ ./float.jl:261 [2] convert @ ./number.jl:7 [3] Complex @ ./complex.jl:14 [4] Complex @ ./complex.jl:43 [5] convert @ ./number.jl:7 [6] widen @ ./operators.jl:891 [7] inv @ ./complex.jl:471 [8] _cpow @ ./complex.jl:808 [9] _broadcast_getindex_evalf @ ./broadcast.jl:709 [10] _broadcast_getindex @ ./broadcast.jl:682 [11] getindex @ ./broadcast.jl:636 [12] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] abs @ ./float.jl:610 [2] isinf @ ./float.jl:635 [3] inv @ ./complex.jl:472 [4] _cpow @ ./complex.jl:808 [5] _broadcast_getindex_evalf @ ./broadcast.jl:709 [6] _broadcast_getindex @ ./broadcast.jl:682 [7] getindex @ ./broadcast.jl:636 [8] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] isinf @ ./float.jl:635 [2] inv @ ./complex.jl:472 [3] _cpow @ ./complex.jl:808 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] abs @ ./float.jl:610 [2] isinf @ ./float.jl:635 [3] inv @ ./complex.jl:472 [4] _cpow @ ./complex.jl:808 [5] _broadcast_getindex_evalf @ ./broadcast.jl:709 [6] _broadcast_getindex @ ./broadcast.jl:682 [7] getindex @ ./broadcast.jl:636 [8] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] isinf @ ./float.jl:635 [2] inv @ ./complex.jl:472 [3] _cpow @ ./complex.jl:808 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] * @ ./float.jl:411 [2] literal_pow @ ./intfuncs.jl:332 [3] inv @ ./complex.jl:473 [4] _cpow @ ./complex.jl:808 [5] _broadcast_getindex_evalf @ ./broadcast.jl:709 [6] _broadcast_getindex @ ./broadcast.jl:682 [7] getindex @ ./broadcast.jl:636 [8] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] muladd @ ./float.jl:414 [2] inv @ ./complex.jl:473 [3] _cpow @ ./complex.jl:808 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] muladd @ ./float.jl:414 [2] inv @ ./complex.jl:473 [3] _cpow @ ./complex.jl:808 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] / @ ./float.jl:412 [2] inv @ ./number.jl:255 [3] inv @ ./complex.jl:473 [4] _cpow @ ./complex.jl:808 [5] _broadcast_getindex_evalf @ ./broadcast.jl:709 [6] _broadcast_getindex @ ./broadcast.jl:682 [7] getindex @ ./broadcast.jl:636 [8] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] * @ ./float.jl:411 [2] inv @ ./complex.jl:474 [3] _cpow @ ./complex.jl:808 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] - @ ./float.jl:407 [2] inv @ ./complex.jl:474 [3] _cpow @ ./complex.jl:808 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] * @ ./float.jl:411 [2] inv @ ./complex.jl:474 [3] _cpow @ ./complex.jl:808 [4] _broadcast_getindex_evalf @ ./broadcast.jl:709 [5] _broadcast_getindex @ ./broadcast.jl:682 [6] getindex @ ./broadcast.jl:636 [7] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] Float32 @ ./float.jl:258 [2] convert @ ./number.jl:7 [3] Complex @ ./complex.jl:14 [4] Complex @ ./complex.jl:43 [5] convert @ ./number.jl:7 [6] oftype @ ./essentials.jl:522 [7] inv @ ./complex.jl:474 [8] _cpow @ ./complex.jl:808 [9] _broadcast_getindex_evalf @ ./broadcast.jl:709 [10] _broadcast_getindex @ ./broadcast.jl:682 [11] getindex @ ./broadcast.jl:636 [12] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Reason: unsupported use of double value Stacktrace: [1] Float32 @ ./float.jl:258 [2] convert @ ./number.jl:7 [3] Complex @ ./complex.jl:14 [4] Complex @ ./complex.jl:43 [5] convert @ ./number.jl:7 [6] oftype @ ./essentials.jl:522 [7] inv @ ./complex.jl:474 [8] _cpow @ ./complex.jl:808 [9] _broadcast_getindex_evalf @ ./broadcast.jl:709 [10] _broadcast_getindex @ ./broadcast.jl:682 [11] getindex @ ./broadcast.jl:636 [12] broadcast_linear @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:89 Hint: catch this exception as `err` and call `code_typed(err; interactive = true)` to introspect the erronous code with Cthulhu.jl Stacktrace: [1] check_ir(job::GPUCompiler.CompilerJob{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}, args::LLVM.Module) @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/validation.jl:147 [2] macro expansion @ ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:382 [inlined] [3] macro expansion @ ~/.julia/packages/TimerOutputs/Lw5SP/src/TimerOutput.jl:253 [inlined] [4] macro expansion @ ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:381 [inlined] [5] @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/utils.jl:108 [6] emit_llvm @ ~/.julia/packages/GPUCompiler/2CW9L/src/utils.jl:106 [inlined] [7] @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:100 [8] codegen @ ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:82 [inlined] [9] compile(target::Symbol, job::GPUCompiler.CompilerJob; kwargs::@Kwargs{}) @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:79 [10] compile @ ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:74 [inlined] [11] (::Metal.var"#154#162"{GPUCompiler.CompilerJob{…}})(ctx::LLVM.Context) @ Metal ~/.julia/packages/Metal/UcSBS/src/compiler/compilation.jl:101 [12] JuliaContext(f::Metal.var"#154#162"{GPUCompiler.CompilerJob{…}}; kwargs::@Kwargs{}) @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:34 [13] JuliaContext(f::Function) @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/driver.jl:25 [14] macro expansion @ ~/.julia/packages/Metal/UcSBS/src/compiler/compilation.jl:100 [inlined] [15] macro expansion @ ~/.julia/packages/ObjectiveC/C7BVt/src/os.jl:264 [inlined] [16] compile(job::GPUCompiler.CompilerJob) @ Metal ~/.julia/packages/Metal/UcSBS/src/compiler/compilation.jl:98 [17] actual_compilation(cache::Dict{…}, src::Core.MethodInstance, world::UInt64, cfg::GPUCompiler.CompilerConfig{…}, compiler::typeof(Metal.compile), linker::typeof(Metal.link)) @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/execution.jl:237 [18] cached_compilation(cache::Dict{…}, src::Core.MethodInstance, cfg::GPUCompiler.CompilerConfig{…}, compiler::Function, linker::Function) @ GPUCompiler ~/.julia/packages/GPUCompiler/2CW9L/src/execution.jl:151 [19] macro expansion @ ~/.julia/packages/Metal/UcSBS/src/compiler/execution.jl:185 [inlined] [20] macro expansion @ ./lock.jl:267 [inlined] [21] mtlfunction(f::Metal.var"#broadcast_linear#216", tt::Type{Tuple{…}}; name::Nothing, kwargs::@Kwargs{}) @ Metal ~/.julia/packages/Metal/UcSBS/src/compiler/execution.jl:180 [22] mtlfunction @ ~/.julia/packages/Metal/UcSBS/src/compiler/execution.jl:178 [inlined] [23] macro expansion @ ~/.julia/packages/Metal/UcSBS/src/compiler/execution.jl:85 [inlined] [24] _copyto! @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:95 [inlined] [25] copyto! @ ~/.julia/packages/Metal/UcSBS/src/broadcast.jl:47 [inlined] [26] copy @ ~/.julia/packages/GPUArrays/qt4ax/src/host/broadcast.jl:29 [inlined] [27] materialize(bc::Base.Broadcast.Broadcasted{Metal.MtlArrayStyle{…}, Nothing, typeof(Base._cpow), Tuple{…}}) @ Base.Broadcast ./broadcast.jl:903 [28] top-level scope @ REPL[55]:1 Some type information was truncated. Use `show(err)` to see complete types. ```
maleadt commented 1 week ago

Yes, the currently implementation of Base._cpow looks GPU-incompatible, or at least Metal.jl-incompatible. We would need a custom function that doesn't fall back to Float64 for its internal computations, but I'm unfamiliar with the operation.

dominic-chang commented 1 week ago

Yeah, I was thinking maybe the glibc implementation of cpowf

maleadt commented 1 week ago

Musl defines cpowf(z,c) as cexpf(c * clogf(z)); maybe that would work here if exp(::Float32) and log(::Float32) work as expected?