Function uses huge memory

I can not figure out as to why the function given below uses huge memory allocations.

function findpi(n::Int64)::Float64
    inside = 0
    x,y=0.0,0.0
       for i in 1:n
       		x, y = rand(2)
            
       		inside += (x^2 + y^2) <= 1 ? 1 : 0
       	end
       	4 * inside / n
end


@time findpi(10000000)
@time findpi(10000000)
@time findpi(10000000)

 0.556831 seconds (10.04 M allocations: 917.497 MiB, 11.59% gc time)
  0.461873 seconds (10.00 M allocations: 915.528 MiB, 10.93% gc time)
  0.486833 seconds (10.00 M allocations: 915.528 MiB, 11.24% gc time)

Don’t mix Int and Float64 in the calculations.

Here is an alternative

julia> function findpi(n)
           inside = 0.
           for i in 1:n
               inside += rand()^2 + rand()^2 <= 1 ? 1. : 0.
           end
           4 * inside / n
       end
findpi (generic function with 1 method)

julia> @benchmark findpi(10000000)
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     43.458 ms (0.00% GC)
  median time:      44.101 ms (0.00% GC)
  mean time:        44.429 ms (0.00% GC)
  maximum time:     54.051 ms (0.00% GC)
  --------------
  samples:          113
  evals/sample:     1
1 Like

Thank you both @LeoK987 and @jbrea for your quick and wonderful response.

rand(2) allocates a vector, which you deconstruct immediately
x,y = rand(), rand() should solve that problem.

5 Likes

Also note that the mixing of float and Int was not a problem in your original code. Everything was type stable, as inside started out as an int and stayed an Int.

6 Likes

Thanks @baggepinnen.

It seems like we are missing a generator version of rand(N).

1 Like
a, b, c, d, e = Iterators.cycle((randn() for i in 1));

works.

1 Like

In this case they were not mixed. And, in general, there’s nothing wrong with mixing them, either.

Using floats is not optimal here. Use Ints, like this:

function findpi2(n)
    inside = 0
    for i in 1:n
        inside += rand()^2 + rand()^2 <= 1 ? 1 : 0
    end
    return 4 * inside / n
end

or, equally fast (but more elegant, IMHO):

function findpi3(n)
    inside = 0
    for i in 1:n
        inside += (rand()^2 + rand()^2 <= 1)
    end
    return 4 * inside / n
end
julia> @btime findpi(10^7)
  38.940 ms (0 allocations: 0 bytes)
3.1421128

julia> @btime findpi2(10^7)
  32.242 ms (0 allocations: 0 bytes)
3.1416336

julia> @btime findpi3(10^7)
  32.220 ms (0 allocations: 0 bytes)
3.1418104
2 Likes

@DNF Thanks