SetThreadAffinityMask的正确使用

问题描述 投票:0回答:4

有 12 个核心,12 个线程正在运行..我想为每个核心绑定 1 个线程。 这就是我在每个线程开头所说的。

int core=12;
SetThreadAffinityMask(GetCurrentThread(),(1<<core)-1);

这就是我所拥有的......我不知道这是否是正确的调用方式。我不确定我是否理解第二个参数是如何工作的..

我还需要调用SetProcessaffinitymask吗?

c++ multithreading winapi
4个回答
9
投票

SetThreadAffinityMask()
的第二个参数是位向量。每一位对应一个逻辑处理器:一个CPU核心或一个超线程。如果第二个参数中的某位设置为1,则允许线程在相应的核心上运行。

对于

core
等于 12,您的掩码
(1<<core)-1
包含 0..11 位集,因此允许每个线程在 12 个核心中的任何一个上运行。大概您希望将每个线程设置为在专用核心上运行。为此,您需要每个线程都有一个 0 到 11 之间的唯一编号,并且仅设置关联掩码的相应位。提示:您可以使用
InterlockedIncrement()
来获取唯一编号。或者,如果您的线程全部在循环中启动,则唯一编号已知(它是循环行程计数),您可以使用它,例如作为参数传递给每个线程,或为同一循环中的新线程设置亲和力。

请注意 David Heffernan 回答中的警告:除非您知道如何利用亲和力做好事,否则最好不要玩弄亲和力。除了 David 已经提到的原因之外,我还将在具有不同数量的套接字、内核和超线程的计算机之间添加应用程序可移植性。


8
投票

您似乎正在设置与所有 12 个处理器的关联性,这不是您想要的。

我会在主线程中循环设置亲和力的所有 12 个线程。不要在线程内设置关联性,因为这需要线程知道其索引,而它通常不需要知道。我声明一个掩码变量并为其分配值 1。每次循环时,您都设置线程亲和力,然后移动 1。您不应该更改进程亲和力。

请注意。设置亲和力是危险的。如果用户更改进程关联性,那么您最终可能会得到一个无法在任何处理器上运行的线程。小心点。

此外,根据我的经验,手动设置亲和力没有性能优势,有时还比较慢。通常系统做得很好。


7
投票

您可以编写如下代码。 GetThreadHandle(i) 是获取每个线程句柄的函数。

int core = 12;
for(int i=0; i<core; i++)  
  SetThreadAffinityMask(GetThreadHandle(i), 1<<i);

0
投票

位掩码通常为 64 位。对于超过 32 个处理器的情况,避免算术溢出的更便携的解决方案是:

auto mask = (static_cast<DWORD_PTR>(1) << core);//core number starts from 0
auto ret = SetThreadAffinityMask(GetCurrentThread(), mask);
© www.soinside.com 2019 - 2024. All rights reserved.