Init
This commit is contained in:
commit
c394677d07
59 files changed
+5149
No files matched your search
@@ -0,0 +1,163 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Лабораторная работа 7 (итоговая): одна задача — четыре подхода.
|
||||
|
||||
Заполните функции ниже. ИНТЕРФЕЙСЫ МЕНЯТЬ НЕЛЬЗЯ — по ним работают
|
||||
автотесты (tests/test_lab07.py, запускаются через подпроцесс).
|
||||
|
||||
Запуск из корня курса:
|
||||
python lab07_comparison/solution.py
|
||||
"""
|
||||
import asyncio
|
||||
import json
|
||||
import multiprocessing
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||
|
||||
from common.benchmark import amdahl, make_table, save_speedup_plot, time_call
|
||||
from common.tasks import TASKS, dispatch_kernel, get_variant, io_fetch
|
||||
|
||||
# TODO: впишите свой номер в журнале (1..20)
|
||||
VARIANT_NUMBER = 0
|
||||
|
||||
|
||||
# ========================= CPU-сценарий ====================================
|
||||
|
||||
def cpu_sequential(task_name: str, params: dict):
|
||||
"""Последовательно (лаба 1). Вернуть (checksum, сек)."""
|
||||
task = TASKS[task_name]
|
||||
# TODO: build -> замер времени -> split(data, 1) -> kernel -> combine -> checksum
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def cpu_threads(task_name: str, params: dict, p: int):
|
||||
"""На p потоках (лаба 3): ожидание S ≈ 1 из-за GIL. Вернуть (checksum, сек)."""
|
||||
# TODO: как в лабе 3 — ThreadPoolExecutor, kernel напрямую в воркере
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def cpu_processes(task_name: str, params: dict, p: int):
|
||||
"""На p процессах (лаба 4): ожидание S ≈ ядра. Вернуть (checksum, сек)."""
|
||||
# TODO: как в лабе 4 — ctx.Pool + dispatch_kernel
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
# ========================= I/O-сценарий ====================================
|
||||
|
||||
def io_sequential(items: int, delay: float):
|
||||
"""Последовательно (лаба 1). Вернуть (список, сек)."""
|
||||
# TODO: [io_fetch(i, delay) for i in range(items)] с замером
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def io_threads(items: int, delay: float, p: int):
|
||||
"""На p потоках (лаба 2). Вернуть (список, сек)."""
|
||||
# TODO: ThreadPoolExecutor + pool.map(io_fetch, ..., [delay]*items)
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
async def _io_async_coro(items: int, delay: float):
|
||||
"""Корутина (лаба 6): gather + asyncio.sleep. Вернуть (список, сек)."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def io_async(items: int, delay: float):
|
||||
"""Обёртка asyncio.run. Вернуть (список, сек)."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def io_async_limited(items: int, delay: float, max_concurrent: int = 8):
|
||||
"""Async с семафором (лаба 6). Вернуть (список, сек)."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
# ========================= main ============================================
|
||||
|
||||
def _smoke():
|
||||
"""Smoke-режим автотестов: быстрый прогон всех подходов, JSON-отчёт.
|
||||
(не удаляйте: тесты запускают solution.py подпроцессом с LAB_SMOKE=1)"""
|
||||
from common.tasks import smoke_params, run_sequential
|
||||
name, sp = "integrate", smoke_params("integrate")
|
||||
exp, _ = run_sequential(name, sp, parts=1)
|
||||
|
||||
cs1, _ = cpu_threads(name, sp, 2)
|
||||
cs2, _ = cpu_processes(name, sp, 2)
|
||||
ok_cpu = (cs1 == exp or abs(cs1 - exp) < 1e-6) and \
|
||||
(cs2 == exp or abs(cs2 - exp) < 1e-6)
|
||||
|
||||
res, t_seq = io_sequential(8, 0.0)
|
||||
res2, t_thr = io_threads(8, 0.02, 4)
|
||||
res3, t_asy = io_async(8, 0.02)
|
||||
ok_io = len(res) == 8 and len(res2) == 8 and len(res3) == 8
|
||||
|
||||
print("LAB_SMOKE_JSON:" + json.dumps({
|
||||
"ok": True, "cpu_ok": bool(ok_cpu), "io_ok": bool(ok_io),
|
||||
"p": 2, "io_times": {"seq": t_seq, "threads": t_thr, "async": t_asy}}))
|
||||
return
|
||||
|
||||
|
||||
def main():
|
||||
if os.environ.get("LAB_SMOKE") == "1":
|
||||
_smoke()
|
||||
return
|
||||
|
||||
v = get_variant(VARIANT_NUMBER)
|
||||
items, delay = v["io"]["items"], v["io"]["delay"]
|
||||
print(f"Вариант {v['variant']}: {v['describe']}")
|
||||
print(f"I/O: {items} запросов по {delay} c\n")
|
||||
|
||||
# --- CPU-сценарий -------------------------------------------------------
|
||||
print("=== CPU-сценарий ===")
|
||||
cs0, t_seq = cpu_sequential(v["task_name"], v["cpu_params"])
|
||||
print(f"последовательно: {t_seq:.3f} c")
|
||||
cpu_results = {"потоки": [], "процессы": []}
|
||||
for p in v["p_list"]:
|
||||
_, (c1, t_thr) = time_call(cpu_threads,
|
||||
(v["task_name"], v["cpu_params"], p), repeats=2)
|
||||
_, (c2, t_proc) = time_call(cpu_processes,
|
||||
(v["task_name"], v["cpu_params"], p), repeats=2)
|
||||
assert (c1 == cs0 or abs(c1 - cs0) < 1e-6) and \
|
||||
(c2 == cs0 or abs(c2 - cs0) < 1e-6), f"checksum не совпал при p={p}"
|
||||
cpu_results["потоки"].append((p, t_thr))
|
||||
cpu_results["процессы"].append((p, t_proc))
|
||||
print(f"p={p}: потоки {t_thr:.3f} c (S={t_seq/t_thr:.2f}) | "
|
||||
f"процессы {t_proc:.3f} c (S={t_seq/t_proc:.2f})")
|
||||
|
||||
# --- I/O-сценарий ---------------------------------------------------------
|
||||
print("\n=== I/O-сценарий ===")
|
||||
_, t_ioseq = io_sequential(items, delay)
|
||||
_, t_iothr = io_threads(items, delay, 8)
|
||||
_, t_ioasy = io_async(items, delay)
|
||||
_, t_ioasy_lim = io_async_limited(items, delay, 8)
|
||||
io_rows = [("последовательно", t_ioseq),
|
||||
("потоки, p=8", t_iothr),
|
||||
("async", t_ioasy),
|
||||
("async, лимит 8", t_ioasy_lim)]
|
||||
print(make_table(io_rows, title="I/O-сценарий"))
|
||||
|
||||
# --- График CPU ------------------------------------------------------------
|
||||
save_speedup_plot(cpu_results,
|
||||
f"CPU: ускорение ({v['describe']})",
|
||||
os.path.join(os.path.dirname(__file__), "speedup_cpu.png"))
|
||||
|
||||
# --- Оценка s по Амдалу -----------------------------------------------------
|
||||
p_max = max(v["p_list"])
|
||||
s_meas = t_seq / cpu_results["процессы"][-1][1]
|
||||
best_s, best_diff = None, float("inf")
|
||||
for i in range(1, 200): # перебираем s = 0.005 .. 0.995
|
||||
s = i / 200
|
||||
diff = abs(amdahl(s, p_max) - s_meas)
|
||||
if diff < best_diff:
|
||||
best_diff, best_s = diff, s
|
||||
print(f"\nИзмеренное S({p_max}) = {s_meas:.2f}; "
|
||||
f"по закону Амдала это соответствует s ≈ {best_s:.3f} "
|
||||
f"(доля последовательного кода с накладными расходами)")
|
||||
|
||||
# TODO: в отчёт — обе таблицы, график, объяснение s, развёрнутые выводы
|
||||
# по всему курсу (это итоговая работа).
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user