在Qt中配置TBB以及简单实用

最近本人在写离线光线追踪渲染器,但是Qt::QtConcurrent的功能有限,所以就尝试使用了一下,顺便分享一些经验。
TBB里面的parallel_for非常适合光线追踪渲染器,而QtConcurrent没有这个函数

平台

  1. Qt:Qt 5.9.4 MSVC x64
  2. TBB:Threading Building Blocks 2018 Update 5
  3. CPU:inter i7-3630QM

配置TBB

首先去https://www.threadingbuildingblocks.org/下载TBB,之后会链接到github:https://github.com/01org/tbb/releases。选择对应平台下载

文件说明

bin:里面的ia32与inter64文件夹分别放着x32与x64的dll文件。虽然网上的教程(配置VS)有所以设置path环境变量与启动路径里设置tbbvars.bat。但是QtCreator貌似做不到这些。

include:c++头文件

lib:里面的ia32与inter64文件夹分别放着x32与x64的lib文件

配置过程

  1. 添加库文件:在Qt项目栏中(显示所有工程文件的那栏)的工程图标中右键-添加库-外部库,选择库文件(tbb.lib)。之后在pro文件中将debug模式的文件名从-ltbbd改成-ltbb_debug。
  2. 添加头文件:在pro中加入INCLUDEPATH += $$PWD/XXXX/include,也就是tbb里的include文件夹路径。
  3. 执行QMake
  4. 将bin里对应平台的文件放到生成程序的目录下,即完成所有配置工作。
    我的配置
    这里我直接新建了一个名为“tbb”的文件夹放在工程目录里了。
INCLUDEPATH += $$PWD/tbb/include

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/tbb/lib/intel64/vc14/ -ltbb
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/tbb/lib/intel64/vc14/ -ltbb_debug

INCLUDEPATH += $$PWD/tbb/lib/intel64/vc14
DEPENDPATH += $$PWD/tbb/lib/intel64/vc14

需要注意的细节

tbb的任务组会使Qt的信号槽不正常,此时把任务组换成QtConcurrent::run,信号槽正常运行。

task_group g;
g.run(
//QtConcurrent::run(
[this](){
    Point2D sp;//采样点坐标
    Point2D pp;//pixel上的采样点
    int nx = setting->imageWidth;
    int ny =  setting->imageHeight;
    int allPixelNum=nx*ny;
    int currentPixelNum=0;

    Vector3D lower_left_corner(-2.0, -1.0, -1.0);
    Vector3D horizontal(4.0, 0.0, 0.0);
    Vector3D vertical(0.0, 2.0, 0.0);
    Point3D origin(0.0, 0.0, 0.0);

    tbb::parallel_for( tbb::blocked_range2d<int>(0, nx, 1, 0, ny, 1),
    [&](const tbb::blocked_range2d<int>& r)
    {
        for( int i=r.rows().begin(); i!=r.rows().end(); ++i ){
            for( int j=r.cols().begin(); j!=r.cols().end(); ++j ) {
                RGBColor pixelColor;
                Ray ray;
                for(int k=0;k<setting->numSamples;k++){
                    sp=setting->samplerPtr->sampleUnitSquare();
                    float u = float(i+sp.x) / float(nx);
                    float v = float(j+sp.y) / float(ny);
                    ray.origin=origin;
                    ray.direction=lower_left_corner+u*horizontal+v*vertical;

                    pixelColor+= tracer_ptr->trace_ray(ray);
                }
                pixelColor/=setting->numSamples;
                currentPixelNum++;

                emit pixelComplete(i,j,currentPixelNum*100/allPixelNum,QColor( int(255.99*pixelColor.r), int(255.99*pixelColor.g), int(255.99*pixelColor.b)));
            }
        }
    });
    g.wait();
    emit renderComplete();});
}

以上代码是在渲染完一个像素后通过信号槽传递到GUI上,更新结果显示,这样做很可能会降低渲染的效率(因为信号槽的机制,这也是Qt的网络库不行的原因之一)。不过渲染每像素时间超过一定量的时候,这种损耗也可以忽略不计(1min以内渲染1024*1024这种明显会降低渲染效率)。

不过因为本人的渲染(测试)的时间不会超过10min,而且可以通过渲染经过时间与像素总数的比值来调整GUI线程更新渲染结果的间隔,从而解决因长时间渲染(30Min以上),GUI线程的无效更新而造成的损耗。

猜你喜欢

转载自www.cnblogs.com/blueroses/p/9394418.html