Програмно отримати розмір рядка кеша?


177

Всі платформи вітаються, будь ласка, вкажіть платформу для своєї відповіді.

Аналогічне запитання: як програмно отримати розмір сторінки кешу CPU у C ++?


8
FWIW, C ++ 17 забезпечить час компіляції наближення цього: stackoverflow.com/questions/39680206 / ...
GManNickG

окрім C / C ++, якщо ви не заперечуєте з використанням збірки для отримання такої інформації, ви можете подивитися (розширюючи інформацію з відповіді negamartin) на вихідний код SDL_GetCPUCacheLineSizeфункції SDL2 , а потім подивіться, cpuid macroякий має вихідний код збірки для кожного моделі процесора. Ви можете подивитися на imgur.com/a/KP57m6s або безпосередньо заглянути до джерела.
haxpor

Відповіді:


186

У Linux (з досить недавнім ядром) ви можете отримати цю інформацію з / sys:

/sys/devices/system/cpu/cpu0/cache/

Цей каталог має підкаталог для кожного рівня кешу. Кожен із цих каталогів містить такі файли:

coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity

Це дає вам більше інформації про кеш, то ви коли-небудь сподіваєтесь знати, включаючи розмір кеш-лінії ( coherency_line_size), а також те, які процесори поділяють цей кеш. Це дуже корисно, якщо ви виконуєте багатопотокове програмування із спільними даними (ви отримаєте кращі результати, якщо дані обміну потоками також діляться кешем).


4
який із файлів містить розмір рядка кеша? Я припускаю, що когерентність_ліній_розмір? чи фізична_лінія_частина?
paxos1977

27
coherency_line_size
spinfire

6
Щоб бути впевненим: це в байтах, так?
Якуб М.

6
Так, coherency_line_size знаходиться в байтах.
Джон Цвінк

4
@android: Я використовую машину fedora-18 x64 з процесором core-i5. cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_sizeповертається 64в мою систему. Те саме для папок index1,2,3 також.
Абід Рахман К

141

У Linux дивіться на sysconf (3).

sysconf (_SC_LEVEL1_DCACHE_LINESIZE)

Ви також можете отримати його з командного рядка за допомогою getconf:

$ getconf LEVEL1_DCACHE_LINESIZE
64

4
прості відповіді - просто найкращі!
Френк.

3
@warunapww Це в байтах.
Маартен Бамеліс

нарешті! сподіваюся, що більше хлопців побачать цю відповідь для економії часу.
elinx

118

Я працював над деякими матеріалами рядка кешу і мені потрібно було написати функцію крос-платформи. Я поклав це на репортаж github за адресою https://github.com/NickStrupat/CacheLineSize , або ви можете просто використати джерело нижче. Не соромтеся робити все, що завгодно.

#ifndef GET_CACHE_LINE_SIZE_H_INCLUDED
#define GET_CACHE_LINE_SIZE_H_INCLUDED

// Author: Nick Strupat
// Date: October 29, 2010
// Returns the cache line size (in bytes) of the processor, or 0 on failure

#include <stddef.h>
size_t cache_line_size();

#if defined(__APPLE__)

#include <sys/sysctl.h>
size_t cache_line_size() {
    size_t line_size = 0;
    size_t sizeof_line_size = sizeof(line_size);
    sysctlbyname("hw.cachelinesize", &line_size, &sizeof_line_size, 0, 0);
    return line_size;
}

#elif defined(_WIN32)

#include <stdlib.h>
#include <windows.h>
size_t cache_line_size() {
    size_t line_size = 0;
    DWORD buffer_size = 0;
    DWORD i = 0;
    SYSTEM_LOGICAL_PROCESSOR_INFORMATION * buffer = 0;

    GetLogicalProcessorInformation(0, &buffer_size);
    buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)malloc(buffer_size);
    GetLogicalProcessorInformation(&buffer[0], &buffer_size);

    for (i = 0; i != buffer_size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
        if (buffer[i].Relationship == RelationCache && buffer[i].Cache.Level == 1) {
            line_size = buffer[i].Cache.LineSize;
            break;
        }
    }

    free(buffer);
    return line_size;
}

