# Difference between indexing a for loop

**URL:** <https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306>\
**Category:** New to Julia\
**Created:** [June 16, 2017, 2:01pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306 "2017-06-16T14:01:14Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![raminammour](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raminammour/32/13572_2.png) [@raminammour](https://discourse.julialang.org/u/raminammour)\
**Post date:** [June 16, 2017, 2:01pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/1 "2017-06-16T14:01:14Z")

</div>

Hello all,

Can someone please explain to me why the following happens. I know that I am accessing the array in the wrong order, it is necessary to reproduce the allocation and slowdown. This came up in an actual application and I could not figure out why:

```julia

function f1(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.
    for i=1:n1,j=1:n2-1:n2
        s+=A[i,j]
    end
    return s
end

function f2(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.
    for i=1:n1, j in [1,n2]
        s+=A[i,j]
    end
    return s
end
n=10;A=rand(n,n)
f1(A);f2(A);
n=10000;A=rand(n,n)
@time s1=f1(A);
@time s2=f2(A);
s1-s2

  0.000608 seconds (5 allocations: 176 bytes)
  0.001324 seconds (20.00 k allocations: 1.068 MB)
  0.0

```

Thanks!

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 16, 2017, 2:30pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/2 "2017-06-16T14:30:58Z")

</div>

> [@raminammour](#):
>
> for i=1:n1,j=1:n2-1:n2

> [@raminammour](#):
>
> for i=1:n1, j in [1,n2]

One is an array, the other isn’t? You have the cost of creating an array in the second.

But I don’t even think that’s the issue.

> [@raminammour](#):
>
> @time s1=f1(A);  
> @time s2=f2(A);

The first time you call a function it will compile. What happens if you time it like:

```julia
@time s1=f1(A);
@time s1=f1(A);
@time s2=f2(A);
@time s2=f2(A);

```

?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [June 16, 2017, 2:31pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/3 "2017-06-16T14:31:01Z")

</div>

It should probably be:

```julia
function f2(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.
    for i=1:n1, j in 1:n2-1:n2 # <---
        s+=A[i,j]
    end
    return s
end

```

`in` and `=` are identical in their for-loop usage.

---

<div class="post-metadata">

**Author:** ![raminammour](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raminammour/32/13572_2.png) [@raminammour](https://discourse.julialang.org/u/raminammour)\
**Post date:** [June 16, 2017, 3:54pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/4 "2017-06-16T15:54:34Z")

</div>

The functions were compiled before, I didn’t post it.

I think you are right about the array issue if you change the function to:

```julia
function f1(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.
    for i=1:n1,j=1:n2-1:n2
        s+=A[i,j]
    end
    return s
end

function f2(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.
    inds=[1,n2]
    for i=1:n1, j in inds
        s+=A[i,j]
    end
    return s
end
n=10;A=rand(n,n)
f1(A);f2(A);
n=10000;A=rand(n,n)
@time s1=f1(A);
@time s2=f2(A);
@time s1=f1(A);
@time s2=f2(A);
s1-s2

  0.000602 seconds (5 allocations: 176 bytes)
  0.000083 seconds (7 allocations: 288 bytes)
  0.000581 seconds (5 allocations: 176 bytes)
  0.000080 seconds (7 allocations: 288 bytes)

```

It becomes even faster! Which I don’t understand either.

I guess in the first version a 2 vector keeps getting created and garbage collected; I thought the compiler could figure out that it was a constant and pre-compute it but it didn’t.

Or I am just lost, which is a perfectly good explanation 🙂

Thanks for the hint.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [June 17, 2017, 4:49am UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/5 "2017-06-17T04:49:33Z")

</div>

Another thing to note, arrays are column-major in Julia, so you’ll get better performance doing:

```julia
for j = 1:(n2-1):n2, i = 1:n1 ; s += A[i, j] ; end

```

---

<div class="post-metadata">

**Author:** ![ericsfraga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericsfraga/32/192_2.png) [@ericsfraga](https://discourse.julialang.org/u/ericsfraga)\
**Post date:** [June 19, 2017, 6:55am UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/6 "2017-06-19T06:55:04Z")

</div>

> Hello all,
> 
> Can someone please explain to me why the following happens. I know  
> that I am accessing the array in the wrong order, it is necessary to  
> reproduce the allocation and slowdown. This came up in an actual  
> application and I could not figure out why:

Cannot answer your question as such (I’m definitely a n00b in Julia) but  
do note that the two ranges for j are different?

---

<div class="post-metadata">

**Author:** ![raminammour](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raminammour/32/13572_2.png) [@raminammour](https://discourse.julialang.org/u/raminammour)\
**Post date:** [June 19, 2017, 1:36pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/7 "2017-06-19T13:36:26Z")

</div>

The `j` ranges are the same. The issue was that the vector `[1,n2]` was being created and garbage collected inside the loop at every iteration, which is slow. With the step range `1:n2-1:n2` that does not happen.

---

<div class="post-metadata">

**Author:** ![anon61610682](https://avatars.discourse-cdn.com/v4/letter/a/ad7895/32.png) [@anon61610682](https://discourse.julialang.org/u/anon61610682)\
**Post date:** [June 19, 2017, 2:04pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/8 "2017-06-19T14:04:08Z")

</div>

I am not sure if you have intended to use the code for matrices of dimensions `min(m,n) > 1`, but in `f1`, there is a bug: when `n2 == 1`, you get an error. Plus, why would you iterate if you know ahead of time that you will use the first and last columns of the matrix?

Below code excerpt will save you one loop, and hence, is more efficient:

```julia
function f1(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.
    for i=1:n1,j=1:n2-1:n2
        s+=A[i,j]
    end
    return s
end

function f2(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.
    inds=[1,n2]
    for i=1:n1, j in inds
        s+=A[i,j]
    end
    return s
end

function f3(A::AbstractMatrix)
  n1, n2 = size(A)
  s = zero(eltype(A))
  for row in 1:n1
    s += A[row, 1] + A[row, n2]
  end
  s
end

function f4{T<:AbstractFloat}(A::AbstractMatrix{T})
  n1, n2 = size(A)
  s = zero(T)
  for row in 1:n1
    s += A[row, 1] + A[row, n2]
  end
  s
end

function f4{T<:Integer}(A::AbstractMatrix{T})
  n1, n2 = size(A)
  s = zero(widen(T))
  for row in 1:nrows
    s += A[row, 1] + A[row, n2]
  end
  s
end

using BenchmarkTools

n=10000; A = rand(n, n);

@benchmark f1(A) # 181.749 us
@benchmark f2(A) # 24.275 us
@benchmark f3(A) # 11.238 us
@benchmark f4(A) # 11.240 us

```

If you still want to use iterations, you should put an assertion for `n2 > 1`. And in `f3` above, for matrices having `Integer` elements, `s` might overflow. Overloading `{T<:Integer}(A::AbstractMatrix{T})` with `s = zero(widen(eltype(A)))` would solve this problem. For `AbstractFloat`s, you don’t have this problem (cf. `f4` above).

Cheers!

---

<div class="post-metadata">

**Author:** ![raminammour](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raminammour/32/13572_2.png) [@raminammour](https://discourse.julialang.org/u/raminammour)\
**Post date:** [June 19, 2017, 2:40pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/9 "2017-06-19T14:40:29Z")

</div>

Thanks for the reply.

This code is just meant to reproduce the behavior I was seeing in another application, `n>>>1` and I am not all that interested in summing matrices 🙂 .

This typically comes up when you iterate on an array, and then you want to do something different at the ends (think boundary conditions). Keeping the same code structure makes for a bit more elegant code. I know that it will always be faster if I rewrote the end cases as two explicit loops, but as dimensions grow, it gets tedious. The end conditions should be much less costly than the body of the loop, until something like my original `f2()` happens.

Cheers!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 19, 2017, 3:35pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/10 "2017-06-19T15:35:50Z")

</div>

For boundary conditions at the ends, the most elegant, flexible, and efficient technique is often to use ghost elements. See my comment about this in another thread on discourse.

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [June 19, 2017, 4:12pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/11 "2017-06-19T16:12:02Z")

</div>

link [Arrays with periodic boundaries - #4 by stevengj](https://discourse.julialang.org/t/arrays-with-periodic-boundaries/4015/4)

---

<div class="post-metadata">

**Author:** ![pint](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pint/32/125_2.png) [@pint](https://discourse.julialang.org/u/pint)\
**Post date:** [June 19, 2017, 4:19pm UTC](https://discourse.julialang.org/t/difference-between-indexing-a-for-loop/4306/12 "2017-06-19T16:19:30Z")

</div>

as a tule of thumb, instead of a constant array, you should always try to use a constant tuple. here is my version, which is faster than the Range version according to my measurements:

```julia
function f3(A)
    n1=size(A,1)
    n2=size(A,2)
    s=0.0
    for i=1:n1,j=(1,n2)
        s+=A[i,j]
    end
    return s
end

```
