1

我正在使用 SDL 和 Pthread 用 C++ 开发光线追踪器。我在使我的程序使用两个内核时遇到问题。线程可以工作,但它们不会 100% 使用两个内核。为了接口 SDL,我直接写入它的内存 SDL_Surface.pixels,所以我认为它不可能是 SDL 锁定我。

我的线程函数如下所示:

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

注意:scene->renderPixel 是 const,所以我假设两个线程都可以从同一个内存中读取。我有两个工作线程在做这件事,在我的主循环中我使用:

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

注意:我也尝试过创建和加入线程而不是同步它们。我用“-lpthread -D_POSIX_PTHREAD_SEMANTICS -pthread”编译它,gcc 没有抱怨。

我的问题最好使用执行期间的 CPU 使用图来说明:( 来源:jopsen.dk执行期间的 CPU 使用率。

从图中可以看出,我的程序一次只使用一个内核,然后每隔一段时间在两者之间切换,但它永远不会将两者都驱动到 100%。我到底做错了什么?我没有在场景中使用任何互斥锁或信号量。我该怎么做才能找到错误?

此外,如果我将 while(true) 放在 scene->renderPixel() 周围,我可以将两个核心都推到 100%。所以我怀疑这是由开销引起的,但我只每 0.5 秒同步一次(例如 FPS:0.5),给定一个复杂的场景。我意识到告诉我我的错误可能并不容易,但是调试它的方法也很棒......我以前没有玩过pthreads......

另外,这可能是硬件或内核问题,我的内核是:

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

笔记:

4

3 回答 3

2

这是没用的:

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

如果您等待等待新框架,请执行以下操作:

int new_frame = 0;

第一个线程:

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

其他线程:

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(),实际释放互斥锁,并取消调度线程,直到条件发出信号。当条件发出信号时,线程被唤醒并重新获取互斥锁。所有这些都发生在 pthread_cond_wait() 函数中

于 2009-04-07T09:36:29.890 回答
1

我会在黑暗中猛烈抨击并说您的工作线程正在花费大量时间等待条件变量。为了在这种代码主要受 CPU 限制的情况下获得良好的 CPU 性能,可以理解为使用面向任务的编程风格,将线程视为“池”,并使用队列结构将工作提供给他们。他们应该花很少的时间将工作从队列中拉出来,而大部分时间都在做实际的工作。

你现在的情况是他们可能正在工作一段时间,然后通过信号量通知主线程他们已经完成。在两个线程都完成了它们当前正在处理的帧的工作之前,主线程不会释放它们。

由于您使用的是 C++,您是否考虑过使用 Boost.Threads?它使处理多线程代码变得更加容易,而且 API 实际上有点类似于 pthreads,但是以“现代 C++”的方式。

于 2009-04-07T09:24:32.680 回答
1

我不是 pthreads 专家,但在我看来,以下代码是错误的:

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

引用这篇文章

pthread_cond_wait()阻塞调用线程,直到发出指定条件的信号。该例程应该在互斥锁被锁定时调用,它会在等待时自动释放互斥锁。收到信号并唤醒线程后,互斥量将自动锁定以供线程使用。然后,程序员负责在线程完成后解锁互斥锁。

所以在我看来,您应该在pthread_cond_wait.

于 2009-04-07T09:31:35.753 回答