#elif defined(linux)

#include <stdio.h>
size_t cache_line_size() {
    FILE * p = 0;
    p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
    unsigned int i = 0;
    if (p) {
        fscanf(p, "%d", &i);
        fclose(p);
    }
    return i;
}

#else
#error Unrecognized platform
#endif

#endif

15
Можливо, краще використовувати sysconf (_SC_LEVEL1_DCACHE_LINESIZE) для Linux.
Метт

@Matt чому? Просто цікаво :-).
користувач35915

31

На x86 ви можете використовувати інструкцію CPUID з функцією 2 для визначення різних властивостей кешу та TLB. Розбір результатів функції 2 є дещо складним, тому я посилаюсь на розділ 3.1.3 Ідентифікації процесора Intel та Інструкції CPUID (PDF).

Щоб отримати ці дані з коду C / C ++, вам потрібно буде використовувати вбудовану збірку, властивості компілятора або викликати функцію зовнішньої збірки для виконання інструкції CPUID.


хтось знає про те, як це зробити з іншими процесорами із вбудованим кешем?
paxos1977

3
@ceretullis: Errr ... x86 має вбудований кеш. Які "інші процесори" ви спеціально шукаєте? Те, що ви просите, залежить від платформи.
Біллі ONeal

9

Якщо ви використовуєте SDL2, ви можете використовувати цю функцію:

int SDL_GetCPUCacheLineSize(void);

Який повертає розмір рядка кешу L1 у байтах.

У моїй машині x86_64 працює цей фрагмент коду:

printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize());

Виробляє CacheLineSize = 64

Я знаю, що я трохи спізнююсь, але просто додаю інформацію для майбутніх відвідувачів. В документації SDL на даний момент сказано, що повернене число знаходиться в КБ, але насправді воно знаходиться в байтах.


О, це справді корисно. Я збираюся написати якусь гру в SDL2, так що це буде дуже корисно
Ніколас Хамфрі

7

На платформі Windows:

від http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx

Функція GetLogicalProcessorInformation дасть вам характеристики логічних процесорів, якими користується система. Ви можете пройти SYSTEM_LOGICAL_PROCESSOR_INFORMATION, повернуту функцією, яка шукає записи типу RelationCache. Кожен такий запис містить ProcessorMask, який повідомляє вам, до якого процесора (-ів) застосовується запис, а в CACHE_DESCRIPTOR він повідомляє, який тип кешу описується і наскільки велика лінія кешу для цього кешу.


4

ARMv6 і вище має C0або Реєстр типів кешу. Однак його доступно лише в пільговому режимі.

Наприклад, з технічного довідника Cortex ™ -A8 :

Мета реєстру типів кешу полягає у визначенні мінімальної довжини рядка кешу інструкцій та даних у байтах, щоб дозволити недійсність діапазону адрес.

Реєстр типів кешу:

  • регістр лише для читання
  • доступний лише в пільгових режимах.

Вміст реєстру типів кешу залежить від конкретної реалізації. На малюнку 3-2 показано бітове розташування реєстру типів кешу ...


Не припускайте, що у процесора ARM є кеш-пам'ять (мабуть, деякі можна налаштувати без одного). Стандартний спосіб визначити це через C0. З озброєння ARM , сторінка B6-6:

З ARMv6, реєстр кешових типів керування системою управління системою - це доручений спосіб визначення кешів L1, див. Реєстр типів кешу на сторінці B6-14. Це також рекомендований метод для більш ранніх варіантів архітектури. Крім того, Враження щодо додаткових рівнів кешу на сторінці B6-12 описує вказівки щодо архітектури підтримки кешу рівня 2.


3

Ви також можете спробувати це зробити програмно, вимірявши деякий час. Очевидно, це не завжди буде настільки точним, як cpuid та подібні, але він більш портативний. ATLAS робить це на етапі конфігурації, ви можете подивитися на це:

http://math-atlas.sourceforge.net/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.