获取共享缓存的逻辑 CPU 核心数(L1、L2、L3)

2024-03-02

下面是一些 C++ 代码,它使用以下命令检测 Windows 上 L1、L2 和 L3 CPU 缓存的大小:

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 and CACHE_关系 https://msdn.microsoft.com/en-us/library/windows/desktop/dd405483(v=vs.85).aspx and 组_亲和力 https://msdn.microsoft.com/en-us/library/windows/desktop/dd405500(v=vs.85).aspx我正在寻找的数据结构,但在尝试之后,这些数据结构似乎对我的目的毫无用处。

问题:

有没有办法使用 C/C++ 获取 Windows 上共享缓存的逻辑 CPU 核心的数量? (理想情况下不使用cpuid直接地)


解决方案:

共享缓存的逻辑 CPU 核心数可以通过以下方式获得GetLogicalProcessorInformationExCACHE_关系 https://msdn.microsoft.com/en-us/library/windows/desktop/dd405483(v=vs.85).aspx and 组_亲和力 https://msdn.microsoft.com/en-us/library/windows/desktop/dd405500(v=vs.85).aspx数据结构。这GROUP_AFFINITY.Mask值包含为共享当前缓存的每个 CPU 核心设置的一位(RelationCache)。以大多数具有超线程功能的 Intel CPU 为例GROUP_AFFINITY.Mask对于具有 4 个物理 CPU 核心和 8 个逻辑 CPU 核心的 CPU,将包含为 L2 高速缓存设置的 2 位和为 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, 0, &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;
}

Caveats:

我发现当在虚拟机中运行 Windows 时,上面的代码无法正确检测共享缓存的 CPU 核心数量,例如在具有 2 个虚拟 CPU 核心的 VM 上,上面的代码报告每个逻辑 CPU 核心都有一个私有 L1、L2 和 L3 缓存。


@RbMm:但 CACHE_RELATIONSHIP 包含所需的所有信息。逻辑 CPU 核心数 = Cache->GroupMask.Mask 中设置的位数

我已经在 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

Or:

| Cache Level |    Processor 1     |    Processor 2     |
|-------------|--------------------|--------------------|
| L1          |  32 KB Data        |  32 KB Data        |
|             |  32 KB Instruction |  32 KB Instruction |
|-------------|--------------------|--------------------|
| L2          | 256 KB Unified     | 256 KB Unified     |
|-------------|--------------------|--------------------|
| L3          |  30 MB Unified     |  30 MB Unified     |

根据MSDN文档:

组掩码.掩码- 指定指定组内零个或多个处理器的关联性的位图。

根据此文档,我期待不同的GroupMask.Mask对于 L3 缓存,但上面的输出没有显示这一点。对我来说数据GroupMask.Mask没有意义!

这里有一个链接到代码 https://github.com/kimwalisch/primesieve/blob/4a0591c5903f56fd0f69f777db6ee55d16a12787/src/primesieve/CpuInfo.cpp#L180产生上面的数据

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

