Как получить размер кеша L1, L2 и L3 с помощью инструкции CPUID в x86

Я столкнулся с проблемой во время подготовки проекта x86 на ассемблере, целью которого является написание программы, получающей данные L1, код L1, размер кеша L2 и L3.

Я пытался найти что-нибудь в документации Intel и в Интернете, но безуспешно.

ГЛАВНАЯ ПРОБЛЕМА: В случае процессоров AMD достаточно просто установить регистр EAX в значения 80000005h и 80000006h и получить нужные данные из регистров ECX и EDX, но в случае Intel я могу получить эту информацию только для L2.

Что мне нужно сделать, чтобы получить размер кеша L1 и L3 для процессоров Intel?


person Tomek Janiuk    schedule 11.01.2013    source источник
comment
Это для вашего личного проекта или что-то, что вы отправите клиентам? Должен ли он быть независимым от ОС?   -  person Marat Dukhan    schedule 11.01.2013
comment
Это мой личный проект, ничего коммерческого. Я хочу, чтобы он работал в Windows, потому что здесь я могу проверить правильность полученных результатов по сравнению с программой CPU-Z, т.е.   -  person Tomek Janiuk    schedule 12.01.2013
comment
Вы можете использовать функции yepLibrary_GetCpuDataCacheSize и yepLibrary_GetCpuInstructionCacheSize из Yeppp! библиотека (www.yeppp.info). Обратите внимание, что эти API официально не поддерживаются и будут удалены в будущей версии.   -  person Marat Dukhan    schedule 12.01.2013
comment
Если вы хотите получить информацию от ЦП напрямую, прочитайте описание инструкции CPUID в Руководстве по архитектуре Intel. Обратите внимание, что имеется около 5 листьев CPUID, в которых можно указать информацию о размере кэша.   -  person Marat Dukhan    schedule 12.01.2013
comment
CPUID выходит с информацией о кеше: 2 (дескрипторы кеша, см. Руководство по архитектуре Intel для их значений, дополнительно см. руководство Cyrix для их значений на процессорах Cyrix, процессоры AMD имеют 0 дескрипторов кэша), 4 (более новые процессоры Intel), 0x80000005 (AMD- только), 0x80000006 (только для AMD, ожидается информация L2, которая также предоставляется на процессорах Intel), 0x8000001D (только для AMD, используется на процессорах Bulldozer и может противоречить листу 0x80000006)   -  person Marat Dukhan    schedule 12.01.2013
comment
Вау, спасибо! Таким образом, чтобы получить информацию о размере кеша в новых процессорах Intel, мне нужно использовать все функции CPUID для 4, а затем просматривать регистры в поисках значений, указанных в документации, верно? Я думал, что это то же самое, что и в AMD (ну, и, честно говоря, я думаю, намного проще), где вы получаете прямое значение в КБ.   -  person Tomek Janiuk    schedule 12.01.2013


Ответы (3)


Марат Духан в основном дал вам правильный ответ. Для более новых процессоров Intel, то есть выпущенных за последние 5-6 лет, лучшим решением является перечисление листа cpuid 4, что означает, что вы вызываете cpuid несколько раз, сначала с EAX=4 и ECX=0, затем с EAX= 4 и ECX=1 и так далее. Это вернет информацию не только о размерах и типах кеша, но также расскажет вам, как эти кеши связаны с ядрами ЦП и модулями гиперпоточности/SMT. Алгоритм и пример кода приведены по адресу https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/ , а точнее в разделе «Перечисление топологии кэша».

person Fizz    schedule 11.07.2014
comment
Я бы также рекомендовал посмотреть, что glibc или другие реализации libc делают для getconf LEVEL2_CACHE_SIZE. исходная точка glibc показана по адресу: superuser.com/questions/55776/ - person Ciro Santilli 新疆再教育营六四事件ۍ 25.12.2018

Вы можете получить размер кеша ЦП L1, L2 и L3 с помощью инструкции CPUID. Согласно Руководству разработчика программного обеспечения Intel x86, том 2 (справочник по набору инструкций). Вы можете получить информацию о кеше ЦП с помощью CPUID insturciton с EAX, равным 2 или 4. EAX=2 — это более старая версия, и кажется, что новый ЦП не использует ее. Итак, я расскажу о случае с EAX=4.

Его выходной формат:

ЦП4_1

ЦП4_2

Таким образом, вы можете рассчитать размер кеша по следующей формуле:

Размер кэша = (Пути + 1) * (Разделы + 1) * (Line_Size + 1) * (Наборы + 1) или

Размер кэша = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1)

Например, я выполняю команду cpuid -li в своей системе Ubuntu и получаю следующий вывод:

   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)=32 КБ

Размер кэша L3: (11+1)(0+1)(63+1)*(12287+1)=9M

person Dahui    schedule 30.10.2020

Для процессоров Intel:

  • для более новых процессоров вы должны использовать CPUID, eax=0x00000004 (с другими значениями в ECX)

  • для старых процессоров (которые не поддерживают первый вариант) следует использовать CPUID, eax=0x00000002. Это включает в себя наличие таблицы для поиска того, что означают значения. Бывают случаи, когда одно и то же значение означает разные вещи для разных ЦП, и вам нужна дополнительная информация (например, семейство/модель/степпинг ЦП).

Для процессоров VIA; используйте те же методы, что и для Intel (с другими таблицами для всего, что связано с семейством/моделью/степпингом).

Для процессоров AMD:

  • для более новых процессоров вы должны использовать CPUID, eax=0x8000001D (с другими значениями в ECX)

  • для старых процессоров (которые не поддерживают первый вариант) вы должны использовать CPUID, eax=0x80000006 (только для L2 и L3), плюс CPUID, eax=0x80000005 (только для L1).

Для всех остальных случаев (очень старые процессоры Intel/VIA/AMD, процессоры других производителей):

  • используйте поставщика/семейства/модели/степпинга ЦП (из CPUID, eax=0x0000001) с таблицей (или, возможно, 1 таблицу для каждого поставщика), чтобы вы могли искать нужный ЦП в своих таблицах и получать информацию таким образом.

  • если CPUID не поддерживается, есть способы попытаться сузить возможности и определить, что такое ЦП с разумной точностью; но в основном вы должны просто сдаться.

Кроме того; для всех ЦП вы должны просмотреть листы с ошибками, чтобы увидеть, предоставляет ли CPUID неверную информацию; и внедрить обходные пути, чтобы исправить эту неверную информацию.

Обратите внимание, что (в зависимости от того, какой диапазон процессоров вы поддерживаете и какой крутой вы хотите, чтобы ваш код был) может потребоваться несколько месяцев работы только для того, чтобы извлечь достоверную информацию о кешах.

person Brendan    schedule 30.10.2020