Skip to content

Support ComplexF32 division #736

@albertomercurio

Description

@albertomercurio

Hello,

I have this simple example

using Metal

x = Metal.rand(ComplexF32, 100)
y = Metal.rand(ComplexF32, 100)

x ./ y

This gives the error

Details
LoadError: InvalidIRError: compiling MethodInstance for (::Metal.var"#broadcast_linear#_copyto!##1")(::MtlDeviceVector{ComplexF32, 1}, ::Base.Broadcast.Broadcasted{Metal.MtlArrayStyle{1, Metal.PrivateStorage}, Tuple{Base.OneTo{Int64}}, typeof(/), Tuple{Base.Broadcast.Extruded{MtlDeviceVector{ComplexF32, 1}, Tuple{Bool}, Tuple{Int64}}, Base.Broadcast.Extruded{MtlDeviceVector{ComplexF32, 1}, Tuple{Bool}, Tuple{Int64}}}}) 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] /
    @ ./complex.jl:377
  [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_linear
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
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] /
    @ ./complex.jl:377
  [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_linear
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] abs
   @ ./float.jl:699
 [2] isinf
   @ ./float.jl:724
 [3] /
   @ ./complex.jl:379
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] isinf
   @ ./float.jl:724
 [2] /
   @ ./complex.jl:379
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] abs
   @ ./float.jl:699
 [2] isinf
   @ ./float.jl:724
 [3] /
   @ ./complex.jl:379
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] isinf
   @ ./float.jl:724
 [2] /
   @ ./complex.jl:379
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
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] /
    @ ./complex.jl:378
  [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_linear
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
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] /
    @ ./complex.jl:378
  [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_linear
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] *
   @ ./float.jl:497
 [2] literal_pow
   @ ./intfuncs.jl:437
 [3] /
   @ ./complex.jl:385
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] muladd
   @ ./float.jl:500
 [2] /
   @ ./complex.jl:385
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] muladd
   @ ./float.jl:500
 [2] /
   @ ./complex.jl:385
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] /
   @ ./float.jl:498
 [2] inv
   @ ./number.jl:255
 [3] /
   @ ./complex.jl:385
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] *
   @ ./float.jl:497
 [2] /
   @ ./complex.jl:386
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] muladd
   @ ./float.jl:500
 [2] /
   @ ./complex.jl:386
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] muladd
   @ ./float.jl:500
 [2] /
   @ ./complex.jl:386
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] muladd
   @ ./float.jl:500
 [2] /
   @ ./complex.jl:387
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] muladd
   @ ./float.jl:500
 [2] /
   @ ./complex.jl:387
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] muladd
   @ ./float.jl:500
 [2] /
   @ ./complex.jl:387
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] *
   @ ./float.jl:497
 [2] /
   @ ./complex.jl:388
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
Reason: unsupported use of double value
Stacktrace:
 [1] *
   @ ./float.jl:497
 [2] /
   @ ./complex.jl:388
 [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_linear
   @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
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] /
    @ ./complex.jl:388
  [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_linear
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
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] /
    @ ./complex.jl:388
  [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_linear
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:97
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/OCZFZ/src/validation.jl:167
  [2] emit_llvm(job::GPUCompiler.CompilerJob; kwargs::@Kwargs{})
    @ GPUCompiler ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:420
  [3] emit_llvm
    @ ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:182 [inlined]
  [4] compile_unhooked(output::Symbol, job::GPUCompiler.CompilerJob; kwargs::@Kwargs{})
    @ GPUCompiler ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:95
  [5] compile_unhooked
    @ ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:80 [inlined]
  [6] compile(target::Symbol, job::GPUCompiler.CompilerJob; kwargs::@Kwargs{})
    @ GPUCompiler ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:67
  [7] compile
    @ ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:55 [inlined]
  [8] (::Metal.var"#compile##0#compile##1"{GPUCompiler.CompilerJob{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}})(ctx::LLVM.Context)
    @ Metal ~/.julia/packages/Metal/EFzAO/src/compiler/compilation.jl:173
  [9] JuliaContext(f::Metal.var"#compile##0#compile##1"{GPUCompiler.CompilerJob{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}}; kwargs::@Kwargs{})
    @ GPUCompiler ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:34
 [10] JuliaContext(f::Function)
    @ GPUCompiler ~/.julia/packages/GPUCompiler/OCZFZ/src/driver.jl:25
 [11] macro expansion
    @ ~/.julia/packages/Metal/EFzAO/src/compiler/compilation.jl:172 [inlined]
 [12] macro expansion
    @ ~/.julia/packages/ObjectiveC/UNTzb/src/os.jl:264 [inlined]
 [13] compile(job::GPUCompiler.CompilerJob)
    @ Metal ~/.julia/packages/Metal/EFzAO/src/compiler/compilation.jl:170
 [14] actual_compilation(cache::Dict{Any, Any}, src::Core.MethodInstance, world::UInt64, cfg::GPUCompiler.CompilerConfig{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}, compiler::typeof(Metal.compile), linker::typeof(Metal.link))
    @ GPUCompiler ~/.julia/packages/GPUCompiler/OCZFZ/src/execution.jl:245
 [15] cached_compilation(cache::Dict{Any, Any}, src::Core.MethodInstance, cfg::GPUCompiler.CompilerConfig{GPUCompiler.MetalCompilerTarget, Metal.MetalCompilerParams}, compiler::Function, linker::Function)
    @ GPUCompiler ~/.julia/packages/GPUCompiler/OCZFZ/src/execution.jl:159
 [16] macro expansion
    @ ~/.julia/packages/Metal/EFzAO/src/compiler/execution.jl:189 [inlined]
 [17] macro expansion
    @ ./lock.jl:376 [inlined]
 [18] mtlfunction(f::Metal.var"#broadcast_linear#_copyto!##1", tt::Type{Tuple{MtlDeviceVector{ComplexF32, 1}, Base.Broadcast.Broadcasted{Metal.MtlArrayStyle{1, Metal.PrivateStorage}, Tuple{Base.OneTo{Int64}}, typeof(/), Tuple{Base.Broadcast.Extruded{MtlDeviceVector{ComplexF32, 1}, Tuple{Bool}, Tuple{Int64}}, Base.Broadcast.Extruded{MtlDeviceVector{ComplexF32, 1}, Tuple{Bool}, Tuple{Int64}}}}}}; name::Nothing, kwargs::@Kwargs{})
    @ Metal ~/.julia/packages/Metal/EFzAO/src/compiler/execution.jl:184
 [19] mtlfunction
    @ ~/.julia/packages/Metal/EFzAO/src/compiler/execution.jl:182 [inlined]
 [20] macro expansion
    @ ~/.julia/packages/Metal/EFzAO/src/compiler/execution.jl:85 [inlined]
 [21] _copyto!
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:104 [inlined]
 [22] copyto!
    @ ~/.julia/packages/Metal/EFzAO/src/broadcast.jl:52 [inlined]
 [23] copy
    @ ~/.julia/packages/GPUArrays/lOLhM/src/host/broadcast.jl:29 [inlined]
 [24] materialize(bc::Base.Broadcast.Broadcasted{Metal.MtlArrayStyle{1, Metal.PrivateStorage}, Nothing, typeof(/), Tuple{MtlVector{ComplexF32, Metal.PrivateStorage}, MtlVector{ComplexF32, Metal.PrivateStorage}}})
    @ Base.Broadcast ./broadcast.jl:894

Apparently the GPUCompiler doesn't know how to handle the simple method

function /(z::Complex{T}, w::Complex{T}) where {T<:Union{Float16,Float32}}
    c, d = reim(widen(w))
    a, b = reim(widen(z))
    if (isinf(c) | isinf(d))
        if isfinite(z)
            return complex(zero(T)*sign(real(z))*sign(real(w)), -zero(T)*sign(imag(z))*sign(imag(w)))
        end
        return T(NaN)+T(NaN)*im
    end
    mag = inv(muladd(c, c, d^2))
    re_part = muladd(a, c, b*d)
    im_part = muladd(b, c, -a*d)
    return oftype(z, Complex(re_part*mag, im_part*mag))
end

Do you have any idea? In principle it is splitting the complex number into real and imag parts, each of them is Float32.

Importantly, the multiplication works x .* y.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions