如何将应用程序分配给特定的NUMA节点?

时间:2018-08-17 12:27:11

标签: delphi

以下代码仅允许更改当前NUMA节点中的亲和力。有没有可以让我指定NUMA节点的功能?我宁愿避免使用start /NODE 3 /AFFINITY 1 program.exe

这样的外部解决方案
procedure TForm1.FormCreate(Sender: TObject);
var AffinityMask:Cardinal;
begin    
  AffinityMask:=1;
  SetProcessAffinityMask(GetCurrentProcess(),AffinityMask);
end;

2 个答案:

答案 0 :(得分:1)

这在Microsoft的NUMA Support文档中有所介绍:

  

首先,您需要确定系统中节点的布局。要检索系统中编号最高的节点,请使用GetNumaHighestNodeNumber函数。请注意,不能保证此数目等于系统中节点的总数。同样,具有序号的节点也不能保证彼此靠近。要检索系统上的处理器列表,请使用GetProcessAffinityMask函数。您可以使用GetNumaProcessorNode函数为列表中的每个处理器确定节点。另外,要检索节点中所有处理器的列表,请使用GetNumaNodeProcessorMask函数。

     

确定哪些处理器属于哪些节点后,可以优化应用程序的性能。 要确保您进程的所有线程都在同一节点上运行,请使用SetProcessAffinityMask函数和进程亲和力掩码,该掩码指定同一节点中的处理器。这样可以提高其线程的应用程序的效率。需要访问相同的内存。另外,要限制每个节点上的线程数,请使用SetThreadAffinityMask函数。

答案 1 :(得分:-4)

似乎有一个未记录的函数,称为 NtSetInformationProcess

https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/e0f49cda-4cbf-4da0-918a-0568271edb9f/process-affinity-on-a-system-with-128-processors?forum=wdk

  

我发现了一个有趣的API,本质上就是我想要的。

     

此处的目标是执行与SetProcessAffinityMask()相同的操作   与团体。事实证明,有这样的功能,但是   未记录。

     

我发现NtSetProcessInformation()将同时设置两个组   以及已经运行的进程的亲和力掩码。它的API是   像这样的东西:

     

GROUP_AFFINITY group_affinity;

     

group_affinity.group = 1; //第二组64个处理器

     

group_affinity.mask = 0x0000FFFF00000000;

     

NtSetProcessInformation(hProcess,0x15,&group_affinity,   group_affinity_size)

     

效果很好,并且与TaskManager用来更改的API相同   亲和力组和进程的掩码。

     

当然,由于它没有记录,因此可能会发生变化,因此   最好不要在零售软件中使用它。我只用它来跑   我们实验室中的性能测试,所以这里没什么大问题。

所以这是我尝试将该代码转换为Delphi7的尝试。将进程分配给第一个NUMA节点上的第一个cpu。

function NtSetInformationProcess(HProcess: CARDINAL; ProcessInformationClass: BYTE; ProcessInformation: POINTER; ProcessInformationLength: CARDINAL): CARDINAL; stdcall; external 'ntdll.dll' name 'NtSetInformationProcess';

type
   TGROUP_AFFINITY = record
     group  : WORD;
     mask   : cardinal;
     Reserved: array [0..2] of WORD;
   end; 

procedure TForm1.FormCreate(Sender: TObject);
var group_affinity:TGROUP_AFFINITY;
    HRES: HRESULT;
begin

  group_affinity.group:= 0;
  group_affinity.mask:= 1;
  HRES:=NtSetInformationProcess(GetCurrentProcess(), $15 , @group_affinity, SizeOf(group_affinity));

  if HRES = S_OK then showmessage('OK') else showmessage('ERROR'); 

end; 

编辑:现在可以了!缺少Reserved: array [0..2] of WORD;的定义,必须使用group : WORD;代替group : cardinal;

_GROUP_AFFINITY结构 https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_group_affinity

NtSetProcessInformation文档 https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FProcess%2FNtSetInformationProcess.html