[英]Small speedup with multiple processes for opencv
在一个应用程序中,我必须分析电影文件(假设计算连续帧对的差异)。 为此,我使用opencv(使用ffmpeg作为lib /编解码器)。 根据视频格式,有不同的CPU负载/用途。 对于wmv3,似乎使用的内核不超过1个。 因此,由于数据是独立的(因此随后必须缝合这些部分),因此让多个线程在影片的不同部分上工作非常容易。 代码(用lap参数剥离)非常简单:
int main(int argc, char *argv[])
{
const string source = "move.wmv";
VideoCapture capt(source);
if (!capt.isOpened())
{
cout << "Could not open file " << source << endl;
return -1;
}
unsigned short nThreads (8);
double *pDiffArray = new double [(size_t) (capt.get(CV_CAP_PROP_FRAME_COUNT)];
capt.release();
ComputeDifferences (source, pDiffArray, nThreads);
return 0;
}
int ComputeDifferences (const string& source, double *pDiffArray, const unsigned short& nThreads)
{
std::vector<std::thread *> threadVector;
for (unsigned int i=0; i< nThreads; i++)
threadVector.push_back (new std::thread (ComputePart, source, pDiffArray, nThreads, i));
for (unsigned int i=0; i< nThreads; i++)
threadVector.at (i)->join();
// Stitching
;
return 0;
};
void ComputePart (const string source, double *pDiffArray,
const unsigned int& nThreads, const unsigned int& nThreadNo)
{
VideoCapture capt(source);
if (!capt.isOpened())
{
cout << "Could not open file " << source << endl;
}
size_t startPosDiffArray;
startPosDiffArray = nThreadNo * (capt.get(CV_CAP_PROP_FRAME_COUNT) / nThreads);
size_t sizePart (capt.get(CV_CAP_PROP_FRAME_COUNT) / nThreads);
size_t startPosFrame;
startPosFrame = capt.get(CV_CAP_PROP_FRAME_COUNT) / nThreads * nThreadNo;
capt.set(CAP_PROP_POS_FRAMES, startPosFrame);
Size refS = Size((int) capt.get(CAP_PROP_FRAME_WIDTH),
(int) capt.get(CAP_PROP_FRAME_HEIGHT));
Mat frame, frameRes;
std::array<Mat, 2> frameDuo;
Scalar s;
capt >> frameDuo [0];
if (!frameDuo [0].data)
return;
for (size_t i = 1; i < sizePart; i++) {
capt >> frameDuo [i%2];
if (!frameDuo [i%2].data)
break;
absdiff (frameDuo [(i-1)%2], frameDuo [i%2], frameRes);
s = sum (frameRes);
pDiffArray [i-1+startPosDiffArray] = (s [0] + s [1] + s [2])/ (refS.height * refS.width);
}
capt.release();
}
如果我在1280x720的wmv3视频上使用abt。 相对于单线程(190秒),我获得了50,000帧的加速(在Intel i7上)。
除了非常失望之外,我不明白这里发生了什么。 我确实知道阿姆达尔定律等,但是在这种情况下,我希望能有更快的速度。 有没有人对我有暗示(成为新手)? 不是定位(capt.set()),因为禁用不会改变任何内容。 关于ffmpeg-lib,opencv,std-lib的线程切换,工作集问题吗?
[编辑:
作为评论的暗示,我发现80%的时间用于
capt >> frameDuo [i%2];
这包括从文件读取,解码和复制到opencv结构中。 从这开始,只有从文件中读取的文件是“顺序类型”的(在阿姆达尔看来)。 由于HDD的访问量不大(即使在MT8上也是如此),并且使用快速SSD时也没有区别,我不明白为什么这个顺序的部分会产生如此大的影响。 8个核心怎么可能完全正常工作,但只能加速3个? 并且:我该如何做得更好?]
实际上,您的大部分数字可以由阿姆达尔定律解释。 如果我将您的结果用于两个线程,并尝试计算并行完成的分数,则得出p = 0.88888的值。 并将此值用于4/8线程
2 1.8
4 2.99
8 4.48
这些数字不能精确地再现您所测量的结果,但是在阿姆达尔定律的基础上,每个线程都有开销,必须考虑更多的东西才能得出真实的数字,因此这只是一个近似值,因此在这种意义上,协议相当好。
结论是:您得到的数字还不错。 考虑到Amdahls定律,它的并行分数约为〜85%,这正是人们所期望的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.