110 lines
6.1 KiB
Markdown
110 lines
6.1 KiB
Markdown
# Лабораторная работа 7. Сравнительный анализ: одна задача — четыре подхода
|
||
|
||
**Время на работу:** 2 пары. **Зависимости:** лабы 1–6. Итоговая работа.
|
||
|
||
## Цель работы
|
||
|
||
Свести весь курс в одну таблицу: ваша CPU-задача и ваша I/O-нагрузка,
|
||
выполненные последовательно, потоками, процессами и асинхронно. Объяснить
|
||
каждую цифру. Это работа для защиты: по ней проверяется понимание всего
|
||
курса.
|
||
|
||
## Теория
|
||
|
||
### Ускорение и эффективность
|
||
|
||
- Ускорение: **S(p) = T(1) / T(p)** — во сколько раз быстрее на p воркерах.
|
||
- Эффективность: **E(p) = S(p) / p** — насколько эффективно используется
|
||
каждый воркер. E = 1 — идеал, E = 0.5 — половина мощности простаивает.
|
||
|
||
### Закон Амдала
|
||
|
||
Если доля последовательного кода задачи равна s (0 ≤ s ≤ 1), то ускорение
|
||
ограничено:
|
||
|
||
```
|
||
S(p) ≤ 1 / (s + (1 − s) / p)
|
||
```
|
||
|
||
При s = 0.1 и p → ∞: S ≤ 10. Даже бесконечное число воркеров не даст
|
||
больше 10×. Отсюда главный вывод курса: **сначала сокращайте
|
||
последовательную часть и накладные расходы, потом наращивайте p.**
|
||
|
||
В `common.benchmark` есть `amdahl(s, p)` — сравните свои S(p) с теорией:
|
||
зная измеренное S(p), можно оценить эффективную долю последовательной части
|
||
вашего эксперимента (создание пулов, pickle, GIL-переключения — всё это
|
||
«последовательная» часть).
|
||
|
||
### Матрица выбора модели
|
||
|
||
| Задача | Потоки | Процессы | asyncio |
|
||
|---|---|---|---|
|
||
| CPU-bound (чистый Python) | ✗ (GIL) | ✓ | ✗ (блокирует loop) |
|
||
| CPU-bound в C-коде (hashlib, numpy) | ✓ | ✓ | ✗ |
|
||
| I/O-bound, десятки задач | ✓ | возможно (дорого) | ✓ |
|
||
| I/O-bound, тысячи задач | дорого | ✗ | ✓✓ |
|
||
|
||
## Задание
|
||
|
||
Заполните `solution.py` — оба сценария из ваших лабораторных:
|
||
|
||
**CPU-сценарий** (задача из варианта):
|
||
1. `cpu_sequential(task_name, params)` — как в лабе 1;
|
||
2. `cpu_threads(task_name, params, p)` — как в лабе 3 (S ≈ 1!);
|
||
3. `cpu_processes(task_name, params, p)` — как в лабе 4 (S ≈ ядра).
|
||
|
||
**I/O-сценарий** (items × delay из варианта):
|
||
4. `io_sequential(items, delay)` — как в лабе 1;
|
||
5. `io_threads(items, delay, p)` — как в лабе 2;
|
||
6. `io_async(items, delay)` — как в лабе 6;
|
||
7. `io_async_limited(items, delay, max_concurrent)` — с семафором 8.
|
||
|
||
**`main()`** — таблицы для обоих сценариев с T(p), S(p), E(p); два графика
|
||
ускорения; оценка доли s по закону Амдала для процессов.
|
||
|
||
### Ожидаемые результаты (сверьтесь)
|
||
|
||
CPU: потоки S ≈ 1; процессы S(p) ≈ до числа физических ядер.
|
||
I/O: последовательный — база; потоки и async — S ≈ p; async без лимита —
|
||
минимальное время (нет расходов на потоки); processes для I/O — работает,
|
||
но с заметными накладными расходами.
|
||
|
||
### Что дополнительно оценить
|
||
|
||
- Разница T(1) у процессов против последовательного — цена старта процессов
|
||
и pickle.
|
||
- По S(p_max) процессов найдите s через `amdahl` (подберите s так, чтобы
|
||
теория совпала с практикой) — укажите его в отчёте.
|
||
|
||
## Контрольные вопросы
|
||
|
||
1. Почему потоки не ускорили CPU-задачу, но ускорили I/O?
|
||
2. Почему asyncio на I/O обгоняет потоки? Откуда выигрыш?
|
||
3. Какая доля последовательного кода получилась у процессов по Амдалу?
|
||
Что в неё входит?
|
||
4. Какую модель вы выбрали бы для веб-краулера на 10 000 страниц?
|
||
Для рендера видео? Обоснуйте.
|
||
5. Что в ваших замерах не совпало с теорией и почему?
|
||
|
||
## Что сдаётся
|
||
|
||
`solution.py` + отчёт: две таблицы (CPU и I/O) с T/S/E, два графика,
|
||
оценка s по Амдалу, развёрнутые выводы (это итоговая работа — выводы
|
||
должны покрывать весь курс), ответы на вопросы.
|
||
|
||
## Критерии оценки
|
||
|
||
| Пункт | Баллы |
|
||
|---|---|
|
||
| Все 7 функций работают, checksum корректен | 3 |
|
||
| Таблицы и графики для обоих сценариев | 3 |
|
||
| Оценка s по закону Амдала с объяснением | 2 |
|
||
| Выводы и ответы на вопросы (защита) | 4 |
|
||
|
||
## Типичные ошибки
|
||
|
||
- Сравнение T(p) разных сценариев при разном объёме работы — объём
|
||
фиксирован внутри сценария.
|
||
- Забыт smoke-режим `LAB_SMOKE` (автотесты запускают solution.py
|
||
подпроцессом — не удаляйте блок в main()).
|
||
- Замеры в один запуск без повторов: `time_call(..., repeats=3)`. |