我尝试将示例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次运行:
[]
的运行时:4.65387毫秒。答案 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];
}