Подтвердить что ты не робот

Программирование с кэшем С++

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

Спасибо!

4b9b3361

Ответ 2

В соответствии с " Что каждый программист должен знать о памяти", Ulrich Drepper вы можете сделать следующее в Linux:

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

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

Это указано в Раздел 6: Какие программы могут выполнять.

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

Интересно, что я написал программу, чтобы сделать это некоторое время назад (в 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/

Ответ 8

Вы можете увидеть эту тему: 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)

Ответ 9

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.

Ответ 11

Есть два случая, которые необходимо различать. Вам нужно знать размеры кэша во время компиляции или во время выполнения?

Определение размера кэша во время компиляции

Для некоторых приложений вы знаете точную архитектуру, на которой будет выполняться ваш код, например, если вы можете скомпилировать код непосредственно на хост-машине. В этом случае упростить поиск размера и жесткое кодирование - это вариант (может быть автоматизирован в системе сборки). На большинстве машин сегодня строка кэша L1 должна быть 64 байта.

Если вы хотите избежать этой сложности или вам нужна поддержка компиляции на неизвестных архитектурах, вы можете использовать функцию С++ 17 std :: hardware_constructive_interference_size в качестве хорошего запасного варианта. Это обеспечит оценку времени компиляции для строки кэша, но следует помнить о ее ограничениях. Обратите внимание, что компилятор не может точно угадать, когда он создает двоичный файл, поскольку размер строки кэша, как правило, зависит от архитектуры.

Определение размера кэша во время выполнения

Во время выполнения у вас есть преимущество в том, что вы знаете точную машину, но вам потребуется код для конкретной платформы, чтобы прочитать информацию из ОС. Хорошей отправной точкой является фрагмент кода из этого ответа, который поддерживает основные платформы (Windows, Linux, MacOS). Аналогичным образом вы также можете прочитать размер кэша L2 во время выполнения.

Я бы посоветовал не пытаться угадать строку кэша, запустив тесты при запуске и измерив, какой из них работает лучше всего. Это может хорошо работать, но также подвержено ошибкам, если процессор используется другими процессами.

Сочетание обоих подходов

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

Ответ 12

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