1

我最近开始tbb在 Ubuntu 12.04 上使用 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类型吗?这些参数在构造函数中创建一次并且永远不会更新。
  • 什么可能导致混合帧通过 TBB 无序到达末端过滤器?

2013 年 6 月 19 日更新:

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

任何帮助将不胜感激!

4

1 回答 1

2

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


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

另外仅供参考,令牌的数量不必等于硬件核心的数量。虽然这个数字有效地限制了并发性,但它主要是为了防止当大量令牌在串行过滤器中等待轮到它们时出现资源不足(例如内存)。

要知道的另一件事是未指定哪个线程执行哪个过滤器。事实上,任何线程都可以执行任何过滤器。因此,例如,如果 sink 过滤器在屏幕上绘制了一些东西,您需要确保该绘制可以由任何线程完成,或者以其他方式将所有绘制重定向到单个线程。据我所知,一些 GUI 框架可能要求所有绘图都由单个线程完成,或者在绘图之前在每个线程中调用一些初始化例程。

于 2013-06-20T10:03:53.100 回答