为什么使用TBB的OpenCV功能比基于Boost的实现快得多?

时间:2013-11-09 02:29:01

标签: c++ multithreading opencv boost

我尝试将示例given here转换为带有Boost threads的多线程版本。

为什么OpenCV LUT功能比我的Boost实现快两倍

我能够击败C实现,但不能击败TBB版本(LUT)。我不明白为什么。我的是4核笔记本电脑。 在他们的例子中,他们已经证明OpenCV LUT功能是最快的。 LUT使用Intel TBB

以下是测量性能并启动Boost线程的部分。

t = (double)getTickCount();
_global_I = I.clone();

int channels = _global_I.channels();
int nRows = _global_I.rows;
_global_NCOLS = _global_I.cols * channels;

CV_Assert(_global_I.isContinuous());
_global_NCOLS *= nRows;

for (int i = 0; i < times; ++i)
{
    NTHREADS = 4; //number of threads
    boost::thread_group tgroup;
    for(int i=0;i<NTHREADS;i++)
    {
        tgroup.create_thread(boost::bind(ScanImageAndReduceBoost,i));
    }
    tgroup.join_all();
}

t = 1000*((double)getTickCount() - t)/getTickFrequency();
t /= times;

cout << "Time of reducing with Boost (averaged for "
     << times << " runs): " << t << " milliseconds."<< endl;

以下是执行映射的函数:

void ScanImageAndReduceBoost(int start)
{
    int i=0;
    uchar* p;
    p = _global_I.ptr<uchar>(i);

    for ( int j = start; j < _global_NCOLS; j=j + NTHREADS)
    {
        p[j] = _global_table[p[j]];
    }
}

_global_I_global_table是表示图像和查找表的全局变量(如示例所示)。

输出,平均100次运行:

  • 使用C运算符[]的运行时:4.65387毫秒。
  • 运行时使用LUT函数:0.79165毫秒。
  • 使用Boost运行时:1.99125毫秒。

1 个答案:

答案 0 :(得分:3)

有一件事是您的时间测量包括线程创建和销毁,这是一项代价高昂的操作。基于TBB的OpenCV实现不会每次都重新创建线程,因此线程创建的成本会在调用函数的次数上分摊;它们的线程池也可能提前初始化。

另一个问题是如何跨线程分发循环迭代,后续索引由不同的线程处理:

for ( int j = start; j < _global_NCOLS; j = j + NTHREADS )
{
    p[j] = _global_table[p[j]];
}

所以线程0处理p[0]p[4]等;线程1处理p[1]p[5]等;等等。它可能导致缓存冲突,因为占用相同缓存行的后续元素由不同的线程处理(它被称为虚假共享)。相反,尝试将整个作业分成更大的块以避免错误共享,例如:

int chunk_size = _global_NCOLS / NTHREADS;
for ( int j = start*chunk_size; j < (start+1)*chunk_size; ++j )
{
    p[j] = _global_table[p[j]];
}
// deal with tail iterations if any
if ( start < _global_NCOLS % NTHREADS ) {
    uchar& c = p[chunk_size*NTHREADS+start];
    c = _global_table[c];
}