Search code examples
pythonbatch-filecmddosaffinity

DOS Batch multicore affinity not working


I have a batch that launches a few executables .exe and .py (python) to process some data.

With start /affinity X mybatch.bat it will work as it should only if X equals to 0, 2, 4 or 8 (the individual cores)
But if I will use a multicore X like 15 or F or 0xF (meaning in my opinion all 4 cores) it will still run only on the first core.

Does it have to do with the fact that the batch is calling .exe files that maybe cannot be affinity controled this way?

OS:Windows 7 64bit


Solution

  • This is more of an answer to a question that arose in comments, but I hope it might help. I have to add it as an answer only because it grew too large for the comment limits:

    There seems to be a misconception about two things here: what "processor affinity" actually means, and how the Windows scheduler actually works.

    What this SetProcessAffinityMask(...) means is "which processors can this process (i.e. "all threads within the process") can run on,"

    whereas

    SetThreadAffinityMask(...) is distinctly thread-specific.

    The Windows scheduler (at the most base level) makes absolutely no distinction between threads and processes - a "process" is simply a container that contains one or more threads. IOW (and over-simplified) - there is no such thing as a process to the scheduler, "threads" are schedulable things: processes have nothing to do with this ("processes" are more life-cycle-management issues about open handles, resources, etc.)

    If you have a single-threaded process, it does not matter much what you set the "process" affinity mask to: that one thread will be scheduled by the scheduler (for whatever masked processors) according to 1) which processor it was last bound to - ideal case, less overhead, 2) whichever processor is next available for a given runnable thread of the same priority (more complicated than this, but the general idea), and 3) possibly transient issues about priority inversion, waitable objects, kernel APC events, etc.

    So to answer your question (much more long-windedly than expected):

    "But if I will use a multicore X like 15 or F or 0xF (meaning in my opinion all 4 cores) it will still run only on the first core"

    What I said earlier about the scheduler attempting to use the most-recently-used processor is important here: if you have a (or an essentially) single-threaded process, the scheduling algorithm goes for the most-optimistic approach: previously-bound CPU for the switchback (likely cheaper for CPU/main memory cache, prior branch-prediction eval, etc). This explains why you'll see an app (regardless of process-level affinity) with only one (again, caveats apply here) thread seemingly "stuck" to one CPU/core.

    So:

    What you are effectively doing with the "/affinity X" switch is

    1) constraining the scheduler to only schedule your threads on a subset of CPU cores (i.e. not all), and
    2) limit them to a subset of what the scheduler kernel considers "available for next runnable thread switch-to", and
    3) if they are not multithreaded apps (and capable of taking advantage of that), "more cores" does not really help anything - you might just be bouncing that single thread of execution around to different cores (although the scheduler tries to minimize this, as described above).

    That is why your threads are "sticky" - you are telling the scheduler to make them so.