如何使用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,如任务管理器中所示。
我应该如何使用数组,集合或其他内容?我无法使用多个值。
感谢。
答案 0 :(得分:13)
它是documentation中描述的位掩码。
进程关联掩码是一个位向量,其中每个位表示允许进程的线程运行的逻辑处理器。
等等。您可以使用逻辑or
来组合它们。因此,处理器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上,这种细微差别并不重要,但是让未来的代码移植变得更容易,这是值得的。
答案 1 :(得分:8)
这是我的XE上的32位位掩码(但它可能是64位XE2上的64位!)
只需定义一组[0..31],其中0 = cpu 1等。
然后将结果键入掩码为dword。
所以
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));