【问题标题】:Multithreading Implementation in C++C++中的多线程实现
【发布时间】:2019-08-05 08:57:56
【问题描述】:

我是在 C++ 中使用多线程的初学者,如果您能给我一些建议,我将不胜感激。

我有一个从视频流中接收前一帧和当前帧的函数(我们称这个函数为readFrames())。该函数的任务是计算运动估计。

调用readFrames() 时的想法是:

  1. 将前一帧和当前帧存储在缓冲区中。
  2. 我想计算缓冲区中每对帧之间的运动值,但不会阻塞函数readFrames(),因为在计算该值时可以接收更多帧。我想我必须编写一个函数computeMotionValue(),每次我想执行它时,创建一个新线程并启动它。这个函数应该返回一些float motionValue
  3. 每当任何线程返回的motionValue 超过阈值时,我想 +1 一个公共 int 变量,我们称之为nValidMotion

我的问题是我不知道在访问motionValuenValidMotion 时如何“同步”线程。

你能用一些伪代码向我解释一下我该怎么做吗?

【问题讨论】:

  • 你可以有一个接收帧队列和一个线程。如您所述计算运动值,您可以弹出 2 个最后输入的帧值和一个函数,这 2 个通过互斥锁和条件变量同步
  • 你可以做nValidMotion atomic,任何对它的访问都会自动同步。
  • 您正在寻找的解决方案是“生产者-消费者”问题的变体:en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem 在您的情况下,生产者线程读取帧并将它们放入处理队列。该队列与消费者线程共享。两个线程都需要一种方法来同步它们对队列的访问,以防止一个线程从另一个线程下面拉出地毯。我的第一个快速搜索出现了这个例子,看起来这将是一个足够好的起点来了解线程:gist.github.com/dpressel/de9ea7603fa3f20b55bf

标签: c++ multithreading


【解决方案1】:

每次我想执行它时,创建一个新线程并启动它

这通常是个坏主意。线程通常相当重,生成线程通常比将消息传递到现有线程池要慢。

无论如何,如果你落后了,你最终会得到比处理器内核更多的线程,然后由于上下文切换开销和内存压力,你会落后得更远。最终创建新线程会失败。

我的问题是我不知道在访问motionValue 和nValidMotion 时如何“同步”线程。

访问共享资源的同步通常使用std::mutex 处理(mutex 的意思是“互斥”,因为一次只有一个线程可以持有锁)。

如果您需要等待另一个线程执行某项操作,请使用std::condition_variable 等待/发出信号。您正在等待/发出某些共享资源状态更改的信号,因此您也需要一个互斥锁。

这种处理的通常建议是每个可用内核最多有一个线程,所有线程都服务于一个线程池。线程池有一个工作队列(受互斥体保护,并带有由 condvar 发出的空->非空转换信号)。

为了组合结果,您可以拥有一个受互斥体保护的全局计数器(但这对于单个整数来说相对较重),或者您可以将每个任务添加到添加到线程池通过promise/future机制返回一个布尔值,或者你可以让你的计数器atomic

【讨论】:

  • 您可以尝试使用 std::async 而不是编写自己的线程池,顺便说一句 - 老实说,我不知道执行的质量如何,但可能值得一试。
【解决方案2】:

这是您可以使用的示例伪代码:

// Following thread awaits notification from worker threads, detecting motion
nValidMotion_woker_Thread()
{
    while(true) { message_recieve(msg_q); ++nValidMotion; }
}


// Worker thread, computing motion on 2 frames; if motion detected, notify uysing message Q to nValidMotion_woker_Thread
WorkerThread(frame1 ,frame2)
{
    x =  computeMotionValue(frame1 ,frame2);

    if x > THRESHOLD
    msg_q.send();
}

// main thread
main_thread()
{
    // 1. create new message Q for inter-thread communication
    msg_q = new msg_q();

    // start listening thread
    Thread a = new nValidMotion_woker_Thread();
    a.start();

    while(true)
    {
        // collect 2 frames
        frame1 =  readFrames();
        frame2 =  readFrames();

        // start workre thread
        Thread b = new WorkerThread(frame1 ,frame2);
        b.start();      
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    相关资源
    最近更新 更多