问题
Currently I'm using this function. It works fine but each query takes about 1 second. So in my case I waste 3 seconds in my application. At the moment I'm thinking about using 3 threads to get this all information in one second.
function GetWMIstring (wmiHost, wmiClass, wmiProperty : string):string;
var // These are all needed for the WMI querying process
Locator: ISWbemLocator;
Services: ISWbemServices;
SObject: ISWbemObject;
ObjSet: ISWbemObjectSet;
SProp: ISWbemProperty;
Enum: IEnumVariant;
Value: Cardinal;
TempObj: OleVariant;
SN: string;
begin
Result := '';
try
Locator := CoSWbemLocator.Create; // Create the Location object
// Connect to the WMI service, with the root\cimv2 namespace
Services := Locator.ConnectServer(wmiHost, 'root\cimv2', '', '', '','', 0, nil);
ObjSet := Services.ExecQuery('SELECT * FROM '+wmiClass, 'WQL',
wbemFlagReturnImmediately and wbemFlagForwardOnly , nil);
Enum := (ObjSet._NewEnum) as IEnumVariant;
while Enum.Next(1, TempObj, Value) = S_OK do
begin
try SObject := IUnknown(TempObj) as ISWBemObject; except SObject := nil; end;
TempObj := Unassigned; // Always need to free interface in TempObj
if SObject <> nil then
begin
SProp := SObject.Properties_.Item(wmiProperty, 0);
SN := SProp.Get_Value;
if not VarIsNull(SN) then
begin
Result := SN;
Break;
end;
end;
end;
except // Trap any exceptions (Not having WMI installed will cause one!)
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
CoInitializeEx(nil,COINIT_MULTITHREADED) ; //required !!! Otherwise "EOleSysError: CoInitialize has not been called" occurs (Microsoft recommends CoInitializeEx instead of CoInitialize)
CPU_PROCESSOR_COUNT := StrToInt( getWMIstring('','Win32_ComputerSystem','NumberOfProcessors') ); // number of cpu on mainboard
CPU_PHYSICAL_CORES := StrToInt( getWMIstring('','Win32_Processor','NumberOfCores') ); // number of phisical cores
CPU_LOGICAL_CORES := StrToInt( getWMIstring('','Win32_Processor','NumberOfLogicalProcessors') ); //number of logical cores
CoUninitialize; //required !!!
end;
回答1:
Here is an example using GetLogicalProcessorInformation :
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
type
TLogicalProcessorInformation = record
LogicalProcessorCount : integer;
NumaNodeCount : integer;
ProcessorCoreCount : integer;
ProcessorL1CacheCount : integer;
ProcessorL2CacheCount : integer;
ProcessorL3CacheCount : integer;
ProcessorPackageCount : integer;
end;
function CountSetBits(bitMask : NativeUInt) : integer;
var
lShift, i : integer;
bitTest : NativeUInt;
begin
lShift := SizeOf(NativeUInt)*8 - 1;
result := 0;
bitTest := 1 shl lShift;
for i := 0 to lShift do begin
if (bitMask and bitTest) <> 0 then Inc(result);
bitTest := bitTest shr 1;
end;
end;
function GetLogicalProcessorInfo : TLogicalProcessorInformation;
var
i: Integer;
ReturnLength: DWORD;
Buffer: array of TSystemLogicalProcessorInformation;
begin
result.LogicalProcessorCount := 0;
result.NumaNodeCount := 0;
result.ProcessorCoreCount := 0;
result.ProcessorL1CacheCount := 0;
result.ProcessorL2CacheCount := 0;
result.ProcessorL3CacheCount := 0;
result.ProcessorPackageCount := 0;
SetLength(Buffer, 256);
if not GetLogicalProcessorInformation(@Buffer[0], ReturnLength) then
begin
if GetLastError = ERROR_INSUFFICIENT_BUFFER then begin
SetLength(Buffer,
ReturnLength div SizeOf(TSystemLogicalProcessorInformation) + 1);
if not GetLogicalProcessorInformation(@Buffer[0], ReturnLength) then
RaiseLastOSError;
end else
RaiseLastOSError;
end;
SetLength(Buffer, ReturnLength div SizeOf(TSystemLogicalProcessorInformation));
for i := 0 to High(Buffer) do begin
case Buffer[i].Relationship of
RelationNumaNode: Inc(result.NumaNodeCount);
RelationProcessorCore:
begin
Inc(result.ProcessorCoreCount);
result.LogicalProcessorCount := result.LogicalProcessorCount + CountSetBits(Buffer[i].ProcessorMask);
end;
RelationCache:
begin
if (Buffer[i].Cache.Level = 1) then Inc(result.ProcessorL1CacheCount)
else if (Buffer[i].Cache.Level = 2) then Inc(result.ProcessorL2CacheCount)
else if (Buffer[i].Cache.Level = 3) then Inc(result.ProcessorL3CacheCount);
end;
RelationProcessorPackage: Inc(result.ProcessorPackageCount);
else
raise Exception.Create('Error: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.');
end;
end;
end;
var
LProcInfo : TLogicalProcessorInformation;
begin
LProcInfo := GetLogicalProcessorInfo;
WriteLn('Logical processor count = ', LProcInfo.LogicalProcessorCount);
WriteLn('NUMA Node count = ', LProcInfo.NumaNodeCount);
WriteLn('Processor Core count = ', LProcInfo.ProcessorCoreCount);
WriteLn('L1 Cache count = ', LProcInfo.ProcessorL1CacheCount);
WriteLn('L2 Cache count = ', LProcInfo.ProcessorL2CacheCount);
WriteLn('L3 Cache count = ', LProcInfo.ProcessorL3CacheCount);
WriteLn('Package count = ', LProcInfo.ProcessorPackageCount);
ReadLn;
end.
For XE2 and higher these WinAPI definitions are included in the RTL. The definitions can otherwise be included manually. An example implementation can be found here.
For a desktop i7 workstation, for example, this outputs :
Logical processor count = 8
NUMA Node count = 1
Processor Core count = 4
L1 Cache count = 8
L2 Cache count = 4
L3 Cache count = 1
Package count = 1
The logical core count includes hyperthread virtual cores, the processor core count is the physical number of cores, the package count returns the number of physical CPUs and the NUMA node count returns the number of processor nodes (for large cluster computers).
If you're expecting this to run on larger clusters be aware, from the docs :
On systems with more than 64 logical processors, the GetLogicalProcessorInformation function retrieves logical processor information about processors in the processor group to which the calling thread is currently assigned. Use the GetLogicalProcessorInformationEx function to retrieve information about processors in all processor groups on the system.
来源:https://stackoverflow.com/questions/46093706/how-to-detect-number-of-logical-and-physical-processors-efficiently