# Why Julia can be faster than C?

**URL:** <https://discourse.julialang.org/t/why-julia-can-be-faster-than-c/88573>\
**Category:** New to Julia\
**Created:** [October 11, 2022, 11:37am UTC](https://discourse.julialang.org/t/why-julia-can-be-faster-than-c/88573 "2022-10-11T11:37:21Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [October 11, 2022, 11:37am UTC](https://discourse.julialang.org/t/why-julia-can-be-faster-than-c/88573/1 "2022-10-11T11:37:21Z")

</div>

To esitimate Pi with using Monte Calo:

C version:

```julia
#include <stdlib.h>
#include <stdio.h>
#include <chrono>
#include <array>

#define N_POINTS 10000000
#define N_REPEATS 5

float estimate_pi(int n_points) {
   double x, y, radius_squared, pi;
   int within_circle=0;

   for (int i=0; i < n_points; i++) {
      x = (double)rand() / RAND_MAX;
      y = (double)rand() / RAND_MAX;

      radius_squared = x*x + y*y;
      if (radius_squared <= 1) within_circle++;
   }

   pi=(double)within_circle/N_POINTS * 4;
   return pi;
}

int main() {
    double avg_time = 0;

    srand(42);

    for (int i=0; i < N_REPEATS; i++) {
        auto begin = std::chrono::high_resolution_clock::now();
        double pi = estimate_pi(N_POINTS);
        auto end = std::chrono::high_resolution_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
        avg_time += elapsed.count() * 1e-9;
        printf("Pi is approximately %g and took %.5f seconds to calculate.\n", pi, elapsed.count() * 1e-9);
    }

    printf("\nEach loop took on average %.5f seconds to calculate.\n", avg_time / N_REPEATS);
}

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/9/195cabcc5f3964a6ea1d77133fcd929b1233af3c.jpeg)

Julia version 1 :

```julia
estimate_pi(n_points::Int) = begin
    s = rand(Uniform(-1, 1), n_points)
    within_circle = 0
    for i = 1 : n_points
        x, y = rand(Uniform(-1, 1), 2)
        radius_squared = x^2 + y^2
        if radius_squared <= 1
            within_circle += 1
        end
    end
    pi_estimate = 4 * within_circle / n_points
end

@time estimate_pi(100_0000)
0.035509 seconds (1000.00 k allocations: 76.294 MiB)

```

Julia version2 :

```julia
estimate_pi(n_points::Int) = estimate_pi(rand(Uniform(-1, 1), (n_points, 2)))
estimate_pi(data::M) = begin
    within_circle = 0
    for i = 1 : size(data, 1)
        x, y = data[i, 1], data[i, 2]
        radius_squared = x^2 + y^2
        if radius_squared <= 1
            within_circle += 1
        end
    end
    pi_estimate = 4 * within_circle / size(data, 1)
end

@time estimate_pi(100_0000);
0.003521 seconds (2 allocations: 15.259 MiB)

```

So, Julia is faster than C, is it the reason that something wrong in the C version code? If not, in what circumencetance we can expect that Julia can be faster than C?  
And besides, Julia version2 is a little defferent to Julia version1, but the performance gap is up to 10x. I would think most people use the version2 more often? Is there a way that Julia can automatically convert the Julia version1 codes to Julia version2 codes?

---

<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:** [October 11, 2022, 11:47am UTC](https://discourse.julialang.org/t/why-julia-can-be-faster-than-c/88573/2 "2022-10-11T11:47:18Z")

</div>

> [@Brian1](#):
>
> `@time estimate_pi(100_0000);`

Sometimes is a compiler flag removes the difference. But note that you are calling the `Uniform` constructor, so one would really need to know what goes on there to understand the details.

Just for the records, this simple alternative is probably faster, and easier to translate to C:

```julia
julia> function estimate_pi(n)
           within_circle = 0
           for i in 1:n
               x, y = rand(), rand()
               radius_squared = x^2 + y^2
               within_circle += ifelse(radius_squared <= 1, 1, 0)
           end
           pi_estimate = 4*within_circle/n
       end
estimate_pi (generic function with 1 method)

julia> @btime estimate_pi(10^5)
  226.446 μs (0 allocations: 0 bytes)
3.14384

```

(actually this is pretty much the translation of your C code, except for which is the random number generator, as mentioned below)

---

<div class="post-metadata">

**Author:** ![jmair](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmair/32/35117_2.png) [@jmair](https://discourse.julialang.org/u/jmair)\
**Post date:** [October 11, 2022, 11:52am UTC](https://discourse.julialang.org/t/why-julia-can-be-faster-than-c/88573/3 "2022-10-11T11:52:35Z")

</div>

Julia also uses a faster rng algorithm by default (Xoshiro256++), which will probably show up in the differences. Part of the discussion here - [Blog: Using Julia on the HPC](https://discourse.julialang.org/t/blog-using-julia-on-the-hpc/88039) - is about this difference when comparing to C/C++

---

<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:** [October 11, 2022, 12:06pm UTC](https://discourse.julialang.org/t/why-julia-can-be-faster-than-c/88573/4 "2022-10-11T12:06:17Z")

</div>

> [@Brian1](#):
>
> `#define N_POINTS 10000000`  
> `@time estimate_pi(100_0000)`

One important reason is that you are calling the C code with 10x as many iterations.
