Dividir un programa en 4 hilos es más lento que un solo hilo

He estado escribiendo un raytracer la semana pasada, y he llegado a un punto en el que está haciendo lo suficiente para que el multihilo tenga sentido. He intentado usar OpenMP para paralelizarlo, pero ejecutarlo con más hilos es en realidad más lento que ejecutarlo con uno.

Al leer otras preguntas similares, especialmente sobre OpenMP, una sugerencia fue que gcc optimiza mejor el código de serie. Sin embargo, ejecuta el código compilado a continuación conexport OMP_NUM_THREADS=1 es dos veces más rápido que conexport OMP_NUM_THREADS=4. Es decir. Es el mismo código compilado en ambas ejecuciones.

Ejecutando el programa contime:

> export OMP_NUM_THREADS=1; time ./raytracer
real    0m34.344s
user    0m34.310s
sys     0m0.008s


> export OMP_NUM_THREADS=4; time ./raytracer
real    0m53.189s
user    0m20.677s
sys     0m0.096s

l tiempo de usuario es mucho más pequeño que el rea, lo cual es inusual cuando se usan múltiples núcleos-usuari debe ser más grande querea ya que varios núcleos se están ejecutando al mismo tiempo.

Code que he paralelizado usando OpenMP

void Raytracer::render( Camera& cam ) {

    // let the camera know to use this raytracer for probing the scene
    cam.setSamplingFunc(getSamplingFunction());

    int i, j;

    #pragma omp parallel private(i, j)
    {

        // Construct a ray for each pixel.
        #pragma omp for schedule(dynamic, 4)
        for (i = 0; i < cam.height(); ++i) {
            for (j = 0; j < cam.width(); ++j) {
                cam.computePixel(i, j);
            }
        }
    }
}

Al leeresta pregunt Pensé que había encontrado mi respuesta. Habla sobre la implementación de llamadas de sincronización gclib rand () para preservar el estado para la generación de números aleatorios entre subprocesos. Estoy usando rand () bastante para el muestreo de Monte Carlo, así que pensé que ese era el problema. Me deshice de las llamadas a rand, reemplazándolas con un solo valor, pero el uso de varios subprocesos aún es más lento. @EDIT: oops Resulta que no probé esto correctamente, ¡fueron los valores aleatorios!

Ahora que están fuera del camino, discutiré una descripción general de lo que se está haciendo en cada llamada acomputePixel, así que espero encontrar una solución.

En mi raytracer esencialmente tengo un árbol de escena, con todos los objetos en él. Este árbol se atraviesa mucho durantecomputePixel cuando los objetos se prueban para la intersección, sin embargo, no se realizan escrituras en este árbol ni en ningún objeto. @computePixel esencialmente lee la escena varias veces, invoca métodos en los objetos (todos los cuales son métodos constantes), y al final escribe un solo valor en su propia matriz de píxeles. Esta es la única parte de la que soy consciente de que más de un hilo intentará escribir en la misma variable miembro. No hay sincronización en ninguna parte ya que no hay dos hilos que puedan escribir en la misma celda en la matriz de píxeles.

¿Alguien puede sugerir lugares donde podría haber algún tipo de disputa? ¿Cosas para probar?

Gracias de antemano

EDITAR Lo siento, fue estúpido no proporcionar más información sobre mi sistema.

Compiler gcc 4.6 (con optimización -O2)Ubuntu Linux 11.10OpenMP 3Intel i3-2310M Quad core 2.1Ghz (en mi computadora portátil en este momento)

Code para calcular píxeles:

class Camera {

    // constructors destructors
    private:
        // this is the array that is being written to, but not read from.
        Colour* _sensor; // allocated using new at construction.
}

void Camera::computePixel(int i, int j) const {

    Colour col;

    // simple code to construct appropriate ray for the pixel
    Ray3D ray(/* params */);
    col += _sceneSamplingFunc(ray); // calls a const method that traverses scene. 

    _sensor[i*_scrWidth+j] += col;
}

De las sugerencias, podría ser el recorrido del árbol el que causa la desaceleración. Algunos otros aspectos: hay una gran cantidad de recursión una vez que se llama a la función de muestreo (rebote recursivo de rayos), ¿podría esto causar estos problemas?

Respuestas a la pregunta(8)

Su respuesta a la pregunta