7

我在准备一个汇编程序 x86 项目时遇到了一个问题,该项目的主题是编写一个获取 L1 数据、L1 代码、L2 和 L3 缓存大小的程序。

我试图在英特尔文档和互联网上找到一些东西,但我失败了。

主要问题是:对于 AMD 处理器,只需将 EAX 寄存器设置为 80000005h 和 80000006h 值并从 ECX 和 EDX 寄存器中获取所需的数据,但对于英特尔,我只能为 L2 获取此信息。

我应该怎么做才能获得英特尔处理器的 L1 和 L3 缓存大小?

4

3 回答 3

4

Marat Dukhan 基本上给了你正确的答案。对于较新的英特尔处理器,即过去 5-6 年制造的处理器,最好的解决方案是枚举 cpuid 叶 4,这意味着您调用 cpuid 几次,首先使用 EAX=4 和 ECX=0,然后使用 EAX= 4和ECX = 1等等。这不仅会返回有关缓存大小和类型的信息,还会告诉您这些缓存如何连接到 CPU 内核和超线程/SMT 单元。算法和示例代码在https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/中给出,更具体地说,在标题为“缓存拓扑枚举”的部分中。

于 2014-07-11T14:37:27.320 回答
1

您可以使用 CPUID 指令获取 CPU L1、L2 和 L3 缓存大小。根据 Intel x86 Software Developer's Manual Volume 2 (Instruction Set Reference)。您可以通过 EAX 等于 2 或 4 的 CPUID insturciton 获取 CPU 缓存信息。EAX=2 是旧版本,似乎较新的 CPU 不使用它。所以我将介绍 EAX=4 的情况。

其输出格式为:

CPUID4_1

CPUID4_2

因此,您可以使用以下公式计算缓存大小:

缓存大小 = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1) 或

缓存大小 = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1)

例如,我在我的 ubuntu 系统中执行“cpuid -li”指令,得到以下输出:

   deterministic cache parameters (4):
  --- cache 0 ---
  cache type                           = data cache (1)
  cache level                          = 0x1 (1)
  self-initializing cache level        = true
  fully associative cache              = false
  extra threads sharing this cache     = 0x1 (1)
  extra processor cores on this die    = 0x7 (7)
  system coherency line size           = 0x3f (63)
  physical line partitions             = 0x0 (0)
  ways of associativity                = 0x7 (7)
  ways of associativity                = 0x0 (0)
  WBINVD/INVD behavior on lower caches = false
  inclusive to lower caches            = false
  complex cache indexing               = false
  number of sets - 1 (s)               = 63
  --- cache 1 ---
  cache type                           = instruction cache (2)
  cache level                          = 0x1 (1)
  self-initializing cache level        = true
  fully associative cache              = false
  extra threads sharing this cache     = 0x1 (1)
  extra processor cores on this die    = 0x7 (7)
  system coherency line size           = 0x3f (63)
  physical line partitions             = 0x0 (0)
  ways of associativity                = 0x7 (7)
  ways of associativity                = 0x0 (0)
  WBINVD/INVD behavior on lower caches = false
  inclusive to lower caches            = false
  complex cache indexing               = false
  number of sets - 1 (s)               = 63
  --- cache 2 ---
  cache type                           = unified cache (3)
  cache level                          = 0x2 (2)
  self-initializing cache level        = true
  fully associative cache              = false
  extra threads sharing this cache     = 0x1 (1)
  **extra processor cores on this die    = 0x7 (7)
  system coherency line size           = 0x3f (63)
  physical line partitions             = 0x0 (0)**
  ways of associativity                = 0x3 (3)
  ways of associativity                = 0x0 (0)
  WBINVD/INVD behavior on lower caches = false
  inclusive to lower caches            = false
  complex cache indexing               = false
  number of sets - 1 (s)               = 1023
  --- cache 3 ---
  cache type                           = unified cache (3)
  cache level                          = 0x3 (3)
  self-initializing cache level        = true
  fully associative cache              = false
  extra threads sharing this cache     = 0xf (15)
  extra processor cores on this die    = 0x7 (7)
  system coherency line size           = 0x3f (63)
  physical line partitions             = 0x0 (0)
  ways of associativity                = 0xb (11)
  ways of associativity                = 0x6 (6)
  WBINVD/INVD behavior on lower caches = false
  inclusive to lower caches            = true
  complex cache indexing               = true
  number of sets - 1 (s)               = 12287

L1数据缓存大小为:(7+1) (0+1) (63+1)*(63+1)=32K

L3缓存大小为:(11+1) (0+1) (63+1)*(12287+1)=9M

于 2020-10-30T11:40:32.653 回答
1

对于英特尔 CPU:

  • 对于较新的 CPU,您应该使用“CPUID, eax=0x00000004”(ECX 中的值不同)

  • 对于较旧的 CPU(不支持第一个选项),您应该使用“CPUID,eax=0x00000002”。这涉及有一个表格来查找这些值的含义。在某些情况下,相同的值对不同的 CPU 意味着不同的东西,您需要额外的信息(例如 CPU 系列/型号/步进)。

对于威盛 CPU;使用与英特尔相同的方法(对于涉及“系列/型号/步进”的任何内容,使用不同的表格)。

对于 AMD CPU:

  • 对于较新的 CPU,您应该使用“CPUID,eax=0x8000001D”(ECX 中的值不同)

  • 对于较旧的 CPU(不支持第一个选项),您应该使用“CPUID, eax=0x80000006”(仅适用于 L2 和 L3),加上“CPUID, eax=0x80000005”(仅适用于 L1)。

对于所有其他情况(非常旧的 Intel/VIA/AMD CPU,其他制造商的 CPU):

  • 使用 CPU “vendor/family/model/stepping”(来自“CPUID,eax=0x0000001”)和一个表(或者每个供应商可能 1 个表),这样您就可以在表中搜索正确的 CPU 并获取以下信息方法。

  • 如果CPUID不支持,则可以尝试缩小可能性并以合理的准确度确定 CPU 是什么;但大多数情况下你应该放弃。

此外; 对于所有 CPU,您应该浏览勘误表以查看 CPUID 是否提供了错误信息;并实施变通方法来纠正错误信息。

请注意(取决于您支持的 CPU 范围以及您希望您的代码有多棒)可能需要几个月的工作才能提取有关缓存的可靠信息。

于 2020-10-30T14:15:39.370 回答