TBB parallel_pipeline令牌似乎偶尔会出现故障

时间:2013-06-17 21:59:44

标签: c++ multithreading parallel-processing multiprocessing tbb

我最近开始在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();
}

几个问题:

  • 由于warpFramesblendFrames都访问成员变量 vector<PanoramaParameters> panoParams,该成员是否应该成为 concurrent_vector类型?这些参数在中创建一次 构造函数,从未更新。
  • 可能导致混合帧到达末端滤波器的原因 订购TBB?

2013年6月19日更新:

感谢@AlexeyKukanov,我能够证明令牌肯定是按顺序。似乎发生的情况是,当所有CPU核心处于100%利用率时,源或接收器过滤器都会出现缓冲问题。我有一个4核处理器,一旦我在飞行中允许4个令牌,CPU就完全饱和并且开始出现口吃。但是,当1,2或3个令牌在飞行中时,似乎没有任何口吃。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

这是一个知识和建议的集合,而不是一个答案,但它的评论太长了。我之前的评论也在这里复制。


代码中的TBB用法似乎是正确的。要确定根本原因是在TBB还是代码中的其他位置,我建议检查最后一个过滤器中的帧是否真的出现故障,例如:通过打印在第一个过滤器中分配的订单ID。由于TBB不公开内部令牌ID,因此您必须自己分配和跟踪ID。

同样,仅供参考,令牌数量不必等于HW核心数量。虽然这个数字有效地限制了并发性,但主要是为了防止在许多令牌在串行过滤器中等待转向时缺少资源(例如内存)。

另一件要知道的是,未指定哪个线程执行哪个过滤器;实际上,任何线程都可以执行任何过滤器。因此,例如,如果接收器过滤器在屏幕上绘制某些内容,则需要确保绘图可以由任何线程完成,或者将所有绘图重定向到单个线程。据我所知,一些GUI框架可能要求所有绘图都由一个线程完成,或者在绘制之前在每个线程中调用一些初始化例程。