About storing the results of Iterators.product into an array efficiently?

function cartesian_power_matrix(V::Vector{T},d) where T
    X=fill(V,d)
    iterable=Iterators.product(X...)
    a = collect(iterable)
    return reshape(reinterpret(T, a), d, length(a))
end

Or, better yet, make sure d is a compile-time constant by storing it in a type:

function cartesian_power_matrix(V::Vector{T}, ::Val{d}) where {T,d}
    X = ntuple(_ -> V, Val{d}())
    iterable=Iterators.product(X...)
    a = collect(iterable)
    return reshape(reinterpret(T, a), d, length(a))
end

which gives timings:

julia> @btime cartesian_power_tuples($V,3);
  1.121 μs (5 allocations: 23.70 KiB)

julia> @btime cartesian_power_matrix($V,3);
  1.308 μs (8 allocations: 23.80 KiB)

julia> @btime cartesian_power_matrix($V,$(Val(3)));
  830.128 ns (2 allocations: 23.56 KiB)

Probably because your iteration is type-unstable, since the type of your iteration elements (x, a d-tuple) depends on a runtime value (d).

3 Likes