英特尔TBB vs Boost

英特尔TBB vs Boost,boost,boost-thread,tbb,Boost,Boost Thread,Tbb,在我的新应用程序中,我可以灵活地决定多线程库的使用。到目前为止,我使用的是pthread。现在想探索跨平台库。我专注于TBB和Boost。我不明白TBB比Boost有什么好处。 我试图找出TBB相对于Boost的优势: TBB wiki摘录相反,该库通过允许将操作视为任务(由库的运行时引擎动态分配给各个内核)并通过自动化缓存的有效使用来抽象对多处理器的访问。TBB程序根据算法创建、同步和销毁相关任务的图形 但是线程库甚至需要担心线程分配到内核吗。这不是操作系统的工作吗? 那么,在Boost之上使

在我的新应用程序中,我可以灵活地决定多线程库的使用。到目前为止,我使用的是pthread。现在想探索跨平台库。我专注于TBB和Boost。我不明白TBB比Boost有什么好处。 我试图找出TBB相对于Boost的优势: TBB wiki摘录相反,该库通过允许将操作视为任务(由库的运行时引擎动态分配给各个内核)并通过自动化缓存的有效使用来抽象对多处理器的访问。TBB程序根据算法创建、同步和销毁相关任务的图形

但是线程库甚至需要担心线程分配到内核吗。这不是操作系统的工作吗?
那么,在Boost之上使用TBB的真正好处是什么呢?

英特尔TBB引入了它自己的线程池/调度程序和执行模型,包括用于构造的并行_之类的东西,而Boost只有基本的线程管理功能创建线程和同步原语,就是这样。使用Boost编写一个好的线程池是可能的,但很困难——TBB已经有了一个高度优化的线程池。因此,这完全取决于您的需求:如果您只需要可移植的pthreads,请使用Boost;如果您需要更多,请使用inteltbb

但是线程库甚至需要担心线程分配到内核吗。这不是操作系统的工作吗?那么,使用TBB而不是Boost的真正好处是什么呢

您是对的,线程库通常不应该关心将线程映射到核心。而TBB则不然。TBB使用任务而不是线程进行操作。TBB的调度程序通过分配线程池并让它动态选择要运行的任务来利用所有内核。这是Boost的主要优势,通过Boost,您需要手动将可用工作映射到线程。然后,TBB提供了高级构造,如parallel_for、parallel_pipeline等,可用于表示最常见的并行模式,并隐藏任务的所有操作

例如,让我们取一段计算曼德尔布罗特分形点的代码,变量初始化省略:

for(unsigned y=0; y<ImageHeight; ++y)
{
    double c_im = MaxIm - y*Im_factor;
    for(unsigned x=0; x<ImageWidth; ++x)
    {
        double c_re = MinRe + x*Re_factor;

        double Z_re = c_re, Z_im = c_im;
        bool isInside = true;
        for(unsigned n=0; n<MaxIterations; ++n)
        {
            double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im;
            if(Z_re2 + Z_im2 > 4)
            {
                isInside = false;
                break;
            }
            Z_im = 2*Z_re*Z_im + c_im;
            Z_re = Z_re2 - Z_im2 + c_re;
        }
        if(isInside) { putpixel(x, y); }
    }
}
现在要使其与TBB并行,您只需将最外层的循环转换为TBB::parallel_,因为为了简洁起见,我使用了C++11 lambda:

tbb::parallel_for(0, ImageHeight, [=](unsigned y)
{
    // the rest of code is exactly the same
    double c_im = MaxIm - y*Im_factor;
    for(unsigned x=0; x<ImageWidth; ++x)
    {
        ...
        // if putpixel() is not thread safe, a lock might be needed
        if(isInside) { putpixel(x, y); }
    }
});

TBB将自动将所有循环迭代分配到可用的内核上,您不必担心迭代次数,并动态平衡负载,这样,如果某个线程有更多的工作要做,其他线程就不会等待它,而是提供帮助,从而最大限度地提高CPU利用率。尝试用原始线程实现它,您会感觉到不同:

您也可以使用pthread设置线程亲缘关系,例如使用pthread\u setaffinity\u npcall@Foo是的,你是对的。我的观点是这样做有多大的实际意义。作为程序员,您可能不希望在应用程序中完成线程调度任务。那么为什么TBB显示出它与其他库的区别呢?为应用程序正确选择核心有一个明显的优势。以线程记录器的简单示例为例。一个线程从网络接口接收数据并将其放在环上;另一个线程从环中读取并写入文件,这有助于缓解使用tcpdump时出现的拥塞。在这种情况下,在双处理器系统上,在同一CPU上设置亲缘关系明显更有效。如果启用了超线程,则使用虚拟核心对的速度要快得多。然而,这需要大量的微观管理,TBB不需要。@Foo谢谢你的解释。我同意在某些情况下,您需要设置线程的亲和力。但是TBB将如何代表您的程序员进行管理呢?换句话说,程序员必须指导TBB。在boost/pthread上也可以这样做!更大的问题是,当TBB比操作系统做得更好时,会出现什么情况?@Foo。即使使用pthread_setaffinity_np正确设置线程的关联性,也不能保证线程将以交错方式运行,特别是在多道程序环境中。。我仍然会说,它可以给你一些好处,但有一个上限。感谢您提供的信息boost::threadpool是为了在boost中完成threadpool的工作。所以它确实提供了一种拥有线程池的方法。我不知道的是,与TBB相比,它的效率/缺陷有多大?boost::threadpool在相当长的一段时间内处于非活动状态,而且功能远不如Intel TBB。@Anteru:我想他是说,但你是对的-boost的类只是一个线程容器,而且不像TBB那样提供内置的日程安排。@Alexey感谢您的解释。现在我看到tbb看起来很有希望。你能为tbb推荐一些教程吗?你能告诉我[=]它捕获了什么吗?@user:lambda函数使用调用上下文中的任何内容。[=]告诉编译器t
它应该通过价值捕获它所需要的一切。对于上面的代码,捕获集可以由MaxIm、Im_factor、MinRe、Re_factor、ImageWidth和MaxIterations组成,除非其中任何一个是全局变量。@我不得不指出,AlexeyKukanov全局变量或其成员。引用类成员只会导致捕获this指针。当然,并行和只读访问可能不是问题。