[英]TBB parallel_pipeline tokens seem to be occasionally out of order
我最近开始在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
vector<PanoramaParameters> panoParams
类型吗? 这些参数在构造函数中创建一次,并且从不更新。 多亏@AlexeyKukanov,我得以证明令牌确实按顺序到达。 似乎发生的是,当所有CPU内核都达到100%利用率时,源过滤器或接收器过滤器都会出现缓冲问题。 我有一个4核处理器,一旦允许运行4个令牌,CPU就会完全饱和,开始卡顿。 但是,当1个,2个或3个令牌飞行时,似乎没有任何卡顿现象。
任何帮助将不胜感激!
它是知识和建议的集合,而不是答案,但是评论太长。 我以前的评论也被复制到这里。
代码中的TBB用法似乎正确。 为了弄清根本原因是在TBB中还是在代码的其他地方,我建议检查框架在最后一个过滤器中是否真的失灵,例如通过打印在第一个过滤器中分配的订单ID。 由于TBB没有公开内部令牌ID,因此您必须自己分配和跟踪ID。
同样,仅供参考,令牌的数量不必等于硬件核心的数量。 尽管此数字有效地限制了并发性,但它的存在主要是为了防止在串行过滤器中有很多令牌等待轮换时资源(例如内存)不足。
要知道的另一件事是,未指定哪个线程执行哪个过滤器;这是一个未知的过程。 实际上,任何线程都可以执行任何过滤器。 因此,例如,如果接收器过滤器在屏幕上绘制了某些内容,则需要确保可以通过任何线程完成绘制,或者将所有绘制重定向到单个线程。 据我所知,某些GUI框架可能要求所有绘图都由单个线程完成,或者某些初始化例程在绘图之前在每个线程中被调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.