# I just decided to migrate from Python+Fortran to Julia as Julia was faster in my test

**URL:** <https://discourse.julialang.org/t/i-just-decided-to-migrate-from-python-fortran-to-julia-as-julia-was-faster-in-my-test/61188>\
**Category:** Community\
**Tags:** fortran, performance, python, tullio, loopvectorization\
**Created:** [May 15, 2021, 4:44am UTC](https://discourse.julialang.org/t/i-just-decided-to-migrate-from-python-fortran-to-julia-as-julia-was-faster-in-my-test/61188 "2021-05-15T04:44:41Z")\
**Posts on this page:** 1\
**Showing post:** 9

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 15, 2021, 10:54pm UTC](https://discourse.julialang.org/t/i-just-decided-to-migrate-from-python-fortran-to-julia-as-julia-was-faster-in-my-test/61188/9 "2021-05-15T22:54:41Z")

</div>

> [@mcabbott](#):
>
> As you can see, people like playing this game around here!

These two versions seem to be slightly faster (yet that may be noise):

```julia
function eval_exp_tweaked_4_serial(N) # ... and range collected
    a = collect(range(0, stop=2*pi, length=N))
    A = Matrix{ComplexF64}(undef, N, N)
    for (j,aj) in pairs(a)
        for i in eachindex(a)
            @inbounds A[i,j] = cis(100*(a[i]^2 + aj^2))
        end
    end
    return A
end

function eval_exp_tweaked_4_parallel(N) # ... and range collected
    a = collect(range(0, stop=2*pi, length=N))
    A = Matrix{ComplexF64}(undef, N, N)
    Threads.@threads for j in eachindex(a)
        for i in eachindex(a)
            @inbounds A[i,j] = cis(100*(a[i]^2 + a[j]^2))
        end
    end
    return A
end

```

Result:

```julia
tweaked3: 15.497 ms (3 allocations: 15.27 MiB)
tweaked3_p: 5.139 ms (24 allocations: 15.27 MiB)
tweaked4: 14.773 ms (3 allocations: 15.27 MiB)
tweaked4_p: 4.971 ms (24 allocations: 15.27 MiB)

```

But I wanted to show the iterations using `pairs` and `eachindex`, which are nice because they do not depend on the array index style and also because you can guarantee `inbounds` with that without having to use the flag. `pairs` probably gives some speedup depending on how indexes and values are used repeatedly in the loop.

> **Code**
>
> ```julia
> using Test, BenchmarkTools
> 
> function eval_exp_tweaked_3_parallel(N) # ... and range collected
> a = collect(range(0, stop=2*pi, length=N))
> A = Matrix{ComplexF64}(undef, N, N)
> @inbounds Threads.@threads for j in 1:N
> for i in 1:N
> A[i,j] = cis(100*(a[i]^2 + a[j]^2))
> end
> end
> return A
> end
> 
> function eval_exp_tweaked_3_serial(N) # ... and range collected
> a = collect(range(0, stop=2*pi, length=N))
> A = Matrix{ComplexF64}(undef, N, N)
> @inbounds for j in 1:N
> for i in 1:N
> A[i,j] = cis(100*(a[i]^2 + a[j]^2))
> end
> end
> return A
> end
> 
> function eval_exp_tweaked_4_serial(N) # ... and range collected
> a = collect(range(0, stop=2*pi, length=N))
> A = Matrix{ComplexF64}(undef, N, N)
> for (j,aj) in pairs(a)
> for i in eachindex(a)
> @inbounds A[i,j] = cis(100*(a[i]^2 + aj^2))
> end
> end
> return A
> end
> 
> function eval_exp_tweaked_4_parallel(N) # ... and range collected
> a = collect(range(0, stop=2*pi, length=N))
> A = Matrix{ComplexF64}(undef, N, N)
> Threads.@threads for j in eachindex(a)
> for i in eachindex(a)
> @inbounds A[i,j] = cis(100*(a[i]^2 + a[j]^2))
> end
> end
> return A
> end
> 
> N = 10000
> @test eval_exp_tweaked_3_serial(N) ≈ eval_exp_tweaked_4_serial(N) ≈
> eval_exp_tweaked_3_parallel(N) ≈ eval_exp_tweaked_4_parallel(N)
> 
> print("tweaked3:"); @btime eval_exp_tweaked_3_serial($N) 
> 
> print("tweaked3_p:"); @btime eval_exp_tweaked_3_parallel($N) 
> 
> print("tweaked4:"); @btime eval_exp_tweaked_4_serial($N)
> 
> print("tweaked4_p:"); @btime eval_exp_tweaked_4_parallel($N)
> 
> nothing
> 
> ```

---

_[View the full topic](https://discourse.julialang.org/t/i-just-decided-to-migrate-from-python-fortran-to-julia-as-julia-was-faster-in-my-test/61188)._
