Введение
В информатике и инженерии транзакционная память стремится упростить параллельное программирование, позволяя группе инструкций загрузки и сохранения выполняться атомарно. Это механизм управления параллелизмом, аналогичный транзакциям в базах данных, предназначенный для контроля доступа к разделяемой памяти в параллельных вычислениях. Системы транзакционной памяти предоставляют высокоуровневую абстракцию как альтернативу синхронизации потоков на низком уровне. Эта абстракция обеспечивает координацию одновременных операций чтения и записи общих данных в параллельных системах.
Мотивация
В параллельном программировании синхронизация необходима, когда параллельные потоки пытаются получить доступ к общему ресурсу. Низкоуровневые конструкции синхронизации потоков, такие как блокировки, являются пессимистичными и запрещают потокам, находящимся вне критической секции, выполнять код, защищенный этой секцией. Процесс установки и снятия блокировок часто создает дополнительную нагрузку в рабочих нагрузках с небольшим количеством конфликтов между потоками. Транзакционная память обеспечивает оптимистичный контроль параллелизма, позволяя потокам выполняться параллельно с минимальными помехами. Цель систем транзакционной памяти – прозрачно поддерживать области кода, помеченные как транзакции, обеспечивая атомарность, согласованность и изолированность. Транзакция – это набор операций, которые могут быть выполнены и зафиксированы, если нет конфликтов. При обнаружении конфликта транзакция откатывается к своему исходному состоянию (до любых изменений) и повторяется до тех пор, пока все конфликты не будут устранены. До успешного подтверждения результат любой операции внутри транзакции является чисто спекулятивным. В отличие от синхронизации на основе блокировок, где операции сериализуются для предотвращения повреждения данных, транзакции допускают дополнительный параллелизм, пока немногие операции пытаются изменить общий ресурс. Поскольку программист не несет ответственности за явное указание блокировок или порядка их получения, программы, использующие транзакционную память, не могут привести к возникновению взаимоблокировки (deadlock). Аппаратные системы транзакционной памяти могут включать изменения в процессорах, кэше и шинном протоколе для поддержки транзакций. Спекулятивные значения в транзакции должны буферизоваться и оставаться невидимыми для других потоков до момента подтверждения. Большие буферы используются для хранения спекулятивных значений, избегая распространения записи через базовый протокол когерентности кэша. Традиционно буферы реализовались с использованием различных структур в иерархии памяти, таких как очереди хранения или кэши. Буферы, расположенные дальше от процессора, например, L2 кэш, могут хранить больше спекулятивных значений (до нескольких мегабайт). Оптимальный размер буфера все еще является предметом обсуждения из-за ограниченного использования транзакций в коммерческих программах и требует минимальной аппаратной поддержки (обычно атомарной операции сравнения и обмена или эквивалентной). Недостатком программных реализаций обычно является снижение производительности по сравнению с аппаратными решениями. Аппаратное ускорение может уменьшить некоторые накладные расходы, связанные с программной транзакционной памятью. В силу более ограниченной природы аппаратной транзакционной памяти (в текущих реализациях) программное обеспечение, использующее ее, может потребовать довольно тщательной настройки для полной реализации ее преимуществ. Например, динамический менеджер памяти может существенно влиять на производительность, а также наполнители структур могут влиять на производительность (из-за выравнивания кэша и проблем ложного совместного использования); в контексте виртуальной машины различные фоновые потоки могут вызывать неожиданные откаты транзакций.
История
Одной из самых ранних реализаций транзакционной памяти был буфер управляемого кэша, использованный в процессорах Crusoe и Efficeon компании Transmeta. Однако он применялся лишь для упрощения спекулятивных оптимизаций при двоичной трансляции, а не для какой-либо формы спекулятивного многопоточного выполнения или предоставления доступа к ней программистам. Azul Systems также реализовала аппаратную транзакционную память для ускорения своей Java-аппаратной платформы, но она также была скрыта от внешнего мира. Sun Microsystems реализовала аппаратную транзакционную память и ограниченную форму спекулятивного многопоточного выполнения в своем высокопроизводительном процессоре Rock. Эта реализация показала, что её можно использовать для устранения блокировок и более сложных гибридных систем транзакционной памяти, где транзакции обрабатываются комбинацией аппаратных и программных средств. Процессор Rock был отменен в 2009 году, незадолго до приобретения компанией Oracle; хотя сами продукты так и не были выпущены, ряд прототипных систем был доступен для исследователей. Начиная с GCC 4.7, доступна экспериментальная библиотека транзакционной памяти, использующая гибридную реализацию. Вариант PyPy языка Python также добавляет поддержку транзакционной памяти в язык.