2009-12-17 4 views
53

есть ли способ в C++ определить размер кэша процессора? У меня есть алгоритм, который обрабатывает много данных, и я хотел бы разбить эти данные на куски, чтобы они вписывались в кеш. Это возможно? Можете ли вы дать мне другие советы по программированию с учетом размера кеша (особенно в отношении обработки многопоточных/многоядерных данных)?Программирование в кэше C++

Спасибо!

+0

Мои эксперименты с заблокированными алгоритмами показывают мне, что это мешает оптимизации GCC. Оптимальный размер блока не всегда равен размеру кеша l1. Я предлагаю сделать тесты с разными размерами блоков. –

ответ

4

прочитайте cpuid процессора (x86), а затем определите размер кэша с помощью таблицы поиска. Таблица должна быть заполнена размерами кэша, которые производитель процессора публикует в своих руководствах по программированию.

+2

эй, это звучит интересно! есть ли такие предварительно подготовленные таблицы, доступные в Интернете? – Mat

+0

http://www.x86-guide.com/ru/index.html Возможно, есть такие таблицы. Однако проблема с этим заключается в том, что вы делаете с неопознанным процессором, и хотите ли вы обновлять программу каждый раз, когда выйдет новый процессор? –

+1

Разве это решение не сломается, если ваша программа используется на процессоре, выпущенном после выпуска вашей программы? –

11

C++ сам по себе не «заботится» о кэшах CPU, поэтому нет поддержки запросов к размерам кеша, встроенных в язык. Если вы разрабатываете для Windows, то есть GetLogicalProcessorInformation()-function, который можно использовать для запроса информации о кэшах CPU.

+0

? Конечно, C++ заботится о кэшировании CPU. Не забота об этом означала бы быть примерно в 100-1000 раз медленнее, чем вы могли бы быть в горячих путях. И никакая поддержка для этого не встроена в язык, потому что номер один не все системы поддерживают его, а номер два, зная, что размер кэша в основном совершенно не имеет значения, не имея полного контроля над стратегиями распределения памяти. C++ дает вам много, но недостаточно, чтобы играть в «cache daddy». – thesaint

+0

. Если что-нибудь, ваш компилятор C/C++ ** заботится о кешировании.Вы можете использовать флаг '-march' в GCC, чтобы он мог оптимизировать определенный процессор. Существует также следующее: http://en.cppreference.com/w/cpp/atomic/memory_order – snowflake

4

В зависимости от того, что вы пытаетесь сделать, вы также можете оставить его в какой-либо библиотеке. Поскольку вы упоминаете многоядерную обработку, вы можете взглянуть на Intel Threading Building Blocks.

TBB включает в себя распределители памяти с кэшем. В частности, проверьте cache_aligned_allocator (в справочной документации я не смог найти прямую ссылку).

-1

Кэш, как правило, поступает правильно. Единственное реальное беспокойство для обычного программиста - это ложное совместное использование, и вы не можете позаботиться об этом во время выполнения, потому что для этого требуются директивы компилятора.

+2

Не затрагивает вопрос. – JBentley

15

Согласно «What every programmer should know about memory», Ульриха Drepper вы можете сделать следующее на Linux:

После того, как мы имеем формулу для памяти требования, мы можем сравнить его с размером кэша. Как упоминалось ранее, кэш может использоваться совместно с другими ядрами . В настоящее время {There определенно скоро будет лучший способ!} Единственный способ получить правильную информацию без жесткого кодирования. Знание через файловую систему/sys . В таблице 5.2 мы видели то, что ядро ​​публикует около аппаратных средств. Программа должна найти каталог:

/sys/devices/system/cpu/cpu*/cache 

Это указано в Section 6: What Programmers Can Do.

Он также описывает короткий тест прямо на рисунке 6.5, который может использоваться для определения размера кеша L1D, если вы не можете получить его из ОС.

Есть еще одна вещь, с которой я столкнулся в своей статье: sysconf(_SC_LEVEL2_CACHE_SIZE) - системный вызов в Linux, который должен вернуть размер кэша L2, хотя он, похоже, не документирован.

8

Предоложить большой массив. Затем последовательно обращайтесь к каждому элементу и записывайте время для каждого доступа. В идеале произойдет переход к времени доступа при пропуске кеша. Затем вы можете вычислить свой кеш L1. Возможно, это не сработает, но стоит попробовать.

4

Интересно, что я написал программу, чтобы сделать это некоторое время назад (в C хотя, но я уверен, что это будет легко включить в код C++).

http://github.com/wowus/CacheLineDetection/blob/master/Cache%20Line%20Detection/cache.c

Функция get_cache_line является интересным, который возвращает местоположение прямо перед самым большим шипом в синхронизации данных массива получает доступ. Он правильно догадался на моей машине! Если что-нибудь еще, это может помочь вам сделать свой собственный.

Он основан от этой статьи, которая первоначально пробудили мой интерес: http://igoro.com/archive/gallery-of-processor-cache-effects/

4

Вы можете видеть эту тему: http://software.intel.com/en-us/forums/topic/296674

Короткий ответ в этом другом потоке:

На современном IA-32, размер строки кеша - 64. Значение 128 - это наследие микроархитектуры Intel Netburst (например, Intel Pentium D), где 64-байтовые линии соединены в 128-байтовые сектора. Когда выбирается строка в секторе, аппаратное обеспечение автоматически выбирает другую линию в этом секторе. Таким образом, с точки зрения ложного обмена эффективный размер линии составляет 128 байтов на процессорах Netburst. (http://software.intel.com/en-us/forums/topic/292721)

1

IIRC, GCC имеет подсказку __builtin_prefetch.

http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Other-Builtins.html

имеет отличный раздел по этому вопросу. В основном, это предполагает:

__builtin_prefetch (&array[i + LookAhead], rw, locality); 

, где RW является 0 (подготовить для чтения) или 1 (подготовить для записи) значения, и местонахождения использует номер 0-3, где ноль нет местонахождения , и 3 - очень сильная локальность.

Оба варианта являются необязательными. LookAhead будет количеством элементов, которые нужно смотреть вперед. Если доступ к памяти составлял 100 циклов, а развернутые циклы были разделены на два цикла, LookAhead может быть установлен на 50 или 51.