<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.252.127.246&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.252.127.246&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/178.252.127.246"/>
		<updated>2026-04-29T13:19:49Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9_%D0%BA%D0%BE%D0%BD%D1%8A%D1%8E%D0%BD%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BF%D1%80%D0%B5%D0%B4%D0%B8%D0%BA%D0%B0%D1%82_(WCP)&amp;diff=71659</id>
		<title>Слабый конъюнктивный предикат (WCP)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9_%D0%BA%D0%BE%D0%BD%D1%8A%D1%8E%D0%BD%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BF%D1%80%D0%B5%D0%B4%D0%B8%D0%BA%D0%B0%D1%82_(WCP)&amp;diff=71659"/>
				<updated>2019-06-14T22:56:07Z</updated>
		
		<summary type="html">&lt;p&gt;178.252.127.246: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Слабый конъюнктивный предикат (WCP)''' — [[Глобальные свойства системы|предикат]], имеющий вид конъюнкции локальных предикатов над состоянием каждого процесса.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Слабый конъюктивный предикат $P$ '''истинен''', если он истинен на хотя бы одном согласованном срезе&lt;br /&gt;
}}&lt;br /&gt;
Сложные предикаты, составленные как логическая комбинация локальных предикатов, можно представить в дизъюнктивной нормальной форме и рассмотреть как дизъюнкцию слабых конъюктивных предикатов.&lt;br /&gt;
&lt;br /&gt;
Более того: некоторые сложные нелокальные предикаты тоже можно так записать.&lt;br /&gt;
Например, если есть предикат на булевских переменных из разных процессов: $x = y$, то можно записать формулу: $(x = 0 \land y = 0) \lor (x = 1 \land y = 1)$.&lt;br /&gt;
&lt;br /&gt;
'''Теорема''': если слабый конъюктивный предикат верен хоть на одном согласованном срезе, то в множестве согласованных срезов с верным предикатом существует наименьший элемент (т.е. который вкладывается во все остальные). Это следует из того, что пересечение согласованных срезов является согласованным срезом: пересечение всех срезов с верными предикатом будет срезом и, более того, в каждом процессе граница этого среза включается хотя бы в один из исходных, следовательно, на границе в каждом процессе соответствующий локальный предикат будет верен.&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
Позволяет обнаружить некоторые нежелательные предикаты.&lt;br /&gt;
Обнаруживает ошибки, которые могли бы быть скрыты в определенном запуске из-за race conditions.&lt;br /&gt;
&lt;br /&gt;
Например, классическую проблема взаимного исключения для двух процессов: локальный предикат &amp;quot;процесс в критической секции&amp;quot;.&lt;br /&gt;
Если есть срез, в котором два процесса в критической секции, то всё плохо.&lt;br /&gt;
А если такого нет, то любые две критические секции упорядочены.&lt;br /&gt;
&lt;br /&gt;
Ещё пример WCP предиката: “в системе нет координатора”, причем локальное условие – “я не координатор”.&lt;/div&gt;</summary>
		<author><name>178.252.127.246</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=CAP_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0&amp;diff=71658</id>
		<title>CAP теорема</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=CAP_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0&amp;diff=71658"/>
				<updated>2019-06-14T22:45:33Z</updated>
		
		<summary type="html">&lt;p&gt;178.252.127.246: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''CAP-теорема''' — утверждение о том, что в распределённых системах нельзя одновременно добиться трёх свойств:&lt;br /&gt;
