【问题标题】:TBB parallel_pipeline tokens seem to be occasionally out of orderTBB parallel_pipeline 令牌似乎偶尔出现故障
【发布时间】:2013-06-14 00:02:07
【问题描述】:

我最近开始在 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&lt;PanoramaParameters&gt; panoParams,这个成员应该是 concurrent_vector 类型?这些参数在 构造函数并且从未更新。
  • 可能导致混合帧到达末端过滤器的原因 用 TBB 订购?

2013 年 6 月 19 日更新:

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

任何帮助将不胜感激!

【问题讨论】:

  • tbb::filter::serial 已弃用。最好是明确的tbb::filter::serial_in_order。 (但两个标志的值相等。)
  • TBB 的使用似乎是正确的。要确定根本原因是否在代码中的 TBB 或其他地方,我建议检查最后一个过滤器中的帧是否真的出现故障,例如通过打印在第一个过滤器中分配的订单 ID。
  • @AlexeyKukanov 好主意。我将添加一种方法来跟踪整个管道中的令牌。有没有办法访问管道的当前令牌,还是我需要用我自己的自定义包装数据结构单独跟踪它?
  • 不幸的是,你必须自己做;令牌 ID 是未公开的实现细节。
  • @AlexeyKukanov 感谢您的提示!它确实帮助我至少开始隔离问题的来源。

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


【解决方案1】:

与其说是答案,不如说是知识和建议的集合,但是评论太长了。我之前的cmets也复制到这里。


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

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

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

【讨论】:

  • 感谢parallel_pipeline 上的简明提示!您是否建议使用concurrent_queue 将混合帧放置到它们到达接收器节点后?然后有一个“作家”线程从队列中拉出东西?非常感谢所有的建议!
猜你喜欢
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
  • 2017-05-25
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-09
相关资源
最近更新 更多