I wrote a simple script for a Schroder fractal (a distant cousin of Newton 
fractals) of a fourth-order polynomial:
function SchroderFourth(a0::Float64, a1::Float64, a2::Float64, a3::Float64, 
a4::Float64, c::Complex{Float64})
x = c
x2 = c
M = 100
R = 10.0^-6
a = 0.1
for j in 1:M
x2 = x
f = a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4
fP = a1 + 2*a2*x + 3*a3*x^2 + 4*a4*x^3
fPP = 2*a2 + 6*a3*x + 12*a4*x^2;
x = x - f*fP/(fP^2 - fPP*f)
if abs(x - x2) < R
return exp(-a*(j - (log(abs(x - x2))-log(R))/log(R)) + angle(x)im)
end
end
return 0.0 + 0.0im
end

I tested it using @time as follows:
@time arr = [SchroderFourth(1.0,2.0,3.0,4.0,5.0,x+y*im) for x in 
linspace(-2,2,1000), y in linspace(-2,2,1000)];
resulting in 
elapsed time: 3.371773428 seconds (2239441280 bytes allocated, 48.23% gc 
time)

So it's allocating 2.2GB throughout the computation, and half the time is 
gc time. I have heard that sometimes this is caused by type instability, 
but the SchroderFourth function is type-stable (always returns 
Complex{Float64}). Am I committing any "great sins" in my implementation?

Given that the array has 1M computations, and each computation loops at 
most M=100 loops, I suppose it's possible that gigabytes of allocation 
could occur if a memory address was gobbled up after each iteration of the 
loop. In comparison, running the same computation on the (simpler) "mandel" 
fractal on the JuliaLang website gives much less memory allocation (8MB):
function mandel(z)
    c = z
    maxiter = 80
    for n = 1:maxiter
        if abs(z) > 2
            return n-1
        end
        z = z^2 + c
    end
    return maxiter
end
@time arr = [mandel(x+y*im) for x in linspace(-2,2,1000), y in 
linspace(-2,2,1000)];
giving
elapsed time: 0.123358763 seconds (8016176 bytes allocated)

Any clues as to the large disparity in memory allocation between the two 
functions? I assume I'm doing something dumb that's causing memory to be 
allocated and gc'ed after each iteration, but am having trouble finding 
what is causing it.


Reply via email to