Create grid coordinates in Julia
Julia 0.6 includes an efficient iterator product
that allows for a fourth solution. Comparison of all solutions:
using Base.Iterators
f1(xs, ys) = [[xs[i] for i in 1:length(xs), j in 1:length(ys)][:] [ys[j] for i in 1:length(xs), j in 1:length(ys)][:]]
f2(xs, ys) = hcat(repeat(xs, outer=length(ys)), repeat(ys, inner=length(xs)))
f3(xs, ys) = vcat(([x y] for y in ys for x in xs)...)
f4(xs, ys) = (eltype(xs) == eltype(ys) || error("eltypes must match");
reinterpret(eltype(xs), collect(product(xs, ys)), (2, length(xs)*length(ys)))')
xs = 1:3
ys = 0:4
@show f1(xs, ys) == f2(xs, ys) == f3(xs, ys) == f4(xs, ys)
using BenchmarkTools
@btime f1($xs, $ys)
@btime f2($xs, $ys)
@btime f3($xs, $ys)
@btime f4($xs, $ys)
On my PC, this results in:
f1(xs, ys) == f2(xs, ys) == f3(xs, ys) == f4(xs, ys) = true
548.508 ns (8 allocations: 1.23 KiB)
3.792 ฮผs (49 allocations: 2.45 KiB)
1.916 ฮผs (51 allocations: 3.17 KiB)
353.880 ns (8 allocations: 912 bytes)
For xs = 1:300
and ys=0:400
we get:
f1(xs, ys) == f2(xs, ys) == f3(xs, ys) == f4(xs, ys) = true
1.538 ms (13 allocations: 5.51 MiB)
1.032 ms (1636 allocations: 3.72 MiB)
16.668 ms (360924 allocations: 24.95 MiB)
927.001 ฮผs (10 allocations: 3.67 MiB)
Edit:
Most likely the fastest method is to loop directly over the preallocated array:
function f5(xs, ys)
lx, ly = length(xs), length(ys)
res = Array{Base.promote_eltype(xs, ys), 2}(lx*ly, 2)
ind = 1
for y in ys, x in xs
res[ind, 1] = x
res[ind, 2] = y
ind += 1
end
res
end
For xs = 1:3
and ys = 0:4
, f5
accepts 65.339 ns (1 allocation: 336 bytes)
.
For xs = 1:300
and ys = 0:400
required 280.852 ฮผs (2 allocations: 1.84 MiB)
.
Edit 2:
Incorporating f6
from Dan Getz's comment:
function f6(xs, ys)
lx, ly = length(xs), length(ys)
lxly = lx*ly
res = Array{Base.promote_eltype(xs, ys), 2}(lxly, 2)
ind = 1
while ind<=lxly
@inbounds for x in xs
res[ind] = x
ind += 1
end
end
for y in ys
@inbounds for i=1:lx
res[ind] = y
ind += 1
end
end
res
end
Given the large column order of Julia arrays, it reduces the timings to 47.452 ns (1 allocation: 336 bytes)
and 171.709 ฮผs (2 allocations: 1.84 MiB)
accordingly.
source to share
sounds like a job for repeat The :
hcat(repeat(0:3, outer=4), repeat(0:3, inner=4))
.
Note that this is too slower than understanding an array when xs
or is ys
small (e.g. 3
, 30
).
source to share