I recently converted the main path of my code to use TBB flow graph, previously I was using combinations of parallel_for and serial code. In addition to this my codebase contains longer running tasks in a seperate task_group which are not waited on, they finish when they finish.
Unfortunatly I am seeing a big problem with performance, each call to graph.wait_for_all() is taking much longer than it should.
My first guess is that somehow wait_for_all() is waiting on my long running tasks, this essentially brings my program to a crawl(it is a video game).
Assuming that this is the case, is there any way to make flow graph only work on the tasks I've given it?
Or is there some other explanation for why flow graph causes such horrible slow down?
Is flow graph suited for a real time application?
PS. This forum is really bad at formating text, it removes all line spaces :(
Flow graph is based on enqueued tasks (not spawned tasks like parallel_for), and perhaps these are now intermingled with the longer-running tasks on a first-come first-served basis. Try to enqueue the latter on a lower-priority basis, using tbb::priority_low. Does that make a difference?
I thought I might be able to use affinity to mask out the main thread from running long running tasks, but it seems enque does not work with set_affinity(), as it said asserted with"affinity is ignored for enqueued tasks".
So I tried switching the long running tasks to spawn() + set_affinity(0xFFFE) but this informs me that the mask is out of range, looking at the code it appears that affinity can only be used to set the specific thread, and not as a thread mask.
...pausing the program shows that the main thread which called graph.wait_for_all() is indeed running a long running task.
Is there anything else I can do with TBB itself to prevent this?
Sorry for quite late reply. Currently, the only way to isolate some tasks from a thread that calls wait_for_all is to start these tasks from a separate application thread.
This problmeaffects not only graph by the way; each TBB algorithms eventually waits for tasks that it starts. Therefore, you better avoid long running tasks with TBB. I believe long-running jobs can almost always besplit into some stages done by different tasks. E.g. if a job contains a serial loop, each iteration of the loop can start as a task; at the end, it will produce (or recycle itselfinto) a task for the next iteration. The only case where a long job cannot be split is long waiting (e.g. for I/O); and waiting is better done with special threads, not with(in) TBB tasks.