Untyped keyword arguments

question
#1

Summary: Is there any performance benefit to annotating keyword arguments with types?

I understand that typed keyword arguments are as efficient as positional arguments. Is that correct?
But what are the performance characteristics of untyped keyword arguments compared to typed keyword arguments?

My understanding is that keyword arguments do not participate in dispatch. But do method calls with different typed keyword arguments get compiled separately? (as is the case for differently typed positional arguments). If so then does this mean that explicitly typing keyword args in function definition does not help performance?

The following is my attempt as investigate this - very likely flawed.
In any case, it seems all four invocations have the same benchmark time.
@code_warntype seems the same for f1, f2.

function f1(A; i::Int=1)
    return A[i]
end

function f2(A; i=1)
    return A[i]
end

using BenchmarkTools
B = [1,2,3]
@btime f1($B)
@btime f2($B)

@btime f1($B, i=2)
@btime f2($B, i=2)
#2

No. Keyword arguments do not participate in dispatch, but, like regular arguments, they get specialized on the actual type of the values. I believe you could demonstrate by timing:

function f3(A; @nospecialize i=1)
    return A[i]
end
2 Likes
#3

OK thanks, that’s good to know.

However, the @nospecialize example didn’t show any timing difference for me.

On a related note, I naively wanted to use a “sentinel” value of the same type for a keyword argument, thinking this would be type-stable (function g below)
But now I realize that by using a different type, a branch could be elided at compile time, effectively giving static dispatch (function h below)

function g(A; i=0)
    if i == 0
        return 1.0
    else
        return A[i]
    end
end

function h(A; i=nothing)
    if isa(i, Nothing)
        return 1.0
    else
        return A[i]
    end
end

@code_warntype shows h(A, i=2) and h(A, i=nothing) are type-stable.

I think i === nothing could also work here, but isa(i, Nothing) produces cleaner output from @code_warntype