Experiments in speeding up runtime dispatch for integer value specialization

Here is a slightly convoluted solution, using a generated function which uses a macro which calls a function to construct the expression:

function valuedispatch_expr(
        ::Val{lower}, ::Val{upper}, fun, val,
    ) where {lower, upper}
    if lower >= upper
        return :( $fun(Val($upper)) )
    end
    midpoint = lower + div(upper - lower, 2)
    expr_a = valuedispatch_expr(Val(lower), Val(midpoint), fun, val)
    expr_b = valuedispatch_expr(Val(midpoint+1), Val(upper), fun, val)
    quote
        if $val <= $midpoint
            $expr_a
        else
            $expr_b
        end
    end
end

macro valuedispatch(lower::Int, upper::Int, fun, val)
    valuedispatch_expr(Val(lower), Val(upper), esc(fun), esc(val))
end

@generated function valuedispatch_gen(
        ::Val{lower}, ::Val{upper}, fun, val,
    ) where {lower, upper}
    :( @valuedispatch($lower, $upper, fun, val) )
end

## Timings
N = rand(1:32, 10000)
@btime foreach(n -> myfunc(Val(n)), $N)
@btime foreach(n -> valuedispatch1to32(myfunc, n), $N)
@btime foreach(n -> valuedispatch(Val(1), Val(32), myfunc, n), $N)
@btime foreach(n -> valuedispatch_gen(Val(1), Val(32), myfunc, n), $N)

  5.518 ms (10000 allocations: 156.25 KiB)
  1.295 ms (0 allocations: 0 bytes)
  1.844 ms (10000 allocations: 156.25 KiB)
  1.282 ms (0 allocations: 0 bytes)
1 Like