0

I wrote a Mandelbrot zoom in c++ but the zoom was limited due to floating point inaccuracy. That's why I wrote the whole thing againg with the GMP library.

But now I have problems with the performance. I'm new to GMP so maybe I just messed up a few things:

Here is the original code:

int iterate(double xp, double yp, int iterations){
double length = 1;
double x = 0;
double y = 0;
double r;
for(int i = 0; i < iterations && length <= 2; i++){
    double xTemp = x;
    //calculate real part
    x = (x*x)+xp-(y*y);
    //calculate imaginary part
    y = 2*xTemp*y+yp;
    //calculate lenth
    length = sqrt(x*x+y*y);
    r = i+1;
}
if(length > 2)
    return r;
return 0;

}

Same function with GMP (I think it's the same), I added two variables, temp and temp2, to store values for calculation but this shouldn't make it 10 times slower:

int iterateGMP(mpf_t xpGMP, mpf_t ypGMP, int iterations){
double r;

mpf_set_default_prec (20);

mpf_t length;
mpf_init(length);
mpf_set_d(length, 1);
mpf_t x;
mpf_init(x);
mpf_set_d(x, 0);
mpf_t y;
mpf_init(y);
mpf_set_d(y, 0);
mpf_t xTemp;
mpf_init(xTemp);
mpf_t TempGMP;
mpf_init(TempGMP);
mpf_t Temp2GMP;
mpf_init(Temp2GMP);


for(int i = 0; i < iterations && mpf_cmp_ui(length, 2)<0; i++){
    mpf_set(xTemp, x);

    //calculate real part
    mpf_mul(TempGMP, x, x);
    mpf_add(TempGMP, TempGMP, xpGMP);
    mpf_mul(Temp2GMP, y, y);
    mpf_sub(x, TempGMP, Temp2GMP);

    //calculate imaginary part
    mpf_mul(TempGMP, xTemp, y);
    mpf_mul_ui(TempGMP, TempGMP, 2);
    mpf_add(y, TempGMP, ypGMP);

    //calculate length
    mpf_mul(TempGMP, x, x);
    mpf_mul(Temp2GMP, y, y);
    mpf_add(TempGMP, TempGMP, Temp2GMP);
    mpf_sqrt(length, TempGMP);
    r = i+1;
}
if(mpf_cmp_ui(length, 2) > 0){
    return r;
}
return 0;

}

I hope someone can help me.

Joel
  • 51
  • 4
  • 2
    Did you turn on optimizations? A 10x performance loss is not totally unreasonable for an arbitrary precision library. – nwp Feb 08 '16 at 16:36
  • 1
    It's OT, but You can make both codes faster avoiding the square root. Just test for (squared) length greater of 4. – Bob__ Feb 08 '16 at 16:56
  • @nwp How can I turn on optimization? – Joel Feb 08 '16 at 16:57
  • What do you expect to find when you zoomin different than you can find without zooming in so deep? I always used double for my fractal software -- one could even have used float -- as it is sufficient for this task. There is no need to zoom in for more than a couple of magnitudes. –  Feb 08 '16 at 17:09
  • Pretty bad library if it does not provide operator overloading. I would rather write the operators than writing software which uses functions and variables instead of expressions. –  Feb 08 '16 at 17:11
  • @ExcessPhase I made just played around with it and wanted to make a zoom in video. That's what I came up with: https://www.youtube.com/watch?v=_i0uTiqD6kg but I can't go deeper – Joel Feb 08 '16 at 17:12
  • OK -- I take everything back -- there is a need for you to zoom in pretty deep. But still -- write (inline) operators. Do not use sqrt(). And potentially use the accurate presentation only when needed. And use optimization settings for the compiler! –  Feb 08 '16 at 17:19
  • If you use gcc or clang you pass -O3, if you use Visual Studio you switch from Debug to Release. Just search for your IDE or Compiler + "compiler flags". – nwp Feb 08 '16 at 21:40
  • 2
    Just a point. Don't waste time taking a `sqrt` and comparing with `2`. Check the square with `4` and you don't need to calculate `x*x` and `y*y` again - you already did that just above. In a Mandelbrot you need a keen eye to spot the slightest inefficiency, since that iteration is done billions of times. – Weather Vane Feb 08 '16 at 22:25
  • That last comment was about the "original code". You also waste time calculating `r` in every iteration, when you could have simply returned `i` – Weather Vane Feb 08 '16 at 22:35
  • Looking at OP's first sentence, he has traded accuracy for execution speed. That's how it goes. – Weather Vane Feb 08 '16 at 23:06
  • 2
    Why aren't you using gmpxx.h, which provides a type `mpf_class` with all the operators you are used to for `double`? – Marc Glisse Feb 14 '16 at 13:00
  • Also, how many iterations are you running for? The number of bits in the numbers you are trying to build up may simply be getting overwhelmingly large... – pnkfelix Feb 17 '16 at 23:04

1 Answers1

4

I added two variables, temp and temp2, to store values for calculation but this shouldn't make it 10 times slower

Operations on float and double are normally handled by the hardware. Whereas operations on GMP types are handled by GMP library in software.

GMP values also require more memory to store and memory is often the bottleneck.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • The problem in this case (a Mandelbrot loop) isn't the extra memory, it's that software extended-precision float is *much* slower than hardware floating point. It's a latency-bound loop with the same data repeatedly. – Peter Cordes Feb 14 '16 at 19:34