3

我尝试将此处给出的示例转换为带有Boost threads的多线程版本。

为什么 OpenCV LUT 函数比我的 Boost 实现快两倍以上?

我能够击败 C 实现,但不能击败 TBB 版本(LUT)。我不明白为什么。我的是4核笔记本电脑。在他们的示例中,他们已经证明 OpenCV LUT 功能是最快的。LUT 使用英特尔 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 毫秒。
4

1 回答 1

4

一件事是您的时间测量包括线程创建和销毁,这是一项昂贵的操作。基于 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];
}
于 2014-06-06T14:29:14.493 回答