* '''C'''onsistency — на всех ''не отказавших'' узлах одинаковые (с точки зрения пользователя) данные&lt;br /&gt;
* '''A'''vailability — запросы ко всем ''не отказавшим'' узлам возвращают ответ&lt;br /&gt;
* '''P'''artition tolerance — даже если связь в системе стала нестабильной (вплоть до разделения системы на куски), но узлы работают, то система в целом продолжает работать&lt;br /&gt;
&lt;br /&gt;
Формально мы это не формулировали и не доказывали.&lt;br /&gt;
Оригинальная формулировка — Brewer's Conjecture (2000), а формализовано в работе Gilbert &amp;amp; Lynch (2004).&lt;br /&gt;
Там есть много тонкостей с тем, что такое &amp;quot;не отказавший узел&amp;quot;, &amp;quot;одинаковые данные&amp;quot;, &amp;quot;разрыв связи&amp;quot;, &amp;quot;система продолжает работать&amp;quot;, &amp;quot;когда система всё-таки окончательно ломается и считается недоступной&amp;quot; и тому подобное.&lt;br /&gt;
&lt;br /&gt;
Для общей эрудиции выглядят неплохо статьи&amp;lt;ref&amp;gt;http://blog.thislongrun.com/2015/04/the-unclear-cp-vs-ca-case-in-cap.html&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/322276/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Классификация алгоритмов ==&lt;br /&gt;
А вот алгоритмы, которые удовлетворяют хотя бы двум свойствам, можно нарисовать на диаграмма Венна:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-cap.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Дальше идут объяснения с лекции, они отличаются в разных источниках (например, где-то 2PC идёт вместе с Paxos в CP, а не в CA&amp;lt;ref&amp;gt;http://www.cedanet.com.au/ceda/fallacies/cap-theorem.php&amp;lt;/ref&amp;gt;), а где-то совпадают с лекцией&amp;lt;ref&amp;gt;http://book.mixu.net/distsys/single-page.html#the-cap-theorem&amp;lt;/ref&amp;gt;, а где-то считают, что не-partition tolerance не нужно&amp;lt;ref&amp;gt;https://codahale.com/you-cant-sacrifice-partition-tolerance/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Если мы хотим согласованность и доступность, то используем [[2 Phase Commit|протокол двухфазного коммита]]: он гарантирует нам согласованное состояние глобально во всей системе и мы всегда можем обслуживать запросы (если только не упал узел с соответствующими данными). Но если потерялась связь (а узлы не упали), то какие-то запросы нельзя обработать, потому что часть данных может быть в одной половине, а часть в другой. Каждый кусок всё ещё будет работать по отдельности, но глобальные транзакции выполнять мы не сможем.&lt;br /&gt;
* Иногда нам не так важна согласованность и мы согласны на простую eventual consistency — это когда информация может быть доступна не сразу везде, а только через какое-то время, если система здорова. Сюда идут [[gossip-протоколы]].&lt;br /&gt;
* Если мы хотим согласованность и толерантность к разделению, то надо жертвовать доступностью. Например, при помощи Paxos мы можем хранить все данные сразу на всех узлах, но тогда узлы, оказавшиеся в меньшинстве, ничего сделать не могут.&lt;/div&gt;</summary>
		<author><name>178.252.127.246</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71657</id>
		<title>Самостабилизирующиеся алгоритмы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71657"/>
				<updated>2019-06-14T18:17:19Z</updated>
		
		<summary type="html">&lt;p&gt;178.252.127.246: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Самостабилизирующие алгоритмы''' — это идея построения алгоритмов, устойчивых к ошибкам:&lt;br /&gt;
* Код потерять сложно, поэтому мы считаем, что он не портится при падении узлов.&lt;br /&gt;
* Алгоритм может работать с любой комбинацией данных.&lt;br /&gt;
* Из любого состояния мы попадаем в '''легальное''' через конечное число шагов (при отсутствии сбоев).&lt;br /&gt;
}}&lt;br /&gt;
Тогда от ''любого'' сбоя мы через конечное число шагов будем восстанавливаться без консенсусов и прочих развлечений.&lt;br /&gt;
== Взаимное исключение ==&lt;br /&gt;
Dijkstra Stabilizing Token Ring Algorithm.&lt;br /&gt;
&lt;br /&gt;
Сначала надо переформулировать задачу: мы говорим, что каждый процесс в системе может либо '''иметь привилегию''', либо не иметь.&lt;br /&gt;
В произвольном состоянии системы привилегия может быть у произвольного количества процессов, но через конечное число шагов она остаётся только у одного процесса и мы входим в легальное состояние.&lt;br /&gt;
Дальше остаёмся только в легальных состояниях.&lt;br /&gt;
&lt;br /&gt;
TODO: а какие сообщения процессы посылают друг другу? Могут ли быть ошибки (наверное, нет)? Может ли система быть асинхронной (наверное, тоже нет)?&lt;br /&gt;
&lt;br /&gt;
Все $N$ процессов будут замкнуты в кольцо, в котором один процесс назван &amp;quot;первым&amp;quot;.&lt;br /&gt;
У каждого процесса есть состояние — число от 0 до $K-1$, причём $K \ge N$ — параметр алгоритма.&lt;br /&gt;
&lt;br /&gt;
По определению положим, что у процесса есть привилегия, если:&lt;br /&gt;
* Он первый и его значение $S$ совпадает со значением $L$ следующего по часовой стрелке процесса.&lt;br /&gt;
* Он не первый и его $S$ не совпадает с $L$.&lt;br /&gt;
&lt;br /&gt;
Например, на рисунке ниже толстая граница у выделенного процесса, а жёлтым обозначена привилегия:&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-self-stabilization-legal.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Правила перехода в новое состояние:&lt;br /&gt;
* Для первого процесса: если была привилегия ($S=L$), то переходим в состояние $(S + 1) \bmod K$&lt;br /&gt;
* Для не-первого процесса: если привилегия есть ($S \neq L$), то переходим в состояние $L$&lt;br /&gt;
Пример двух переходов:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-1.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, в легальном состоянии привилегия у нас ходит по кругу, как в алгоритме с токеном.&lt;br /&gt;
Но там потеря токена была смертельной для алгоритма, а у нас — не смертельна.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство стабилизируемости ===&lt;br /&gt;
'''Лемма''': в любом состоянии хотя бы у одного процесса есть привилегия.&lt;br /&gt;
В противном случае у нас, с одной стороны, все значения машин равны друг другу (потому что для каждой машины, кроме первой, её значение совпадает со следующей по кругу), а с другой стороны значение первой машины и её соседа должны отличаться, противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': что бы не происходило в системе, через $O(N^2)$ шагов в системе первый процесс сделает ход.&lt;br /&gt;
'''Доказательство (с лекции)''': если первый процесс не делает ход, то следующий за ним против часовой стрелки процесс 2 сможет сделать максимум один ход: взять себе значение первого процесса.&lt;br /&gt;
Процесс 3 после каждого хода процесса 2 может сделать максимум один ход: взять себе значение процесса 2.&lt;br /&gt;
То есть процесс 3 может сделать не больше двух ходов (один исходно, один после хода процесса 2).&lt;br /&gt;
Аналогично, процесс 4 может сделать не больше трёх ходов, и так далее.&lt;br /&gt;
Итого мы получаем, что если первый процесс не делает шаги, то через $O(N^2)$ шагов привилегия полностью исчезнет, чего не бывает.&lt;br /&gt;
&lt;br /&gt;
'''Альтернативное доказательство (проверено рандомом)''': если первый процесс может сделать ход сразу, то всё доказали. &lt;br /&gt;
Иначе у него нет привилегии.&lt;br /&gt;
Заметим, что если следующий за ним по часовой стрелке процесс 2 либо имеет значение, равное ему, либо отличающееся (тогда он имеет привилегию и сразу делает ход).&lt;br /&gt;
Таким образом, через один ход процессы 1 и 2 имеют одинаковые значения.&lt;br /&gt;
Аналогично, через два хода процессы 1, 2 и 3 имеют одинаковые значения.&lt;br /&gt;
А через $N-1$ шаг все процессы гарантированно имеют одинаковые значения (если первый процесс так и не походил).&lt;br /&gt;
Таким образом, через $N-1$ шаг у первого процесса появляется привилегия и он ходит, $N=O(N^2)$.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': рано или поздно у первого процесса будет уникальное $S$.&lt;br /&gt;
'''Доказательство''': все остальные процессы умеют только копировать состояния друг у друга, а первый процесс ходит бесконечно.&lt;br /&gt;
Поэтому рано или поздно он перейдёт на состояние, которое не совпадает ни с одним из оставшихся $N-1$ состоянием.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': через $O(N^2)$ после этого система стабилизируется.&lt;br /&gt;
'''Альтернативное доказательство (не с лекции)''': это состояние будет сразу же скопировано на второй процесс, потом сразу же скопировано на третий, и так далее, после чего мы прийдём в состояние, где все значения равны, а оно легальное.&lt;br /&gt;
&lt;br /&gt;
== Поиск остовного дерева ==&lt;br /&gt;
Такая задача возникает, например, в internet of things: набросали с вертолёта на поле размером 3км*3км много хрупких устройств со слабыми антеннами, которым надо соединиться в единую сеть. При этом топология связи там неполная и половина устройств подохла.&lt;br /&gt;
А мы хотим построить дерево, чтобы узлы могли друг с другом общаться (а не каждый каждому передавать, потому что тогда надо бороться с циклами).&lt;br /&gt;
&lt;br /&gt;
Решение начинается с инициатора (например, узел, которому надо что-нибудь узнать про всех остальных), которому это дерево нужно.&lt;br /&gt;
&lt;br /&gt;
Каждый узел поддерживает у себя $d$ (расстояние до корня) и $p$ (узел-предок в дереве).&lt;br /&gt;
Корень всегда ставит у себя $d=0$ и $p=-1$, а остальные узлы в постоянном режиме делают:&lt;br /&gt;
* Найти соседа $j$ с минимальным $d_j$&lt;br /&gt;
* Установить его в качестве своего родителя и $d_i=d_j+1$&lt;br /&gt;
&lt;br /&gt;
Тогда корень стабилизируется сразу, узлы, которым корень виден, стабилизируются через одну итерацию, их соседи — через две, и так далее.&lt;br /&gt;
&lt;br /&gt;
Если какой-нибудь узел выпадает, то его дети найдут себе кого-нибудь ещё и снова встроятся в дерево.&lt;br /&gt;
&lt;br /&gt;
Единственная проблема — если умирает корень, но тогда узнавший об этом узел может инициировать перестроение дерева (если у нас цель — связь).&lt;/div&gt;</summary>
		<author><name>178.252.127.246</name></author>	</entry>

	</feed>