在一个应用程序中我要分析电影文件 (假设计算连续帧对的差异)。 为此,我使用opencv(使用ffmpeg作为lib / codecs)。 根据视频格式,有不同的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();
}
如果我在wmv3视频上使用它,1280x720,abt。 50,000帧, 相对于单线程(190秒),我得到了这个加速(在Intel i7上)。
除了非常失望之外,我不明白这里发生了什么。 我确实知道阿姆达尔的法律等,但在这种情况下,我预计会有更好的加速。 有没有人给我一个提示(作为新手)? 这不是定位(capt.set()),因为禁用不会改变任何东西。 是关于ffmpeg-lib,opencv,std-lib的线程切换,工作集问题?
[编辑:
根据评论中的暗示,我发现80%的时间用于
capt >> frameDuo [i%2];
这包括从文件读取,解码和复制到opencv结构。 从这一点来看,只有从文件中读取的是“顺序类型”(在Amdahl的意义上)。 由于HDD没有显示重型访问(即使在MT8时),也没有区别 当使用快速SSD时,我不明白为什么这个顺序部分应该产生如此大的影响。 8个内核如何完全正常工作但速度只有3? 而且:我怎么能做得更好?]
答案 0 :(得分:0)
Amdahls法律确实可以解释您数字的最大部分。 如果我将结果用于两个线程并尝试计算并行完成的分数,则得到p = 0.88888的值。并使用此值为4/8线程我得到
2 1.8
4 2.99
8 4.48
这些数字并不能准确地再现你所测量的数字,但除了Amdahls定律之外,每个线程还有一些开销和更多必须考虑获得实际数字的东西,因此它只是第一个近似值,在这个意义上协议很好。
作为结论:你得到的数字并不是那么糟糕。当考虑Amdahls定律时,它正是人们所期望的平行分数约为85%。