c – 获取共享缓存的逻辑CPU核心数(L1,L2,L3)
下面是一些使用
GetLogicalProcessorInformation在Windows上检测L1,L2和L3 CPU缓存大小的C代码:
typedef BOOL (WINAPI *LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,PDWORD); LPFN_GLPI glpi = (LPFN_GLPI) GetProcAddress( GetModuleHandle(TEXT("kernel32")),"GetLogicalProcessorInformation"); if (glpi) { DWORD bytes = 0; glpi(0,&bytes); size_t size = bytes / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> info(size); glpi(info.data(),&bytes); for (size_t i = 0; i < size; i++) { if (info[i].Relationship == RelationCache) { if (info[i].Cache.Level == 1) l1_cache_Size = info[i].Cache.Size; if (info[i].Cache.Level == 2) l2_cache_Size = info[i].Cache.Size; if (info[i].Cache.Level == 3) l3_cache_Size = info[i].Cache.Size; } } } 作为下一步,我希望获得共享缓存的逻辑CPU核心数量.在具有超线程的x64 CPU上,两个逻辑CPU内核通常共享L2缓存,并且所有逻辑CPU内核共享L3缓存. 通过MSDN阅读之后,我认为GetLogicalProcessorInformationEx和CACHE_RELATIONSHIP和GROUP_AFFINITY我在寻找数据结构,但在尝试了这些数据结构之后,对我来说似乎毫无用处. 题: 有没有办法让使用C/C++在Windows上共享缓存的逻辑CPU核心数量? (理想情况下不直接使用cpuid) 解: 可以使用GetLogicalProcessorInformationEx和CACHE_RELATIONSHIP和GROUP_AFFINITY数据结构获得共享高速缓存的逻辑CPU核心数. GROUP_AFFINITY.Mask值包含为共享当前缓存(RelationCache)的每个CPU核心设置的一个位.作为大多数具有超线程的Intel CPU的示例,GROUP_AFFINITY.Mask将包含为L2缓存设置的2位和为具有4个物理CPU核心和8个逻辑CPU核心的CPU设置的用于L3缓存的8位. 这是C代码: #include <windows.h> #include <vector> #include <iostream> using namespace std; typedef BOOL (WINAPI *LPFN_GLPI)(LOGICAL_PROCESSOR_RELATIONSHIP,PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX,PDWORD); int main() { LPFN_GLPI glpi = (LPFN_GLPI) GetProcAddress( GetModuleHandle(TEXT("kernel32")),"GetLogicalProcessorInformationEx"); if (!glpi) return 1; DWORD bytes = 0; glpi(RelationAll,&bytes); vector<char> buffer(bytes); SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info; if (!glpi(RelationAll,(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) &buffer[0],&bytes)) return 1; for (size_t i = 0; i < bytes; i += info->Size) { info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) &buffer[i]; if (info->Relationship == RelationCache && (info->Cache.Type == CacheData || info->Cache.Type == CacheUnified)) { cout << "info->Cache.Level: " << (int) info->Cache.Level << endl; cout << "info->Cache.CacheSize: " << (int) info->Cache.CacheSize << endl; cout << "info->Cache.GroupMask.Group: " << info->Cache.GroupMask.Group << endl; cout << "info->Cache.GroupMask.Mask: " << info->Cache.GroupMask.Mask << endl << endl; } } return 0; } 注意事项: 我发现在虚拟机内运行Windows时,上面的代码无法正确检测共享缓存的CPU核心数量,例如:在具有2个虚拟CPU核心的VM上,上面的代码报告每个逻辑CPU核心具有专用的L1,L2和L3缓存. 解决方法
我已经在AppVeyor CI上测试了这个(甚至在发布到stackoverflow之前).这是x64 CPU的输出: info->Cache.Level: 1 info->Cache.CacheSize: 32768 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 1 info->Cache.Level: 1 info->Cache.CacheSize: 32768 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 1 info->Cache.Level: 2 info->Cache.CacheSize: 262144 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 1 info->Cache.Level: 3 info->Cache.CacheSize: 31457280 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 1 info->Cache.Level: 1 info->Cache.CacheSize: 32768 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 2 info->Cache.Level: 1 info->Cache.CacheSize: 32768 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 2 info->Cache.Level: 2 info->Cache.CacheSize: 262144 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 2 info->Cache.Level: 3 info->Cache.CacheSize: 31457280 info->Cache.GroupMask.Group: 0 info->Cache.GroupMask.Mask: 2 根据MSDN文档:“GroupMask.Mask – 指定指定组内零个或多个处理器的亲和性的位图.”基于此文档,我期待L3缓存的不同GroupMask.Mask,但上面的输出不显示这一点.对我来说,GroupMask.Mask中的数据毫无意义! 这是一个产生上述数据的link to the code (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |