Fractals/Computer graphic techniques/2D/optimisation

"Your current attempt runs in about O(N^2). So even if you had enough memory, it won't finish in your lifetime." Alexander Yee

"premature optimization is the root of all evil" - Donald Knuth in paper "Structured Programming With Go To Statements"

"good algorithms beat optimized code" Bruce Dawson ( Fractal extreme )

=Software optimisation= =How to ask about optimisation ?=
 * Profiling code
 * benchmarking
 * "If you've actually profiled the code, have specific snippets so that everyone can run the same code to see its performance, and you have this library published somewhere where it can be seen (GitHub, Bitbucket, etc.), then I don't necessarily see a problem with it going on Code Review. Including the results from your profiler of choice with identified bottlenecks would go a long way towards keeping it on-topic.
 * If you're just starting the code but have profiled a small amount of code that exhibits the aberrant performance, then asking it on Stack Overflow would be acceptable. Including the results from your profiler of choice with identified bottlenecks would go a long way towards keeping it on-topic.
 * If you're asking for people to just help you optimize the code, don't ask it anywhere. Getting a code dump and being asked to find the performance bottleneck is only something I do professionally, not on my free time." (Makoto)

See also : code review

Inner loop

 * inner loop in wikipedia

number type

 * double is faster then float
 * "In my tests (with perturbation) in Fraktaler-3, x87 long double is about 4.2x slower than double on AMD 2700X CPU. floatexp (float + int32) on AMD RX 580 GPU is about 2.3x faster than x87 long double on AMD 2700X CPU, so depending on hardware there might not be any point to x87 long double..."fractalforums.org: from-java-to-cplusplus

Distance

 * Distance approximation
 * Koebe 1/4 theorem

Decomposition

 * quadtree decomposition

"I did a web-based quad-tree Mandelbrot once. I labelled the quadrants (eg a,b,c,d) the tile files were in directories (something like a.png b.png a/a.png a/b.png a/c/a/b.png), along with an sqlite database that said which tiles  were boring (all same colour), along with their period (0 for 100% exterior, 1 for 100% inside the main cardioid, 2 for 100% inside the main circle, etc).  The client was really simple, just a web page with tile paths; the server  would do a redirect to the relevant boring tile 0.png 1.png 2.png etc if any parent of the tile was boring, otherwise it'd try to serve the tile.png.  Meanwhile there was another process that just generated the tiles and populated the database.  I can't remember if I made 404 tile not found errors bump the priority of the tile for the renderer, but maybe. Eventually i abandoned the project because recalculating from scratch is typically faster and more flexible for shallow zooms, and for deep zooms the storage is prohibitive." Claude Heiland-Allen

Mirror symmetry
Parameter plane and the Mandelbrot set is symmetric with respect to the x-axis in the plane :

colour(x,y) = colour(x,-y)

Here is a C code that shows how to divide symmetric image (with axis in the middle of its height) into 3 parts :
 * axis of symmetry
 * 2 symmetric parts : above and below axis

See also Pascal code ( Delphi) for general case

Rotational symmetry
Dynamical plane and the Julia set have rotational symmetry. It can be used to speed up computing :

Complex numbers
Computations without explicit definition of complex numbers or without complex type are usually faster.

Parallel computing
In Mandelbrot and Julia sets each point/pixel is calculated independently, so it can be easly divided into an smaller tasks and carried out simultaneously.

Types of parallel computing : Wikipedia description
 * Multi-core (computing)
 * Parallella and OpenCl
 * Intel MIC
 * MPI
 * OpenMP
 * General-purpose computing on graphics processing units (GPGPU):
 * OpenCl
 * CUDA
 * WebGl

C

 * gcc vector extension
 * Intel® Advanced Vector Extensions

c++

 * Mandelbrot in Eigen - Explicit vectorization

R
Vectorisation

Here is R code of above image with comments:
 * 1) based on the R code by Jarek Tuszynski
 * 2) http://commons.wikimedia.org/wiki/File:Mandelbrot_Creation_Animation_%28800x600%29.gif

iMax=20; # number of frames and iterations

cxmin = -2.2; cxmax = 1.0; cymax = 1.2; cymin = -1.2;
 * 1) world coordinate ( float )


 * 1) screen coordinate ( integer)

dx=800; dy=600 ;          # define grid size

cxseq = seq(cxmin, cxmax, length.out=dx); cyseq = seq(cymin, cymax, length.out=dy); cxrseq = rep(cxseq, each = dy); cyrseq = rep(cyseq, dx); C = complex( real=cxrseq, imag = cyrseq); # complex vector C = matrix(C,dy,dx)      # convert from vector to matrix
 * 1) sequences of  values = rows and columns
 * 1) sequences of  values = rows * columns
 * 1) Now C is a matrix of c points coordinates (cx,cy)

F = array(0, dim = c(dy,dx,iMax)) # dy*dx*iMax array filled with zeros
 * 1) allocate memory for all the frames

Z = 0                    # initialize Z to zero for (i in 1:iMax)        # perform iMax iterations { Z = Z^2+C               # iteration; uses n point to compute n+1 point F[,,i] = exp(-abs(Z))              # an omitted index is used to represent an entire column or row # store magnitude of the complex number, scale it using an exponential function to emphasize fine detail, }

library(caTools)         # load library with write.gif function jetColors = colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000")) write.gif(F, "Mandelbrot.gif", col=jetColors, delay=100, transparent=0)
 * 1) color and save F array to the file
 * 1) mapped to color palette jetColors . Dark red is a very low number, dark blue is a very high number

Multicore
"I always create as many worker threads as I have cores. More than that and your system spends too much time task switching" - Duncan C

Using OpenMP :

Cell
"The Sony PlayStation 3 is one of the cheapest parallel computers available on the consumer market."

GPGPU
Canvas : list of supporting browsers
 * CUDA
 * Yellow Dog Linux for CUDA
 * par4all
 * OpenCl
 * GLSL - Tools for GLSL editing
 * Fragmentarium : playground for working with GPU (GLSL) based pixel graphics built in C++, OpenGL/GLSL, and Qt 4.
 * shader editor using kickjs
 * GLSL Sandbox by Ricardo Cabello Miguel using three.js
 * jsfiddle and example
 * WebGl : GLSL thru html. It is a 3D graphics API for JavaScript based on the OpenGL ES 2.0 API, that developers can use to create fully 3D web apps.
 * shadertoy by Inigo Quilez, Pol Jeremias : a browser based Fragment Shader editor for 2D effects with it.
 * how does a shadertoy work ?
 * Chrome Experiments
 * WebGL playground - new is not working !!
 * examples :
 * brainjam - webgl spiral
 * webgl examples by Evgeny Demidov
 * |WebGl example by Hvidtfeldt Christensen

Effects
Effects on 2 core CPU ( with 1 thread per core )

GPU should be:
 * 62 time faster than CPU
 * 760 times faster

Perturbation algorithm with series approximation ( 100 times faster on zoom levels around e100! )

Using WinXP Intel 2.9 GHz CPU (1 CPU used) with a GTX 480 GPU I get the following using 1000x1000 plot with 1000 max iterations :

=References=