You should probably use CartesianIndex for this. They are fixed-length, and can be used directly in place of some or all of the indices without the need for splatting.
More importantly, they are also immutable, which means they require no allocation, and may also open up more compiler optimizations.
Some benchmarks (CartesianIndex used in test3 below):
function test1(latt1)
N = size(latt1,1)
mvup!(xvec, d) = xvec[d] == N ? xvec[d] = 1 : xvec[d] += 1
obs = 0.0
for d = 1:3, i3 = 1:N, i2 = 1:N, i1 = 1:N
x = [i1, i2, i3]
mvup!(x, d)
obs += latt1[i1, i2, i3, d] * latt1[x[1], x[2], x[3], d]
end
obs
end
function test2(latt1)
N = size(latt1,1)
mvup!(xvec, d) = xvec[d] == N ? xvec[d] = 1 : xvec[d] += 1
links = Iterators.product(1:N, 1:N, 1:N, 1:3)
obs = 0.0
for link in links
x = [link[1:3]...]
d = link[4]
mvup!(x, d)
obs += latt1[link...] * latt1[x[1], x[2], x[3], d]
end
end
function test3(latt1)
N = size(latt1,1)
mvup(x::CartesianIndex, d) = CartesianIndex(ntuple(i -> i==d ? mod1(x[i]+1,N) : x[i], length(x)))
obs = 0.0
for d = 1:3, x in CartesianIndex(1, 1, 1):CartesianIndex(N,N,N)
obs += latt1[x, d] * latt1[mvup(x, d), d]
end
obs
end
julia> @benchmark test1(latt1) setup=(latt1=rand(250,250,250,3))
BechmarkTools.Trial: 2 samples with 1 evaluations.
Range (min … max): 3.444 s … 3.508 s ┊ GC (min … max): 13.96% … 18.72%
Time (median): 3.476 s ┊ GC (median): 16.36%
Time (mean ± σ): 3.476 s ± 45.332 ms ┊ GC (mean ± σ): 16.36% ± 3.37%
█ ██
█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁
3.44 s Histogram: frequency by time 3.51 s <
Memory estimate: 4.89 GiB, allocs estimate: 46875000.
julia> @benchmark test2(latt1) setup=(latt1=rand(250,250,250,3))
BechmarkTools.Trial: 2 samples with 1 evaluations.
Range (min … max): 3.363 s … 3.387 s ┊ GC (min … max): 19.70% … 14.64%
Time (median): 3.375 s ┊ GC (median): 17.16%
Time (mean ± σ): 3.375 s ± 17.231 ms ┊ GC (mean ± σ): 17.16% ± 3.58%
█ ██
█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁
3.36 s Histogram: frequency by time 3.39 s <
Memory estimate: 4.89 GiB, allocs estimate: 46875000.
julia> @benchmark test3(latt1) setup=(latt1=rand(250,250,250,3))
BechmarkTools.Trial: 10 samples with 1 evaluations.
Range (min … max): 389.657 ms … 416.891 ms ┊ GC (min … max): 0.00% … 0.00%
Time (median): 397.419 ms ┊ GC (median): 0.00%
Time (mean ± σ): 400.080 ms ± 9.444 ms ┊ GC (mean ± σ): 0.00% ± 0.00%
▁ █ ▁ ▁ ▁ ▁ ▁ ▁ ▁▁
█▁▁▁▁█▁█▁▁▁▁▁█▁▁▁▁▁▁▁█▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁█ ▁
390 ms Histogram: frequency by time 417 ms <
Memory estimate: 0 bytes, allocs estimate: 0.