获取共享缓存的逻辑 CPU 核心数(L1、L2、L3) 的相关文章

  • 更改 Visual Studio 2015 扩展中项目内的文件 ProjectItem 的内容?

    如何更改文件的内容 ProjectItem在给定的范围内Project 我想用字符串替换它的所有内容 这个问题有解决办法吗 我想做一些改变ProjectItem CS 文件 通过使用 VSIX 包 以及我现在看到的唯一一种执行此操作的方法
  • System.MissingMethodException:找不到方法?

    以前工作的 ASP NET WebForms 应用程序现在抛出此错误 System MissingMethodException 找不到方法 The DoThis方法位于同一个类上 它应该可以工作 我有一个这样的通用处理程序 public
  • Ruby 解释器嵌入到 C 代码中

    我只是尝试书中的一个简单例子 我有一个 sum rb 文件 class Summer def sum max raise Invalid maximum max if max lt 0 max max max 2 end end 还有一个
  • 如何从 Windows 批处理文件中的 ECHO 字符串中去除引号?

    我正在创建一个 Windows 批处理文件 但我必须 ECHO 一个大型复杂字符串 因此我必须在两端加上双引号 问题是引号也被回显到我正在写入的文件中 如何 ECHO 这样的字符串并去掉引号 UPDATE 我花了两天的时间研究这个问题 终于
  • C++ 中的字符串到 LPCWSTR

    我正在尝试从字符串转换为 LPCWSTR 我使用多位 1 例如 LPCWSTR ToLPCWSTR string text LPCWSTR sw LPCWSTR text c str return sw 2 返回中文字符 LPCWSTR T
  • ASP .NET MVC 5 - 客户地址一对一关系

    我在这里查看了论坛 实际上发现了一些类似的问题 但不是相同的问题 类似的解决方案没有给我正确的答案 我正在使用实体框架和代码优先方法来处理 ASP NET MVC 5 我想建立客户 gt 地址一对一关系的模型 我建模的是 客户等级 publ
  • 获取光标相对于控件的位置 - C#

    我想获取鼠标相对于鼠标指针所在控件的位置 这意味着当我将光标置于控件的起点 左上角 时 它应该给出 0 0 我正在使用以下代码 private void panel1 MouseMove object sender MouseEventAr
  • string.empty 和 string[0] == '\0' 之间的区别

    假设我们有一个字符串 std string str some value is assigned 有什么区别str empty and str 0 0 C 11 及更高版本 string variable 0 如果字符串为空 则需要返回空字
  • 是否有更好(更简单)的方法来获取特定域 SID?

    我被指派修改 WinForms 应用程序 主要检查登录用户是否属于特定域 这是我到目前为止所想出的 byte domainSid var directoryContext new DirectoryContext DirectoryCont
  • 输入缓冲区刷新

    考虑下面的代码 include
  • 如何使用 ASP.NET MVC 4.0 DonutOutputCache VaryByCustom 使缓存失效

    我正在为我的 ASP NET 应用程序使用 DevTrends MvcDonutCaching 包 它工作得很好 我目前遇到的一个问题是使我为子操作设置的 VaryByCustom 缓存无效 这是我用于 VaryByCustom 设置的一些
  • C# 列表框 ObservableCollection

    我正在尝试使用 ListBox DataSource ObservableCollection 但是我不知道如何在 OC 更新时让列表框自动更新 我可以在 OC 上挂接 CollectionChanged 事件 但是我需要对列表框执行什么操
  • 为什么long long 2147483647 + 1 = -2147483648? [复制]

    这个问题在这里已经有答案了 为什么这段代码不打印相同的数字 long long a b a 2147483647 1 b 2147483648 printf lld n a printf lld n b 我知道int变量的最大数量是2147
  • 当应用程序未聚焦时监听按键

    我有一个应用程序 C 4 0 WPF 它是隐藏的 可以通过单击系统托盘图标或我创建的其他框架 停靠在左侧和最上面的小框架 来显示 My customer wants to add a new way to display the appli
  • 那里有更好的 DateTime.Parse 吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有一个库 付费或免费 能够处理比 DateTime Parse 使用的更常见的日期时间格式 能够
  • std::regex 转义正则表达式中使用的特殊字符

    我是字符串来创建一个std regex FILE 作为单元测试的一部分 检查一些打印文件名的异常输出 在 Windows 上失败并显示 regex error error escape 表达式包含无效的转义字符或尾随转义 因为 FILE 宏
  • C中的pipe()和fork()

    我需要创建两个子进程 一个子进程需要运行命令 ls al 并将其输出重定向到下一个子进程的输入 而下一个子进程又将对其输入数据运行命令 sort r n k 5 最后 父进程需要读取该数据 已排序的数据 并将其显示在终端中 终端中的最终结果
  • Python 中的 C 指针算术

    我正在尝试将一个简单的 C 程序转换为 Python 但由于我对 C 和 Python 都一无所知 这对我来说很困难 我被 C 指针困住了 有一个函数采用 unsigned long int 指针并将其值添加到 while 循环中的某些变量
  • 任何浮点密集型代码是否会在任何基于 x86 的架构中产生位精确的结果?

    我想知道使用浮点运算的 C 或 C 代码是否会在任何基于 x86 的体系结构中产生位精确的结果 无论代码的复杂性如何 据我所知 自 Intel 8087 以来的任何 x86 架构都使用准备处理 IEEE 754 浮点数的 FPU 单元 并且
  • 为什么没有参数的函数(与实际函数定义相比)可以编译?

    我刚刚看到某人的 C 代码 我很困惑为什么要编译它 有两点我不明白 The 函数原型与实际函数定义相比没有参数 中的参数函数定义没有类型 include

随机推荐