Optimizar la función de estimación Pi en C++
He escrito un programa que aproxima Pi usando el método de Monte Carlo. Funciona bien, pero me pregunto si puedo hacer que funcione mejor y más rápido, porque al insertar algo como ~n=100000000
y mayores a partir de ese punto, tarda un tiempo en realizar los cálculos e imprimir el resultado.
He imaginado cómo podría intentar aproximarlo mejor haciendo una mediana para los resultados de n
, pero considerando lo lento que es mi algoritmo para números grandes, decidí no hacerlo.
Básicamente, la pregunta es: ¿Cómo puedo hacer que esta función funcione más rápido?
Aquí está el código que tengo hasta ahora:
double estimate_pi(double n)
{
int i;
double x, y, distance;
srand((unsigned) time(0));
double num_point_circle = 0;
double num_point_total = 0;
double final;
for (i = 0; i < n; i++)
{
x = (double) rand() / RAND_MAX;
y = (double) rand() / RAND_MAX;
distance = sqrt(x * x + y * y);
if (distance <= 1)
{
num_point_circle += 1;
}
num_point_total += 1;
}
final = ((4 * num_point_circle) / num_point_total);
return final;
}
davy.ai
Hay varias formas de optimizar el código actual para hacer que funcione más rápido:
for
puede ejecutarse en paralelo utilizando el multihilo para acelerar cálculos. Esto es particularmente útil para valores grandes den
. Hay varias bibliotecas disponibles que se pueden usar para la paralelización en C++ como OpenMP o std::thread.Optimización del compilador: El uso de banderas de optimización al compilar el código puede mejorar su rendimiento. Por ejemplo, el uso del nivel de optimización
-O3
en g++ puede reducir significativamente el tiempo de ejecución del código.Evitar cálculos innecesarios: La función
sqrt()
es una operación computacionalmente costosa, y se llama en cada iteración del buclefor
. Podemos optimizar el código calculando la distancia al cuadrado en lugar de la distancia en sí misma. Esto se puede lograr cambiando la líneadistance = sqrt(x*x + y*y);
adistance = x*x + y*y;
. Este cambio simple puede mejorar significativamente el rendimiento del código.Usar funciones en línea: La función
rand()
se llama dos veces en cada iteración del buclefor
. Podemos mejorar el rendimiento utilizando una función en línea para generar números aleatorios. Esto se puede lograr agregando la siguiente función al principio del código:Y cambiando las líneas
x = (double)rand()/RAND_MAX;
yy = (double)rand()/RAND_MAX;
ax = my_rand();
yy = my_rand();
respectivamente.Al implementar estas optimizaciones, el código puede hacerse más rápido y eficiente, lo que le permite manejar valores más grandes de
n
sin tomar demasiado tiempo.