如何在Delphi XE7 for Windows 2012 R2中以编程方式设置SetProcessAffinityMask

我有一个工作站,其操作系统是64位
Windows Server 2012 R2.我正在使用Delphi XE7 Update 1.工作站有72个内核,包括超线程.

我希望我的所有应用程序都能在每次运行应用程序时可用的所有核心上运行.我希望以编程方式执行此操作,而不是在任务主服务器中使用set affinity(它一次只适用于一个组,我有两组36 cpus,我想同时使用)或者从msconfig预先设置启动选项.

我意识到这个问题类似于或包含了Stackoverflow上已经提出的以下问题

Delphi TParallel not using all available cpu

Strange behaviour of TParallel.For default ThreadPool

SetProcessAffinityMask – Select more than one processor?.

我也看了一下edn.embarcadero.com/article/27267的建议.

但我的SetProcessAffinityMask问题涉及使用64位操作系统的64个内核,并不仅限于使用TParallel.

我尝试的解决方案是改编自Marco van de Voort提供的解决方案

   var 
   cpuset  : set of 0..71;
   i: integer;
   begin
   cpuset:=[];
   for i:=0 to 71 do
   cpuset:=cpuset+[i];

   SetProcessAffinityMask(ProcInfo.hProcess, dword(cpuset)); 

   end;

但它不起作用.

我会很感激任何建议.

最佳答案 正如评论中所讨论的,亲和性掩码在32位代码中是32位,在64位代码中是64位.您正在尝试设置72位掩码.显然这是行不通的.

您将需要了解处理器组,详细信息在MSDN:Processor Groups上,包括此链接到Supporting Systems That Have More Than 64 Processors.

由于您有72个处理器,因此您将拥有多个处理器组.您需要使用多个进程来访问所有组,或使用多进程组.来自doc:

After the thread is created, its affinity can be changed by calling SetThreadAffinityMask or SetThreadGroupAffinity. If a thread is assigned to a different group than the process, the process’s affinity is updated to include the thread’s affinity and the process becomes a multi-group process. Further affinity changes must be made for individual threads; a multi-group process’s affinity cannot be modified using SetProcessAffinityMask.

这是非常粗糙的东西.如果您掌控自己的线程,那么您应该可以使用SetThreadGroupAffinity完成所需的操作.如果您使用的是Delphi线程库,则无法控制线程.这可能使单个流程解决方案难以维持.

另一个需要考虑的问题是内存局部性.如果机器使用NUMA内存,那么我知道没有可以在NUMA内存中运行良好的Delphi内存管理器.在NUMA环境中,如果性能对您很重要,您可能需要每个线程在线程的NUMA节点上分配内存.

这里的底线是没有简单的快速修复来生成将有效使用所有这些机器资源的代码.从我上面链接的文档开始,并执行一些试验,以确保您了解处理器组和NUMA的所有含义.

点赞