我需要以恒定的帧速率显示图像,因此我使用两个线程,一个用于使用VSYNC进行渲染,一个用于使用CUDA进行计算,这可能需要很长时间。我希望计算线程在渲染线程间隔中运行(在交换缓冲区之后,在下一帧开始渲染之前)。
我有两个问题:
glutSwapBuffers()
之后,图像可能无法实际显示在屏幕上。我还没有找到通知显示完成的API。this_thread::yield()
但它仍然经常运行计算线程。我不熟悉多线程编程。我将C ++ 11用于多线程,CUDA用于计算,OpenGL用于渲染。
更新
由于计算需要很长时间,但渲染必须以60Hz执行,所以我必须分成两个线程。
我刚刚使用condition_variable
解决了这个问题,它类似于'生产者 - 消费者'问题。并且不需要知道图像何时在屏幕上实际绘制,你可以让它一直计算,而CUDA计算线程似乎不会在一个GPU中中断OpenGL渲染线程,它们是并行的。
以下是代码:
计算线程:
void update(){
while(1){
unique_lock<mutex> locker(buffer_mutex);
buffCond.wait(locker, []{return !updateFlag;});
runSolver(d_x);// compute next several images, d_x point to the images buffer
updateFlag = true;
locker.unlock();
buffCond.notify_one();
}
}
渲染线程:
void render(){
initGL();
glutMainLoop();
}
void display(){
if(updateFlag){
unique_lock<mutex> locker(buffer_mutex);
updateBuffer(d_x);
updateFlag = false;
locker.unlock();
buffCond.notify_one();
}
.../* OpenGL rendering*/
glutSwapBuffers();
}
答案 0 :(得分:1)
图形渲染通常从单个线程完成,至少从单个线程一次完成。我相信更精细的细节取决于你的软件堆栈;例如,来自Xlib:
线程应用程序:虽然Xlib确实尝试支持多线程,但API使这很困难且容易出错。
来自a rather opinionated but informed article的更多信息:
[...]但是,大多数现实生活中的程序通过更高级别的库访问Xlib,并且库不会代表它们初始化Xlib线程。今天,大多数具有多个X11连接和多个线程的程序都是错误的。
话虽如此,多线程CUDA应该仍然是一个选项,所以如果用OpenGL完成,一个线程可以进入CUDA。这样CUDA仍然可以在另一个线程渲染最后一帧时取得进展,但是在延迟下一帧的关键时期,没有线程在等待。当然,如果你真的必须在渲染每个帧之前和之后重新加入,那么你只是在没有并发性的情况下自愿承担切换上下文的成本。在这种情况下,不需要线程。
对于线程之间的共享标志,您也可以从阅读文档或<atomic>
的一些示例(尤其是atomic_bool
)中受益。如果使用正确,它们可以在线程之间安全地发出状态信号,成本非常低