Intel TBB 4.3 Update 5 introduced global_control class for application-wide control of allowed parallelism and thread stack size.
What is the intended usage, why does it take this form (with a "selection" rule), and why is there no way to query the current selection?
I would suggest a shorter name, though: "max_num_threads" (instead of the mouthful "max_allowed_parallelism"), to go with "default_num_threads". You could also rename task_scheduler_init's parameter (now "max_threads") for consistency (no API change).
I would also want to come back to the original suggestion of an environment variable. Maybe it's true that developers don't want users to be able to "fiddle" with their programs (why not, exactly?), but it's also true that sometimes users of a shared server don't want others to hog the machine whenever they run an off-the-shelf program using TBB... and those others currently have no other way to avoid causing resentment (aka. to be polite) than to not run those programs, which isn't much of a solution compared to being able to just set TBB_MAX_NUM_THREADS (also shorter than TBB_MAX_ALLOWED_PARALLELISM), which would logically participate in the selection rule and could also limit market capacity (the latter would just be an invisible implementation matter, but might be relevant to reliably avoid overshooting the mark and then having to park the excess threads).
BTW, if there are multiple master threads, does TBB try to compensate for that by parking one or more idle worker threads?
Raf, thank you for feedback.
The intended usage for global_control is at the top level of an application (e.g. main()) to limit the number of threads TBB can use, no matter what was specified in various program modules by task_scheduler_init or task_arena. One particular use case is to facilitate implementation of an application-specific environment variable to control the number of threads.
The selection rule is there to provide a limited form of composability in case more than one global_control object is activated at the same time. We think it's more composable than if a new setting always overrode the previous one.
To query the current selection, there is global_control::active_value() static method.
We discussed various names and decided that "max_allowed_parallelism" best describes the semantics of the setting, though of course it's subjective and the difference with e.g. max_num_threads is subtle. Thank you for bringing this up, we might reconsider the name later.
I still believe that providing the developers with a way to implement a max-threads environment variable (if they wish so) is better than doing it ourselves and leaving them no control. An environment variable recognized directly by TBB could cause undesirable effects for end users as well: being set for/by one application, it could inadvertently affect other TBB-based applications on a system (think of Windows where it's common to set an environment variable globally).
Resource distribution on shared servers is controlled by job managers, and those usually utilize taskset or similar utilities to run a program on a given subset of cores. TBB recognizes and respects the process affinity masks, thus job managers have a way to limit how much HW is available for a TBB based app.
TBB still does not try to compensate for multiple master threads running at the same time.
"To query the current selection, there is global_control::active_value() static method." Oops, I missed that...
"I still believe that providing the developers with a way to implement a max-threads environment variable (if they wish so) is better than doing it ourselves and leaving them no control." Call me old-fashioned (using first person to mean any user), but if I bought the computer, and I decided to run a particular program on it, shouldn't I also be in control?
"think of Windows where it's common to set an environment variable globally" And how exactly does that mean that nobody else can have nice things? What exactly would be the scenario where a program developer would be aware, in advance, of a need to restrain execution and could easily build in a program-specific setting (following the recommendation of TBB's newly adapted documentation), but decides to instead advise his users to use a global setting and ignore their inevitable complaints that this interferes with other programs? Besides, I probably even would want to (be able to) set this in my login profile so I would have to explicitly disable it in a shell or for a specific program if I wanted to use the whole machine (for a specific need, or during quiet time): I would want to use this as an "environment" variable. It's not unlikely that a server's administrator would want to have a say in the matter as well, by setting it up as a default for all users.
"Resource distribution on shared servers is controlled by job managers" This isn't (only) about scheduled jobs: maybe I have an account on a server that I'm sharing with others, and I'm already using "-j 8" instead of "-j" to restrict my use of parallelism to build programs because I don't want to keep having lunch by myself all the time. Using taskset(1) is awkward because it involves some kind of partitioning that has to be coordinated with others, which is annoying enough by itself if it only has to be done occasionally. And if a machine has 32 cores and 25 potential users, do I only get a single core, or how do I coordinate with others in real time so our respective subsets don't overlap, without also restricting who can use the machine at each particular time? Why couldn't I just let the O.S. figure out for itself how to allocate resources like it normally would? And on top of that I also have to remember to use this each and every time I start a program!
Parallel programs haven't made scheduling shared resources any easier, and there's no definitive solution in sight, but why withhold this as an obvious workaround?