# Optimizing Calculation in Julia compared to C (New to Julia)

**URL:** <https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723>\
**Category:** Performance\
**Created:** [December 26, 2019, 7:30pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723 "2019-12-26T19:30:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![loki](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@loki](https://discourse.julialang.org/u/loki)\
**Post date:** [December 26, 2019, 7:30pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/1 "2019-12-26T19:30:00Z")

</div>

Hello, just starting to make the switch to Julia from Matlab/C. I’ve been reading up on the speed advantages of Julia and recognize the power that can be wielded in the right hands. I was hoping I could receive some pointers on how to optimize my code. I’m comparing the code below to a vectorized C style that performs the same calculation but has been converted to julia’s syntax. The code below is both slower and requires significantly more memory allocation than the C version. I use the same variables declared outside of each function with most of the being Vector{Floats64} with b1 being a Vector{Complex{Float64}}.

Any recommendations on how I could speed this up and make it significantly less memory intensive would be greatly appreciated!

```julia
using LinearAlgebra
x_pts = 1000
num_pts = 5000
Xpos = range(-FOV/2,FOV/2,length = x_pts)

M = zeros(3,num_pts)
M[:,1] = [0;0;1]

function Sim1d(Xpos, num_pts, resol, b1, gradx, offset, M)

    Mout = zeros(3, length(Xpos))
    B1 = [0.0; 0.0; 0.0]

    for n = 1:length(Xpos)
        for tt = 1:num_pts-1
            Δω = gam * Xpos[n] * grad[tt] + offset[n]
            B1 = [real(b1[tt]); imag(b1[tt]); Δω]
            θ = norm(B1) * resol

            if abs(θ) > 1e-9
                B1 = B1 / norm(B1)
                M[:, tt+1] = M[:, tt] * cos(θ) + cross(B1, M[:, tt]) * sin(θ) +
                       B1 * dot(B1, M[:, tt]) * (1 - cos(θ))
            else
                M[:, tt+1] = M[:, tt]
            end
        end
        Mout[:, n] = M[:, end]
    end
    return Mout
end

```

---

<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:** [December 26, 2019, 7:40pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/2 "2019-12-26T19:40:09Z")

</div>

The key 2 problems here are that `M` is a non const global, and that you need to use `@views` to prevent right hand side, non-scalar indexing from allocating.

---

<div class="post-metadata">

**Author:** ![bashonubuntu](https://avatars.discourse-cdn.com/v4/letter/b/f19dbf/32.png) [@bashonubuntu](https://discourse.julialang.org/u/bashonubuntu)\
**Post date:** [December 26, 2019, 7:51pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/3 "2019-12-26T19:51:09Z")

</div>

To build off what @Oscar_Smith said, I would personally recommend reading the content below and re-editing parts of your code

> **[7 Julia Gotchas and How to Handle Them - Stochastic Lifestyle](https://www.stochasticlifestyle.com/7-julia-gotchas-handle/)**
>
> Let me start by saying Julia is a great language. I love the language, it is what I find to be the most powerful and intuitive language that I have ever used. It’s undoubtedly my favorite language. That said, there are some “gotchas”, tricky little...

This really helped me when I started and both the suggestions given above are included in it too with a more detailed explanation. Feel free to post an edited version of the above code at some point based on what you tried after reading this link!

---

<div class="post-metadata">

**Author:** ![loki](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@loki](https://discourse.julialang.org/u/loki)\
**Post date:** [December 26, 2019, 8:07pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/4 "2019-12-26T20:07:35Z")

</div>

Thank you for the link! I’ll start working my way through it and try to make the appropriate change into my code. It seems @views is an important thing to learn and master.

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [December 26, 2019, 8:14pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/5 "2019-12-26T20:14:26Z")

</div>

Also have a look at Julia Performance Tips: [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/)

---

<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:** [December 26, 2019, 8:28pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/6 "2019-12-26T20:28:50Z")

</div>

For this example, putting a const in front of your first use of M, and views before the outer for loop should bring it to C speeds. In general, it won’t always be quite that easy

---

<div class="post-metadata">

**Author:** ![bashonubuntu](https://avatars.discourse-cdn.com/v4/letter/b/f19dbf/32.png) [@bashonubuntu](https://discourse.julialang.org/u/bashonubuntu)\
**Post date:** [December 26, 2019, 9:23pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/7 "2019-12-26T21:23:56Z")

</div>

You’re welcome! And, when you time make sure to do something like the following if you are using global variables inside your function argument.

```julia
using BenchMarkTools

julia> A = rand(3,3);

julia> @btime inv($A); # we interpolate the global variable A with $A
  1.191 μs (10 allocations: 2.31 KiB)

```

---

<div class="post-metadata">

**Author:** ![loki](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@loki](https://discourse.julialang.org/u/loki)\
**Post date:** [December 26, 2019, 10:02pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/8 "2019-12-26T22:02:54Z")

</div>

Quick question regarding global variables and const. Coming from matlab, my work flow would be to do some minor calculations to create arrays (see example code below) then feed them into functions, like Sim1d up above, which would perform the bulk of the calculations. Would this work flow be frowned upon when using Julia? If I am reading all of the recommended documentation correctly, it seems that this would be bad as it could lead to significantly more computations than needed and potentially large data usage assuming I am not using @view properly.

Also here is a link to my full code showing how I structured it plus the two different implementations of my algorithm that was discussed above ([https://github.com/loki3118/Julia\_Code.git](https://github.com/loki3118/Julia_Code.git))

Example Code:

```julia
resol = 1e-6
tp = 0.005
num_pts = Int(round(tp / resol))
ts = range(-1, 1, length = num_pts)
#--------------------------------------------------------------------------
bw1 = 4.5 / tp
FOV = 10

scale = (2 * pi * bw1) / (gam * FOV)
grad = scale * ones(1, num_pts)

```

---

<div class="post-metadata">

**Author:** ![bashonubuntu](https://avatars.discourse-cdn.com/v4/letter/b/f19dbf/32.png) [@bashonubuntu](https://discourse.julialang.org/u/bashonubuntu)\
**Post date:** [December 26, 2019, 10:28pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/9 "2019-12-26T22:28:11Z")

</div>

Yes, see below. From the link I shared, one notes that “REPL/Global scope does not allow for type-specificity”. In `sum_bad()` we define x, y in the global scope without a `const` in front so the compiler can’t specialize on the types. In the next two functions, I either pass x, y as arguments or declare them as a `const`. In both cases, the compiler can generate specialized code (see the output of `@code_warntype`) which results in a dramatic performance improvement.

Personally, I prefer the style of `sum_good(x, y)` because it’s easy for readability and you know what arguments the function operates on. In `sum_also_good()`, while there is no performance hit rel. to `sum_good()`, you would have to figure out from the REPL that you passed `x,y` with a `const` in front. This becomes cumbersome for large pieces of code.

```julia
julia> x = 1
1

julia> y = 2
2

julia> function sum_bad()
        x + y
       end
sum_bad (generic function with 1 method)

julia> @code_warntype sum_bad()
Variables
  #self#::Core.Compiler.Const(sum_bad, false)

Body::Any
1 ─ %1 = (Main.x + Main.y)::Any
└── return %1

######################
# Two possible fixes 
######################

# 1) passing x, y as arguments
julia> function sum_good(x, y)
        x + y
       end
sum_good (generic function with 1 method)

julia> @code_warntype sum_good(x, y)
Variables
  #self#::Core.Compiler.Const(sum_good, false)
  x::Int64
  y::Int64

Body::Int64
1 ─ %1 = (x + y)::Int64
└── return %1

# 2) declaring globals with 'const' in front
julia> const a = 1
1

julia> const b = 2
2

julia> function sum_also_good()
        a + b
       end
sum_also_good (generic function with 1 method)

julia> @code_warntype sum_also_good()
Variables
  #self#::Core.Compiler.Const(sum_also_good, false)

Body::Int64
1 ─ %1 = (Main.a + Main.b)::Core.Compiler.Const(3, false)
└── return %1

#benchmarks 
julia> @btime sum_bad()
  20.744 ns (0 allocations: 0 bytes)
3

julia> @btime sum_good($x, $y)
  0.001 ns (0 allocations: 0 bytes)
3

julia> @btime sum_also_good()
  0.001 ns (0 allocations: 0 bytes)
3

```

---

<div class="post-metadata">

**Author:** ![Daniel\_Berge](https://avatars.discourse-cdn.com/v4/letter/d/eb9ed0/32.png) [@Daniel\_Berge](https://discourse.julialang.org/u/Daniel_Berge)\
**Post date:** [December 26, 2019, 10:36pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/10 "2019-12-26T22:36:40Z")

</div>

You generally want to use a barrier function if the dynamic dispatch will have to occur. If you really want to use a global variable, you should enclose it in a barrier function to limit the number of times dispatch has to occur. In the following example, you can see that the normal usage of the global variable results in many allocations. By using a barrier function, you limit to the dynamic dispatch cost to a single function call.

```julia
using BenchmarkTools

scale = 2.0
a=rand(1000);

foo(a) = sum(x->x*scale,a)

function foo_caller(a)
    foo_inner(a,scale)
end

function foo_inner(a,scale)
    sum(x->x*scale,a)
end

@btime foo($a)
  37.999 μs (2999 allocations: 46.86 KiB)
@btime foo_caller($a) # The barrier limits the allocations
  228.454 ns (2 allocations: 32 bytes)
@btime foo_inner($a,$scale) #No allocations were necessary past the barrier
  83.090 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [December 26, 2019, 11:18pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/11 "2019-12-26T23:18:20Z")

</div>

I would store M as a vector of static arrays since one dimension (3) is known and fixed. This will probably speed things up quite a lot.

See my previous answer here for a similar situation

> [@Optimising code: Multiplying a list of matrices by a matrix](https://discourse.julialang.org/t/optimising-code-multiplying-a-list-of-matrices-by-a-matrix/31298/8):
>
> I changed your code to use static arrays, the timing of devectorized is printed in the bottom using LinearAlgebra, BenchmarkTools, StaticArrays # De-vectorised code function devectorised!(mu, S, A, ATranspose, R, simulationLength, u) n = length(mu) for i = 1:simulationLength for j = 1:n mu[j] = A\*mu[j] + u S[j] = A\*S[j]\*ATranspose + R end end end # Admin d = 6 n = 1000 simulationLength = 30 # Motion model T = 20e-3 A = [Array(1.0I, 3, 3) T\*Ar…

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [December 27, 2019, 12:29am UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/12 "2019-12-27T00:29:36Z")

</div>

That is not a problem here, M is an input argument to the function so it should be just fine.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [December 27, 2019, 10:39am UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/13 "2019-12-27T10:39:37Z")

</div>

I have converted a fair amount of Matlab/C code to Julia. If you have existing and tested computational C code, my advice is to keep the code as is and only do the necessary syntactical and indexing changes. Julia will handle loops perfectly fine and converting to a vectorized style is only worth it if it adds clarity without compromising performance.

---

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [December 27, 2019, 1:20pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/14 "2019-12-27T13:20:40Z")

</div>

> [@GunnarFarneback](#):
>
> vectorized style is only worth it if it adds clarity without compromising performance.

it also gives access to threading and gpu

---

<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:** [December 27, 2019, 1:40pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/15 "2019-12-27T13:40:22Z")

</div>

Threading can certainly be done with loops (in fact, I thought threaded loops were the normal way). I’m not veryfamiliar with gpu processing, but there are things like [GitHub - vchuravy/GPUifyLoops.jl](https://github.com/vchuravy/GPUifyLoops.jl)

Vector/matrix operation can benefit from BLAS, though.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [December 27, 2019, 2:51pm UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/16 "2019-12-27T14:51:13Z")

</div>

> [@DNF](#):
>
> Vector/matrix operation can benefit from BLAS, though.

Yes, but in the context of porting code from Matlab/C, chances are that the parts that were implemented in C were so exactly because they would not fit into BLAS calls.

---

<div class="post-metadata">

**Author:** ![loki](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@loki](https://discourse.julialang.org/u/loki)\
**Post date:** [January 1, 2020, 12:24am UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/17 "2020-01-01T00:24:44Z")

</div>

Thank you everyone for the feed back (and Happy New Year). It has been a big help getting though I am still running into issues where I am not utilizing the features of Julia. Per all of the recommendations, I tried to specify the input type to avoid any Type-Instabilities but have been struggling getting a sense of how to properly utilize in-place operations (like foo! and .\*) and @views. I am trying to optimize the following code to better utilize these operations to cut down on garbage collecting. Also any recommendations on how to track down where I am generating garbage would be greatly appreciated.

```julia
function M_Avg(numAvg::Int64, Readout::Int64, x_pts::Int64, y_pts::Int64, M_in_vec::Array{Float64,1})
    M_in_mat = reshape(M_in_vec, Readout, x_pts,y_pts)
    M_out = zeros(Readout,Int(x_pts/numAvg),Int(y_pts/numAvg))

    @progress for n1 in 1:Int(x_pts/numAvg)
        for n2 in 1:Int(y_pts/numAvg)
            M_out[:, n1, n2]=
                sum(sum(M_in_mat[:,1+numAvg*(n1-1):n1*numAvg,1+numAvg*(n2-1):n2*numAvg],dims = 3),dims = 2)/numAvg
        end
    end
    return M_out
end

```

---

<div class="post-metadata">

**Author:** ![bashonubuntu](https://avatars.discourse-cdn.com/v4/letter/b/f19dbf/32.png) [@bashonubuntu](https://discourse.julialang.org/u/bashonubuntu)\
**Post date:** [January 1, 2020, 12:37am UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/18 "2020-01-01T00:37:48Z")

</div>

1. Can you time your code using @btime and report the output? This will help us see where there might be potential for improvements.

2. Use @codewarntype to check for type-instabilities in your code and let us know the ouput in the reply. This will also be helpful as a first step.

3. Where is `M_out_RO` initialized?

---

<div class="post-metadata">

**Author:** ![loki](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@loki](https://discourse.julialang.org/u/loki)\
**Post date:** [January 1, 2020, 1:16am UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/19 "2020-01-01T01:16:31Z")

</div>

Addressing point #3 first. I miss typed it, sorry about that. It was initialized as all zeros that is then filled during the two for loops.

Regarding the other points, I have this function inside of another function that I then run, i.e. setup like the sudo code below. I believe placing @btime when I call my outer most function wont be that informative as it includes several different functions being called. That might be also true of @codewarntype but I am not that familiar with that package. To over come this I’ve been using @profiler to get a better sense of whats going on.

```julia
# Defined in its own .jl files else where
Function Function_to_Calculate_things()
     more calculation stuff
return more calculation stuff
end

Function M_Avg()
return output
end

Function Do_stuff(....)
     calculates_stuff = Function_to_Calculate_things(...)
     Matrix_avg = M_Avg(Calculated_stuff,...)
return Matrix_avg 
end

# Main .jl file that defined everything required for Do_stuff()
include("Do_stuff.jl")
Final_out = Do_stuff(...)

```

---

<div class="post-metadata">

**Author:** ![bashonubuntu](https://avatars.discourse-cdn.com/v4/letter/b/f19dbf/32.png) [@bashonubuntu](https://discourse.julialang.org/u/bashonubuntu)\
**Post date:** [January 1, 2020, 1:39am UTC](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723/20 "2020-01-01T01:39:11Z")

</div>

Hmm, I see. I thought you wanted help in `M_Avg()` only. Can you give an example for the values of arguments that you are running `M_Avg()` with?

If you’d like, we could start looking at things starting at `M_Avg()` first and see if we can improve this inner-most function. Then, maybe you can scale up based on suggestions that I or others might have in the responses.

[Next page](https://discourse.julialang.org/t/optimizing-calculation-in-julia-compared-to-c-new-to-julia/32723.md?page=2)
