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

时间:2015-07-18 18:46:31

标签: delphi delphi-xe7

我有一个工作站,其操作系统是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;

但它不起作用。

我会很感激任何建议。

1 个答案:

答案 0 :(得分:2)

如评论中所讨论的,亲和性掩码在32位代码中是32位,在64位代码中是64位。您正在尝试设置72位掩码。显然,这不会起作用。

您需要了解MSDN上详细介绍的处理器群组:Processor Groups,包括指向Supporting Systems That Have More Than 64 Processors的链接。

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

  

创建线程后,可以通过调用SetThreadAffinityMask或SetThreadGroupAffinity来更改其亲和性。如果将线程分配给与进程不同的组,则更新进程的亲和性以包括线程的亲和性,并且该进程变为多组进程。必须对各个线程进行进一步的亲和力改变;无法使用SetProcessAffinityMask修改多组进程的亲和力。

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

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

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