Pregunta

Estoy desarrollando un trazador de rayos en C ++ usando SDL y Pthread. Tengo problemas haciendo mi programa utiliza dos núcleos. Los hilos de trabajo, pero que no utilizan ambos núcleos a 100%. Para interconectar SDL escribo directamente a su memoria, SDL_Surface.pixels, así que supongo que no puede ser SDL me bloqueo.

Mi función del hilo se ve así:

void* renderLines(void* pArg){
while(true){
    //Synchronize
    pthread_mutex_lock(&frame_mutex);
    pthread_cond_wait(&frame_cond, &frame_mutex);
    pthread_mutex_unlock(&frame_mutex);

    renderLinesArgs* arg = (renderLinesArgs*)pArg;
    for(int y = arg->y1; y < arg->y2; y++){
        for(int x = 0; x < arg->width; x++){
            Color C = arg->scene->renderPixel(x, y);
            putPixel(arg->screen, x, y, C);
        }
    }

    sem_post(&frame_rendered);
    }
}

Nota: escena-> renderPixel es constante, así que supongo que los dos hilos se pueden leer desde la misma memoria. He dos subprocesos de trabajo haciendo esto, en mi bucle principal hago estos trabajos usando:

//Signal a new frame
pthread_mutex_lock(&frame_mutex);
pthread_cond_broadcast(&frame_cond);
pthread_mutex_unlock(&frame_mutex);

//Wait for workers to be done
sem_wait(&frame_rendered);
sem_wait(&frame_rendered);

//Unlock SDL surface and flip it...

Nota: También he intentado crear y unirse a los hilos en lugar de sincronizarlos. Compilo esto con "-lpthread -D_POSIX_PTHREAD_SEMANTICS -pthread" y gcc no se queja.

Mi problema se ilustra mejor el uso de un gráfico de la utilización de la CPU durante la ejecución: uso de la CPU durante la ejecución.
(fuente: jopsen.dk )

Como se puede observar en el gráfico mi programa sólo utiliza un núcleo a la vez, a continuación, se cambia entre los dos cada vez en cuando, pero no conducir tanto al 100% nunca. Lo que en el mundo he hecho mal? No estoy usando cualquier mutex o semaphors en escena. ¿Qué puedo hacer para encontrar el error?

también si pongo while (true) alrededor de escena-> renderPixel () puedo empujar ambos núcleos a 100%. Así que me he sospechado que esto es causado por la sobrecarga, pero sólo sincronizar cada 0,5 segundo (FPS por ejemplo: 0,5), dada una escena compleja. Me di cuenta de que podría no ser fácil para decirme lo que mi error es, pero un acercamiento con la depuración de esto sería grande también ... No he jugado con pthreads antes ...

Además, esto puede ser un problema de hardware o kernel, el kernel es:

$uname -a
Linux jopsen-laptop 2.6.27-14-generic #1 SMP Fri Mar 13 18:00:20 UTC 2009 i686 GNU/Linux

Nota:

¿Fue útil?

Solución

Esto es inútil:

pthread_mutex_lock(&frame_mutex);
pthread_cond_wait(&frame_cond, &frame_mutex);
pthread_mutex_unlock(&frame_mutex);

si se espera que esperar a un nuevo marco de hacer algo como:

int new_frame = 0;

primer hilo:

pthread_mutex_lock(&mutex); 
new_frame = 1; 
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

otro hilo:

pthread_mutex_lock(&mutex); 
while(new_frame == 0)
  pthread_cond_wait(&cond, &mutex); 
/* Here new_frame != 0, do things with the frame*/
pthread_mutex_unlock(&mutex); 

pthread_cond_wait (), en realidad liberar el mutex, y Cancelar la planificación del hilo hasta se señaliza la condición. Cuando se señaliza la condición de la rosca se despierten y se vuelve a tomar el mutex. Todo esto sucede dentro de la función pthread_cond_wait ()

Otros consejos

Me gustaría tener una puñalada salvaje en la oscuridad y decir sus subprocesos de trabajo están gastando un montón de tiempo de espera en la variable de condición. Para obtener un buen rendimiento de la CPU en este tipo de situación en la que su código es en su mayoría depende de la CPU, se entiende utilizar un estilo orientado a las tareas de programación, donde se trata a los hilos como una "piscina" y utiliza una estructura de cola para alimentar el trabajo a ellos. Deben pasar una cantidad muy pequeña de tiempo de trabajo tirando de la cola y la mayor parte de su tiempo haciendo el trabajo real.

Lo que tenemos ahora es una situación en la que es probable que estén haciendo el trabajo por un tiempo, y luego notificar al hilo principal mediante el semáforo que se hacen. El hilo principal no liberará hasta que los dos hilos han terminado de trabajar en el marco que se están procesando actualmente.

Desde que está utilizando C ++, han considerado el uso de Boost.Threads? Esto hace que el trabajo con código multiproceso mucho más fácil, y la API es en realidad algo similar a pthreads, pero en una "C ++ moderna" tipo de camino.

No soy un gurú pthreads, pero me parece que el código siguiente es incorrecto:

pthread_mutex_lock(&frame_mutex);
pthread_cond_wait(&frame_cond, &frame_mutex);
pthread_mutex_unlock(&frame_mutex);

Para citar este artículo

  

Los bloques pthread_cond_wait() la llamada   enrosque hasta que la condición especificada   se señala. Esta rutina debe ser   llamada mientras mutex está bloqueado, y se   dará a conocer de forma automática el mutex   mientras espera. Después de señal es   recibido y el hilo se despierta, mutex   se bloqueará automáticamente para su uso   por el hilo. El programador es entonces   responsable de desbloqueo de mutex cuando   el hilo se termina con él.

así que me parece que debe ser la liberación el mutex después el bloque de código follwing la pthread_cond_wait.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top