For some reason the where N in f(x) is causing allocations:
julia> f(x) where N = √sum(abs2,x .- 2^6) - 2^5
f (generic function with 1 method)
julia> @btime f($x)
22.725 ns (2 allocations: 48 bytes)
78.32565875726226
julia> f(x) = √sum(abs2,x .- 2^6) - 2^5
f (generic function with 1 method)
julia> @btime f($x)
5.862 ns (0 allocations: 0 bytes)
78.32565875726226
I had to change that to get what you report:
julia> @benchmark oint($f,$n_auto,$p)
BechmarkTools.Trial: 10000 samples with 1 evaluations.
Range (min … max): 114.826 μs … 284.301 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 115.015 μs ┊ GC (median): 0.00%
Time (mean ± σ): 117.534 μs ± 9.510 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
█ ▁ ▁ ▁ ▁ ▁
█▆█▆▇▇▆▆█▃▄▃█▄▁▄▁▇▆▇▇▇▇▅▅▆▅▇▅▅▆▅▇▆▃▅▅▅▇▆▆▆▅▅▆▆▅▆▅▅▅█▄▅▅▅▅▇█▇▆ █
115 μs Histogram: log(frequency) by time 160 μs <
Memory estimate: 96 bytes, allocs estimate: 1.
Then, with these changes, you get 0 allocations:
julia> function oint(f,n,p::Array{T,N}) where {T,N}
s = zeros(SVector{N,T}) # static vector here
for I ∈ CartesianIndices(p)
x = SVector{N,T}(ntuple(i->I[i],N)) # initialize svector with size defined at compile time
d = f(x)::Float64
abs(d) ≤ 1 && (s += n(x).*p[I]*(1+cos(π*d))/2) # remove a dot in s .+=
end
return s
end
oint (generic function with 1 method)
julia> @benchmark oint($f,$n_auto,$p)
BechmarkTools.Trial: 10000 samples with 1 evaluations.
Range (min … max): 105.190 μs … 221.240 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 105.372 μs ┊ GC (median): 0.00%
Time (mean ± σ): 107.170 μs ± 7.259 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
█ ▃▂ ▁ ▁
█▆▅▆▇████▆▆▄▅█▄▁▄▆▆▄▅▄▅▇▅▅▅▅▇▁▅▃▃▄▇▄▃▄▅▄▇▅▅▄▅▃▇▄▃▅▃▄▄▇▄▅▃▃▄▅█ █
105 μs Histogram: log(frequency) by time 145 μs <
Memory estimate: 0 bytes, allocs estimate: 0.