company_banner

Анонсирована аппаратная поддержка транзакционной памяти в Haswell

    Haswell будет очень инновационным Tock'ом. Еще в прошлом году стало доступно описание новых операций с целыми в AVX. А на этой неделе было опубликовано очередное расширение архитектуры X86. В Haswell появится аппаратная поддержка транзакционной памяти! На англоязычных сайтах обсуждение кипит. ISN Arstechnica LWN Engadget

    Я думаю, что это самое нетривиальное расширение архитектуры X86 за много-много лет. Фича называется Transactional Synchronization Extensions (далее TSX), и состоит из двух частей — Hardware Lock Elision (HLE) и Restricted Transactional Memory (RTM). Обратите внимание на слово «Restricted». Все верно, есть некоторые ограничения по объему, гранулярности и уровню вложенности транзакций.

    Об этих ограничениях и как это все будет работать подробнее под катом. (Никаких картинок, скучный технический текст)

    Software Transactional Memory (STM) — достаточно известная концепция. В двух словах ее суть в том, что определяются транзакции, внутри которых все изменения любых участков памяти атомарно коммитятся при условии отсутствия конфликтов с другими потоками, или полностью отменяются при конфликте. У STM есть два ключевых преимущества перед параллелизмом с блокировками — потенциально лучшая scalability и удобство программирования (использовать транзакции намного проще, чем блокировки, и в отличие от блокировок, транзакции легко могут быть композитными).

    Есть масса программных реализаций, например Intel STM compiler или TBoost.STM. Есть предложение о добавлении поддержки транзакционной памяти в С++. В моей любимой Clojure STM вообще единственный идиоматичный механизм многопоточной работы с разделяемой общей памятью.

    К сожалению, в основном из-за проблем с производительностью, STM для императивных языков не приобрела особой популярности.

    Производители процессоров давно облизывались на поддержку Transactional Memory в железе. Это потенциально решило бы проблемы с производительностью. Например, был такой процессор UltraSPARC Rock с аппаратной поддержкой транзакционной памяти, но он, к сожалению, не взлетел. У Azul и IBM также есть работающее железо, поддерживающее транзакционную память.

    Как все устроено в Haswell? Обычно начинают объяснение с HLE, потом идет RTM, а потом как оно устроено внутри. Я начну с внутренностей, потом перейду к RTM, и оставлю HLE напоследок, так будет интереснее.

    В реализации кэша в Haswell появится некая магия, которая для каждой кэш линии будет определять ее принадлежность к read-set и write-set активных транзакций. Также появляются несколько новых u-ops, нужных чтобы начать и завершить транзакцию, узнать причину отката и для диагностики.

    RTM — это просто использование этих новых инструкций программистом. Инструкция XBEGIN начинает транзакцию и устанавливает обработчик для прерванной транзакции, XEND — завершает, и XABORT прерывает. Естественно, если программа с RTM исполняется на X86 процессоре, не поддерживающем TSX, произойдет #UD.

    HLE устроен гораздо хитрее внутри, но просто для программиста. Представьте, что есть такое Т.З.: используя реализацию вышеописанных примитивов, добиться улучшения производительности уже написанного многопоточного софта с локами (можно перекомпилировать, нельзя ничего менять.) При этом в отличие от RTM, требуется, чтобы получившийся бинарник исполнялся корректно как на процессорах с TSX, так и без.

    Как же это было сделано? В некотором смысле HLE можно считать вариантом rw-lock для переменной, используемой для блокировки + транзакция :). Вводятся префиксы XAQUIRE и XRELEASE. Это не инструкции, это префиксы (типа LOCK, REP)! Они игнорируются процессором, который не поддерживает TSX. Эти префиксы рекомендуется использовать перед взятием блокировки и ее освобождением соответственно. При взятии блокировки, запись в переменную не происходит, вместо этого она помещается в read-set процесса, и начинается транзакция. Благодаря этой магии (или хаку, если будет так угодно) остальные процессы тоже могут исполнять залоченный код, пока не будет конфликта по write-set. Потом при XRELEASE и записи в блокировку(которая также игнорируется) транзакция коммитится, если исполнилась без конфликтов. Если конфликты были, то происходит возвращение к обычной семантике.

    Перечислю ограничения TSX.
    1. Так как гранулярность — 64 байта, неаккуратное размещение данных в памяти наряду с false sharing будет теперь вызвать false transaction abort… Так как read-set'ы и write-set'ы определены в кэше, это ограничивает объем памяти, с которой транзакция может успешно сработать.
    2. Существует куча условий, когда транзакции обрываются. (При приходе прерывания, использовании инструкций типа PAUSE, X87, переключении контекста, отладке и т.д.)
    3. Вложенность. Есть ограничение уровня вложенности. (Сорри не могу сказать, какое) Прерывание транзакции по любой причине на любом уровне вложенности сбрасывает все вложенные транзакции!
    При прерывании транзакции можно посмотреть причину. Но все равно очень весело будет все это дебажить и профилировать! Конечно, для анализа производительности появятся новые CPU каунтеры, считающие связанные с TSX события.

    Поддержка в софте уже начала появляться, например, в Binutils уже закоммитили. На очереди HLE в pthreads :), а потом, я надеюсь, использование RTM в реализациях STM.
    Как я писал выше, подробности доступны в документе на сайте Intel.

    Intel

    144,00

    Компания

    Поделиться публикацией
    Комментарии 14
      +3
      Насчет префиксов, используется тот же опкод что для rep (0xF2/0xF3), конфликтов не возникает ибо обрласть применения префиксов различается — rep работает только с несколькими строковыми инструкциями, а в HLE — с другим набором.
      Если процессор не поддерживает TSX, то эти префиксы перед не-строковыми инструкциями («округленно», там есть еще несколько вариантов) приводят к UB, хотя на самом деле, поведение стандартно — просто игнорирование.
        0
        А Microsoft в курсе? У них тоже был проект STM.NET, возможно производительность повысят
          0
          Я не работаю непосредственно с Microsoft, но уверен, что коллеги, которые работают в штате Вашингтон им сообщили по секрету где-то в прошлом году.

          Надеюсь, STM.NET это поможет, и-или F# тоже.
            0
            Так ведь этот проект закрыли давно, не?
              0
              Судя по всему — да, общался более года назад с разработчиками из PnP группы, они сказали что планов по развитию нету. Уж слишком криво это интегрируется в язык.
                0
                В шестом выпуске fprog.ru, в интервью SPJ из Microsoft Research есть несколько мыслей по поводу STM.NET и STM вообще.
            +1
            Вопросы от полного дилетанта в этой теме:
            -а какой прирост производительности от этого чуда ожидается на каких-нибудь известных задачах?
            -"Производители процессоров давно облизывались на поддержку Transactional Memory в железе. Это потенциально решило бы проблемы с производительностью" -это ведь только в случае сильно многопоточных приложений, да?
            и еще более глупый вопрос: а чем синтаксис транзакций может\должен отличаться от синтаксиса критической секции? она тоже определяет область кода, внутри которой,… хотя там внутри и совсем другой механизм, но для программиста в чем разница?
              0
              1. У меня пока нет железки, так что не мерял. Плюс мы же вроде не имеем права публиковать бенчмарки до выхода железа. По идее если просто перекомпилять с HLE pthreads mutexes, и запустить что-то с большим количеством локов но низким контеншеном на EP или лучше EX будет очень хороший спидап.

              2. Да, конечно, в случае сильно многопоточных приложений просто будет лучше скейлится. Но так как цена работы программиста давно уже больше цены процессорного времени, упрощение разработки многопоточного кода тоже хорошая мотивация.

              3. Для программиста основная разница в том, что с критической секцией надо постоянно держать в голове, что при взаимодействии с другими локами возможен deadlock, в транзакции нет. Плюс если критическая секция возникла из-за того, что код внутри работает с разделяемой структурой (хэшом, массивом, списком) логично, что оптимистическое выполнение этого кода многими транзакциями одновременно будет часто быстрее, чем обычное сериализованное.
                0
                По первым двум пунктам все ясно. Неясно, почему для stm предлагается отдельный синтаксис (расширение С++), а для обычной критической секции — нет. Мне кажется, что уж если делать, то целиком для всех. Тем более, что HLE все равно все скроет.
                  0
                  да, я бы тоже добавил к обычной critical_section optimistic_critical_section с HLE, и чтобы программист или компилятор/рантайм решали, какую выбрать, в зависимости от контеншна, величины, кода внутри.
              0
              Эх… как всё хорошо начиналось. А теперь везде эту фичу выключили (баги) и опять нету ни одного живого процессора с TSX.
                0
                В Broadwell наверняка поправят же.
                  0
                  Судя по слухам, то только в Skylake…
                    0
                    По, например, этим слухам пофиксят в Broadwell, до выхода десктопных же еще довольно много времени.

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

              Самое читаемое