JuliaSIMD / LoopVectorization.jl

Macro(s) for vectorizing loops.
MIT License
742 stars 66 forks source link

Trouble understanding @turbo and passing kwargs #493

Closed alex-s-gardner closed 1 year ago

alex-s-gardner commented 1 year ago

I've posted this question on Discourse but I'm now starting to wonder if it's specific to @turbo. I can see that the developer is overwhelmed.. hopefully my questions is helpful.

https://discourse.julialang.org/t/trouble-understanding-turbo-and-passing-kwargs/99023

Repeating hear so no one needs to follow the link.

After searching for awhile I'm stuck trying to understand why

This works fine

using LoopVectorization
x = rand(10)
y = rand(10)

function turbofun(x,y)
    return x*y
end

@turbo turbofun.(x, y)

and so does this

function turbofun2(x, y; a=2)
    return x * y
end

@turbo turbofun2.(x, y)

but not this

@turbo turbofun2.(x, y; a = 1)

I get a cryptic error:

LoadError: TypeError: in typeassert, expected Expr, got a value of type GlobalRef

I suspect the answer is obvious but I'll be damned if I can find an answer

chriselrod commented 1 year ago

The @turbo macro wasn't written to support kwargs like this. Feel free to make a PR fixing it, perhaps via

struct KwargCall{F,T}
    f::F
    x::T
end
@inline (f::KwargCall)(args...) = f.f(args...; f.x...)

Then

julia> function turbofun2(x, y; a=2)
           return x * y - a
       end
turbofun2 (generic function with 1 method)

julia> f = KwargCall(turbofun2, (a=10,));

julia> f(1,3)
-7

You can have the macro replace kwarg functions with KwargCall as a preprocessing step.

alex-s-gardner commented 1 year ago

Should I just add

"""
    KwargCall(fun, kwarg)

replace kwarg functions with KwargCall to allow passing to @turbo
"""
struct KwargCall{F,T}
  f::F
  x::T
end
@inline (f::KwargCall)(args...) = f.f(args...; f.x...)

to constructors.jl

Then export it... then add a description to the readme?

chriselrod commented 1 year ago

I would only add it to the package if you can make the macro automate applying it. If someone is doing so manually, they could just define an anonymous function. We'd rather avoid the anonymous function ourselves to support using @turbo inside generated functions.

If you don't want to update the macro, you could add using an anonymous function to the docs.

alex-s-gardner commented 1 year ago

A note and solution have been added in #494