(4) Каждое сообщение может содержать O(w) бит. Каждое сообщение может содержать не более постоянного числа идентификаторов процессов. Это предположение сделано для того, чтобы позволить справедливое сравнение сложности сообщений различных алгоритмов.
Уже было замечено, что идентификаторы процессов могут использоваться для нарушения симметрии между процессами. Можно разработать алгоритм выбора так, чтобы выбирался процесс с наименьшим идентификатором. Согласно результатам в Подразделе 6.1.5, наименьший идентификатор может быть вычислен за одну волну. Это означает, что выбор можно провести, выполняя волну, в которой вычисляется наименьший идентификатор, после чего процесс с этим идентификатором становится лидером. Т.к. алгоритм выбора должен быть децентрализованным, этот принцип может быть применен только к децентрализованным волновым алгоритмам (см. Таблицу 6.19).
Выбор с помощью древовидного алгоритма. Если топология сети - дерево или доступно остовное дерево сети, выбор можно провести с помощью древовидного алгоритма (Подраздел 6.2.2). В древовидном алгоритме требуется, чтобы хотя бы все листья были инициаторами алгоритма. Чтобы получить развитие алгоритма в случае, когда некоторые процессы также являются инициаторами, добавляется фаза wake-up. Процессы, которые хотят начать выбор, рассылают сообщение <wakeup> всем процессам. Логическая переменная ws используется, чтобы каждый процесс послал сообщения <wakeup> не более одного раза, а переменная wr используется для подсчета количества сообщений <wakeup>, полученных процессом. Когда процесс получит сообщение <wakeup> через каждый канал, он начинает выполнять Алгоритм 6.3, который расширен (как в Теореме 6.12) таким образом, чтобы вычислять наименьший идентификатор и чтобы каждый процесс принимал решение. Когда процесс принимает решение, он знает идентификатор лидера; если этот идентификатор совпадает с идентификатором процесса, он становится лидером, а если нет - проигравшим; см. Алгоритм 7.1.
var wsp : boolean init false ;
wrp : integer init 0 ;
recp[q] : boolean для всех q Î Neighpinit false ;
vp : P init p ;
statep : (sleep, leader, lost) init sleep ;
begin if p - инициатор then
begin wsp := true ;
forall q Î Neighpdo send <wakeup> to q
end ;
while wrp < # Neighpdo
begin receive <wakeup> ; wrp := wrp + 1 ;
if not wsp then
begin wsp := true ;
forall q Î Neighpdo send <wakeup> to q
end
end ;
(* Начало древовидного алгоритма *)
while # {q : Ørecp[q]} > 1 do
begin receive <tok,r> from q ; recp[q] := true ;
vp := min (vp,r)
end ;
send <tok,vp> to q0 with Ørecp[q0] ;
receive <tok,r> from q0 ;
vp := min (vp,r) ; (* decide с ответом vp *)
if vp = p then statep := leader else statep := lost ;
forall q Î Neighp, q ¹ q0do send <tok,vp> to q
end
Алгоритм 7.1 Алгоритм выборов для деревьев.
Теорема 7.2 Алгоритм 7.1 решает задачу выбора на деревьях, используя O(N) сообщений и O(D) единиц времени.
Доказательство. Когда хотя бы один процесс инициирует выполнение алгоритма, все процессы посылают сообщения <wakeup> всем своим соседям, и каждый процесс начинает выполнение древовидного алгоритма после получения сообщения <wakeup> от каждого соседа. Все процессы завершают древовидный алгоритм с одним и тем же значением v, а именно, наименьшим идентификатором процесса. Единственный процесс с этим идентификатором закончит выполнение в состоянии лидер, а все остальные процессы - в состоянии проигравший.
Через каждый канал пересылается по два сообщения <wakeup> и по два сообщения <tok,r>, откуда сложность сообщений равна 4N-4. В течение D единиц времени после того, как первый процесс начал алгоритм, каждый процесс послал сообщения <wakeup>, следовательно, в течение D+1 единиц времени каждый процесс начал волну. Легко заметить, что первое решение принимается не позднее, чем через D единиц времени после начала волны, а последнее решение принимается не позднее D единиц времени после первого, откуда полное время равно 3D+1. Более тщательный анализ показывает, что алгоритм всегда завершается за 2D единиц времени, но доказательство этого оставлено читателю; см. Упражнение 7.2.
Если порядок сообщений в канале может быть изменен (т.е. канал - не FIFO), процесс может получить сообщение <tok,r> от соседа прежде чем он получил сообщение <wakeup> от этого соседа. В этом случае сообщение <tok,r> может быть временно сохранено или обработано как сообщения <tok,r>, прибывающие позднее.
Количество сообщений может быть уменьшено с помощью двух модификаций. Во-первых, можно устроить так, чтобы не-инициатор не посылал сообщение <wakeup> процессу, от которого он получил первое сообщение <wakeup>. Во-вторых, сообщение <wakeup>, посылаемое листом, может быть объединено с сообщением <tok,r>, посылаемым этим листом. С этими изменениями количество сообщений, требуемое алгоритмом, уменьшается до 3N-4+k, где k - количество нелистовых стартеров [Tel91b, с.139].
Выбор с помощью фазового алгоритма. Фазовый алгоритм можно использовать для выбора, позволив ему вычислять наименьший идентификатор за одну волну, как в Теореме 6.12.
Теорема 7.3 С помощью фазового алгоритма (Алгоритм 6.7) можно провести выбор в произвольных сетях, используя O(D*|E|) сообщений и O(D) единиц времени.
Алгоритм Пелега [Peleg; Pel90] основан на фазовом алгоритме; он использует O(D*|E|) сообщений и O(D) времени, но не требует знания D, т.к. включает в себя вычисление диаметра.
Выбор с помощью алгоритма Финна. Алгоритм Финна (Алгоритм 6.9) не требует, чтобы диаметр сети был известен заранее. Длина O(N*|E|) сообщений, используемых в алгоритме Финна, гораздо больше, чем допускаемая предположениями в этой главе. Следовательно, каждое сообщение в алгоритме Финна должно считаться за O(N) сообщений, откуда сложность сообщений составляет O(N2|E|).
В этом разделе рассматриваются некоторые алгоритмы выбора для однонаправленных колец. Задача выбора в контексте кольцевых сетей была впервые изложена ЛеЛанном [LeLann; LeL77], который также дал решение со сложностью сообщений O(N2). Это решение было улучшено Чангом (Chang) и Робертсом (Roberts) [CR79], которые привели алгоритм с наихудшей сложностью O(N2), но со средней сложностью только O(N logN). Решения ЛеЛанна и Чанга-Робертса обсуждаются в Подразделе 7.2.1. Вопрос о существовании алгоритма с наихудшей сложностью O(N logN) оставался открытым до 1980 г., когда такой алгоритм был приведен Hirschberg и Sinclair [HS80]. В отличие от более ранних решений, в решении Hirschberg-Sinclair требуется, чтобы каналы были двунаправленными. Предполагалось, что нижняя граница для однонаправленных колец равна W(N2), но Petersen [Pet82] и Dolev, Klawe и Rodeh [DKR82] независимо друг от друга предложили решение, составляющее O(N log N) для однонаправленного кольца. Это решение рассматривается в Подразделе 7.2.2.
Алгоритмы были дополнены соответствующими нижними границами примерно в то же время. Нижняя граница для наихудшего случая для двунаправленных колец, равная » 0.34N logN сообщений, была доказана Бодлендером [Bodlaender; Bod88]. Pachl, Korach и Rotem [PKR84] доказали нижние границы в W(N logN) для средней сложности, как для двунаправленных так и для однонаправленных колец. Их результаты по нижним границам будут рассмотрены в Подразделе 7.2.3.
7.2.1 Алгоритмы ЛеЛанна и Чанга-Робертса
В алгоритме ЛеЛанна [LeL77] каждый инициатор вычисляет список идентификаторов всех инициаторов, после чего выбирается инициатор с наименьшим идентификатором. Каждый инициатор посылает маркер, содержащий его идентификатор, по кольцу, и этот маркер передается всеми процессами. Предполагается, что каналы подчиняются дисциплине FIFO, и что инициатор должен сгенерировать свой маркер до того, как он получит маркер другого инициатора. (Когда процесс получает маркер, он после этого не инициирует алгоритм.) Когда инициатор p получает свой собственный маркер, маркеры всех инициаторов прошли через p, и p выбирается лишь в том случае, если p - наименьший среди инициаторов; см. Алгоритм 7.2.
var Listp : set of P init {p} ;
statep ;
begin if p - инициатор then
begin statep := cand ; send <tok,p> to Nextp ; receive <tok,q> ;
while q ¹ p do
begin Listp := Listp È {q} ;
send <tok,q> to Nextp ; receive <tok,q> ;
end ;
if p = min (Listp) then statep := leader
else statep := lost
end
else repeat receive <tok,q> ; send <tok,q> to Nextp ;
if statep = sleep then statep := lost
until false
end
Алгоритм 7.2 Алгоритм выбора ЛеЛанна.
Теорема 7.4 Алгоритм ЛеЛанна (Алгоритм 7.2) решает задачу выбора для колец, используя O(N2) сообщений и O(N) единиц времени.
Доказательство. Так как порядок маркеров в кольце сохраняется (из предположения о каналах FIFO), и инициатор q отправляет <tok,q> до того как получит <tok,p>, то инициатор p получает <tok,q> прежде, чем вернется <tok,p>. Отсюда следует, что каждый инициатор p заканчивается со списком Listp, совпадающим с множеством всех инициаторов, и единственным выбираемым процессом становится инициатор с наименьшим идентификатором. Всего получается не больше N маркеров и каждый делает N шагов, что приводит к сложности сообщений в O(N2). Не позднее чем через N-1 единицу времени после того, как первый инициатор отправил свой маркер, это сделали все инициаторы. Каждый инициатор получает свой маркер обратно не позднее, чем через N единиц времени с момента генерации этого маркера. Отсюда следует, что алгоритм завершается в течение 2N-1 единиц времени.