#python #windows #winapi #ctypes #processor
Вопрос:
Поэтому я пытаюсь получить группировки процессоров по сокетам. У меня есть POC на C , который это делает, вывод выглядит следующим образом.
[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,],[0,1,2,3,4,5,6,7,8,9,10,11,],] [[12,13,14,15,16,17,18,19,20,21,22,23,],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,],]
И хотя я мог бы просто сделать что-то вроде следующего, я бы предпочел иметь непрерывность кода и сохранить проект на чистом python. К тому же это казалось хорошей головоломкой для решения ради опыта.
socket_groups = eval(run_cmd_popen("get_logical_processor_information.exe", return_output=True).strip("n"))
То, что у меня есть до сих пор, работает, но только в одной системе сокетов, для двух систем сокетов, во втором сокете, похоже, нет никаких данных, и выводится следующее.
[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,][0,1,2,3,4,5,6,7,8,9,10,11,]] []
Вот что у меня есть до сих пор:
import os import math import platform from ctypes.wintypes import BYTE, INT, WORD, DWORD, BOOL, PDWORD, UINT from ctypes import Structure, Union, WinDLL, c_uint64, POINTER, byref, get_last_error, WinError from wmi import WMI if platform.machine().endswith('64'): KAFFINITY = c_uint64 else: KAFFINITY = UINT wmi = WMI() NUM_SOCKETS = 0 for wmi_obj in wmi.query(f'SELECT * FROM Win32_processor '): if wmi_obj is not None: NUM_SOCKETS = 1 NUM_CPUS = os.cpu_count() NUM_CPU_GROUPS = math.ceil(NUM_CPUS / 64) ANYSIZE_ARRAY = NUM_CPU_GROUPS ERROR_INSUFFICIENT_BUFFER = 122 RELATION_CACHE = 2 RELATION_NUMA_NODE = 1 RELATION_PROCESSOR_CORE = 0 RELATION_PROCESSOR_PACKAGE = 3 RELATION_GROUP = 4 RELATION_ALL = 0xffff class _GROUP_AFFINITY(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-group_affinity typedef struct _GROUP_AFFINITY { KAFFINITY Mask; WORD Group; WORD Reserved[3]; } GROUP_AFFINITY, *PGROUP_AFFINITY; ''' _fields_ = ( ('Mask', KAFFINITY), ('Group', WORD), ('Reserved', WORD * 3) ) class _PROCESSOR_GROUP_INFO(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-processor_group_info typedef struct _PROCESSOR_GROUP_INFO { BYTE MaximumProcessorCount; BYTE ActiveProcessorCount; BYTE Reserved[38]; KAFFINITY ActiveProcessorMask; } PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO; ''' _fields_ = ( ('MaximumProcessorCount', BYTE), ('ActiveProcessorCount', BYTE), ('Reserved', BYTE * 38), ('ActiveProcessorMask', KAFFINITY), ) class _GROUP_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-group_relationship typedef struct _GROUP_RELATIONSHIP { WORD MaximumGroupCount; WORD ActiveGroupCount; BYTE Reserved[20]; PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY]; } GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP; ''' _fields_ = ( ('MaximumGroupCount', WORD), ('ActiveGroupCount', WORD), ('Reserved', BYTE * 20), ('GroupInfo', _PROCESSOR_GROUP_INFO * ANYSIZE_ARRAY) ) class _DUMMYUNIONNAME_CACHE_RELATIONSHIP(Union): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-cache_relationship union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; ''' _fields_ = ( ('GroupMask', _GROUP_AFFINITY), ('GroupMasks', _GROUP_AFFINITY * ANYSIZE_ARRAY) # * number of groups ) class _CACHE_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-cache_relationship typedef struct _CACHE_RELATIONSHIP { BYTE Level; BYTE Associativity; WORD LineSize; DWORD CacheSize; PROCESSOR_CACHE_TYPE Type; BYTE Reserved[18]; WORD GroupCount; union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; } CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP; ''' _fields_ = ( ('Level', BYTE), ('Associativity', BYTE), ('LineSize', WORD), ('CacheSize', DWORD), ('Type', INT), # PROCESSOR_CACHE_TYPE is an Enum type, which, At least for GCC, is just a simple numeric type. (https://stackoverflow.com/questions/1546355/using-enums-in-ctypes-structure/1546467#1546467) ('Reserved', BYTE * 18), ('GroupCount', WORD), ('DUMMYUNIONNAME ', _DUMMYUNIONNAME_CACHE_RELATIONSHIP) ) class _DUMMYUNIONNAME_NUMA_NODE_RELATIONSHIP(Union): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-numa_node_relationship union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; ''' _fields_ = ( ('GroupMask', _GROUP_AFFINITY), ('GroupMasks', _GROUP_AFFINITY * ANYSIZE_ARRAY) # * number of groups ) class _NUMA_NODE_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-numa_node_relationship typedef struct _NUMA_NODE_RELATIONSHIP { DWORD NodeNumber; BYTE Reserved[18]; WORD GroupCount; union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; } NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP; ''' _fields_ = ( ('NodeNumber', DWORD), ('Reserved', BYTE * 18), ('GroupCount', WORD), ('DUMMYUNIONNAME', _DUMMYUNIONNAME_NUMA_NODE_RELATIONSHIP) ) class _PROCESSOR_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-processor_relationship typedef struct _PROCESSOR_RELATIONSHIP { BYTE Flags; BYTE EfficiencyClass; BYTE Reserved[20]; WORD GroupCount; GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; } PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP; ''' _fields_ = ( ('Flags', BYTE), ('EfficiencyClass', BYTE), ('Reserved', BYTE * 20), ('GroupCount', WORD), ('GroupMask', _GROUP_AFFINITY * ANYSIZE_ARRAY) # * number of groups ) class _DUMMYUNIONNAME_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX(Union): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-system_logical_processor_information_ex union { PROCESSOR_RELATIONSHIP Processor; NUMA_NODE_RELATIONSHIP NumaNode; CACHE_RELATIONSHIP Cache; GROUP_RELATIONSHIP Group; } DUMMYUNIONNAME; ''' _fields_ = ( ('Processor', _PROCESSOR_RELATIONSHIP), ('NumaNode', _NUMA_NODE_RELATIONSHIP), ('Cache', _CACHE_RELATIONSHIP), ('Group', _GROUP_RELATIONSHIP) ) class _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-system_logical_processor_information_ex typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { LOGICAL_PROCESSOR_RELATIONSHIP Relationship; DWORD Size; union { PROCESSOR_RELATIONSHIP Processor; NUMA_NODE_RELATIONSHIP NumaNode; CACHE_RELATIONSHIP Cache; GROUP_RELATIONSHIP Group; } DUMMYUNIONNAME; } SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; ''' _anonymous_ = 'DUMMYUNIONNAME', _fields_ = ( ('Relationship', INT), # _LOGICAL_PROCESSOR_RELATIONSHIP is an Enum type, which, At least for GCC, is just a simple numeric type. (https://stackoverflow.com/questions/1546355/using-enums-in-ctypes-structure/1546467#1546467) ('Size', DWORD), ('DUMMYUNIONNAME', _DUMMYUNIONNAME_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ) def GetLogicalProcessorInformationEx(relation_type): '''https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex BOOL GetLogicalProcessorInformationEx( [in] LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, [out, optional] PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, [in, out] PDWORD ReturnedLength ); ''' dll = WinDLL('kernel32', use_last_error=True) dll.GetLogicalProcessorInformationEx.argtypes = INT, POINTER(_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX), PDWORD dll.GetLogicalProcessorInformationEx.restype = BOOL byte_len = DWORD() # Call with null buffer to get required buffer size result = dll.GetLogicalProcessorInformationEx(relation_type, None, byref(byte_len)) if (err := get_last_error()) != ERROR_INSUFFICIENT_BUFFER: raise WinError(err) # Allocate buffer allocated_structure = (_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX * NUM_SOCKETS)() global byte_len_for_advance byte_len_for_advance = byte_len # Now do the call with the allocated buffer to fill it up result = dll.GetLogicalProcessorInformationEx(relation_type, allocated_structure, byref(byte_len)) if not result: raise WinError(get_last_error()) return allocated_structure def _print_mask(mask): # print(f"{mask=}") digits = [int(x) for x in mask] group_core_list = [] print("[", end='') core = 0 for i in digits: if i == 1: print(f"{core},", end='') group_core_list.append(core) core = 1 print("]", end='') # print(group_core_list) if __name__ == "__main__": enum_info = GetLogicalProcessorInformationEx(RELATION_PROCESSOR_PACKAGE) for p_info in enum_info: print("[", end='') for group_index in range(0, p_info.Processor.GroupCount): _print_mask(f"{p_info.Processor.GroupMask[group_index].Mask:8b}") print("]n", end='') breakpoint
Я думаю, мне нужно что-то сделать с перемещением указателя на следующую структуру, может быть? Но я не знаю, как это сделать. Кроме того, я не уверен, что _print_mask() будет делать именно то, что я хочу, когда я получу информацию о вторых сокетах, но это более поздняя проблема.
Any thought internet?
Edit
Thanks to Mark Tolonen for the answer/help!
Here is my working solution:
from typing import Dict, List from ctypes.wintypes import BYTE, INT, WORD, DWORD, BOOL, PDWORD, WPARAM from ctypes import Structure, Union, WinDLL, c_char_p, POINTER, byref, cast, get_last_error, WinError, create_string_buffer KAFFINITY = WPARAM # WPARAM is 32-bit or 64-bit unsigned depending on platform ANYSIZE_ARRAY = 1 ERROR_INSUFFICIENT_BUFFER = 122 RELATION_CACHE = 2 RELATION_NUMA_NODE = 1 RELATION_PROCESSOR_CORE = 0 RELATION_PROCESSOR_PACKAGE = 3 RELATION_GROUP = 4 RELATION_ALL = 0xffff class _GROUP_AFFINITY(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-group_affinity typedef struct _GROUP_AFFINITY { KAFFINITY Mask; WORD Group; WORD Reserved[3]; } GROUP_AFFINITY, *PGROUP_AFFINITY; ''' _fields_ = ( ('Mask', KAFFINITY), ('Group', WORD), ('Reserved', WORD * 3) ) class _PROCESSOR_GROUP_INFO(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-processor_group_info typedef struct _PROCESSOR_GROUP_INFO { BYTE MaximumProcessorCount; BYTE ActiveProcessorCount; BYTE Reserved[38]; KAFFINITY ActiveProcessorMask; } PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO; ''' _fields_ = ( ('MaximumProcessorCount', BYTE), ('ActiveProcessorCount', BYTE), ('Reserved', BYTE * 38), ('ActiveProcessorMask', KAFFINITY), ) class _GROUP_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-group_relationship typedef struct _GROUP_RELATIONSHIP { WORD MaximumGroupCount; WORD ActiveGroupCount; BYTE Reserved[20]; PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY]; } GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP; ''' _fields_ = ( ('MaximumGroupCount', WORD), ('ActiveGroupCount', WORD), ('Reserved', BYTE * 20), ('GroupInfo', _PROCESSOR_GROUP_INFO * ANYSIZE_ARRAY) ) class _DUMMYUNIONNAME_CACHE_RELATIONSHIP(Union): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-cache_relationship union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; ''' _fields_ = ( ('GroupMask', _GROUP_AFFINITY), ('GroupMasks', _GROUP_AFFINITY * ANYSIZE_ARRAY) ) class _CACHE_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-cache_relationship typedef struct _CACHE_RELATIONSHIP { BYTE Level; BYTE Associativity; WORD LineSize; DWORD CacheSize; PROCESSOR_CACHE_TYPE Type; BYTE Reserved[18]; WORD GroupCount; union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; } CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP; ''' _fields_ = ( ('Level', BYTE), ('Associativity', BYTE), ('LineSize', WORD), ('CacheSize', DWORD), ('Type', INT), # PROCESSOR_CACHE_TYPE is an Enum type, which, At least for GCC, is just a simple numeric type. (https://stackoverflow.com/questions/1546355/using-enums-in-ctypes-structure/1546467#1546467) ('Reserved', BYTE * 18), ('GroupCount', WORD), ('DUMMYUNIONNAME ', _DUMMYUNIONNAME_CACHE_RELATIONSHIP) ) class _DUMMYUNIONNAME_NUMA_NODE_RELATIONSHIP(Union): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-numa_node_relationship union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; ''' _fields_ = ( ('GroupMask', _GROUP_AFFINITY), ('GroupMasks', _GROUP_AFFINITY * ANYSIZE_ARRAY) ) class _NUMA_NODE_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-numa_node_relationship typedef struct _NUMA_NODE_RELATIONSHIP { DWORD NodeNumber; BYTE Reserved[18]; WORD GroupCount; union { GROUP_AFFINITY GroupMask; GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; } DUMMYUNIONNAME; } NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP; ''' _fields_ = ( ('NodeNumber', DWORD), ('Reserved', BYTE * 18), ('GroupCount', WORD), ('DUMMYUNIONNAME', _DUMMYUNIONNAME_NUMA_NODE_RELATIONSHIP) ) class _PROCESSOR_RELATIONSHIP(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-processor_relationship typedef struct _PROCESSOR_RELATIONSHIP { BYTE Flags; BYTE EfficiencyClass; BYTE Reserved[20]; WORD GroupCount; GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; } PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP; ''' _fields_ = ( ('Flags', BYTE), ('EfficiencyClass', BYTE), ('Reserved', BYTE * 20), ('GroupCount', WORD), ('GroupMask', _GROUP_AFFINITY * ANYSIZE_ARRAY) ) class _DUMMYUNIONNAME_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX(Union): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-system_logical_processor_information_ex union { PROCESSOR_RELATIONSHIP Processor; NUMA_NODE_RELATIONSHIP NumaNode; CACHE_RELATIONSHIP Cache; GROUP_RELATIONSHIP Group; } DUMMYUNIONNAME; ''' _fields_ = ( ('Processor', _PROCESSOR_RELATIONSHIP), ('NumaNode', _NUMA_NODE_RELATIONSHIP), ('Cache', _CACHE_RELATIONSHIP), ('Group', _GROUP_RELATIONSHIP) ) class _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX(Structure): '''https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-system_logical_processor_information_ex typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { LOGICAL_PROCESSOR_RELATIONSHIP Relationship; DWORD Size; union { PROCESSOR_RELATIONSHIP Processor; NUMA_NODE_RELATIONSHIP NumaNode; CACHE_RELATIONSHIP Cache; GROUP_RELATIONSHIP Group; } DUMMYUNIONNAME; } SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; ''' _anonymous_ = 'DUMMYUNIONNAME', _fields_ = ( ('Relationship', INT), # _LOGICAL_PROCESSOR_RELATIONSHIP is an Enum type, which, At least for GCC, is just a simple numeric type. (https://stackoverflow.com/questions/1546355/using-enums-in-ctypes-structure/1546467#1546467) ('Size', DWORD), ('DUMMYUNIONNAME', _DUMMYUNIONNAME_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ) def _GetLogicalProcessorInformationEx(relation_type): '''https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex BOOL GetLogicalProcessorInformationEx( [in] LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, [out, optional] PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, [in, out] PDWORD ReturnedLength ); ''' dll = WinDLL('kernel32', use_last_error=True) # Manage the allocated buffer as a c_char_p for easier pointer manipulation dll.GetLogicalProcessorInformationEx.argtypes = INT, c_char_p, PDWORD dll.GetLogicalProcessorInformationEx.restype = BOOL byte_len = DWORD() # Call with null buffer to get required buffer size result = dll.GetLogicalProcessorInformationEx(relation_type, None, byref(byte_len)) if (err := get_last_error()) != ERROR_INSUFFICIENT_BUFFER: raise WinError(err) # Allocate byte buffer buffer = create_string_buffer(byte_len.value) # Now do the call with the buffer to fill it up result = dll.GetLogicalProcessorInformationEx(relation_type, buffer, byref(byte_len)) if not result: raise WinError(get_last_error()) return buffer, byte_len.value # return buffer and length def get_socket_to_group_mappings() -gt; List[Dict[int, List[int]]]: ''' ''' # The returned structure array can vary in element size, so walk the buffer by the size of its element. buffer, buffer_len = _GetLogicalProcessorInformationEx(RELATION_PROCESSOR_PACKAGE) offset = 0 sockets = [] while offset lt; buffer_len: # Cast the current offset to the structure and extract contents processor_info = cast(byref(buffer, offset), POINTER(_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)).contents # print(f"{processor_info.Size=} {processor_info.Processor.GroupCount=}") # Cast the group mask array to the correct size group_infos = cast(byref(processor_info.Processor.GroupMask), POINTER(_GROUP_AFFINITY * processor_info.Processor.GroupCount)).contents groups = {} for group_info in group_infos: # print(f"{group_affinity.Mask=:016X} {group_affinity.Group=}") core_index = 0 group_cores = [] # Convert the mask to the binary representation of an 8-digit, zero-padded on the left string. # Then turn that string of 1's and 0's into a list, and reverse it. for i in [int(x) for x in f"{group_info.Mask:8b}"][::-1]: if i == 1: # If the this core is part of this socket in this group (indicated by a 1 in the mask). # Add the groups core number to the groups core list group_cores.append(core_index) core_index = 1 # Add this group to this sockets groups dict groups[group_info.Group] = group_cores # Add this sockets group info to the systems socket list sockets.append(groups) # Advance by the size consumed offset = processor_info.Size return sockets
Ответ №1:
У меня есть только одно ядро с 8 логическими процессорами, поэтому я не могу подтвердить, что у меня все правильно для вашей ситуации, но попробуйте это:
from ctypes.wintypes import BYTE, INT, WORD, DWORD, BOOL, PDWORD, UINT, WPARAM from ctypes import (Structure, Union, WinDLL, c_uint64, POINTER, byref, cast, get_last_error, WinError, c_char_p, create_string_buffer) KAFFINITY = WPARAM # WPARAM is 32-bit or 64-bit unsigned depending on platform ANYSIZE_ARRAY = 1 # actual definition # # unchanged portion elided # def GetLogicalProcessorInformationEx(relation_type): '''https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex BOOL GetLogicalProcessorInformationEx( [in] LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, [out, optional] PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, [in, out] PDWORD ReturnedLength ); ''' dll = WinDLL('kernel32', use_last_error=True) # manage the allocated buffer as a c_char_p for easier pointer manipulation dll.GetLogicalProcessorInformationEx.argtypes = INT, c_char_p, PDWORD dll.GetLogicalProcessorInformationEx.restype = BOOL byte_len = DWORD() # Call with null buffer to get required buffer size result = dll.GetLogicalProcessorInformationEx(relation_type, None, byref(byte_len)) if (err := get_last_error()) != ERROR_INSUFFICIENT_BUFFER: raise WinError(err) # Allocate byte buffer buffer = create_string_buffer(byte_len.value) # Now do the call with the buffer to fill it up result = dll.GetLogicalProcessorInformationEx(relation_type, buffer, byref(byte_len)) if not result: raise WinError(get_last_error()) return buffer,byte_len.value # return buffer and length if __name__ == "__main__": # The returned structure array can vary in element size, # so walk the buffer by the size of its element. buffer,len = GetLogicalProcessorInformationEx(RELATION_PROCESSOR_PACKAGE) offset = 0 while offset lt; len: # cast the current offset to the structure and extract contents info = cast(byref(buffer,offset), POINTER(_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)).contents print(f'{info.Size=} {info.Processor.GroupCount=}') # cast the group mask array to the correct size gaffs = cast(byref(info.Processor.GroupMask),POINTER(_GROUP_AFFINITY * info.Processor.GroupCount)).contents for gaff in gaffs: print(f'{gaff.Mask=:016X} {gaff.Group=}') # advance by the size consumed offset = info.Size
Вывод на моем одном ядре, 8 логических процессоров:
info.Size=48 info.Processor.GroupCount=1 gaff.Mask=00000000000000FF gaff.Group=0
Если это не работает для вашей сложной системы, опубликуйте возвращенное buffer,len
из моего решения, возвращенное вашей системой, и я исправлю это.
Комментарии:
1. Большое вам спасибо, что сделали это! Я не знал этого о «WPARAM», и я изначально установил «ANNYSIZE_ARRAY» на 1, но получал странные размеры структуры. Но теперь я понимаю, что это было связано с более фундаментальной проблемой.