Fractale de Mandelbrot

Fermé
LittDev - Modifié par LittDev le 25/07/2016 à 03:59
 LittDev - 3 août 2016 à 08:38
Salut

J'ai programmé un petit générateur de fractales de mandelbrot avec la SDL, mais il prend beaucoup de temps pour calculer, malgré un nombre d’itérations assez faible, n'y aurait pas t-il des optimisations a faire dans le code ou des erreurs qui ralentissent le calcul ?

Pour ceux qui ne savent pas ce que c'est :
https://fr.wikipedia.org/wiki/Ensemble_de_Mandelbrot

#include <complex>
#include <cstdlib>
#include <iostream>
#include <string>
#include <cmath>

#include <SDL/SDL.h>

#define X 899
#define Y 599

using namespace std;

//Structure simple pour les couleurs
typedef struct
{
    int r;
    int g;
    int b;
}Color;

void set_color(Color& color, int const& r, int const& g, int const& b)
{
    color.r = r;
    color.g = g;
    color.b = b;
}

//Fonction gaussienne
double gauss(long double const& x, long double const& var, long double const& moy)
{
    return exp(-1*((x-moy)*(x-moy))/var);
}

//Calcule la couleur en fonction de l'iteration en utilisant la fonction gaussienne
Color calculate_color(int const& iterations, int const& iter_max)
{
    Color result;

    if(iterations == iter_max)
    {
        set_color(result,0,0,0);
        return result;
    }

    double temp(static_cast <double>(iterations%768)/768), var(0.1);
    set_color(result, static_cast <int>(256*gauss(temp,0.25*var,0.5)),  static_cast <int>(256*gauss(temp,var,0.5)),  static_cast <int>(256*gauss(temp,0.5*var,0.5)));

    return result;
}

//La fonction qui permet de generer les termes de la suite en fonction de cst et du nombre d'iterations maximum
int mandelbrot_suite(complex <long double> const& cst, int iter_max)
{
    complex <long double> result(0,0);
    for(int i(0);i<iter_max;i++)
    {
        result = result*result + cst;
        if(norm(result)>2)
            return i;
    }

    return iter_max;
}

int main (int argc, char** argv)
{
    //Zoom : Nombre de pixels par unité (ex : 45000 par 1.5)
    long zoom = 30000;
    SDL_Surface* screen = SDL_SetVideoMode(X, Y, 16, SDL_HWSURFACE|SDL_DOUBLEBUF);
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
        return 1;

    atexit(SDL_Quit);

    SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 255, 255, 255));
    SDL_Flip(screen);

    bool done(false);
    
    SDL_Rect pos;
    pos.x = 0;
    pos.y = 0;
    pos.h = 1;
    pos.w = 1;

    while (!done)
    {
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
            case SDL_QUIT:
                done = true;
                break;
            case SDL_KEYDOWN:
                {
                    if (event.key.keysym.sym == SDLK_ESCAPE)
                        done = true;
                    break;
                }
            }
        }

        //Transformation des points de l'ecran en nombre complexe, en fonction du zoom
        complex <long double> cst(static_cast <long double>(pos.x - (X+1)/2)/zoom - 0.11,static_cast <long double>(((Y+1)/2) - pos.y)/zoom + 0.895);
        //Calcul du nombre d'iterations
        int result(mandelbrot_suite(cst,768));
        //Choix de la couleur
        Color color(calculate_color(result,768));
        //Creation du pixel en fonction de la couleur choisie et de la position
        SDL_FillRect(screen,&pos,SDL_MapRGB(screen->format,color.r,color.g,color.b));

        if(pos.x < screen->w-1)
            pos.x++;
        else if(pos.y < screen->h-1)
        {
            pos.y++;
            pos.x=0;
        }
        else
            SDL_Flip(screen);
    }

    return 0;
}


Merci d'avance
A voir également:

1 réponse

Franck7511 Messages postés 14296 Date d'inscription jeudi 24 décembre 2009 Statut Membre Dernière intervention 10 août 2017 1 121
Modifié par Franck7511 le 28/07/2016 à 18:44
Utilise un Profiler pour voir là où le programme passe du temps, je n'ai pas pu compiler ton code (j'utilise SDL2 et non SDL1)

Sache que c'est fortement parallélisable/vectorisable comme code, si tu veux te lancer là dedans :)

En plus, sauf si tu as besoin vraiment de précision étendue, double est bien plus rapide. Pour un GPU float sera encore plus rapide.
0
Merci de la réponse

J'ai tout changé, je suis passé à la SFML, j'ai bien revu la boucle du programme, bien factorisé le code, et j'ai trouvé des optimisations de calcul, et j'ai mainenant un resultat plutôt satisfaisant :)
0