OpenMP 不在不同的线程中运行这个 for 循环,我该如何修复它
Posted
技术标签:
【中文标题】OpenMP 不在不同的线程中运行这个 for 循环,我该如何修复它【英文标题】:OpenMP doesn't run this for loop in different threads, how can I fix it 【发布时间】:2013-09-03 16:38:27 【问题描述】:我有这个代码:
#pragma omp parallel for
for( i=0;i<(int)table.size();i++)
Vec3b bgrPixel;
TableElement element=table[i];
bgrPixel = inputImage.at<Vec3b>(element.InputPixel.y,element.InputPixel.x);
outputImage.at<Vec4b>(element.OutputPixel.y,element.OutputPixel.x)[0] = bgrPixel[0];
outputImage.at<Vec4b>(element.OutputPixel.y,element.OutputPixel.x)[1] = bgrPixel[1];
outputImage.at<Vec4b>(element.OutputPixel.y,element.OutputPixel.x)[2] = bgrPixel[2];
outputImage.at<Vec4b>(element.OutputPixel.y,element.OutputPixel.x)[3] = 255;
当我运行它时,我可以看到只使用了 25% 的处理器功率。我相信它不是并行运行的。为什么它不是并行运行的,我该如何提高它的性能?
图像是 OpenCV mat 对象。
【问题讨论】:
桌子的尺寸是多少?另外, OMP_NUM_THREADS 的值是多少? 表比较大(大约 100K 条目),我的系统最多可以有 4 个线程。我在同一个应用程序中有另一个并行运行的循环,并且在该循环期间我的 CPU 使用率为 100%。 循环内部的逻辑看起来很简单(我不熟悉你的代码,所以如果我错了请纠正我)。因此,每个执行一些简单分配的 4 个线程可能不会消耗。所以也许低使用率是预期的。尝试增加线程数,看看会发生什么。 @GabiTurliu 好的,我会这样做,但在我的 i7 笔记本电脑上,整个循环工具大约需要 5 秒。我需要一种方法来减少这个时间。我的 CPU 可以并行运行 4 个线程,所以我认为使用 4 个线程是最佳的。 一个愚蠢的问题 - 您在编译代码时是否启用了 OpenMP 支持?现在几乎没有编译器默认启用此支持,并且必须明确启用它:-fopenmp
for GCC,-openmp
for Intel,-mp
for PGI,/openmp
(或项目中的相应选项设置)用于 MSVC++。
【参考方案1】:
在 cmets 中建议,Mat::at 可能会进行某种锁定。我检查了 OpenCV 源代码,但似乎并非如此。 Mat::at 的一个版本转载如下:
template<typename _Tp> inline _Tp& Mat::at(int i0, int i1)
CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
(unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels(⇉
CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
return ((_Tp*)(data + step.p[0]*i0))[i1];
在我看来,正如 cmets 中所建议的那样,CPU 使用率低的原因很可能是您的代码对 CPU 没有什么可做的。由于代码只是简单的内存分配,您的代码可能是内存,而不是 CPU 绑定。我的建议是不要复制数据(OpenCV Mat 格式非常灵活,只需创建一个新标头即可使用两个矩阵指向相同的数据)。如果 InputPixel 和 OutputPixel 值不相关或具有复杂相关性,您可能需要接受随机访问内存(即大量缓存未命中)将需要一些时间这一事实。
【讨论】:
以上是关于OpenMP 不在不同的线程中运行这个 for 循环,我该如何修复它的主要内容,如果未能解决你的问题,请参考以下文章