Блокировки очередей на основе массивов - Array Based Queuing Locks

Блокировка очереди на основе массива (ABQL) является продвинутым замок алгоритм, который гарантирует, что потоки вращаются в уникальных ячейках памяти, что обеспечивает справедливость получения блокировки в сочетании с улучшенной масштабируемостью.

Обзор

Синхронизация является важной проблемой при проектировании и программировании Общая память[1] мультипроцессоры. Общая проблема с реализациями блокировки - это высокая конкуренция в сети из-за того, что процессоры вращаются на общем флаге синхронизации или области памяти. Таким образом, масштабируемость блокировки значительно снижается с точки зрения количества конкурирующих процессоров.

Блокировка очереди на основе массива является расширением билетный замок алгоритм, который гарантирует, что при снятии блокировки только один процессор пытается получить блокировку, уменьшая количество кешей промахов. Этого эффекта можно добиться, если все процессоры будут работать в уникальных ячейках памяти.[2] Одна аналогия, используемая для объяснения механизма блокировки, - это эстафета, когда спортсмен передает эстафету следующему спортсмену в очереди, что гарантирует, что только один спортсмен получает эстафету за раз.

ABQL также гарантирует справедливость получения блокировки за счет использования первым прибыл, первым обслужен (FIFO) механизм на основе очередей. Кроме того, объем аннулирования значительно меньше, чем при реализации блокировки на основе билета, поскольку только один процессор вызывает промах в кэше при снятии блокировки.

Выполнение

Основным требованием реализации блокировки очередей на основе массивов является обеспечение того, чтобы все потоки вращались в уникальных ячейках памяти. Это достигается с помощью массива, длина которого равна количеству потоков, конкурирующих за блокировку. Все элементы массива инициализируются значением 0, за исключением первого элемента, который принимает значение 1, что обеспечивает успешное получение блокировки первым потоком в очереди. При снятии блокировки удержание передается следующему потоку в очереди, устанавливая для следующего элемента массива значение 1. Запросы предоставляются потокам в порядке FIFO.

Пример псевдокода приведен ниже.[3]

ABQL_init(int *next_ticket, int *can_serve){  *next_ticket = 0;  за (int я = 1; я < МАКСИМАЛЬНЫЙ РАЗМЕР; я++)    can_serve[я] = 0;  can_serve[0] = 1; }ABQL_acquire(int *next_ticket, int *can_serve){  *my_ticket = fetch_and_inc(next_ticket);  пока (can_serve [*my_ticket] != 1) ; }ABQL_release (int *can_serve){  can_serve[*my_ticket + 1] = 1;  can_serve[*my_ticket] = 0; // готовимся к следующему разу}

Чтобы реализовать ABQL в псевдокоде выше, введены 3 переменные, а именно can_serve, next_ticket и my_ticket. Роли каждого описаны ниже:

  • can_serve Массив представляет уникальные ячейки памяти, в которых вращаются потоки, ожидающие в очереди получения блокировки.
  • next_ticket представляет следующий доступный номер билета, который назначается новому потоку.
  • my_ticket представляет поток билетов каждого уникального потока в очереди.

В методе инициализации (ABQL_init) переменная next_ticket инициализируется значением 0. Все элементы can_serve массив, за исключением первого элемента, инициализируются значением 0. Инициализация первого элемента в массиве can_serve на 1, гарантирует успешное получение блокировки первым потоком в очереди.

В методе приобретения используется атомная операция fetch_and_inc, чтобы получить следующий доступный номер билета (после этого номер билета увеличивается на 1), который новый поток будет использовать для продолжения. Потоки в очереди вращаются на своих местах, пока значение my_ticket не будет установлено в 1 предыдущим потоком. При получении блокировки нить входит в критическая секция кода.

При снятии блокировки потоком управление передается следующему потоку путем установки следующего элемента в массиве can_serve на 1. Следующий поток, который ожидал получения блокировки, теперь может сделать это успешно.

Работа ABQL может быть представлена ​​в таблице ниже, если предположить, что 4 процессора борются за вход в критическую секцию, при условии, что поток входит в критическую секцию только один раз.

Шаги выполнения
next_ticket
can_serve
my_ticket (P1)
my_ticket (P2)
my_ticket (P3)
my_ticket (P4)
Комментарии
первоначально0[1, 0, 0, 0]0000начальное значение всех переменных 0
P1: fetch_and_inc1[1, 0, 0, 0]0000P1 пытается и успешно получает блокировку
P2: fetch_and_inc2[1, 0, 0, 0]0100P2 пытается получить блокировку
P3: fetch_and_inc3[1, 0, 0, 0]0120P3 пытается получить блокировку
P4: fetch_and_inc4[1, 0, 0, 0]0123P4 пытается получить блокировку
P1: can_serve [1] = 1;

can_serve [0] = 0

4[0, 1, 0, 0]0123P1 снимает блокировку, а P2 успешно получает блокировку
P2: can_serve [2] = 1;

can_serve [1] = 0

4[0, 0, 1, 0]0123P2 снимает блокировку, а P3 успешно получает блокировку
P3: can_serve [3] = 1;

can_serve [2] = 0

4[0, 0, 0, 1]0123P3 снимает блокировку, а P4 успешно получает блокировку
P1: can_serve [3] = 04[0, 0, 0, 0]0123P4 освобождает замок

Показатели эффективности

Следующие критерии производительности могут использоваться для анализа реализаций блокировки:

  • Незаконное получение блокировки задержка - Определяется как время, затрачиваемое потоком на получение блокировки при отсутствии раздор между потоками. Из-за относительно большего количества выполняемых инструкций по сравнению с другими реализациями блокировки, неконтролируемая задержка получения блокировки для ABQL высока.
  • Трафик - Он определяется как количество сгенерированных транзакций шины, которое зависит от количества потоков, участвующих в борьбе за блокировку. При снятии блокировки только 1 блок кэша становится недействительным, что приводит к единственному промаху кэша. Это приводит к гораздо меньшему автобусному движению.
  • Справедливость - Это гарантирует, что все процессоры, ожидающие приобретения замок могут делать это в том порядке, в котором отправляются их запросы. Благодаря тому, что потоки ожидают в очереди, чтобы получить блокировку, при этом каждый поток вращается в отдельной области памяти, обеспечивается справедливость.
  • Место хранения - Объем памяти, необходимый для обработки механизма блокировки. Требования к хранилищу масштабируются с количеством потоков из-за увеличения размера массива. can_serve.

Преимущества

  • ABQL предлагает улучшенную масштабируемость, поскольку каждое приобретение или снятие блокировки вызывает только 1 промах в кэше, в результате чего только блок кэша страдает от промаха кэша для перезагрузки блока.
  • Справедливость получения блокировки обеспечивается за счет использования очереди, которая гарантирует, что потоки успешно получают блокировку в том порядке, в котором их потоки выпущены.

Недостатки

  • ABQL не следует использовать с потоками, которые могут быть приостановлены (спящий или контекст switch), поскольку любой поток, не готовый немедленно получить блокировку, увеличит задержку для всех тех, кто за ним ожидает блокировки.

Смотрите также

Рекомендации

  1. ^ «Алгоритмы масштабируемой синхронизации на мультипроцессорах с общей памятью».
  2. ^ https://cs.unc.edu/~anderson/papers/survey.pdf
  3. ^ Солихин, Ян (2009). Основы параллельной компьютерной архитектуры: многокристальные и многоядерные системы. С. 265–267. ISBN  978-0-9841630-0-7.