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

84 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
"""Лабораторная работа 2: многопоточный код (I/O-bound).
Заполните функции ниже. ИНТЕРФЕЙСЫ МЕНЯТЬ НЕЛЬЗЯ — по ним работают
автотесты (tests/test_lab02.py).
Запуск из корня курса:
python lab02_threads/solution.py
"""
import os
import sys
import threading
import time
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from common.benchmark import make_table, save_speedup_plot, time_call
from common.tasks import get_variant, io_fetch
# TODO: впишите свой номер в журнале (1..20)
VARIANT_NUMBER = 0
def _split_range(items: int, parts: int):
"""Разбиение range(items) на parts почти равных кусков (списки item'ов)."""
# TODO: верните список из parts списков номеров запросов
raise NotImplementedError
def run_io_threads_manual(items: int, delay: float = 0.05, p: int = 4):
"""I/O-нагрузка на p ручных потоках.
Каждый поток обрабатывает СВОЙ кусок и кладёт результаты в СВОЙ список.
Вернуть (список_результатов, elapsed_seconds), упорядочено по item.
Подсказки:
- threading.Thread(target=worker, args=(...));
- start() всех потоков ДО первого join() — иначе выйдет последовательно.
"""
raise NotImplementedError
def run_io_threads_pool(items: int, delay: float = 0.05, p: int = 4):
"""I/O-нагрузка через ThreadPoolExecutor(max_workers=p) и pool.map.
Вернуть (список_результатов, elapsed_seconds), упорядочено по item.
pool.map сохраняет порядок входа независимо от порядка завершения.
"""
raise NotImplementedError
def main():
v = get_variant(VARIANT_NUMBER)
items, delay = v["io"]["items"], v["io"]["delay"]
print(f"Вариант {v['variant']}: I/O-нагрузка {items} запросов по {delay} c\n")
rows = {"ручные потоки": [], "пул потоков": []}
for p in v["p_list"]:
t1, (res, _) = time_call(run_io_threads_manual, (items, delay, p), repeats=1)
assert [r[0] for r in res] == list(range(items)), "порядок нарушен!"
rows["ручные потоки"].append((p, t1))
t2, (res, _) = time_call(run_io_threads_pool, (items, delay, p), repeats=1)
assert [r[0] for r in res] == list(range(items)), "порядок нарушен!"
rows["пул потоков"].append((p, t2))
ideal = items * delay / p
print(f"p={p}: вручную {t1:.3f} c | пул {t2:.3f} c | идеал ≈ {ideal:.3f} c")
print()
table_rows = [(f"пул, p={p}", t) for p, t in rows["пул потоков"]]
print(make_table(table_rows, title="Пул потоков"))
save_speedup_plot(
rows,
f"Ускорение I/O-нагрузки потоками ({items} запросов)",
os.path.join(os.path.dirname(__file__), "speedup.png"))
# TODO: в отчёт — почему ускорение близко к идеальному?
# TODO (по желанию, +1 балл): submit + as_completed, порядок завершения
if __name__ == "__main__":
main()