Files
2026-10-07 13:06:47 +05:00

6.1 KiB
Raw Permalink Blame History

Лабораторная работа 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).