SetProcessAffinityMask - 选择多个处理器?

发布于 2024-12-29 18:20:31 字数 2177 浏览 3 评论 0原文

如何使用 SetProcessAffinityMask 选择多个逻辑处理器?

在 Windows 任务管理器中,您可以执行此操作作为示例:

在此处输入图像描述

我更新了我的 CreateProcess 过程来执行此操作:

type
  TProcessPriority = (ptLow         = $00000040,
                      ptBelowNormal = $00004000,
                      ptNormal      = $00000020,
                      ptAboveNormal = $00008000,
                      ptHigh        = $00000080,
                      ptRealtime    = $00000100);

procedure RunProcess(FileName: string; Priority: TProcessPriority);
var
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
  CmdLine: string;
  Done: Boolean;
begin
  FillChar(StartInfo, SizeOf(TStartupInfo), #0);
  FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
  StartInfo.cb := SizeOf(TStartupInfo);

  CmdLine := FileName;
  UniqueString(CmdLine);
  try
    Done := CreateProcess(nil, PChar(CmdLine), nil, nil, False,
                          CREATE_NEW_PROCESS_GROUP + Integer(Priority),
                          nil, nil, StartInfo, ProcInfo);
    if Done then
    begin
      // Todo: Get actual cpu core count before attempting to set affinity!
      // 0 = <All Processors>
      // 1 = CPU 0
      // 2 = CPU 1
      // 3 = CPU 2
      // 4 = CPU 3
      // 5 = CPU 5
      // 6 = CPU 6
      // 7 = CPU 6
      // 8 = CPU 7

      // this sets to CPU 0 - but how to allow multiple parameters to
      // set more than one logical processor?
      SetProcessAffinityMask(ProcInfo.hProcess, 1); 
    end else
      MessageDlg('Could not run ' + FileName, mtError, [mbOk], 0)
  finally
    CloseHandle(ProcInfo.hProcess);
    CloseHandle(ProcInfo.hThread);
  end;
end;

请注意我在那里添加的注释。最好更新我的过程以包含一个新的 Affinity 参数,我可以将其传递给 SetProcessAffinityMask。

出于显而易见的原因,调用其中任何一个都不会选择相应的处理器,它们给出了我想要执行的操作的想法:

SetProcessAffinityMask(ProcInfo.hProcess, 1 + 2); 
SetProcessAffinityMask(ProcInfo.hProcess, 1 and 2);

例如,为进程选择任何 CPU,如任务管理器中所示。

我应该如何使用数组、集合或其他东西来做到这一点?我无法让它与多个值一起工作。

谢谢。

How can I use SetProcessAffinityMask to select more than one logical processor?

In Windows Task Manager you can do this as an example:

enter image description here

I updated my CreateProcess procedure to do this:

type
  TProcessPriority = (ptLow         = $00000040,
                      ptBelowNormal = $00004000,
                      ptNormal      = $00000020,
                      ptAboveNormal = $00008000,
                      ptHigh        = $00000080,
                      ptRealtime    = $00000100);

procedure RunProcess(FileName: string; Priority: TProcessPriority);
var
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
  CmdLine: string;
  Done: Boolean;
begin
  FillChar(StartInfo, SizeOf(TStartupInfo), #0);
  FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
  StartInfo.cb := SizeOf(TStartupInfo);

  CmdLine := FileName;
  UniqueString(CmdLine);
  try
    Done := CreateProcess(nil, PChar(CmdLine), nil, nil, False,
                          CREATE_NEW_PROCESS_GROUP + Integer(Priority),
                          nil, nil, StartInfo, ProcInfo);
    if Done then
    begin
      // Todo: Get actual cpu core count before attempting to set affinity!
      // 0 = <All Processors>
      // 1 = CPU 0
      // 2 = CPU 1
      // 3 = CPU 2
      // 4 = CPU 3
      // 5 = CPU 5
      // 6 = CPU 6
      // 7 = CPU 6
      // 8 = CPU 7

      // this sets to CPU 0 - but how to allow multiple parameters to
      // set more than one logical processor?
      SetProcessAffinityMask(ProcInfo.hProcess, 1); 
    end else
      MessageDlg('Could not run ' + FileName, mtError, [mbOk], 0)
  finally
    CloseHandle(ProcInfo.hProcess);
    CloseHandle(ProcInfo.hThread);
  end;
end;

Note the comments I put in there. It would be good to update my procedure to include a new Affinity parameter which I can pass to SetProcessAffinityMask.

Calling any of these won't select the corresponding processors for obvious reasons, they give the idea of what I am wanting to do:

SetProcessAffinityMask(ProcInfo.hProcess, 1 + 2); 
SetProcessAffinityMask(ProcInfo.hProcess, 1 and 2);

eg, select any of the CPU's for a process, as shown in Task Manager.

How should I do this, using an Array, Set or something else? I cannot get it to work with multiple values.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷情妓 2025-01-05 18:20:31

它是一个位掩码,如文档中所述。

进程关联掩码是一个位向量,其中每个位代表一个允许运行进程线程的逻辑处理器。

  • 处理器 0 是 $01。
  • 处理器 1 的价格为 02 美元。
  • 处理器 2 的价格为 04 美元。
  • 处理器 3 的售价为 08 美元。
  • 处理器 4 售价 10 美元。

等等。您可以使用逻辑来组合它们。因此处理器 0 和 1 将是 $01$02,等于 $03

我将使用移位运算符 shl 为特定处理器创建值。像这样:

function SingleProcessorMask(const ProcessorIndex: Integer): DWORD_PTR;
begin
  //When shifting constants the compiler will force the result to be 32-bit
  //if you have more than 32 processors, `Result:= 1 shl x` will return
  //an incorrect result.
  Result := DWORD_PTR(1) shl (ProcessorIndex); 
end;

您可以轻松地扩展它,以在循环中使用逻辑 or 生成处理器列表的掩码。

function CombinedProcessorMask(const Processors: array of Integer): DWORD_PTR;
var
  i: Integer;
begin
  Result := 0;
  for i := low(Processors) to high(Processors) do
    Result := Result or SingleProcessorMask(Processors[i]);
end;

您可以测试处理器是否处于位掩码中,如下所示:

function ProcessorInMask(const ProcessorMask: DWORD_PTR; 
  const ProcessorIndex: Integer): Boolean;
begin
  Result := (SingleProcessorMask(ProcessorIndex) and ProcessorMask)<>0;
end;

注意:我使用的是DWORD_PTR,因为对于 64 位目标,位掩码是 64 位宽。这种细微差别对于 XE 上的您来说并不重要,但值得正确对待它以使将来的代码移植更容易。

It is a bitmask as described in the documentation.

A process affinity mask is a bit vector in which each bit represents a logical processor on which the threads of the process are allowed to run.

  • Processor 0 is $01.
  • Processor 1 is $02.
  • Processor 2 is $04.
  • Processor 3 is $08.
  • Processor 4 is $10.

And so on. You can use logical or to combine them. So processors 0 and 1 would be $01 or $02 which equals $03.

I would use the shift operator shl to create values for specific processors. Like this:

function SingleProcessorMask(const ProcessorIndex: Integer): DWORD_PTR;
begin
  //When shifting constants the compiler will force the result to be 32-bit
  //if you have more than 32 processors, `Result:= 1 shl x` will return
  //an incorrect result.
  Result := DWORD_PTR(1) shl (ProcessorIndex); 
end;

You can readily extend this to generate masks for lists of processors using logical or in a loop.

function CombinedProcessorMask(const Processors: array of Integer): DWORD_PTR;
var
  i: Integer;
begin
  Result := 0;
  for i := low(Processors) to high(Processors) do
    Result := Result or SingleProcessorMask(Processors[i]);
end;

You can test for a processor being in a bit mask like this:

function ProcessorInMask(const ProcessorMask: DWORD_PTR; 
  const ProcessorIndex: Integer): Boolean;
begin
  Result := (SingleProcessorMask(ProcessorIndex) and ProcessorMask)<>0;
end;

Note: I'm using DWORD_PTR because for 64 bit targets the bitmask is 64 bits wide. That nuance doesn't matter for you on XE but it's worth getting it right to make any future code porting easier.

小女人ら 2025-01-05 18:20:31

它在我的 XE 上是 32 位位掩码(但在 64 位 XE2 上可能是 64 位!)

只需定义一组 [0..31],其中 0=cpu 1 等。

然后将结果键入掩码为双字。

所以

var 
  cpuset  : set of 0..31;

begin
  cpuset:=[1,2]; // cpus 2 and 3
  include (cpuset,5); // add cpu 6
  SetProcessAffinityMask(ProcInfo.hProcess, dword(cpuset)); 

It's a 32-bit bitmask on my XE (but it could be 64-bit on 64-bit XE2!)

Just define a set of [0..31] where 0=cpu 1 etc.

Then typemask the result to a dword.

So

var 
  cpuset  : set of 0..31;

begin
  cpuset:=[1,2]; // cpus 2 and 3
  include (cpuset,5); // add cpu 6
  SetProcessAffinityMask(ProcInfo.hProcess, dword(cpuset)); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文