Существует ли штраф за кеширование для смешивания двоичных данных и инструкций в непосредственной близости друг от друга? - PullRequest
4 голосов
/ 14 сентября 2009

Я процедурно генерирую 128-байтовые блоки с некоторым установленным n-байтовым заголовком, зарезервированным для функций машинного языка, которые я просто вызываю с помощью встроенной сборки. Они нигде не определены и генерируются во время выполнения на страницах, выделенных в память с доступом для выполнения. Однако я хочу зарезервировать конечные (128 - n) байтов этих блоков для хранения данных для использования в этих функциях из-за возможности сокращения вызовов смещения памяти до 8 бит вместо 32 бит, а также (возможно?) Помощи с кэширование. Тем не менее, я беспокоюсь о кешировании.

Предполагая, что у меня есть процессор, который имеет как кеш (ы) для данных, так и кеш команд, насколько хорошо типичный процессор этого типа справляется с таким форматированием? Будет ли он пытаться загрузить данные после моих инструкций как самих инструкций в кэш инструкций? Может ли это привести к значительному снижению производительности, поскольку процессор пытается выяснить, как справляться с этими ненужными и, возможно, недействительными «инструкциями», учитывая, что они будут перемещаться в непосредственной близости практически для каждого вызова? Будут ли они загружать эти данные в обычные кэши L1 / L2 после того, как я впервые получу доступ к ним в начале сегмента данных, или в этот момент все будет запутано?

Редактировать: Думаю, я должен добавить, что оптимизация сквозной передачи, очевидно, довольно важна. Насколько запутанная или сложная оптимизация не имеет значения в этом случае, просто минимизируя время выполнения кода.

Ответы [ 3 ]

2 голосов
/ 14 сентября 2009

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

Редактировать: Вы делаете это таким образом, чтобы минимизировать размер сгенерированного кода, или вы гарантированно храните данные в кеше, когда у вас есть инструкции, или по какой-то другой причине? Это может быть более сложным, чем вам действительно нужно. Опять же, тесты и профилирование - ваш друг.

1 голос
/ 10 ноября 2009

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

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

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

Если вы убедитесь, что у вас нет магазинов рядом с сегментом кода, все будет в порядке.

1 голос
/ 14 сентября 2009

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

Процессор, вероятно, не будет пытаться декодировать данные в блоках, поскольку у вас, вероятно, есть возвратная или безусловная ветвь в качестве последней инструкции. Любой здравомыслящий процессор не будет извлекать или декодировать инструкции, следующие за этим.

...