Red de conocimiento informático - Aprendizaje de código fuente - Implementación de programación del conjunto de Mandelbrot

Implementación de programación del conjunto de Mandelbrot

Cálculo y visualización de conjuntos de Mandelbrot

El conjunto de Mandelbrot es un ejemplo típico de computación paralela simple. Los algoritmos paralelos están diseñados para ser estáticos mediante la técnica de divide y vencerás.

Asignación de tareas y asignación dinámica de tareas (grupo de trabajo o grupo de procesadores disponibles).

1. Caso de prueba

Los datos desde la parte inferior (real_min, IMAG_min) hasta (real_max, IMAG_max) representan la ventana del plano complejo y real_min la representa.

El valor mínimo de la parte real, imag_min representa el valor mínimo de la parte imaginaria, real_max representa el valor máximo de la parte real e imag_max representa el valor máximo de la parte imaginaria.

Valor.

(-0,84950, 0,21000) a (-0,84860, 0,21090) (0,32000, -0,45000) a (0,50000, 0,05000) (0,26304, 0,00233) a (0,26329, 0,00267)

(-0,63500, 0,68000) a (-0,62500, 0,69000) (-0,46510, -0,56500) a (-0,46470, -0,56460) (-1,50000, -1,00000) a (0,50000, 1,0000)

2. Cálculo del conjunto de Mandelbrot

Mostrar el conjunto de Mandelbrot es un ejemplo de trabajo con imágenes de mapa de bits. En primer lugar, se debe calcular la imagen, lo cual es muy costoso desde el punto de vista computacional.

El gran conjunto de Mandelbrot es un conjunto de puntos en el plano complejo que estarán en un estado casi estable cuando una función se calcula de forma iterativa.

Estado (cuasi estable), que aumentará o disminuirá, pero no superará un determinado límite. Generalmente la función es:

zk+1 = zk

2 + c

donde zk+1 es la iteración k+1 del número complejo z = a+bi, c es el valor inicial del número complejo. Determine la ubicación de este punto en el plano complejo.

El valor es 0. Las iteraciones continuarán hasta que la magnitud de z (longitud del vector, aquí 22ba+) sea mayor que 2 o el número de iteraciones.

Este número ha alcanzado un límite arbitrario.

Cálculos simplificados.

z2 = ​​​​a2 - b2 + 2abi

Usa zreal para representar la parte real de z y usa zimag para representar la parte imaginaria de z.

zreal = a2 - b2 + creal

zimag = 2ab + cimag

3. Código de secuencia

La estructura es compleja{

Real flotante;

Imagen flotante;

};

Rutina para calcular el valor del punto y devolver el número de iteraciones:

int cal_pixel(número complejo c)

{ int count, max

Número complejo z;

Temperatura de punto flotante, longitud q;

máx = 256

z .real = 0;

z .imag = 0; p>Hacer {

temp = z . real * z . real-z . z imag+c .imag;

z.real = temp

longitud sqc = z real* z real+z .

count++;

} while((length sq & lt; 4.0)& amp; & amp(count & ltmax)); //Hasta que la amplitud de z sea mayor que 2 o el número de las iteraciones alcanzan el máximo.

Devuelve el recuento;

}

Por lo tanto, todas las características de Mandelbrot dadas deben estar dentro de un círculo con el origen como centro y un radio de 2.

El código que calcula y muestra estos puntos necesita escalar el sistema de coordenadas para que coincida con el sistema de coordenadas del área de visualización.

Supongamos que la altura de visualización es disp_height, el ancho es disp_width y la posición del punto en el área de visualización es (x, y). Si se muestra,

esta ventana del plano complejo tiene un valor mínimo (real_min, imag_min) y un valor máximo (real_max, imag_max), entonces cada

punto debe ser escalado por los siguientes factores.

c . real = real _ min+x *(real _ max-real _ min)/disp _ ancho

c . _ max-imag _ min)/disp _ height

establecer escala _ real =(real _ max-real _ min)/disp _ width

escala _ imag =( imag_max-imag_min)/disp_height;

Código de escala:

for(x = 0; x & ltdisp_widthx++)

for (y = 0; y & ltdisp _ alto++) {

c . real = real _ min+((float)x * escala _ real

c . _ imag);

color = cal _ pixel(c

Pantalla (x, y, color

}

4. Código paralelo

1) Asignación de tareas estáticas

Suponiendo que el área de visualización es 640 × 480, se calcularán 10 líneas para un proceso, es decir, 10. × 640 píxeles reemplazados por un grupo, ***48.

Proceso. El código es el siguiente:

Proceso principal maestro

for (i = 0, fila = 0; i<48;i++, fila = fila + 10)

enviar(&line,pi)

for(i=0;i<(480*640);i++)

recv(&c,&color, PANY);

Pantalla (c, color);

}

Proceso esclavo proceso esclavo (proceso I)

recv(& amp; fila, p maestro);

for(x = 0; x & ltdisp _ anchox++)

for(y = fila; y & lt(fila + 10)); >c real = real _ min+((float)x * escala _ real);

c imag = imag _ min+((float)y * escala _ imag);

color = cal _ pixel(c);

send(&c,&color,pmaster);

}

Mejora: Enviar datos en grupos. Reducir el número de inicios de comunicación. Primero guarde los resultados en una matriz y luego envíe todos los datos en un solo mensaje.

El array se envía al proceso principal. El proceso maestro puede recibir mensajes de procesos esclavos en cualquier orden utilizando comodines.

2) Asignación dinámica de tareas-grupo de trabajo/grupo de procesadores.

El método del grupo de trabajo puede lograr un equilibrio de carga dinámico. En nuestro problema, consta de una colección de píxeles (más precisamente, una colección de coordenadas).

El número de tareas es fijo y el número de píxeles a calcular se conoce antes del cálculo. Cada procesador solicita del grupo de trabajadores.

Las coordenadas del siguiente subconjunto de píxeles.

Proceso principal

count = 0

fila = 0

for(k = 0; k & ltprocnok++) {

Enviar(&row,pk,data_tag);

count++;

fila++;

}

hacer {

recv(&slave&r,color,pany,result_tag);

count-;

if(line 0 )

Proceso esclavo

recv(y, Pmaster, ANYTAG, source_tag); //Recibe el punto de la línea y enviada por Pmaster.

While(source_tag == data_tag) {//Determine si hay un mensaje que deba procesarse.

c . imag = imag _ min+((float)y * escala _ imag

for(x = 0; x & ltdisp _ widthx++) {

c . real = real _ min+((float)x * escala _ real

color = cal _ pixel(c

}

Send(&i&y,color,Pmaster,result_tag); //Envía el color calculado del punto de la línea Y a Pmaster.

recv(y&r,Pmaster,source_tag);//Recibir la siguiente tarea

}//Si sale del ciclo while, debe ser source_tag = terminar _ tag, indicando que no hay tarea y el programa finaliza.