# MATLAB outperforms Julia (20 times faster) running this nested loop

**URL:** <https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691>\
**Category:** Performance\
**Tags:** question, performance, matlab, time, finitediff\
**Created:** [January 9, 2023, 2:46am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691 "2023-01-09T02:46:16Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![SantiagoOrtiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/santiagoortiz/32/25378_2.png) [@SantiagoOrtiz](https://discourse.julialang.org/u/SantiagoOrtiz)\
**Post date:** [January 9, 2023, 2:46am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/1 "2023-01-09T02:46:16Z")

</div>

Hello Fellas,

I am relatively new to Julia Programming. So far, Julia’s high performance has caught my attention. However, it was disappointing to see that **MATLAB** performs **20 times faster** in executing the following program. I tested this program on two different workstations, getting consistent results.

_ **Context:** _ This program solves Laplace’s Equation using the (Central) Finite difference method in a nested Loop fashion. The program uses elementary programming structures (no packages are imported !).

* * *

```julia
n = 100
T = zeros(n, n)
Tₖ₋₁ = zeros(n, n)
T[1, 1:n] .= 500
T[n, 1:n] .= 500
T[1:n, 1] .= 200
T[1:n, n] .= 500

error = 1.0;
tolerance = 1E-6
@time begin
    while error > tolerance
        Tₖ₋₁ .= T
        for i = 2:n-1
            for j = 2:n-1
                T[i, j] = 1/4*(T[i,j+1] + T[i,j-1] + T[i+1,j] + T[i-1,j])
            end
        end
        global error = maximum(abs.(Tₖ₋₁ .- T))
    end
end

```

The MATLAB version is a literal translation of the Julia code and can be downloaded from ([MATLAB laplacEq - Google Drive](https://drive.google.com/drive/folders/1yiHSGj1Rv14HdsSiE6q_iZPYiHATLqlU?usp=share_link))

* * *

_ **Results:** _

Julia (1.8.3) → `35.892180 seconds (901.65 M allocations: 16.409 GiB, 2.00% gc time, 0.62% compilation time)`

MATLAB (R2022b) → `Elapsed time is 1.578888 seconds.`

* * *

There are two relevant _ **questions** _ arising from this problem:

1. Why is Julia outperformed by MATLAB in this case?
2. What can be done to improve Julia’s performance?

Since this is a fairly simple program with no dependency on additional packages, solving this puzzle might help new Julia users (like me) to develop Julia code with good programming practices, building up a strong foundation from the start.

All the best,  
Santiago

---

<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:** [January 9, 2023, 2:50am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/2 "2023-01-09T02:50:16Z")

</div>

[https://docs.julialang.org/en/v1/manual/performance-tips/#Performance-critical-code-should-be-inside-a-function](https://docs.julialang.org/en/v1/manual/performance-tips/#Performance-critical-code-should-be-inside-a-function)

---

<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:** [January 9, 2023, 3:34am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/3 "2023-01-09T03:34:33Z")

</div>

Yup, just putting the Julia code in a function (and [fixing the loop order](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-column-major)) makes it more than 30x faster:

```julia
function doit!(T, Tₖ₋₁=copy(T); tolerance=1e-6)
    m, n = size(T)
    error = 1.0
    while error > tolerance
        Tₖ₋₁ .= T
        for j = 2:m-1, i = 2:n-1
            T[i, j] = 1/4*(T[i,j+1] + T[i,j-1] + T[i+1,j] + T[i-1,j])
        end
        error = maximum(abs.(Tₖ₋₁ .- T))
    end
    return T
end

```

But then you can make another 2x faster by completely eliminating the `Tₖ₋₁` array and a couple of other tricks:

```julia
function doit2!(T; tolerance=1e-6)
    m, n = size(T)
    while true
        error = zero(eltype(T))
        @inbounds for j = 2:m-1, i = 2:n-1
            Tᵢⱼ = T[i, j]
            T[i, j] = 1/4*(T[i,j+1] + T[i,j-1] + T[i+1,j] + T[i-1,j])
            error = max(error, abs(T[i, j] - Tᵢⱼ))
        end
        error ≤ tolerance && break
    end
    return T
end

```

and I get another factor of 3 by using the LoopVectorization package:

```julia
using LoopVectorization
function doit3!(T; tolerance=1e-6)
    m, n = size(T)
    while true
        error = zero(eltype(T))
        @turbo for j = 2:m-1, i = 2:n-1
            Tᵢⱼ = T[i, j]
            T[i, j] = 1/4*(T[i,j+1] + T[i,j-1] + T[i+1,j] + T[i-1,j])
            error = max(error, abs(T[i, j] - Tᵢⱼ))
        end
        error ≤ tolerance && break
    end
    return T
end

```

I would benchmark with something like:

```julia
using BenchmarkTools
@btime doit3!($T; tolerance=1e-6) setup=(T[2:n-1,2:n-1] .= 0);

```

to get accurate numbers. (If you use the more primitive `@time`, be sure to run the benchmark a couple of times at least, since the first run you are measuring compilation time.)

- Moral of this story: **the first Julia code you write is almost always quite slow** , especially if you haven’t yet [grokked](http://www.catb.org/jargon/html/G/grok.html) the [performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/). But you can usually make it _much_ faster using only **localized tweaks** (as opposed to throwing your code in the trash and rewriting it in Fortran).

(Of course, the code can be made faster yet because [Gauss–Seidel](https://en.wikipedia.org/wiki/Gauss%E2%80%93Seidel_method) is a terrible way to solve Laplace’s equation, but that would be “cheating”.)

---

<div class="post-metadata">

**Author:** ![cmichelenstrofer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cmichelenstrofer/32/44392_2.png) [@cmichelenstrofer](https://discourse.julialang.org/u/cmichelenstrofer)\
**Post date:** [January 9, 2023, 3:52am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/4 "2023-01-09T03:52:04Z")

</div>

> [@stevengj](#):
>
> factor of 3 by using the LoopVectorization

What is loop vectorization doing under the hood? Would it be better practice to code in vectorized form instead of using for loops?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [January 9, 2023, 4:13am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/5 "2023-01-09T04:13:50Z")

</div>

That’s a lot of potential globals there. Have you tried throwing all of this into a function? When I do, I get faster times on old hardware.

```julia
julia> function santiago()

       n = 100
       W = 20
       H = 20
       δx = W/n
       δy = H/n
       x = 0:δx:W
       y = 0:δy:H

       T = zeros(n, n)
       Tₖ₋₁ = zeros(n, n)
       T[1, 1:n] .= 500
       T[n, 1:n] .= 500
       T[1:n, 1] .= 200
       T[1:n, n] .= 500

       error = 1.0;
       tolerance = 1E-6
       @time begin
           while error > tolerance
               Tₖ₋₁ .= T
               for i = 2:n-1
                   for j = 2:n-1
                       T[i, j] = 1/4*(T[i,j+1] + T[i,j-1] + T[i+1,j] + T[i-1,j])
                   end
               end
               error = maximum(abs.(Tₖ₋₁ .- T))
           end
       end
       return T

       end
santiago (generic function with 1 method)

julia> T = santiago();
  1.410719 seconds (26.72 k allocations: 1019.899 MiB, 2.50% gc time)

```

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [January 9, 2023, 4:15am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/6 "2023-01-09T04:15:51Z")

</div>

Possibly tangential, but why isn’t performance in Matlab affected by global variables in the same way as in Julia?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [January 9, 2023, 4:41am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/7 "2023-01-09T04:41:45Z")

</div>

I’m taking a wild guess here, but Julia has thread-based concurrency for all functions. MATLAB only introduced threads recently and it is only limited to [several builtin functions](https://www.mathworks.com/help/matlab/matlab_prog/run-functions-on-threads.html).

If you only have to worry about one piece of code modifying a set of globals at a time, you can make a fair number of assumptions that we cannot in Julia. [Binding globals to types](https://github.com/JuliaLang/julia/pull/43671) is one thing that really accelerates the use of globals in Julia.

---

<div class="post-metadata">

**Author:** ![SantiagoOrtiz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/santiagoortiz/32/25378_2.png) [@SantiagoOrtiz](https://discourse.julialang.org/u/SantiagoOrtiz)\
**Post date:** [January 9, 2023, 5:11am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/8 "2023-01-09T05:11:55Z")

</div>

This is awesome!  
Thank you all for following up—specially @stevengj, for your timeline response. As a new Julia Programming user, I have learned much from this discussion.

To summarize, the piece of code below is the fastest so far.

My initial “lazy” Julia code: `35.892180 seconds (901.65 M allocations: 16.409 GiB)`  
The MATLAB literal translation: `1.578888 seconds`  
The “turbo” Julia code: `0.072218 seconds (2 allocations: 78.17 KiB)`

```julia
using LoopVectorization

function doit3!(n; tolerance=1e-6)

    T = zeros(n, n)
    T[1, 1:n] .= 500
    T[n, 1:n] .= 500
    T[1:n, 1] .= 200
    T[1:n, n] .= 500

    while true
        error = zero(eltype(T))
        @turbo for j = 2:n-1, i = 2:n-1
            Tᵢⱼ = T[i, j]
            T[i, j] = 1/4*(T[i,j+1] + T[i,j-1] + T[i+1,j] + T[i-1,j])
            error = max(error, abs(T[i, j] - Tᵢⱼ))
        end
        error ≤ tolerance && break
    end
    return T
end

```

The initial motivation of the post was to see that MATLAB performed better than an identical implementation in Julia. Now I understand that to take full advantage of Julia’s capabilities, in some cases, one will have to go a bit deeper into the language.

Note that:

1. The appropriateness of the numerical method implemented here is separate from this discussion.
2. The MATLAB code can also be modified to achieve better performance.

All the best,  
Santiago

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 9, 2023, 5:57am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/9 "2023-01-09T05:57:01Z")

</div>

> [@SantiagoOrtiz](#):
>
> The MATLAB code can also be modified to achieve better performance.

Do you have the modified MATLAB code that gives the improved performance?

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 9, 2023, 6:03am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/10 "2023-01-09T06:03:44Z")

</div>

Hi! I’m the author of LoopVectorization.jl.

The “Vectorization” in LoopVectorization is not about “vectorized form”, but about “vector” (i.e. SIMD) CPU instructions. SIMD means “Single Instruction Multiple Data”, i.e. LoopVectorization.jl makes each CPU instruction operate on multiple loop iterations at a time.  
Note that even without `@turbo` Julia will use SIMD/vector instructions. `@turbo` just tries hard to do better than the default autovectorizer that is used by Julia (and other languages like c++ or Rust).

TLDR: The “Vectorization” in “LoopVectorization” is a low level implementation detail that in the future won’t be exposed (I’m rewriting it, and the new version will get a new name).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 9, 2023, 6:28am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/11 "2023-01-09T06:28:43Z")

</div>

> [@cmichelenstrofer](#):
>
> Would it be better practice to code in vectorized form instead of using for loops?

( **Edit:** Oops, missed that the author of Loopvectorization.jl had already answered this question 😄)

Loopvectorization.jl is concerned with [simd vectorization](https://en.m.wikipedia.org/wiki/Single_instruction,_multiple_data), which is not the same as “vectorized style”.

You can use Loopvectorization.jl on either loops or dot-broadcasted expressions, and, as you can see, the given example was a loop.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 9, 2023, 6:41am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/12 "2023-01-09T06:41:40Z")

</div>

> [@DNF](#):
>
> You can use Loopvectorization.jl on either loops or dot-broadcasted expressions, and, as you can see, the given example was a loop.

Ironically, the vectorized style is actually harder to vectorize because of the semantics of broadcasting.  
That’s why (for example) `FastBroadcast.jl` defaults to not actually broadcasting, you need to pass an argument to enable that when using `FastBroascast.@..`.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 9, 2023, 6:44am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/13 "2023-01-09T06:44:09Z")

</div>

> [@mkitti](#):
>
> I’m taking a wild guess here, but Julia has thread-based concurrency for all functions.

There’s no multithreading in this Julia code.

Matlab simply does not appear to be affected by type instabilities. Traditionally, this was because it was interpreted; today it is jit-compiled, but that is closed source and little is known about the details of how it works, but I believe it is ‘classical’ jit compilation, which possibly means it happens at a later stage, and may have access to more information than Julia’s ‘(just) ahead-of-time’ compiler.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [January 9, 2023, 7:06am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/14 "2023-01-09T07:06:36Z")

</div>

> [@DNF](#):
>
> There’s no multithreading in this Julia code.
> 
> Matlab simply does not appear to be affected by type instabilities. Traditionally, this was because it was interpreted; today it is jit-compiled, but that is closed source and little is known about the details of how it works.

It doesn’t matter that there is no multithreading here. The semantics of Julia mean that we cannot make certain assumptions about globals without a type assertion, in part due to multithreading. MATLAB can make assumptions about globals that Julia cannot, in part because multithreading is not generally part of the language. In MATLAB, you can assume that if the type of a global changes, it is because the block of code you are executing changed it.

Do you have evidence that MATLAB jit is not affected by type instability? It seems that MATLAB performance with globals may be degrading.

> **[Why has matlab become extremely inefficient with global variables?](https://www.mathworks.com/matlabcentral/answers/1639475-why-has-matlab-become-extremely-inefficient-with-global-variables)**
>
> I have a program which I have been running for years on various versions of Matlab. It uses a file of global variables, which I pass between functions. Running profiler:
> In Matlab 2012b, the glo...

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 9, 2023, 7:41am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/15 "2023-01-09T07:41:09Z")

</div>

But the performance issue of non-const globals predates multithreading in Julia, afaik. And I’ve not heard that as the main explanation, anyway.

> [@mkitti](#):
>
> Do you have evidence that MATLAB jit is not affected by type instability?

I said ‘appears’. And also, that’s what the OP is about, Matlab not suffering from the type instability, so the OP itself is evidence.

Anyway, I’ll add that your explanation does in fact make sense.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [January 9, 2023, 7:43am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/16 "2023-01-09T07:43:22Z")

</div>

Isn’t everything a matrix in Matlab?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 9, 2023, 7:55am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/17 "2023-01-09T07:55:17Z")

</div>

> [@mkitti](#):
>
> It seems that MATLAB performance with globals may be degrading.

I followed that link now, and I don’t think it supports the hypothesis that there are increasing performance issues with globals in Matlab. The person asking the question thinks so, but the other posters (including staff) could not reproduce.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [January 9, 2023, 8:11am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/18 "2023-01-09T08:11:20Z")

</div>

> [@giordano](#):
>
> Isn’t everything a matrix in Matlab?

They also have a class, equivalent to “element type”.

```julia
>> a = 1

a =

     1

>> class(a)

ans =

    'double'

>> size(a)

ans =

     1 1

>> b = uint16(2)

b =

  uint16

   2

>> whos
  Name Size Bytes Class Attributes

  a 1x1 8 double              
  ans 1x2 16 double              
  b 1x1 2 uint16             

```

---

<div class="post-metadata">

**Author:** ![RoyiAvital](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/royiavital/32/571_2.png) [@RoyiAvital](https://discourse.julialang.org/u/RoyiAvital)\
**Post date:** [January 9, 2023, 8:49am UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/19 "2023-01-09T08:49:29Z")

</div>

If we put `LoopVectorization` aside for a moment, this is what I get when I apply the same on both codes (Changing the order, which MATLAB and Julia share):

```matlab
function [mT] = SolveLaplace( mT, numItr )

[numRows, numCols] = size(mT);

for kk = 1:numItr
    for jj = 2:(numCols - 1)
        for ii = 2:(numRows - 1)
            mT(ii, jj) = 0.25 * (mT(ii - 1, jj) + mT(ii + 1, jj) + mT(ii, jj - 1) + mT(ii, jj + 1));
        end
    end
end

end

```

For Julia:

```julia
function SolveLaplace( mT, numItr )
    numRows, numCols = size(mT);

    for kk in 1:numItr
        for jj in 2:(numCols - 1)
            for ii in 2:(numRows - 1)
                mT[ii, jj] = 0.25 * (mT[ii - 1, jj] + mT[ii + 1, jj] + mT[ii, jj - 1] + mT[ii, jj + 1]);
            end
        end
    end
    return mT;
end

```

Running this in MATLAB:

```matlab
clear();

n = 100;
T = zeros(n);
T(1, 1:n) = 200;
T(n, 1:n) = 500;
T(1:n, 1) = 500;
T(1:n, n) = 500;

numItr = 1000;

hF = @() SolveLaplace(T, numItr);

TimeItMin(hF)

```

Will yield: `ans = 0.0422`.

In Julia `@btime SolveLaplace($T, $numItr);` will yield `41.179 ms (0 allocations: 0 bytes)`.

So they both, probably, yield equivalent machine code for those simple loops.

**Remark**  
The function `TimeItMin()` is the same as MATLAB’s `timeit()` with a single modification I made which is using the minimum run time instead of the median in order to match Julia’s `@btime`.

---

<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:** [January 9, 2023, 2:45pm UTC](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691/20 "2023-01-09T14:45:11Z")

</div>

> [@SantiagoOrtiz](#):
>
> ```julia
> function doit3!(n; tolerance=1e-6)
> T = zeros(n, n)
> 
> ```

The `!` at the end of the function name is a Julia convention for functions that modify (“mutate”) an argument in-place. I used it my code because I was passing `T` as an argument and modifying it in the function. If you rewrite the function to take `n` as an argument then you shouldn’t use `!`. Again, this is purely a convention — you can name your functions whatever you want, but if you’re going to be using Julia seriously you’ll want to understand the `!` meaning.

Conceptually, I think it is cleaner to separate the code that allocates `T` and initializes it to a particular set of boundary conditions and initial values from the code that solves Laplace’s equation.

For benchmarking, neither your original Matlab code nor your original Julia code include the initialization of `T` in the timing. Of course, you can put a `@time` call inside the function, but from coding standpoint it is usually better to separate benchmarking from implementation. (Especially if you want to use a package like [BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl) to get more reliable timing statistics, or do more fine-grained [performance profiling](https://docs.julialang.org/en/v1/manual/profile/).)

[Next page](https://discourse.julialang.org/t/matlab-outperforms-julia-20-times-faster-running-this-nested-loop/92691.md?page=2)
