How do I keep thread pool threads, or other threads in general, from competing with my render thread for CPU?


Processor affinity lets you specify which processor or processors a thread can run on. This works for threads you control, but what about threads you don't control?

Consider a game. You want your render thread to run with as little interference as possible because it is time-critical. You can set the processor affinity for the render thread to one of the processors, and set the processor affinity for all the other threads you create to other processors. That way, none of your other threads will compete for CPU resources with the render thread.

But what about threads that aren't yours? Suppose the thread pool creates a thread. Well, you don't get a chance to set that thread's affinity. It defaults to the process affinity, which means that depending on how lucky or unlucky you are, those threads might end up running on the same CPU as your precious render thread.

Enter CPU sets.

What you can do is call Get­System­Cpu­Set­Information to identify the available CPU sets. Assign your render thread to one of the CPU sets, and set the process default CPU sets to all the other CPU sets. The process default CPU sets are used by a thread which has not been explicitly assigned any CPU sets. The thread pool threads, therefore, will run on the process default CPU sets, which means that they won't try to run on the same CPU as your render thread, because you carefully set things up so that the render thread runs on a dedicated CPU set.

Comments (27)
  1. It would really be nice of you to make a tiny notice on what OS version supports this feature. Some of us are still stuck with Windows 7.

    And some of us (like me) are stuck with Windows XP SP2.

    1. Antonio Rodríguez says:

      MSDN notes that Get­System­Cpu­Set­Information requires Windows 10. So no luck for you.

      It’s the same story over and over again: every time Microsoft introduces an useful API, you have to wat between 3 and 6 years before you can take advantage of it, because you can’t rely on an API that will be supported only in 10% of your clients’ computers. For example, Vista- and 7-era APIs, many of them introduced in 2006, didn’t get mainstream until 2011-2012, when Windows 7 surpassed Windows XP’s usage quota.

      If you are a small software workshop, the problem is worse: usually, you can’t afford to maintain two versions of the code, one that uses the new API and other that supports older systems. You can’t afford to lose the clients that use the older platform, either. And thus, you are locked to XP- or Vista-era APIs.

      1. Mark Sowul says:

        To be fair, they aggressively tried to solve this problem with Windows 10, by making it free and trying to encourage everyone to upgrade to it by hook or by crook. As I recall this was exactly one of the reasons why: so everyone could develop for it. (Reality, of course, didn’t go quite that well.)

        1. Radosław Cybulski says:

          Well… no.

          The correct way to resolve this issue is to backport the new and useful api to older systems. Which, considering amount of resources Microsoft has is not a big deal. Except that would reduce pressure to upgrade to new windows on Microsoft’s clients. Enter the current solution – create new api in new system to lure clients into upgrading. Except clients arent exactly idiots and they figured out by themselves by now, that applications rarely take advantage (or allow to) of new api because of reasons you stated. So they dont upgrade anyway, even if upgrade is free. Why? Because upgrade is always a pain, something might go wrong and it always will take work. For no benefits at all.

          Maybe if Microsoft would this whole “lure clients into upgrading” bullshit and went back to roots and make everything backward compatible… A man can dream.

          1. xcomcmdr says:

            Microsoft manpower is not infinite.
            Besides, backporting might not be possible, and also has it’s own problems (ie. does it break anything ? does it work as expected ? etc…)

          2. smf says:

            “Well… no.

            The correct way to resolve this issue is to backport the new and useful api to older systems.”

            Windows 10 is an older system with new and useful api added to it.
            Repeating the process to try to come up with a different answer that people might want to install seems like insanity.

            The only real mistake was that XP and Vista users didn’t get a free upgrade. There are plenty of XP machines that would run Windows 10 fine, because so many people avoided Vista. The Vista machines should run Windows 10 as well and they deserve a break.

      2. Azarien says:

        @Antonio Rodríguez You can use it right away, just use LoadLibrary/GetProcAddress and make it NOP for older systems (or, if you really want, do something that sorta makes sense in a given situation).

    2. torrinj says:

      Windows XP? Doh! I’m probably preaching to the choir to say support for that ended almost 3 years ago.

      1. Brian_EE says:

        Except for the US Government. They had extended support for XP past the commercial support expiration.

      2. morlamweb says:

        Things move slowly in the corporate world. My last WinXP client – a large company with over 10,000 users – just moved off of 2006-era Windows XP Tablet PCs in 2014; and yes, their motivation was XP’s end-of-life date. My company moved over to Win7 for their corporate standard PC earlier, circa 2011. I had maintained one XP machine – physical, not virtual – for use with one app that required XP and was no longer supported by the vendor (stop me if you’ve heard this story before). This year, we finally virtualized that machine, and cloned it so that the app could be made available to more people in my group, people who had been clamoring for access to it for years.

        1. Richard says:

          If Virtualizing the application worked, then why not XP Mode on Windows 7 (assuming you’re using a “corporate” edition of Windows 7)?

          1. morlamweb says:

            XP Mode = a virtual machine running within Windows 7. Instead, what we did is use the existing VM server infrastructure to host the virtual XP box on the server, rather than on the client. The server have many more resources available vs. even the most powerful laptop. The VM server’s rich toolset also allowed us to easily provision copies of the VM for every member of the team. “Provisioning” here means making copies of the VM files and automatically updating the VM’s hostname. That all took place on the VM server. Now, the equivalent in XP Mode would be to install the virtual environment, live with the performance penalty of the VM on the client, and involve the local IT people, who are the only ones who have licenses for the app.

        2. HiTechHiTouch says:

          Yes, Very (Very) Slowly.

          A short decade of very austere budgets left us with lots of legacy hardware that must run XP because manufactures would not provide Vista/Win7 drivers. When the disk drives and MB sub-systems like LAN and video finally started failing, and we ran out of PCI slots to plug in new LAN and Video, and IDE drives got hard to buy, we were finally told to replace hardware!

          1. smf says:

            What hardware did you have that wouldn’t run in Windows 7? I had a sony usb web cam that didn’t work, they pulled the same trick on the 2000 to XP transition as well. But that was it. The only thing that has ever stopped me upgrading was when they started putting in CPU feature checks.

          2. Scarlet Manuka says:

            The oldest of my kids’ computers is like that. It actually got upgraded to Win7 at one point, but it was running extremely slowly and painfully; when I investigated, I found that there were no Vista/7 era drivers for the motherboard and associated hardware. When I found that out I was frankly impressed that Win7 had nevertheless managed to boot up and even operate correctly (just very slowly) – I guess it must have been doing some kind of fallback safest-guess driver selection. But I put it out of its misery and reinstalled XP on it.

            I’ll replace it when I can afford to, but for now it just sits there chugging along whenever the kids are desperate enough to use it. It’s not connected to the network (and, of course, old) so it’s at the bottom of their preferred machine list.

          3. Klimax says:

            @Scarlet Manuka: Hm, based on description I don’t think slowness is caused by absence of drivers. It sounds like either Pentium II/III era computer or maybe early Pentium 4. (Generic drivers work often quite well and even XP-based drivers can be used…) Those processors were quite slow IIRC the only usable Pentium III for Windows 7 are 1GHz or higher with full L2 cache (256kB). Also having sufficiently new AGP/PCI GPU that already supports WDDM could improve performance. (GeForce 6 and 7 series, not sure for AMD)

            Generally Core 2 or late Pentium 4 (Prescott and co) are usable minimum for W7 or equivalent AMD CPUs.

      3. Jan Ringoš says:

        It did not for POSReady 2009 which one of our client still deploys.

  2. Alois Kraus says:

    The documentation for SetProcesssDefaultCpuSets spells count in the parameter CpuSetIdCound name wrong:
    https://msdn.microsoft.com/en-us/library/windows/desktop/mt186427(v=vs.85).aspx
    I guess it should be CpuSetIdCount. I hope that fixing it will not be considered a breaking Api change.

    1. Jan Ringoš says:

      Also the second parameter is a pointer. For the most recent APIs one should stick to header file declarations rather than documentation.

    2. Rapha says:

      And it specifies the Library as “windows.h” instead of a “.lib” of some sort.

  3. David Haim says:

    Wouldn’t it be more sensible to increase the thread priority to highest in this case? It is well backward supported and much simpler. The scheduler will opt the rendering thread over others when competition occurs

    1. smf says:

      You don’t want to give a busy thread a high priority, or it makes it difficult to switch away and do something else.

      The more cpu a thread needs, the lower the priority you should give it. Having it squeeze out the last few percent won’t make much different to it, but it will have a negative effect on you.

  4. Joshua A Schaeffer says:

    How would we discover these new APIs if we weren’t told about them here?

  5. What happens when multiple programs decide they need their own CPU set?

    1. Zarat says:

      How about bothering reading the documentation? It’s right there in the linked page.

      > If a process attempts to use a CPU Set assignment which is allocated exclusively to other processes, its request is ignored and threads assigned to disallowed CPU sets are scheduled elsewhere. <

      1. ranta says:

        “Some versions of Windows support Core Reservation policies”; which versions are those, and how does one install such a policy? It doesn’t look like SetProcessDefaultCpuSets can do that.

  6. OldFart2 says:

    This sure seems similar to “How do I keep my topmost window on top of all other topmost windows?”

Comments are closed.

Skip to main content