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

116 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Лабораторная работа 1. Последовательное вычисление и профилирование
**Время на работу:** 2 пары.
## Цель работы
Создать базовую линию: последовательную реализацию своей задачи и её замеры.
Без неё невозможно показать ускорение в следующих лабораторных — нечего будет
ускорять.
## Теория
### Последовательное вычисление
Программа выполняет операцию за операцией, в одном потоке управления. Это
простейшая и самая предсказуемая модель: результат не зависит от порядка
выполнения, время выполнения = сумма времён всех операций. Все дальнейшие
лабораторные сравниваются с этой базой.
### Два типа нагрузки
**CPU-bound** — программа ограничена скоростью процессора: считает, шифрует,
сортирует. Время определяется числом элементарных операций.
**I/O-bound** — программа ограничена ожиданием: сеть, диск, база данных.
Время определяется временем ожидания ответов, процессор при этом простаивает.
Отличить просто: если удалить «полезную работу», а программа всё равно
медленная — это I/O-bound; если быстрая — CPU-bound. Тип нагрузки определяет,
какая модель параллелизма поможет (потоки — для I/O, процессы — для CPU,
async — для I/O в больших количествах).
### Время: настенное и процессорное
- `time.perf_counter()` — «настенные» часы: сколько времени прошло реально
(включая сон и ожидание). Ими меряют всё в этом курсе.
- `time.process_time()` — только время, потраченное процессором.
Разница между ними для I/O-задачи огромна — это её диагноз.
Обе функции монотонные (не откатываются назад, как `time.time()` при
переводе часов), имеют наносекундное разрешение — всегда используйте их, а не
`time.time()`.
### Профилирование
Профилировщик отвечает на вопрос «где программа проводит время». `cProfile`
собирает статистику по функциям: число вызовов, суммарное время, время без
вложенных вызовов.
```python
import cProfile
cProfile.run("main()", sort="cumulative")
```
Интерпретация: колонка `cumtime` — общее время функции (с вызовами),
`totime` — собственное. Первые строки обычно сразу показывают узкое место.
## Задание
Ваша задача и параметры — по варианту (`common/варианты.md`), доступ:
```python
from common.tasks import get_variant, TASKS
v = get_variant(13) # ваш номер
task = TASKS[v["task_name"]]
data = task["build"](v["cpu_params"])
```
Заполните `solution.py` (интерфейсы менять нельзя):
1. **`run_cpu_sequential(task_name, params, parts=4)`** — выполняет задачу
последовательно: `build` → разбиение на `parts` кусков → `kernel` для
каждого куска в цикле → `combine` → вернуть `checksum`. Куски
обязательны: в следующих лабораторных те же куски уйдут воркерам.
2. **`run_io_sequential(items, delay)`** — для каждого элемента вызывает
`common.tasks.io_fetch(item, delay)` и собирает результаты в список
(в порядке возрастания item).
3. **`main()`** — запускает обе части на параметрах своего варианта, выводит
таблицу времен (`common.benchmark.make_table`) и значения checksum.
### Измерения для отчёта
- CPU-часть: T(1) при разбиении на 1, 2, 4 куска (убедитесь, что checksum
одинаков и время почти не меняется — разбиение не должно менять работу).
- I/O-часть: суммарное время для items из варианта; сравните
`perf_counter` и `process_time` — увидите, сколько времени машина спит.
- Профилирование CPU-части: `cProfile.run(...)`, топ-5 функций по времени.
Укажите в отчёте, какая функция — узкое место.
## Контрольные вопросы
1. Чем CPU-bound задача отличается от I/O-bound? Какая у вас?
2. Почему для замеров нужен `perf_counter`, а не `time.time()`?
3. Что показывает `cumtime` и `tototime` в выводе cProfile?
4. Почему checksum не должен зависеть от числа кусков? Что это проверяет?
## Что сдаётся
`solution.py` + отчёт по шаблону: таблицы T(1/2/4 кусков), время I/O-части,
сравнение perf_counter/process_time, топ-5 из cProfile, анализ.
## Критерии оценки
| Пункт | Баллы |
|---|---|
| `run_cpu_sequential` работает, checksum совпадает при разном разбиении | 2 |
| `run_io_sequential` работает | 1 |
| Замеры и сравнение perf_counter/process_time | 2 |
| Профилирование и вывод об узком месте | 2 |
| Отчёт: таблицы, анализ, ответы на вопросы | 3 |
## Типичные ошибки
См. `common/типичные_ошибки.md` (пп. 8, 9). Здесь их всего две: замеры в
отладчике и замеры без повторов.