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

Cancelling Pipeline Execution

Intel_C_3
Beginner
597 Views
I've been reading a bit on the blog about the new cancellation feature being incorporated into TBB. Since the TBB pipeline does not involve direct manipulation of tasks, I'm curious if and how it will support cancellation. It seems that cancel_group_execution() should be sufficient, but it is not clear to me how this should be exposed in the pipeline.


0 Kudos
6 Replies
Alexey-Kukanov
Employee
597 Views

Cancelling pipeline internally (i.e. from insideone of its filters) is always possible with

 tbb::task::self().cancel_group_execution();

The interface to cancel a pipeline externally is not yet added; it will be done later and we will announce it. The interface most probably will allow you to pass a reference to an instance of tbb::task_group_context into pipeline.run(), and another thread in your application could call cancel_group_execution() for that instance to cancel (the rest of) pipeline execution.

0 Kudos
Andrey_Marochko
New Contributor III
597 Views
Right, it's exactly as Alexey said. I just want to add that if your pipeline is running inside another TBB algorithm (for example is used by the body of tbb::parallel_for), then cancelling the pipeline will cancel the nesting algorithm (or task) too. This is because currently pipeline shares the cancellation context of its caller. If this poses a problem for you, write to the forum, and we'll suggest a workaroundsmiley [:-)].
0 Kudos
Intel_C_3
Beginner
597 Views

Thanks for the pointer. I think using

tbb::task::self().cancel_group_execution();

will be sufficient for my use case. I didn't realize this was possible.

Also, I'm not running the pipeline inside another algorithm so that should not

pose a problem.

0 Kudos
Intel_C_3
Beginner
597 Views
An update: I have a simple three stage pipeline with serial input and output stages
and a parallel middle stage. The first stage listens creates jobs for the second stage
of the pipeline and checks an interrupt flag set by an interrupt handler.
If an interrupt is detected the first filter calls
tbb::task::self().cancel_group_execution();

and returns NULL. This seems to work correctly when the number of tokens is small, but if I make the number of tokens larger the code hangs in


#0 0xffffe405 in __kernel_vsyscall ()
#1 0xf7dfd0ac in sched_yield () from /lib/tls/libc.so.6
#2 0xf7f99118 in tbb::internal::CustomScheduler<:INTERNAL::INTELSCHEDULERTRAITS>::wait_for_all ()
 from .../tbb20_20080512oss_src/build/linux_ia32_gcc_cc4.0.4_libc2.3.4_kernel2.6.9_release/libtbb.so.2
#3 0xf7f92a5f in tbb::pipeline::run () from ...


This happens only with more than one thread running and is very repeatable on different machines and with different numbers of threads. I'll try and post a simple
representative example shortly. Any thoughts?




0 Kudos
Alexey-Kukanov
Employee
597 Views

We thought more of it. Actually, my advice of using task::self() to cancel the execution was not good.

The proper solution depends on the effect you want to achieve. In case of the interrupt, you might want either 1) stop producing new jobs, or 2) cancel all jobs in the fly, or 3) suspend jobs between pipeline stages and resume later. The first case is simple to do and you do not need cancellation for that; you just return NULL from the input stage. The third case is the most complex, it is impossible now, and I'm afraid it will remain impossible. For the second case, cancellation should work; but unlike I thought before, the pipeline implementation should be improved to support cancellation, even internally initiated.

I apologize for confusing you. Definitely we will work on supporting cancellation (as in case 2) for tbb::pipeline. For now, your only resort is the case 1), when you return NULL from the input stage but have to wait for the jobs already started to fly through the pipeline.

0 Kudos
Intel_C_3
Beginner
597 Views
Thanks for the update. I'm currently using option one. The problem is that if I use a large number of tokens (to improve load balancing) option one results in a possibly large latency time between the interrupt and the halting of the pipeline. So, option two is preferable, but as you say currently unavailable. Option three certainly seems difficult and is beyond my current needs anyway. Thanks again.
0 Kudos
Reply