Consider the following simplified code for Julia 0.6:
using BenchmarkTools
@noinline g(x) = x[1]
function f1(M, ::Type{Val{N}}) where N
s = 0
for j = 1:M
x = ntuple(i -> i + j, Val{N})
s += g(x)
end
return s
end
@generated function f2(M, ::Type{Val{N}}) where N
t = Expr(:tuple, [:($k+j) for k=1:N]...)
return quote
s = 0
for j = 1:M
x = $t
s += g(x)
end
return s
end
end
@btime f1(10000, Val{3})
@btime f2(10000, Val{3})
Timing results are
julia> @btime f1(10000, Val{3})
2.647 ms (77422 allocations: 1.33 MiB)
50015000
julia> @btime f2(10000, Val{3})
22.971 μs (0 allocations: 0 bytes)
50015000
Is there any way to create an NTuple performantly without resorting to generated functions?