Похоже, вы пытаетесь создать отдельный поток для каждого ЦП , кроме"текущего" ЦП, на котором работает ваш обработчик OnClick
. Но вы никогда не используете CPU 0 в своих аффинных масках, потому что вы увеличиваете a
слишком рано. Но что более важно, маска сходства потока должна быть подмножеством маски сходства процесса, которая указывает процессоры, на которых разрешено запускать процесс:
Поток может работать только на тех процессорах, на которых может выполняться его процесс. Следовательно, маска соответствия потоков не может указывать 1 бит для процессора, когда маска соответствия процессов указывает 0 бит для этого процессора .
Маска сходства процесса сама является подмножеством маски сходства системы, которая указывает, какие ЦП установлены.
Таким образом, вероятной причиной вашей ошибки является то, что вы вычисляете маски сходства потоков, которые ОС отклоняет как недопустимые для вашего процесса.
Вместо этого попробуйте что-нибудь подобное (примечание: это не учитывает группы процессорных процессоров, если в ОС установлено более 64 процессоров):
procedure TForm2.BtnCreateLookup5x5to3x3UsingSpeculativeExplorationClick(Sender: TObject);
var
ThreadCount, MaxThreadCount: integer;
Threads: TArray<TThread>;
i, CurrentProcessor: integer;
ProcessAffinityMask, SystemAffinityMask, AllowedThreadMask, NewThreadMask: DWORD_PTR;
Thread: TThread;
...
begin
if not GetProcessAffinityMask(GetCurrentProcess(), ProcessAffinityMask, SystemAffinityMask) then RaiseLastOSError;
// optional: up the CPUs this process can run on, if needed...
{
if not SetProcessAffinityMask(GetCurrentProcess(), SystemAffinityMask) then RaiseLastOSError;
ProcessAffinityMask := SystemAffinityMask;
}
AllowedThreadMask := DWORD_PTR(-1) and ProcessAffinityMask;
CurrentProcessor := GetCurrentProcessorNumber;
ThreadCount := 0;
MaxThreadCount := System.CpuCount;
NewThreadMask := 1;
SetLength(Threads, MaxThreadCount);
try
for i := 0 to MaxThreadCount-1 do
begin
if (i <> CurrentProcessor) and //Skip the current processor.
((AllowedThreadMask and NewThreadMask) <> 0) then // is this CPU allowed?
begin
Thread := TThread.CreateAnonymousThread(
procedure
begin
CreateLookupUsingGridSolver(...);
end
);
try
Thread.FreeOnTerminate := false;
if not SetThreadAffinityMask(Thread.Handle, NewThreadMask) then RaiseLastOSError;
Thread.Start;
except
Thread.Free;
raise;
end;
Threads[ThreadCount] := Thread;
Inc(ThreadCount);
end;
NewThreadMask := NewThreadMask shl 1;
end;
CreateLookupUsingGridSolver(...);
// Wait for all threads to finish...
// ...
finally
for i := 0 to ThreadCount-1 do
Threads[i].Free;
end;
end;