# Optimizing performance (newcomer from Matlab)

**URL:** <https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825>\
**Category:** General Usage\
**Tags:** first-steps\
**Created:** [November 7, 2019, 12:17pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825 "2019-11-07T12:17:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonneguyt](https://avatars.discourse-cdn.com/v4/letter/j/c4cdca/32.png) [@jonneguyt](https://discourse.julialang.org/u/jonneguyt)\
**Post date:** [November 7, 2019, 12:17pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/1 "2019-11-07T12:17:10Z")

</div>

Hi all,

I am encountering slower than hoped for performance in my usage of Julia (in comparison to Matlab). I am sure that my coding style is largely responsible for this, but would appreciate any pointers.

I am calculating the probability of observing a given set (conditional on some values and a cut-off). I have tried to abstract away from the problem as much as possible and give a MWE that’s as minimal as possible. I’ve annotated to provide some insights on what I doing. The Julia profiler and Matlab profiler differ a lot, up to the point that I find it very hard to navigate any output the profiler gives me (I’m not a programmer, just an applied user).

```julia

using Combinatorics

a = 5;
values = randn(5, 15, 500)
sets = collect(powerset(1:a))
deleteat!(sets,1)

inv_set = collect(1:a)
p_set = zeros(size(sets,1), 15, 500)

@time for Z in 1:size(sets,1)
    current_set = vcat(hcat(sets[Z,:]...)...); # get the vector with the current set
    inv_current_set = setdiff(inv_set,hcat(sets[Z,:]...)); # get the vector with inverse of current set
    first_part = prod(1 .-exp.(-exp.(-1 .*(0 .-values[current_set,:,:]))), dims = 1); # calculate p current set
    second_part = prod(exp.(-exp.(-1 .*(0 .-values[inv_current_set,:,:]))), dims = 1); # calculate p inv set
    third_part = prod(exp.(-exp.(-1 .*(0 .-values[:,:,:]))), dims = 1); # calculate p empty set
    p_set[Z,:,:] = (first_part.*second_part) ./ (1 .- third_part); # wrap it all up
end

```

versioninfo() generates:  
Julia Version 1.2.0  
Commit c6da87ff4b (2019-08-20 00:03 UTC)  
Platform Info:  
OS: macOS (x86\_64-apple-darwin18.6.0)  
CPU: Intel(R) Core™ i7-7920HQ CPU @ 3.10GHz  
WORD\_SIZE: 64  
LIBM: libopenlibm  
LLVM: libLLVM-6.0.1 (ORCJIT, skylake)  
Environment:  
JULIA\_NUM\_THREADS = 4  
JULIA\_EDITOR = atom -a

PS: using threads speeds it up (~2x), but that’s as far as I get

---

<div class="post-metadata">

**Author:** ![Karajan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karajan/32/8545_2.png) [@Karajan](https://discourse.julialang.org/u/Karajan)\
**Post date:** [November 7, 2019, 12:29pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/2 "2019-11-07T12:29:33Z")

</div>

Welcome!

Before going too deep into optimizing the problem head over to the [performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/) which lists common pitfalls. Two things stand out: the use of non-constant globals (which are necessary to avoid for optimal performance) and using `@time` which can include compilation time in the results. To get more meaningful results usually wrapping things in a function and using `@btime` from `BenchmarkTools` is the preferred way to go.

---

<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:** [November 7, 2019, 12:30pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/3 "2019-11-07T12:30:00Z")

</div>

Welcome to Julia! Without having the time to look at your code, I’ll just point you to  
[https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-tips-1](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-tips-1)

I can definitely see that you didn’t put your code into a function.

---

<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:** [November 7, 2019, 12:34pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/4 "2019-11-07T12:34:40Z")

</div>

Why write

```julia
vcat(hcat(sets[Z,:]...)...);

```

instead of

```julia
sets[Z]

```

for example?

---

<div class="post-metadata">

**Author:** ![jonneguyt](https://avatars.discourse-cdn.com/v4/letter/j/c4cdca/32.png) [@jonneguyt](https://discourse.julialang.org/u/jonneguyt)\
**Post date:** [November 7, 2019, 12:40pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/5 "2019-11-07T12:40:32Z")

</div>

It lives inside a function in my actual code. For the sake of the MWE I moved it out, now back in.

I’ve changed the code as suggested by kristoffer.carlsson, but it doesn’t shave off a lot of time.  
See for an updated code below:

```julia

using Combinatorics

a = 5;
values = randn(5,15,500)
sets = collect(powerset(1:a))
deleteat!(sets,1)

inv_set = collect(1:a)
p_set = zeros(size(sets,1), 15, 500)

function MWE_function()
    for Z in 1:size(sets,1)
    current_set = sets[Z];
    inv_current_set = setdiff(inv_set,sets[Z]);
    first_part = prod(1 .-exp.(-exp.(-1 .*(0 .-values[current_set,:,:]))), dims = 1);
    second_part = prod(exp.(-exp.(-1 .*(0 .-values[inv_current_set,:,:]))), dims = 1);
    third_part = prod(exp.(-exp.(-1 .*(0 .-values[:,:,:]))), dims = 1);
    p_set[Z,:,:] = (first_part.*second_part) ./ (1 .- third_part);
    end
end

@time MWE_function()

```

This still leaves me with roughly 0.129681 seconds (3.01 k allocations: 78.161 MiB, 5.85% gc time)

I’ll have a look at the benchmarktools, but still happy with any other pointers.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [November 7, 2019, 12:43pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/6 "2019-11-07T12:43:47Z")

</div>

> [@jonneguyt](#):
>
> MWE\_function()

You still have non-constant globals here (`a`, `values`, etc). Instead, make `MWE_function` take them as arguments. That way, Julia can compile a specialized version of `MWE_function` based on the types of those arguments, which is one way Julia gets good performance.

---

<div class="post-metadata">

**Author:** ![Karajan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karajan/32/8545_2.png) [@Karajan](https://discourse.julialang.org/u/Karajan)\
**Post date:** [November 7, 2019, 12:55pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/7 "2019-11-07T12:55:57Z")

</div>

As we said, please look at the performance tips. For example, the first three topics are

1. Avoid global variables (already mentioned)
2. Measure performance with `@time` and pay attention to memory allocation (you got a lot of allocations there, probably some of them can be avoided by reusing memory)
3. Tools (suggestions for a visual profiler output)

By the way, isn’t `-1 .*(0 .-values[current_set,:,:]) == values[current_set,:,:]`?  
Also, you don’t need any of the semicolon in you code, statements don’t have to be terminated if you just have one per line.

---

<div class="post-metadata">

**Author:** ![bernhard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bernhard/32/2619_2.png) [@bernhard](https://discourse.julialang.org/u/bernhard)\
**Post date:** [November 7, 2019, 1:06pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/8 "2019-11-07T13:06:46Z")

</div>

What is the matlab time one the same computer?

---

<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:** [November 7, 2019, 1:13pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/9 "2019-11-07T13:13:45Z")

</div>

Just to start a little bit without doing a deep dive. Two things, it is better to put the indices for `current_set` and `inv_current_set` as the last indices. So instead of `values ` being `5 x 15 x 500` it is `15 x 500 x 5` and you index the last index and change to `dims = 3`.

Also, it seems you are computing `exp` on many values in `values` multiple times. Might as well pull that out. You can throw in some `@views` as well. So something like the code below should be a bit faster but it can very likely be made much faster. It depends on how much effort you are willing to put in and how ugly the code is allowed to be.

```julia
function runit()
    a = 5;
    values = randn(15, 500, 5)
    sets = collect(powerset(1:a))
    deleteat!(sets,1)

    inv_set = collect(1:a)
    p_set = zeros(15, 500, size(sets,1))
    exp_values = exp.(-exp.(values))

     @time for Z in 1:size(sets,1)
         current_set = sets[Z]
         inv_current_set = setdiff(inv_set, sets[Z]) # get the vector with inverse of current set

         # exp_values = exp.(-exp.(values)) # moved outside loop based on reply
        
         first_part = prod(1 .- @view exp_values[:, :, current_set]; dims=3)
         second_part = prod(@view exp_values[:, :, inv_current_set]; dims=3)
         third_part = prod(exp_values; dims=3)
         
         p_set[:,:,Z] = @. (first_part * second_part) / (1 - third_part); # wrap it all up
    end
    return p_set
end

```

---

<div class="post-metadata">

**Author:** ![Karajan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karajan/32/8545_2.png) [@Karajan](https://discourse.julialang.org/u/Karajan)\
**Post date:** [November 7, 2019, 1:19pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/10 "2019-11-07T13:19:07Z")

</div>

Maybe move that line out of the loop, for good measure 😉

---

<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:** [November 7, 2019, 1:20pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/11 "2019-11-07T13:20:44Z")

</div>

Ah, of course. And that cuts the runtime something tremendous. The original code does a bit too much per line imo. Moving things out makes it more clear what is loop invariant and can be hoisted.

---

<div class="post-metadata">

**Author:** ![jonneguyt](https://avatars.discourse-cdn.com/v4/letter/j/c4cdca/32.png) [@jonneguyt](https://discourse.julialang.org/u/jonneguyt)\
**Post date:** [November 7, 2019, 1:52pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/12 "2019-11-07T13:52:01Z")

</div>

Firstly: very impressed by the speed and the amount of pointers you have given me.

- Moving stuff out of the loop helped a lot.
- In my main code there are no global vars, I think that in creating the MWE I probably offended more of the performance tips than I did in my original code (not putting it in a function, using globals) - either way, lesson learnt!
- Don’t really understand why using the last indices has better performance (I guess something with storing/accessing it
- Don’t understand views, but will look into that
- I was under the impression that more per line would avoid temporary storage and be faster, which makes my coding style a little bit dense
- @Karajan, in my optimization, the "-1 ._(0 .-values[current\_set,:,:])" part contains a parameter rather than the 0. In the following manner: -1 ._(beta .-values[current\_set,:,:]). Otherwise I could indeed simplify that part.

For my use case this (for now) is already good enough of a speed-up, so thanks again to all, and in specific to @kristoffer.carlsson!

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [November 7, 2019, 2:13pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/13 "2019-11-07T14:13:25Z")

</div>

The reason the array index order matters is that in Julia, arrays are stored column major, meaning that looping over the last dimension keeps the indices close in memory, which makes caches efficient

---

<div class="post-metadata">

**Author:** ![Karajan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karajan/32/8545_2.png) [@Karajan](https://discourse.julialang.org/u/Karajan)\
**Post date:** [November 7, 2019, 2:45pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/14 "2019-11-07T14:45:11Z")

</div>

> Don’t understand views, but will look into that

Every time you do something like `matrix[1, :]` a vector gets allocated so you can work with it. `@view` avoids that and points to the underlying matrix instead. For example:

```julia
julia> const a = rand(100);

julia> @btime sum(a[1:50])
  78.759 ns (1 allocation: 496 bytes)
25.72627355400477

julia> @btime sum(a)
  19.883 ns (0 allocations: 0 bytes)
50.702224176185574

```

`a[1:50]` allocates so in this example summing half the array is slower than doing the whole thing.

> I was under the impression that more per line would avoid temporary storage and be faster, which makes my coding style a little bit dense

This can be true but it doesn’t have to be. For example using `.` to utilize loop fusion can make things faster and for this you have to write things into one line. But the above example wouldn’t be faster than

```julia
b = a[1:50]
sum(b)

```

Putting this all into action and trying to avoid the temporary arrays:

```julia
function runit()
    a = 5;
    values = randn(15, 500, 5)
    sets = collect(powerset(1:a))[2:end]

    inv_set = collect(1:a)
    p_set = zeros(15, 500, size(sets,1))

    exp_values = exp.(-exp.(values))
    third_part = prod(exp_values; dims=3)
    
    @time @inbounds for Z in 1:size(p_set, 3)
        current_set = sets[Z]
        inv_current_set = setdiff(inv_set, sets[Z]) # get the vector with inverse of current set

        for j in 1:size(p_set, 2)
            for i in 1:size(p_set, 1)
                first_part = 1.0
                for k in current_set
                    first_part *= 1 - exp_values[i, j, k]
                end
                second_part = 1.0
                for k in inv_current_set
                    second_part *= exp_values[i, j, k]
                end
                p_set[i,j,Z] = (first_part * second_part) / (1 - third_part[i, j]); # wrap it all up
            end
        end
    end
    return p_set
end

```

which is another ~4 times faster for me. Please make sure this still delivers the correct result, screwing up the code can happen quickly while playing around 😄

As Oscar said, you want to loop over the first dimension in the tightest loop (which I didn’t do to preserve the dimensions Kristoffer used, but in a test it gave another 50%). You can see the difference when you swap the lines `for j in 1:size(p_set, 2)` and `for i in 1:size(p_set, 1)`

---

<div class="post-metadata">

**Author:** ![ElectronicTeaCup](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/electronicteacup/32/12647_2.png) [@ElectronicTeaCup](https://discourse.julialang.org/u/ElectronicTeaCup)\
**Post date:** [November 7, 2019, 3:17pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/15 "2019-11-07T15:17:30Z")

</div>

I really like this thread. As someone moving from MATLAB to Julia, I write long scripts, dumping the entire workspace with lots of variables along the way. **I was wondering, is there a book that teaches programming in a more julian way?** (I have read how to think like a computer scientist, which now has a Julia version called “Think Julia” but was hoping to find something new)

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [November 7, 2019, 3:45pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/16 "2019-11-07T15:45:45Z")

</div>

The manual is actually very helpful that way. It is partially a reference, but partially a guidebook with really good pointers for beginners. For instance the sections on performance should be required reading. 🙂

---

<div class="post-metadata">

**Author:** ![ElectronicTeaCup](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/electronicteacup/32/12647_2.png) [@ElectronicTeaCup](https://discourse.julialang.org/u/ElectronicTeaCup)\
**Post date:** [November 7, 2019, 3:53pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/17 "2019-11-07T15:53:00Z")

</div>

Thanks. Gosh, it’s like learning how to program again. I was very happy to see a style guide! [Style Guide · The Julia Language](https://docs.julialang.org/en/v1/manual/style-guide/)

Could you recommend some other essential pages in the manual that could be useful for a beginner? I often find tutorials explaining the syntax but hardly anything teaching me to write good code.

---

<div class="post-metadata">

**Author:** ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)\
**Post date:** [November 7, 2019, 3:54pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/18 "2019-11-07T15:54:32Z")

</div>

While in the manual, notice the small links to source just below descriptions of various functions. Those take you straight to the source files on GitHub. Since most of Julia is written in Julia, that’s a great place to find examples.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [November 7, 2019, 9:24pm UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/19 "2019-11-07T21:24:26Z")

</div>

> [@ElectronicTeaCup](#):
>
> Could you recommend some other essential pages in the manual that could be useful for a beginner? I often find tutorials explaining the syntax but hardly anything teaching me to write good code.

Not necessarily exactly what you had in mind, but if you come from a Matlab background, this chapter might be useful: [Noteworthy differences from MATLAB](https://docs.julialang.org/en/v1/manual/noteworthy-differences/#Noteworthy-differences-from-MATLAB-1).

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 8, 2019, 5:47am UTC](https://discourse.julialang.org/t/optimizing-performance-newcomer-from-matlab/30825/20 "2019-11-08T05:47:17Z")

</div>

Julia is quite a young language and best practices are still evolving, so books are scarce and become outdated quite quickly. I would recommend just reading code in `Base`, the standard libraries, and packages you use anyway, you can learn a lot from that. There are topics with similar discussions, eg

> [@High Quality Packages to Learn From](https://discourse.julialang.org/t/high-quality-packages-to-learn-from/15101):
>
> As a newcomer to Julia I found reading through docs and the underlying code of high quality packages to be one of the best ways to learn idiomatic ways to do things, style and best of all a bunch of useful functions in base and how they are applied. So far I have gone through DataFrames, I would love other recommendations of packages that would show a reader and exploring of the language good techniques.
