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

The method on_scheduler_exit() is not executed

Bartlomiej1
Beginner
657 Views
Hello, I'm trying to use tbb::task_secheduler_observer to gather some statistics, collected by worker threads, when performing various tasks (parallel_do, mostly, but also other ones). Unfortunately - the method on_scheduler_exit() is never called; on_scheduler_entry() is called normally, at the beginning, but not the former one. What am I doing wrong? I've read that the process does NOT wait for all threads to clear up, but ading a ten-seconds-long sleep() in the main function changed nothing. Oh, and should observe(false); be called or not? I tried both and failed for both. Thanks in advance and best regards Bartlomiej
0 Kudos
9 Replies
RafSchietekat
Valued Contributor III
657 Views

You could try again with a task_scheduler_init with limited lifetime.

0 Kudos
Bartlomiej1
Beginner
657 Views
Dear Raf, Thanks, but it does not seem like the solution. I'm not sure what feature do you mean, but *why* would I set any deadline for the task scheduler? I wanted to check *when* the on_scheduler_exit() method will get called - apparently never. I have no idea, why. But the only logical solution is to force the process to wait for these functions to be called in each thread and also... make them be called. Why aren't they? Best regards, Bartlomiej
0 Kudos
RafSchietekat
Valued Contributor III
657 Views

Did you try and it didn't work, or did you dismiss it out of hand? It's not a deadline: you create the task_scheduler_init (as an automatic variable, on the stack), you do the work, and you allow the task_scheduler_init to be automatically destroyed.

You may have to adjust your expectations about these callbacks: they are for lifetime or probably career events (to/from RML), but not for taking naps (even if they last until program exit).

 

0 Kudos
Bartlomiej1
Beginner
657 Views

Yes, that's exact;y what I did!

0 Kudos
Bartlomiej1
Beginner
657 Views
Hi, I managed to improve the things. The observer has been an automatic variable with the same scope as the task scheduler! Now, I made the observer as a static variable, so that it didn't get killed early. And now, some on_scheduler_exit() functions get called. Yet, I'm not sure how to assure all the threads have executed it and I can proceed. Would a condvar be a proper approach here? I suppose so; a counter that gets incremented in on_scheduler_entry() and decremented in on_scheduler_exit(). We wait for it became zero... Best regards, Bartlomiej
0 Kudos
RafSchietekat
Valued Contributor III
657 Views

The documentation for ~task_scheduler_init() says:

"If no existing thread has any active task_scheduler_init objects, then the internal worker threads are terminated."

If indeed you don't get all exit notifications by the time task_schedule_init destruction has finished (a small reproducer would be useful!), probably the documentation should be adapted, because it may be too difficult to make TBB behave exactly as described here.

0 Kudos
Bartlomiej1
Beginner
657 Views
Here goes an example. For smaller values of N (say 100 or more) it works perfectly (the message gets displayed), but not for higher values (e.g., 100000). Other observations: - it seems to work properly more often, when using the Intel's compiler (icc) than GCC (g++), - it seems to work properly more often on Xeon than on i7 processor (possibly a coincidence), - the correct or incorrect behavior is *not* deterministic - especially for icc. Oh, I'm working in Linux, obviously; kernel versions 3.10.22-1-MANJARO (for i7) and 3.10.0-123.el7.x86_64 (for Xeon). Best regards, Bartlomiej
0 Kudos
Bartlomiej1
Beginner
657 Views
PS. I realized, the observer is initialized *before* the task scheduler in my example, so I added a line: count = stat_counter(); after initializing the init variable. This did *not* change the results. Regards,
0 Kudos
RafSchietekat
Valued Contributor III
657 Views

I verified from your reproducer (thanks!) that ~task_scheduler_init() does not wait for the worker threads to terminate and be observed to have done so. This did reliably happen shortly afterwards if program exit was slightly delayed (too quickly to notice, but I did not time it). I think that's acceptable... except that the documentation should be more forthcoming (if I can't recall where this may have been mentioned, it's probably not enough notice).

0 Kudos
Reply