Можно ли выделить в пользовательском пространстве не кешируемый блок памяти в Linux? - PullRequest
7 голосов
/ 20 мая 2009

В моем приложении есть куча буферов (от 25 до 30), которые достаточно велики (.5 МБ) и доступны одновременно. Что еще хуже, данные в них обычно читаются только один раз и часто обновляются (например, 30 раз в секунду). Вроде идеальный шторм неоптимального использования кэша.

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

Итак, есть ли способ получить блок памяти, помеченный как не кешируемый в Linux?

Ответы [ 4 ]

9 голосов
/ 20 мая 2009

Как избежать загрязнения кэшей данными, подобными этим, описано в Что должен знать каждый программист о памяти (PDF) - Это написано с точки зрения разработки Red Hat, которая идеально подходит для вас. Тем не менее, большинство из них кроссплатформенные.

То, что вы хотите, называется «Временный доступ», и попросите процессор ожидать, что значение, которое вы сейчас читаете, больше не понадобится какое-то время. Затем процессор избегает кэширования этого значения.

См. Стр. 49 PDF-файла, на который я ссылался выше. Он использует встроенную информацию Intel для потоковой передачи по кешу.

На стороне чтения, процессоры, пока в последнее время не было поддержки, кроме слабые подсказки, использующие невременный доступ (NTA) инструкции предварительной выборки. Есть нет эквивалента комбинированию записи для читает, что особенно плохо для некэшируемая память, такая как отображенный в память ввод / вывод. Intel, с Расширения SSE4.1, представленный NTA грузы. Они реализованы с использованием небольшое количество потоковой загрузки буферы; каждый буфер содержит кеш линия. Первая инструкция movntdqa для данной строки кэша загрузит строка кэша в буфер, возможно замена другой строки кэша. Последующие 16-байтовые выравниваемые доступы к будет обслуживаться та же строка кэша из буфера загрузки при небольших затратах. Если нет других причин делать Итак, строка кеша не будет загружена в кэш, что позволяет загрузка больших объемов памяти без загрязнения кешей. Компилятор обеспечивает внутреннюю эта инструкция:

#include <smmintrin.h>
__m128i _mm_stream_load_si128 (__m128i *p); 

Это свойство должно использоваться несколько раз, с адресами 16-байтовые блоки передаются как параметр, пока каждая строка кэша не будет читать. Только тогда должен следующий кеш линия будет начата. Так как есть несколько потоковые буферы чтения это может быть можно читать из двух памяти места сразу

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

2 голосов
/ 20 мая 2009

Часто обновляемые данные на самом деле являются идеальным приложением кеша. Как уже упоминалось в jdt, современные кэши ЦП довольно велики, и 0.5 МБ вполне могут поместиться в кэш. Что еще более важно, однако, чтение-изменение-запись в не кэшированную память ОЧЕНЬ медленное - начальное чтение должно блокироваться в памяти, затем операция записи ТАКЖЕ должна блокироваться в памяти для фиксации. И просто чтобы добавить оскорбление ране, ЦП может реализовать память без кеша, загружая данные в кеш, а затем немедленно аннулируя строку кеша, тем самым оставляя вас в положении, которое гарантированно будет хуже, чем раньше.

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

С другой, более практичной отметки, если вы выполняете 30 RMW в секунду, в худшем случае это будет порядка 1920 байтов площади кеша. Это всего лишь 1/16 от размера L1 современного процессора Core 2 и, вероятно, будет потеряно из-за общего шума системы. Так что не волнуйтесь об этом слишком много:)

Тем не менее, если под «одновременным доступом» вы подразумеваете «одновременный доступ к нескольким потокам», будьте осторожны с пересылкой строк кэша между процессорами. Этому не поможет не кешированная ОЗУ - во всяком случае, это будет хуже, поскольку данные должны будут каждый раз возвращаться в физическую ОЗУ, а не проходить через более быструю шину между процессорами - и это единственный путь чтобы избежать этого как проблемы, нужно минимизировать частоту доступа к общим данным. Подробнее об этом см. http://www.ddj.com/hpc-high-performance-computing/217500206

1 голос
/ 20 мая 2009

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

0 голосов
/ 20 мая 2009

На некоторых архитектурах процессора существуют специальные инструкции, которые можно использовать для пометки определенных строк кэша как отключенных. Однако они обычно зависят от архитектуры и зависят от некоторых инструкций по сборке. Итак, я бы посоветовал вам обратиться к документации по архитектуре процессора и выяснить, как это сделать в сборке. Затем вы можете использовать встроенную сборку с GCC, чтобы активировать его. Хотя производительность может быть отстойной.

PS: Если вы можете, вы можете подумать о другом способе обработки данных?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...