# Performance of for loop

**URL:** <https://discourse.julialang.org/t/performance-of-for-loop/124240>\
**Category:** Performance\
**Created:** [December 29, 2024, 2:46am UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240 "2024-12-29T02:46:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jgr](https://avatars.discourse-cdn.com/v4/letter/j/cdc98d/32.png) [@jgr](https://discourse.julialang.org/u/jgr)\
**Post date:** [December 29, 2024, 2:46am UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/1 "2024-12-29T02:46:38Z")

</div>

Hi,  
I want to run a for loop for matrix M with size (200,200,5). I have been told that for the sake of performance, it is better to loop from the outer to the inner (that is, dimension 3 → dim 2 → 1). But here the size of dimension 3 is much smaller than the other two. Is it still better to run from outer to the innermost? Is there any general rule that helps speed up for loops in Julia? Thanks.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [December 29, 2024, 2:49am UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/2 "2024-12-29T02:49:28Z")

</div>

> **[Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-column-major)**
>
> Documentation for The Julia Language.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 29, 2024, 6:55am UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/3 "2024-12-29T06:55:01Z")

</div>

The lengths of the high level dimensions are not important, the pattern of elements in virtual memory is. That matters because CPUs typically read nearby or patterned data in hopes it will be loaded soon and more quickly than from main memory. From the Avoid Cache Misses section of this blog [viralinstruction.com/posts/hardware/](https://viralinstruction.com/posts/hardware/):

> - By _spacial locality_, I mean that you should access data from memory addresses close to each other. Your CPU does not copy _just_ the requested bytes to cache. Instead, your CPU will always copy data in larger chunks called _cache lines_ (usually 512 consecutive bits, depending on the CPU model).

The nonideal order of dimensions will still have a pattern and can be optimized by prefetching (also covered in that blog), but you still suffer from the aforementioned cache misses.

Note that for some algorithms, helper methods like `eachindex` are designed to iterate an n-dimensional array in the typically best order.

---

<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:** [December 29, 2024, 1:43pm UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/4 "2024-12-29T13:43:04Z")

</div>

> [@jgr](#):
>
> But here the size of dimension 3 is much smaller than the other two

Alternatively, you can think about re-ordering your dimensions to optimize for the access pattern you want. e.g. if you often access elements of dimension 3 together, maybe you should re-order it to be dimension 1.

But it’s hard to give specific advice without knowing more about the structure/purpose of your code.

> [@jgr](#):
>
> Is there any general rule that helps speed up for loops in Julia?

The number one rule is to not use global variables — put your loops into functions, and pass data via parameters. Also, read [the Julia performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/).

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [December 29, 2024, 3:22pm UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/5 "2024-12-29T15:22:17Z")

</div>

> [@jgr](#):
>
> I have been told that for the sake of performance, it is better to loop from the outer to the inner (that is, dimension 3 → dim 2 → 1)

~~Note that Julia arrays are column-major. This means you should iterate opposite of what you wrote, i.e.~~  
I apparently was very confused when I wrote this. Edited for correctness (thanks @stevengj)

```julia
arr = rand(200,200,5)
for i in axes(arr, 3) # 1:5 is discouraged
    for j in axes(arr, 2)
        for k in axes(arr, 1)
            arr[k,j,i] += 3 # some computation
        end
    end
end

```

Alternatively you can also look into `eachindex` and `CartesianIndices`

---

<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:** [December 29, 2024, 5:34pm UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/6 "2024-12-29T17:34:48Z")

</div>

> [@abraemer](#):
>
> Note that Julia arrays are column-major. This means you should iterate opposite of what you wrote, i.e.
> 
> ```julia
> arr = rand(200,200,5)
> for i in axes(arr, 1) # 1:200 is discouraged
> 
> ```

No, you have it backwards. The optimal explicit loop order should be:

```julia
for k in axes(arr, 3), j in axes(arr, 2), i in axes(arr, 1)
   # ...
end

```

for column-major order, as @jgr wrote. (The [_first_ index is contiguous](https://en.wikipedia.org/wiki/Row-_and_column-major_order) in memory.)

(This is the only real downside of column-major, in my mind — the loop ordering is unnatural for humans.)

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [December 29, 2024, 6:09pm UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/7 "2024-12-29T18:09:59Z")

</div>

You are right of course and that’s also how I did it in my codes all the time. I don’t know how I was **that** confused earlier… 😮  
\*edits post ashamed and head shaking

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [January 1, 2025, 2:06pm UTC](https://discourse.julialang.org/t/performance-of-for-loop/124240/8 "2025-01-01T14:06:52Z")

</div>

Perhaps for cultures that use columnar writing it is less unnatural.
