Concatening matrix in a loop

Dear users,
I need to build a matrix using a loop, like this:

X = zeros(3,1)
for i=1:10 
     x = rand(3,1)
     X = [X x]

i.e., I need to build the columns of X using a looping. What’s the better way to do its?

To be more efficient, preallocate X and then fill it. Something like this

X = zeros(3,10)
for i = 1:10
    X[:,i] = rand(3)

(In this particular case, you could do X=rand(3,10).)

reduce(hcat, (rand(3) for i in 1:10); init=X)

Also, please don’t post the same thing multiple times.

Because I just couldn’t resist, and as this is something I can see myself using often enough:

function func1(;n=10, m=3)
    X = zeros(m,1)
    for i=1:n 
        x = rand(m,1)
        X = [X x]
    return  X

function func2(;n=10, m=3)
    X = zeros(m,n)
    for i = 1:n
        X[:,i] = rand(m)
    return X

function func3(;n=10, m=3)
    X = zeros(m,n)
    reduce(hcat, (rand(m) for i in 1:n); init=X)  
    return X

julia> @btime func1(n=10, m=3)
  878.317 ns (31 allocations: 3.89 KiB)

julia> @btime func2(n=10, m=3)
  502.572 ns (11 allocations: 1.42 KiB)

julia> @btime func3(n=10, m=3)
  1.210 μs (32 allocations: 6.33 KiB)

julia> @btime func1(n=100, m=3)
  20.901 μs (301 allocations: 148.00 KiB)

julia> @btime func2(n=100, m=3)
  4.586 μs (101 allocations: 13.44 KiB)

julia> @btime func3(n=100, m=3)
  48.901 μs (302 allocations: 384.52 KiB)

julia> @btime func1(n=10, m=30)
  2.589 μs (31 allocations: 20.52 KiB)

julia> @btime func2(n=10, m=30)
  1.080 μs (11 allocations: 5.78 KiB)

julia> @btime func3(n=10, m=30)
  5.433 μs (32 allocations: 43.92 KiB)

Potential shortcomings in my benchmarking aside, I was not expecting the large differences, especially with the 100 x 3 case.


Note that these 3 functions don’t have quite the same output. And also that collecting the generator makes a big difference:

julia> func4(;n, m) = reduce(hcat, rand(m) for i in 1:n);

julia> @btime func4(n=100, m=3);
  19.821 μs (301 allocations: 145.44 KiB)

julia> func5(;n, m) = reduce(hcat, [rand(m) for i in 1:n]);

julia> @btime func5(n=100, m=3);
  6.063 μs (102 allocations: 14.31 KiB)
1 Like