A divisão de um programa em 4 threads é mais lenta que em um único thread

Escrevi um raytracer na semana passada e cheguei a um ponto em que está fazendo o suficiente para que o multi-threading fizesse sentido. Tentei usar o OpenMP para paralelizar, mas executá-lo com mais threads é mais lento do que executá-lo com u

Lendo outras perguntas semelhantes, especialmente sobre o OpenMP, uma sugestão foi que o gcc otimiza melhor o código serial. No entanto, executar o código compilado abaixo comexport OMP_NUM_THREADS=1 é duas vezes mais rápido que comexport OMP_NUM_THREADS=4. I.e. É o mesmo código compilado em ambas as execuçõe

Executando o programa comtime:

> 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

O tempo do usuário é muito menor que o real, o que é incomum ao usar vários núcleos-do utilizado deve ser maior querea como vários núcleos estão sendo executados ao mesmo temp

ódigo que paralelizei usando o 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);
            }
        }
    }
}

Ao leressa questã Pensei ter encontrado minha resposta. Ele fala sobre a implementação de chamadas de sincronização gclib rand () para preservar o estado da geração aleatória de números entre threads. Estou usando bastante o rand () para amostragem monte carlo, então pensei que esse era o problema. Livrei-me das chamadas para rand, substituindo-as por um único valor, mas o uso de vários threads ainda é mais lento.EDIT: oops Acontece que eu não testei isso corretamente, eram os valores aleatórios!

Agora que estão fora do caminho, discutirei uma visão geral do que está sendo feito em cada chamada paracomputePixel, espero que seja possível encontrar uma soluçã

No meu raytracer, eu essencialmente tenho uma árvore de cena, com todos os objetos nela. Essa árvore é percorrida muito durantecomputePixel quando objetos são testados para interseção, no entanto, nenhuma gravação é feita nessa árvore ou em nenhum objeto.computePixel @ essencialmente lê a cena várias vezes, chamando métodos nos objetos (todos os quais são métodos const) e, no final, grava um único valor em sua própria matriz de pixels. Esta é a única parte que eu conheço onde mais de um segmento tentará gravar na mesma variável de membro. Não há sincronização em nenhum lugar, pois não há dois segmentos que podem gravar na mesma célula na matriz de pixel

Alguém pode sugerir lugares onde possa haver algum tipo de disputa? O que tentar?

Agradeço antecipadamente

EDITAR Desculpe, foi estúpido por não fornecer mais informações no meu sistem

Compiler gcc 4.6 (com otimização de -O2)Ubuntu Linux 11.10OpenMP 3Intel i3-2310M Quad core 2.1Ghz (no meu laptop no momento)

Código para pixel de computação:

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;
}

Das sugestões, pode ser o deslocamento da árvore que causa a desaceleração. Alguns outros aspectos: há muita recursão envolvida quando a função de amostragem é chamada (ressalto recursivo de raios) - isso poderia causar esses problemas?