0

I am a beginner using multithreading in C++, so I'd appreciate it if you can give me some recommendations.

I have a function which receives the previous frame and current frame from a video stream (let's call this function, readFrames()). The task of that function is to compute Motion Estimation.

The idea when calling readFrames() would be:

  1. Store the previous and current frame in a buffer.
  2. I want to compute the value of Motion between each pair of frames from the buffer but without blocking the function readFrames(), because more frames can be received while computing that value. I suppose I have to write a function computeMotionValue() and every time I want to execute it, create a new thread and launch it. This function should return some float motionValue.
  3. Every time the motionValue returned by any thread is over a threshold, I want to +1 a common int variable, let's call it nValidMotion.

My problem is that I don't know how to "synchronize" the threads when accessing motionValue and nValidMotion.

Can you please explain to me in some pseudocode how can I do that?

3
  • 1
    you can have a queue of receive frames and a thread for this. for computing motion value as you described, you can pop 2 last entered value of frames and a function for this , which these 2 synchronize by mutex and condition variable Commented Aug 5, 2019 at 9:11
  • You can do nValidMotion atomic and any access to it will be synchronized automatically. Commented Aug 5, 2019 at 9:11
  • The solution you're looking for is a variant of the 'producer-consumer' problem: en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem In your case the producer thread reads the frames and puts them into a processing queue. This queue is shared with a consumer thread. Both threads need a means to synchronize their access to the queue to prevent one from pulling the rug out from under the other. My first quick search turned up this example which looks like it would be a decent enough starting point to learn about threading: gist.github.com/dpressel/de9ea7603fa3f20b55bf Commented Aug 5, 2019 at 9:20

2 Answers 2

2

and every time I want to execute it, create a new thread and launch it

That's usually a bad idea. Threads are usually fairly heavy-weight, and spawning one is usually slower than just passing a message to an existing thread pool.

Anyway, if you fall behind, you'll end up with more threads than processor cores and then you'll fall even further behind due to context-switching overhead and memory pressure. Eventually creating a new thread will fail.

My problem is that I don't know how to "synchronize" the threads when accessing motionValue and nValidMotion.

Synchronization of access to a shared resource is usually handled with std::mutex (mutex means "mutual exclusion", because only one thread can hold the lock at once).

If you need to wait for another thread to do something, use std::condition_variable to wait/signal. You're waiting-for/signalling a change in state of some shared resource, so you need a mutex for that as well.

The usual recommendation for this kind of processing is to have at most one thread per available core, all serving a thread pool. A thread pool has a work queue (protected by a mutex, and with the empty->non-empty transition signalled by a condvar).

For combining the results, you could have a global counter protected by a mutex (but this is relatively heavy-weight for a single integer), or you could just have each task added to added to the thread pool return a bool via the promise/future mechanism, or you could just make your counter atomic.

Sign up to request clarification or add additional context in comments.

1 Comment

You can try using std::async instead of writing your own thread pool, BTW - I don't know what quality of implementation to expect for this, honestly, but it may be worth a try.
0

Here is a sample pseudo code you may use:

// 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();      
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.