# -*- 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()