fill_W1! allocates memory because it makes copies when constructing the
right hand sides. fill_W2 allocates memory in order to construct the
comprehensions (that you then discard). In both cases memory allocation
could plausibly be avoided by a sufficiently smart compiler, but until
Julia becomes that smart, have a look at the sub function to provide views
instead of copies for the right hand sides of fill_W1!.
On Thursday, July 21, 2016 at 5:07:34 PM UTC+2, Michael Prange wrote:
>
> I'm a new user, so have mercy in your responses.
>
> I've written a method that takes a matrix and vector as input and then
> fills in column icol of that matrix with the vector of given values that
> have been shifted upward by ishift indices with periodic boundary
> conditions. To make this clear, given the matrix
>
> W = [1 2
> 3 4
> 5 6]
>
> the vector w = [7 8 9], icol = 2 and ishift = 1, the new value of W is
> given by
>
> W = [1 8
> 3 9
> 5 7]
>
> I need a fast way of doing this for large matrices. I wrote three methods
> that should (In my naive mind) give the same performance results, but @time
> reports otherwise. The method definitions and the performance results are
> given below. Can someone teach me why the results are so different? The
> method fill_W! is too wordy for my tastes, but the more compact notation in
> fill_W1! and fill_W2! achieve poorer results. Any why do these latter two
> methods allocate so much memory when the whole point of these methods is to
> use already-allocated memory.
>
> Michael
>
> ### Definitions
>
>
> function fill_W1!{TF}(W::Matrix{TF}, icol::Int, w::Vector{TF},
> ishift::Int)
> @assert(size(W,1) == length(w), "Dimension mismatch between W and w")
> W[1:(end-ishift),icol] = w[(ishift+1):end]
> W[(end-(ishift-1)):end,icol] = w[1:ishift]
> return
> end
>
>
> function fill_W2!{TF}(W::Matrix{TF}, icol::Int, w::Vector{TF},
> ishift::Int)
> @assert(size(W,1) == length(w), "Dimension mismatch between W and w")
> [W[i,icol] = w[i+ishift] for i in 1:(length(w)-ishift)]
> [W[end-ishift+i,icol] = w[i] for i in 1:ishift]
> return
> end
>
>
> function fill_W!{TF}(W::Matrix{TF}, icol::Int, w::Vector{TF},
> ishift::Int)
> @assert(size(W,1) == length(w), "Dimension mismatch between W and w")
> n = length(w)
> for j in 1:(n-ishift)
> W[j,icol] = w[j+ishift]
> end
> for j in (n-(ishift-1)):n
> W[j,icol] = w[j-(n-ishift)]
> end
> end
>
>
> # Performance Results
> julia>
> W = rand(1000000,2)
> w = rand(1000000)
> println("fill_W!:")
> println(@time fill_W!(W, 2, w, 2))
> println("fill_W1!:")
> println(@time fill_W1!(W, 2, w, 2))
> println("fill_W2!:")
> println(@time fill_W2!(W, 2, w, 2))
>
>
> Out>
> fill_W!:
> 0.002801 seconds (4 allocations: 160 bytes)
> nothing
> fill_W1!:
> 0.007427 seconds (9 allocations: 7.630 MB)
> [0.152463397611579,0.6314166578356002]
> fill_W2!:
> 0.005587 seconds (7 allocations: 7.630 MB)
> [0.152463397611579,0.6314166578356002]
>
>
>