Frage

Ich bin ein Ray Tracer in C ++ Entwicklung unter Verwendung von SDL und Pthread. Ich habe Probleme machen mein Programm zwei Kerne nutzen. Die Fäden arbeiten, aber sie nicht verwenden beide Kerne auf 100%. Um SDL Schnittstelle schreibe ich direkt mit ihm dem Gedächtnis, SDL_Surface.pixels, so nehme ich an, dass es nicht SDL sein, mich zu verriegeln.

Meine Thread-Funktion sieht wie folgt aus:

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

Hinweis: Szene-> renderPixel ist const, so nehme ich an beiden Fäden aus dem gleichen Speicher lesen können. Ich habe zwei Worker-Threads dies zu tun, in meiner Haupt-Schleife mache ich diese Arbeit mit:

//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...

Hinweis: Ich habe auch versucht, die Erstellung und die Fäden verbinden, anstatt sie zu synchronisieren. Ich kompilieren dies mit "-lpthread -D_POSIX_PTHREAD_SEMANTICS -pthread" und gcc beschwert sich nicht.

mit einem Diagramm der CPU-Auslastung während der Ausführung

Mein Problem ist am besten veranschaulicht: CPU-Auslastung während der Ausführung.
(Quelle: jopsen.dk )

jeder einmal in eine Weile

Wie aus dem Diagramm mein Programm zu sehen ist nur ein Kern in einer Zeit verwendet, dann zwischen den beiden Schalt, aber es fahren nicht beide zu 100% je. Was in der Welt habe ich falsch gemacht? Ich verwende keine Mutex oder Semaphoren in Szene. Was kann ich tun, um den Fehler zu finden?

Auch wenn ich while (true) setzen um Szene-> renderPixel () Ich kann beide Kerne auf 100% drücken. Also ich habe den Verdacht, dass dies durch Overhead verursacht wird, aber ich synchronisieren nur alle 0,5 Sekunden (z FPS: 0,5), eine komplexe Szene gegeben. Ich weiß, es ist nicht leicht sein könnte, mir zu sagen, was mein Fehler, sondern ein Ansatz, um dies zu groß, um das zu Debuggen wäre ... Ich habe nicht mit pthreads vor ...

gespielt

Auch kann dies eine Hardware oder Kernel-Problem sein, mein Kern ist:

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

Hinweis:

War es hilfreich?

Lösung

Dies ist nutzlos:

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

Wenn Sie warten auf einen neuen Rahmen zu warten, so etwas wie:

int NEW_FRAME = 0;

Erstes Thema:

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

anderer Thread:

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 (werden), lassen tatsächlich den Mutex und Unschedule des Thread, bis der Zustand signalisiert wird. Wenn der Zustand signalisiert wird, der Faden wird aufgeweckt und die mutex wieder aufgenommen wird. All dies innerhalb der pthread_cond_wait () Funktion geschehen

Andere Tipps

Ich würde einen wilden Stich in der Dunkelheit nehmen und sagen, dass Ihre Arbeitsthreads viel Zeit mit Warten auf die Bedingungsvariable ausgeben. Um eine gute CPU-Leistung in dieser Art von Situation, wo der Code meist CPU gebunden ist, versteht es sich um eine Aufgabe orientierte Art der Programmierung zu verwenden, in dem Sie die Fäden als „Pool“ zu behandeln und Sie verwenden, um eine Warteschlangenstruktur zu füttern Arbeit Sie. Sie sollten eine sehr kleine Menge Zeit damit verbringen, Arbeit aus der Warteschlange ziehen und die meiste Zeit die eigentliche Arbeit zu tun.

Was Sie jetzt haben, ist eine Situation, wo sie wahrscheinlich Arbeit für eine Weile tun werden, dann über die Semaphore den Haupt-Thread darüber informiert, dass sie fertig sind. Der Haupt-Thread wird sie nicht loslassen, bis beide Threads fertig sind auf dem Rahmen arbeiten sie gerade bearbeiten.

Da Sie C ++ verwenden, haben Sie als Boost.Threads verwenden? Es macht mit multithreaded Code arbeitet viel einfacher, und die API ist eigentlich ganz ähnlich wie pThreads, aber in einer „modernen C ++“ Art und Weise.

Ich bin kein pThreads Guru, aber es scheint mir, dass der folgende Code ist falsch:

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

dieser Artikel

  

pthread_cond_wait() blockiert die Berufung   Thread, bis der festgelegte Bedingung   signalisiert wird. Diese Routine sollte   genannt, während Mutex gesperrt ist, und es   die Mutex automatisch freigeben   während sie wartet. Nach dem Signal   empfangen und Faden aufgeweckt wird, mutex   wird für den Einsatz automatisch gesperrt   durch das Gewinde. Der Programmierer ist dann   verantwortlich für das Entriegeln Mutex, wenn   der Faden wird damit fertig.

so scheint es mir, dass Sie die Mutex der Freigabe sollten nach der Code-Block follwing die pthread_cond_wait.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top