这更像是对 cmets 中出现的问题的回答,但我希望它可能会有所帮助。我必须将其添加为答案,只是因为它对于评论限制来说太大了:
这里似乎对两件事有误解:“处理器亲和性”的实际含义,以及 Windows 调度程序的实际工作方式。
SetProcessAffinityMask(...) 的意思是“哪些处理器 可以处理(即“所有 个线程内进程") 可以继续运行,"
而
SetThreadAffinityMask(...) 显然是特定于线程的。
Windows 调度程序(在最基本的级别)完全不区分线程和进程——“进程”只是一个包含一个或多个线程的容器。 IOW(并且过于简化) - 调度程序没有 进程 这样的东西,“线程”是可调度的东西:进程 什么都没有 与此相关(“进程”更多是关于打开句柄、资源等的生命周期管理问题)
如果您有一个单线程进程,那么将“进程”关联掩码设置为什么并不重要:调度程序将调度 一个 线程(对于任何掩码处理器)根据 1) 它最后绑定到哪个处理器 - 理想情况下,开销更少,2) 无论哪个处理器下一个可用于相同优先级的给定 runnable 线程(比这更复杂,但一般想法),以及 3)可能是暂时的关于优先级反转、可等待对象、内核 APC 事件等的问题。
所以回答你的问题(比预期的要冗长得多):
“但是,如果我使用 15 或 F 或 0xF 之类的多核 X(在我看来意味着所有 4 个内核),它仍将仅在第一个内核上运行”
我之前所说的关于调度程序尝试使用最近使用的处理器的内容在这里很重要:如果您有一个(或本质上)单线程进程,调度算法将采用最乐观的方法:之前用于切换的绑定 CPU(对于 CPU/主内存缓存、先前的分支预测评估等可能更便宜)。这就解释了为什么您会看到一个应用程序(无论进程级别的关联性如何)只有一个(同样,此处需要注意事项)线程似乎“卡”在一个 CPU/内核上。
所以:
您使用“/affinity X”开关有效地做的是
1) 限制调度程序仅在 CPU 内核的子集上调度您的线程(即不是全部),并且
2) 将它们限制为调度程序内核认为“可用于下一个可运行线程切换到”的子集,并且
3)如果它们不是多线程应用程序(并且能够利用它),“更多内核”并没有真正帮助 - 你可能只是将单个执行线程反弹到不同的内核(尽管调度程序试图最小化这个,如上所述)。
这就是为什么你的线程是“粘性的”——你是在告诉调度程序让它们如此。