es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo hacer que este código sea seguro para hilos con openMP? Integración de Monte Carlo bidimensional.

Estoy tratando de aprender la paralelización con openmp.
Este código realiza una integración de Monte Carlo bidimensional.
El tiempo de ejecución del programa (con omp) es de aproximadamente 25 segundos para N = 900 millones.

#include <cmath>
#include <cstdint>
#include <iostream>
#include <omp.h>
#include <random>

double func(double x, double y) {
    return sqrt(x+y);
}

using std::cout;
using std::endl;

const double a = 0.0, b = 1.0, c = 3.0, d = 5.0;
const uint64_t N = 900000000; 

int main() {
    double sum = 0.0;
    std::random_device rd; 

    #pragma omp parallel
    {
        uint32_t seed;

        #pragma omp critical
        {
            seed = rd();
        }

        std::mt19937 gen(seed);
        std::uniform_real_distribution<double> dist(0.0, 1.0);
        #pragma omp for reduction(+ : sum)
        for (int64_t i = 0; i < N; i++) { 

            double x = a + (b - a) * dist(gen);
            double y = c + (d - c) * dist(gen);

            #pragma omp atomic
            sum += func(x, y);
        }
    }

    double ans = sum * (b - a) * (d - c)/ N;
    cout << ans << endl;
    return 0;
}

¿Cómo puedo convertir esto en un código seguro para hilos (según dijo el profesor que no es seguro para hilos)?</omp.h>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para convertir el código en thread-safe, necesitamos abordar el problema de múltiples hilos accediendo y modificando la misma variable (sum) simultáneamente. Podemos usar una sección critical de OpenMP para asegurar que solo un hilo acceda a la variable a la vez. El código actualizado se muestra a continuación:

    #include <cmath>
    #include <cstdint>
    #include <iostream>
    #include <omp.h>
    #include <random>
    
    double func(double x, double y) {
        return sqrt(x+y);
    }
    
    using std::cout;
    using std::endl;
    
    const double a = 0.0, b = 1.0, c = 3.0, d = 5.0;
    const uint64_t N = 900000000;
    
    int main() {
        double sum = 0.0;
        std::random_device rd;
    
    #pragma omp parallel
        {
            uint32_t seed;
    
    #pragma omp critical // Hacer de la sección crítica
            {
                seed = rd();
            }
    
            std::mt19937 gen(seed);
            std::uniform_real_distribution<double> dist(0.0, 1.0);
            double local_sum = 0.0; // Inicializar una suma local para cada hilo
    
    #pragma omp for
            for (int64_t i = 0; i < N; i++) { 
    
                double x = a + (b - a) * dist(gen);
                double y = c + (d - c) * dist(gen);
    
                local_sum += func(x, y); // Actualizar la suma local en cada hilo
            }
    #pragma omp critical // Añadir las sumas locales a la suma global
            {
                sum += local_sum;
            }
        }
    
        // El resultado se calcula después de la sección paralela
    
        double ans = sum * (b - a) * (d - c)/ N;
        cout << ans<<endl;
        return 0;
    }
    

    en el código actualizado, inicializamos una variable local local_sum en cada hilo para almacenar la suma local de ese hilo. luego usamos una sección critical para agregar las sumas locales a la variable global sum. esto asegura que solo un hilo accede a sum a la vez y evita condiciones de carrera. return=”” 0;=”” }=”” ="" en="" el="" código="" actualizado,="" inicializamos="" una="" variable="" local="" `local_sum`="" en="" cada="" hilo="" para="" almacenar="" la="" suma="" local="" de="" ese="" hilo.="" luego="" usamos="" una="" sección="" `critical`="" para="" agregar="" las="" sumas="" locales="" a="" la="" variable="" global="" `sum`.="" esto="" asegura="" que="" solo="" un="" hilo="" accede="" a="" `sum`="" a="" la="" vez="" y="" evita="" condiciones="" de=""></endl;
    return 0;
    }

    en el código actualizado, inicializamos una variable local local_sum en cada hilo para almacenar la suma local de ese hilo. luego usamos una sección critical para agregar las sumas locales a la variable global sum. esto asegura que solo un hilo accede a sum a la vez y evita condiciones de carrera.></omp.h>

Comments are closed.