В продолжение постов об использовании железа с х86 архитектурой в системах реального времени. Там я вкраце описал, насколько x86 удовлетворяют realtime требованиям, и что этому мешает.
Небольшое лирическое отступление. Системы реального времени — один из наименее известных двигателей компьютерного прогресса. Например, первый портативный компьютер был создан благодаря им. Сейчас почему-то считается, что первым серийным портативным компьютером был Osborn. На самом деле устройство на картинке выше было создано в Сименсе как cредство управления и программирования промышленной автоматизации за два года до Osborn. Переносные компьютеры этого семейства (Siemens Simatic) выпускаются и сейчас, хотя, конечно, железо много раз менялось.
Но перейдем к делу. В этом топике я подробнее остановлюсь на одном из факторов, который мешает предсказуемости времени выполнения realtime кода. Под катом будет не длинный, но нудноватый текст.
Эффективное использование кэша полезно большинству ворклоадов, не только для realtime. Очень жизненный пример — на одном ядре работает код, который просыпается раз в миллисекунду, опрашивает датчики, исполняет PLC код, управляет какой-то железкой. Одновременно на другом ядре работает код ГУИ, который все это отображает на мониторе и позволяет оператору иногда вмешиваться. Современный ГУИ достаточно «толстый», и с удовольствием использует весь доступный кэш, который, кстати, общий с первым ядром. Так что когда риалтайм код просыпается, никаких своих данных в общем кэше он не найдет — придется тащить заново из памяти, тратя десятки или сотни микросекунд.
Вообще, архитектура х86 предоставляет не очень много возможностей программного управления работой кэша. Перечислю все эти способы, как раз хватит пальцев на одной руке:
1. PREFETCHx — вытащить линию из памяти в кэш заренее
2. CFLUSH, WBINV(Очень «злая» команда, кстати) — «обнулить» линию или весь кэш
3. non temporal COVNTDQ/MOVNTDQA/MOVNTPS, ordering control (L/S/MFENCE) — управление кэшируемостью некоторых операций с данными
4. Всякие косвенные способы. Здесь я имею в виду хитрые способы хранения и доступа к данным, например, более дружественные префетчерам
5. Прямая запись в кэш через ДМА. Эта не очень популярная фича актуальна для производителей периферии.
Можно кэш вообще отключить, но это как-то слишком экстремально.
Как видите, среди этих способов нет ничего похожего, например, на cache lockdown — фичу, которая есть в ARM, или аналогичные возможности MIPS. Зарезервировать кусочек кэша бывает полезно дла разработчиков realtime кода, например, в случае, описанном выше. Не исключено, что когда-нибудь и в х86 появится нечто похожее, хотя это и противоречит идеологии прозрачной работы памяти. Но пока можно воспользоваться паллиативом.
На картинке видно, что у физического адреса и адреса в кэше есть общие 5 бит. Ну, так получилось — просто повезло. Это позволяет «покрасить» физическую память постранично в 32 цвета. Зачем? Ядро ОС при создании адресного пространства для приложения тогда может отдавать ему виртуальную память только одного цвета. Если давать основным потребителям кэша память разных цветов, то их данные не смогут вытеснять друг друга из кэша.
В примере, приведенном выше очевидно, что если выделять обоим задачам память разного цвета, проблема будет решена. ГУИ достанется меньше кэша, но очень вероятно, что оператор никаких тормозов не заметит. Есть, конечно, один большой недостаток — речь может идти только о виртуальной памяти, и если что-то в ядре тоже хочет много кэша, то ничто не сможет ему помешать.
Этот же метод используется в ядрах Windows и FreeBSD, чтобы более равномерно распределять память в по сетам в ассоциативном кэше. При низкой ассоциативности кэша это достаточно важно для того, чтобы никакой его кусочек не пропал зря. Чтобы использовать этот подход, от программиста ничего не требуется — все делает ОС. Но ни в одной production ОС сейчас не используется раскраска кэша для разделения данных процессов, есть только неофициальные патчи.
Ну и кстати всем разработчикам realtime на x86 желаю не забывать отключать C-states и Speedstep.
Кстати, если кто знает русскую замену всяким англицизмам, которые я использовал в топике — пожалуйста, дайте знать в комментариях, а я поправлю в тексте.
Небольшое лирическое отступление. Системы реального времени — один из наименее известных двигателей компьютерного прогресса. Например, первый портативный компьютер был создан благодаря им. Сейчас почему-то считается, что первым серийным портативным компьютером был Osborn. На самом деле устройство на картинке выше было создано в Сименсе как cредство управления и программирования промышленной автоматизации за два года до Osborn. Переносные компьютеры этого семейства (Siemens Simatic) выпускаются и сейчас, хотя, конечно, железо много раз менялось.
Но перейдем к делу. В этом топике я подробнее остановлюсь на одном из факторов, который мешает предсказуемости времени выполнения realtime кода. Под катом будет не длинный, но нудноватый текст.
Эффективное использование кэша полезно большинству ворклоадов, не только для realtime. Очень жизненный пример — на одном ядре работает код, который просыпается раз в миллисекунду, опрашивает датчики, исполняет PLC код, управляет какой-то железкой. Одновременно на другом ядре работает код ГУИ, который все это отображает на мониторе и позволяет оператору иногда вмешиваться. Современный ГУИ достаточно «толстый», и с удовольствием использует весь доступный кэш, который, кстати, общий с первым ядром. Так что когда риалтайм код просыпается, никаких своих данных в общем кэше он не найдет — придется тащить заново из памяти, тратя десятки или сотни микросекунд.
Вообще, архитектура х86 предоставляет не очень много возможностей программного управления работой кэша. Перечислю все эти способы, как раз хватит пальцев на одной руке:
1. PREFETCHx — вытащить линию из памяти в кэш заренее
2. CFLUSH, WBINV(Очень «злая» команда, кстати) — «обнулить» линию или весь кэш
3. non temporal COVNTDQ/MOVNTDQA/MOVNTPS, ordering control (L/S/MFENCE) — управление кэшируемостью некоторых операций с данными
4. Всякие косвенные способы. Здесь я имею в виду хитрые способы хранения и доступа к данным, например, более дружественные префетчерам
5. Прямая запись в кэш через ДМА. Эта не очень популярная фича актуальна для производителей периферии.
Можно кэш вообще отключить, но это как-то слишком экстремально.
Как видите, среди этих способов нет ничего похожего, например, на cache lockdown — фичу, которая есть в ARM, или аналогичные возможности MIPS. Зарезервировать кусочек кэша бывает полезно дла разработчиков realtime кода, например, в случае, описанном выше. Не исключено, что когда-нибудь и в х86 появится нечто похожее, хотя это и противоречит идеологии прозрачной работы памяти. Но пока можно воспользоваться паллиативом.
На картинке видно, что у физического адреса и адреса в кэше есть общие 5 бит. Ну, так получилось — просто повезло. Это позволяет «покрасить» физическую память постранично в 32 цвета. Зачем? Ядро ОС при создании адресного пространства для приложения тогда может отдавать ему виртуальную память только одного цвета. Если давать основным потребителям кэша память разных цветов, то их данные не смогут вытеснять друг друга из кэша.
В примере, приведенном выше очевидно, что если выделять обоим задачам память разного цвета, проблема будет решена. ГУИ достанется меньше кэша, но очень вероятно, что оператор никаких тормозов не заметит. Есть, конечно, один большой недостаток — речь может идти только о виртуальной памяти, и если что-то в ядре тоже хочет много кэша, то ничто не сможет ему помешать.
Этот же метод используется в ядрах Windows и FreeBSD, чтобы более равномерно распределять память в по сетам в ассоциативном кэше. При низкой ассоциативности кэша это достаточно важно для того, чтобы никакой его кусочек не пропал зря. Чтобы использовать этот подход, от программиста ничего не требуется — все делает ОС. Но ни в одной production ОС сейчас не используется раскраска кэша для разделения данных процессов, есть только неофициальные патчи.
Ну и кстати всем разработчикам realtime на x86 желаю не забывать отключать C-states и Speedstep.
Кстати, если кто знает русскую замену всяким англицизмам, которые я использовал в топике — пожалуйста, дайте знать в комментариях, а я поправлю в тексте.