How it works
It calls getAffinity once to determine which threads are generally available to all processes. By default this is all of them but if you have isolated specific CPU e.g. using isolcpus= it will detect which ones and uses these to assign critical threads to.
If you haven't done this, or you want to run multiple processes like this, you can specify which threads a process can reserve. This can be set with -Daffinity.reserved=CC or whatever hex mask indicates which cpus can be used. I suggest allocating whole cores (all the threads for a core) to a process as I suspect, but haven't tested, that this would be the best performing.
To allocate a thread to a cpu, it sets the thread affinity to only one cpu, assuming no other thread will be assigned to it. It can't prevent other thread or interrupts using the CPU, however you can configure the OS (Linux definitively and Window I would expect you can) not to use certain CPUs unless specific scheduled to do so.
A machine has one or more Sockets (whole chips). Many machine have only one socket, but some have two and a few have four.
Each socket can have a number of cores, between one and eight is common.
Each core can have many threads one or two is common but some have up to 32.
It is these logical threads which appear as individual cpus to the operating system and it is these you can bind to.
How are threads allocated?
The library reads the CPU layout from /proc/cpuinfo (Linux), or a cpuinfo or properties file you provide (Windows or Linux).
Using the layout information you can declare how you want your threads laid out relative to one another.
- SAME_CORE - on the same core as
- SAME_SOCKET - on the same socket, but not the same core
- DIFFERENT_SOCKET - on a different socket
- DIFFERENT_CORE - any other core.
- ANY - any available.
The strategies are evaluated in order to (like a search path) to find the next appropriate thread. The first match is taken. If ANY is not the last strategy, a warning is logged and no cpu is assigned (leaving the OS to choose)
- SAME_SOCKET, SAME_CORE, ANY means preferably on a different core on the same socket, or the same core, otherwise any cpu.
- DIFFERENT_SOCKET, DIFFERENT_CORE means preferably on a different socket, or a different core otherwise don't bind the thread and let the OS pick one.
It is assumed that cpu ids stride cores. i.e. if you have four cores, the last four cpu ids will be on different cores. This matters because it allocates cpu ids from the last to first (not cpu 0) and you will natrually want to spread across cores if possible, only sharing cores if you have to.
CPU 0 cannot be allocated because its is assumed that the OS, interrupts, other processes and your threads which are not bound need to run somewhere and the minimum number of cpus for this is 1. On Linux, CPU 0 is more likey to be used by the OS, interrupts unless you change it, so it is a natural choice to leave.
This means that if you want to bind more thread than you have reservable CPUs, those threads will be left to the OS to schedule (possibly on cpu 0)