130 lines
12 KiB
Markdown
130 lines
12 KiB
Markdown
# Знакомство с gossip
|
||||
|
|
|
|||
|
|
В этой работе сравним push, pull и push-pull в симуляторе на [AnySystem](https://github.com/systems-group/anysystem). Перед каждым экспериментом запишите прогноз, затем сравните его с результатом и объясните различия.
|
|||
|
|
|
|||
|
|
## Подготовка
|
|||
|
|
|
|||
|
|
Откройте корень репозитория курса в IDE. Для VS Code с Pylance [стаб AnySystem](../../../../typings/anysystem/__init__.pyi) подключается через [настройки проекта](../../../../pyrightconfig.json). Для другой IDE укажите папку `typings` в корне репозитория как каталог стабов. Стаб содержит объявления и документацию API; реализация доступна в [исходнике AnySystem 0.3.0](https://github.com/osukhoroslov/anysystem/blob/v0.3.0/python/anysystem.py).
|
|||
|
|
|
|||
|
|
При запуске симулятора локально или в Docker Python-модуль встроен в AnySystem. Отдельный `anysystem.py` и настройка `PYTHONPATH` не нужны.
|
|||
|
|
|
|||
|
|
Из корня репозитория перейдите в каталог лабораторной:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
cd materials/04-group-comm/seminar/gossip
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Если установлен Rust, соберите текущую версию симулятора:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
cargo install --locked --path simulator
|
|||
|
|
distsys-gossip -h
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Для запуска в Docker соберите образ из текущего кода:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
docker build -t distsys-gossip-seminar simulator
|
|||
|
|
docker run --rm -t -v ./:/impl distsys-gossip-seminar -h
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Далее заменяйте `distsys-gossip` на `docker run --rm -t -v ./:/impl distsys-gossip-seminar`. Команды выполняются из каталога `gossip`. Если оболочка не передаёт относительный путь монтирования, в PowerShell используйте `--mount "type=bind,source=$($PWD.Path),target=/impl"` вместо `-v ./:/impl`.
|
|||
|
|
|
|||
|
|
## Модель и метрики
|
|||
|
|
|
|||
|
|
Распространяется одно сообщение, изначально известное процессу `0`. Все узлы знают состав группы и выбирают случайных соседей, исключая себя. Сетевая задержка равна 0,1 единицы модельного времени, периодический таймер срабатывает через 1. В этих экспериментах узлы не отказывают; можно задавать вероятность потери сетевого сообщения.
|
|||
|
|
|
|||
|
|
Основные параметры:
|
|||
|
|
|
|||
|
|
| Параметр | Значение |
|
|||
|
|
| --- | --- |
|
|||
|
|
| `-i` | Файл реализации |
|
|||
|
|
| `-n` | Число узлов, не меньше 2 |
|
|||
|
|
| `-f` | Число соседей для одного обмена, от 1 до `n - 1` |
|
|||
|
|
| `-d` | Вероятность потери сообщения, от 0 до 1 |
|
|||
|
|
| `-s` | Seed для воспроизведения запуска |
|
|||
|
|
| `-t` | Положительный лимит модельного времени |
|
|||
|
|
| `-q` | Завершить симуляцию при обнаружении полного охвата |
|
|||
|
|
|
|||
|
|
В таблице вывода `time` — модельное время, `delivered` — число узлов, доставивших сообщение приложению, `stopped` — число узлов, прекративших периодические инициативные обмены, `messages` — накопленное число сетевых отправлений, включая запросы и ответы. `STOPPED` не означает выключение узла: он сохраняет информацию и может отвечать на входящие запросы.
|
|||
|
|
|
|||
|
|
Симулятор выводит статистику после продвижения времени интервалами по 1. В итоговой строке `First full-coverage sample` указаны время первой напечатанной строки с `delivered = n` и число отправлений к ней. Обозначим их `t_all` и `M_all`. Это показатели с дискретностью вывода, а не точные мгновение последней доставки и число отправлений в это мгновение.
|
|||
|
|
|
|||
|
|
Строка `Finished` объясняет завершение:
|
|||
|
|
|
|||
|
|
- `full coverage (--quick-mode)` — сработало условие `-q`;
|
|||
|
|
- `no pending events` — в симуляции не осталось событий;
|
|||
|
|
- `time limit reached` — достигнут лимит времени.
|
|||
|
|
|
|||
|
|
Если условия совпали, отсутствие событий проверяется первым, затем полный охват с `-q`, затем лимит. Строка `Final state` всегда показывает фактический охват и трафик к завершению. Если полного охвата не было, выводится `Full coverage: not reached`. Завершение по лимиту не означает, что алгоритм сам остановился.
|
|||
|
|
|
|||
|
|
## 1. Сравнение push, pull и push-pull
|
|||
|
|
|
|||
|
|
Изучите [push.py](push.py), [pull.py](pull.py) и [push_pull.py](push_pull.py). В push информированный узел посылает данные соседям. В pull неинформированный узел запрашивает их; после получения перестаёт инициировать запросы, но продолжает отвечать другим. В push-pull запрос сам может нести информацию, а информированный получатель отвечает своими данными.
|
|||
|
|
|
|||
|
|
До запуска ответьте:
|
|||
|
|
|
|||
|
|
1. Какой подход быстрее распространит информацию в начале, когда источник один?
|
|||
|
|
2. Какой подход быстрее найдёт последних неинформированных участников?
|
|||
|
|
3. Должен ли самый быстрый вариант отправить меньше всего сообщений?
|
|||
|
|
|
|||
|
|
Запустите алгоритмы с одинаковыми параметрами:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
distsys-gossip -i push.py -n 1000 -f 2 -s 123 -d 0 -t 60 -q
|
|||
|
|
distsys-gossip -i pull.py -n 1000 -f 2 -s 123 -d 0 -t 60 -q
|
|||
|
|
distsys-gossip -i push_pull.py -n 1000 -f 2 -s 123 -d 0 -t 60 -q
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Заполните таблицу. Если полного охвата нет, укажите достигнутый охват и число отправлений к лимиту вместо `t_all` и `M_all`.
|
|||
|
|
|
|||
|
|
| Алгоритм | `n` | `f` | `d` | seed | `t_all` | `M_all` | Причина завершения |
|
|||
|
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|||
|
|
| push | 1000 | 2 | 0 | 123 | | | |
|
|||
|
|
| pull | 1000 | 2 | 0 | 123 | | | |
|
|||
|
|
| push-pull | 1000 | 2 | 0 | 123 | | | |
|
|||
|
|
|
|||
|
|
Сравните начальный рост и доставку последним узлам. Объясните результат через действия отправителей. Флаг `-q` использует глобальную статистику симулятора: сами процессы не узнают, что сообщение уже получили все. В push и push-pull периодические обмены без этого ограничения продолжаются.
|
|||
|
|
|
|||
|
|
## 2. Изменение одного параметра
|
|||
|
|
|
|||
|
|
Выберите один алгоритм и сравните каждый следующий запуск с его базовым результатом. В командах замените `push.py` на выбранный файл.
|
|||
|
|
|
|||
|
|
Сначала увеличьте fanout с 2 до 4:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
distsys-gossip -i push.py -n 1000 -f 4 -s 123 -d 0 -t 60 -q
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Затем верните fanout 2 и добавьте вероятность потери 0,2:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
distsys-gossip -i push.py -n 1000 -f 2 -s 123 -d 0.2 -t 60 -q
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Для каждого запуска сначала запишите прогноз, затем добавьте строку результатов в таблицу. Как изменились время и цена охвата? Почему больше контактов за раунд не обязательно означает пропорционально меньшую задержку? Что можно заключить, если охват не достигнут за 60 единиц времени?
|
|||
|
|
|
|||
|
|
Один запуск показывает конкретное выполнение. При наличии времени повторите сравнение на seed `124` и `125`. Одинаковый seed воспроизводит запуск данной реализации; разные алгоритмы расходуют случайные числа по-разному, поэтому их контакты и потери не обязаны совпадать. Если меняете лимит времени, используйте один лимит для сопоставляемых запусков.
|
|||
|
|
|
|||
|
|
## 3. Полный охват и прекращение обменов
|
|||
|
|
|
|||
|
|
Изучите [push_pull_stop.py](push_pull_stop.py) и запустите его без `-q`:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
distsys-gossip -i push_pull_stop.py -n 1000 -f 2 -s 123 -d 0 -t 60
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
При повторном получении информации через `got_info` узел с вероятностью 0,8 отменяет свой таймер и выдаёт `STOPPED`. Он продолжает отвечать на запросы. Неинформированные узлы продолжают искать данные; остановка таймера у держателя не удаляет доступную копию.
|
|||
|
|
|
|||
|
|
Выпишите показатели первой строки с полным охватом и показатели завершения. Совпадают ли они? Какой трафик возникает между ними? Подтвердите по `Finished`, что запуск завершился из-за отсутствия событий, а не по лимиту.
|
|||
|
|
|
|||
|
|
Для сравнения стоимости распространения используйте `M_all` всех четырёх вариантов. Число отправлений к концу запуска с остановкой — другая метрика. Итоговые `max/min/mean` отправлений по узлам также относятся к концу запуска, который может наступить позже полного охвата.
|
|||
|
|
|
|||
|
|
## Обсуждение
|
|||
|
|
|
|||
|
|
- Какие оптимизации могут уменьшить число повторных передач?
|
|||
|
|
- Почему успешный запуск при потерях не доказывает Uniform Agreement при отказах процессов?
|
|||
|
|
- Какая дополнительная информация и логика понадобятся для нескольких сообщений и причинного порядка доставки?
|
|||
|
|
|
|||
|
|
Сформулируйте вывод о скорости распространения, сетевых затратах и прекращении активности отдельно. Свяжите каждый вывод с наблюдением из таблицы и предположениями модели.
|