我最近开始在Ubuntu 12.04上使用tbb
版本4.0 + r233-1来加速视频全景拼接器。我看到的错误有点奇怪,希望有人可以解决这个问题。
似乎发生的事情是令牌无序到达汇聚节点(尽管我发现很难相信它实际上是TBB中的错误)。我在混合视频帧中看到 抖动 (例如,当应该显示混合帧N时,显示混合帧N + 3,这会导致视频显示为口吃)。我知道它与并行滤波器有关,因为如果我将飞行中的数字标记设置为1而不是4,则不再发生口吃。
我的管道架构如下:
Read Frames Vector from files (serial) -> Warp Frames Vector (parallel) -> Blend Frames Vector (parallel) -> Write Blended Frame to file (serial)
以下是相关的代码片段,相信显示问题的区域:
的 PipelineStitcher.h
class PipelinedStitcher {
public:
PipelinedStitcher(
const std::string& projectFilename,
const std::string& outputFilename,
double scaleFactor);
...
void run();
private:
std::vector<PanoramaParameters> panoParams;
std::vector<cv::Mat> readFramesFromVideos();
std::vector<cv::Mat> warpFrames(const std::vector<cv::Mat>& frames);
cv::Mat blendFrames(std::vector<cv::Mat>& warpedFrames);
};
的 PipelineStitcher :: run()的
void PipelinedStitcher::run()
{
parallel_pipeline( 4,
make_filter< void, std::vector<Mat> > (
tbb::filter::serial,
[&](flow_control & fc)-> std::vector<Mat>
{
vector<Mat> frames = readFramesFromVideos();
if(frames.empty())
{
fc.stop();
}
return frames;
}
) &
make_filter< std::vector<Mat>, std::vector<Mat> > (
tbb::filter::parallel,
[&](std::vector<Mat> src) {
vector<Mat> dst = warpFrames(src);
return dst;
}
) &
make_filter< std::vector<Mat>, Mat > (
tbb::filter::parallel,
[&](std::vector<Mat> src) {
Mat dst = blendFrames(src);
return dst;
}
) &
make_filter<Mat, void> (
tbb::filter::serial,
[&](Mat src) {
if(!videoWriter.isOpened())
{
videoWriter.open(outputFilename, CV_FOURCC('D','I','V','X'), 30.0, src.size(), true);
}
videoWriter << src;
imshow("panoramic view", src);
waitKey(3);
}
)
);
videoWriter.release();
}
几个问题:
warpFrames
和blendFrames
都访问成员变量
vector<PanoramaParameters> panoParams
,该成员是否应该成为
concurrent_vector
类型?这些参数在中创建一次
构造函数,从未更新。感谢@AlexeyKukanov,我能够证明令牌肯定是按顺序。似乎发生的情况是,当所有CPU核心处于100%利用率时,源或接收器过滤器都会出现缓冲问题。我有一个4核处理器,一旦我在飞行中允许4个令牌,CPU就完全饱和并且开始出现口吃。但是,当1,2或3个令牌在飞行中时,似乎没有任何口吃。
非常感谢任何帮助!
答案 0 :(得分:2)
这是一个知识和建议的集合,而不是一个答案,但它的评论太长了。我之前的评论也在这里复制。
代码中的TBB用法似乎是正确的。要确定根本原因是在TBB还是代码中的其他位置,我建议检查最后一个过滤器中的帧是否真的出现故障,例如:通过打印在第一个过滤器中分配的订单ID。由于TBB不公开内部令牌ID,因此您必须自己分配和跟踪ID。
同样,仅供参考,令牌数量不必等于HW核心数量。虽然这个数字有效地限制了并发性,但主要是为了防止在许多令牌在串行过滤器中等待转向时缺少资源(例如内存)。
另一件要知道的是,未指定哪个线程执行哪个过滤器;实际上,任何线程都可以执行任何过滤器。因此,例如,如果接收器过滤器在屏幕上绘制某些内容,则需要确保绘图可以由任何线程完成,或者将所有绘图重定向到单个线程。据我所知,一些GUI框架可能要求所有绘图都由一个线程完成,或者在绘制之前在每个线程中调用一些初始化例程。