Concurrency, Synchronization and Consistency. Пост №3. Когерентность.
Пришло время перейти от совсем академической теории в чуть менее академичекую. В двух постах ранее мы рассмотрели как работает компьютер и за счет каких оптимизаций инжнеры разгоняли компьютеры и двигали индустрию вперед.
Хочется остановиться подробнее на внедрении кешей и разобраться с тем как их наличие влияет на то как мы пишем код.
1. Single Core CPU.
В случае когда у нас одноядерный CPU мы получаем более менее понятную картину. Изменение в основной памяти всегда проходят через единственное ядро и его кеши, поэтому ситуации нарушения согласованности маловероятна.
2. Multi Core CPU.
Вот тут уже интереснее. У нас появляется N ядер и у каждого есть свой кеш. Ядра обеспечивают самый настоящий параллелизм и выполняют работу одновременно. При этом они взаимодействуют с общей памятью, изменяют ее, хранят в своих кешах информацию, которая потенциально может быть изменена другим ядром.
Как обеспечить согласованность в таком сценарии?
- Отказаться от идеи отдельных кешей на ядра. Сделать кеш общим на все ядра (бутылочным горлышком). Грустить что кучу времени уходит на синхронизацию ядер
- Научить процессор синхронизировать кеши ядер между собой в более менее детерминированном и очевидном порядке.
И тут на сцену выходит когерентность. Кэш называется когерентным, если выполняются следующие условия:
- информирование о записи: изменение данных в любом из кэшей должно быть распространено на другие копии этих данных в соседних кэшах;
- сериализация транзакций: операции чтения и записи в одну и ту же ячейку памяти должны быть видимы для всех процессоров в одинаковом порядке.
В общем, очень важное свойство, без него нам бы пришлось писать только однопоточные программы, чтобы гарантировать хоть какую то согласованность и корректность. Но в таком случае бенефиты от наличия нескольких ядер были бы нам недоступны 🤪
К слову, можно заметить что определение когеретного кеша почти идентично определению Sequential Consistency модели памяти Лэмпорта. Но как и с честной когерентностью добиться Sequential Consistencу трудно не жертвуя производительностью. В реальном мире всегда есть места допущениям и послаблениям. CPU не исключение. Рекомендую посмотреть мои прошлые посты про модели памяти. Эти понятия прочно связаны между собой. Оба направлены на то чтобы детерминировать поведение железа и упростить нам как инженерам программирование конкурентных программ.
Для достижения когеретности инженеры и ученые придумали специальные алгоритмы - протоколы когерентности. О них поговорим попозже.
Промежуточный вывод
Согласованность и производительность идут рука об руку везде. Сегодня мы убедились в этом еще и на уровне CPU. Создание копии данных для ускорения работы - очень эффективная практика, главное не забывать о том как гарантировать согласованность данных / состояния для других участников системы. Эта проблема актуальна везде, хоть на уровне железки хоть в распределенной системе.
В общем, автор цитаты про две проблемы программирования был прав: инвалидация кэша действительно сложная проблема, пронизывающая весь Computer Science.
Как всегда, спасибо за то что прочитали, пишите комментарии если допустил неточность, ставьте реакции😊
Связанные посты:
- Что такое модель памяти? Sequential Consistency.
- Модель памяти X86
- Модель памяти ARM
- Выводы по моделям памяти + материалы
Post #393
1.74K

- 👍 14
- 🔥 6
- ❤ 1