Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Starting a pipeline with thread_bound_filter

Roman_L_1
Beginner
319 Views
Hello,
 

I am trying to parallelize an algorithm that accepts a callback and looks like this:

class Object;

class MyCallback
{
public:
virtual void NotifyAboutCompletion (Object* o) = 0;

};


void Foo (Object* o, size_t n, MyCallback* c)
{
   for (size_t i = 0; i < n; ++i) {
     DoSomeHeavyWork (o);
     c->NotifyAboutCompletion (o);
   }
}

 

Foo() must provide a guarantee that the callback c will be called inside the same thread where Foo() itself has been called and that the callback will be called in the same order in which Objects were provided.

TBB pipeline should be quite usable to concurrently process objects and ensure the order. However I have a challenge how to meet the same thread guarantee.
thread_bound_filter as the last serial-in-order filter could be used to ensure that (for instance, as given in the documentation https://software.intel.com/en-us/node/467926). However the documentation explicitly requires that it must be another thread which invokes the pipeline itself.

The challenge is where to get that thread which would invoke the pipeline ? Creating an arbitrary thread (as shown in the example in the documentation) each time is expensive and can oversubscribe the machine - Foo() can be called any time from any place. To avoid oversubscription I thought to grab some TBB worker thread just to start the pipeline. AFAIU this could probably be done with tbb::task::enqueue(). However I am concerned that in some degenerated cases when there are no workers (explicit tbb::task_scheduler_init(1), or isolated arena or single CPU machine) the pipeline would never start and hence Foo() would never actually return.
 
Meanwhile I will rather resort to explicit thread(s) in charge of invoking the pipeline but would appreciate any better recommendations.
 
Thank you in advance,
Roman
0 Kudos
2 Replies
MLema2
New Contributor I
319 Views

I suspect the problem comes from a UI thread that must display some progress notification and redrawing widgets must be done from the main thread.

If this is the case, I would use an event that the main thread listen to.  Once completed, your callback function would enqueue it's completed status somewhere and then post the event.  Once posted, the main thread would wake up and dequeue status and update UI accordingly.

 

 

0 Kudos
Roman_L_1
Beginner
319 Views

Hello Michel,

Thank you for the response. Yes, this is what I am rather leaning to myself too.

The guarantee for Foo() will be relaxed and the MyCallback::NotifyAboutCompletion() may be called from any thread the Foo() will run in. And it will be a developer responsibility to make sure that redefined NotifyAboutCompletion() will post events which will be picked up later on by the main thread.

Thanks again,

Roman

 

0 Kudos
Reply