58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""Демо: предвестник лабы 3 — потоки НЕ ускоряют счёт.
|
||
|
||
Запуск из корня курса:
|
||
python lab02_threads/examples/03_threads_cpu_demo.py
|
||
|
||
Та же схема, что с sleep, но вместо sleep — счёт. Время не уменьшается:
|
||
GIL разрешает исполнять байт-код Python только одному потоку.
|
||
Подробное исследование — лабораторная 3.
|
||
"""
|
||
import os
|
||
import sys
|
||
import threading
|
||
import time
|
||
|
||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
||
|
||
|
||
def cpu_worker(n: int) -> None:
|
||
s = 0.0
|
||
for i in range(n):
|
||
s += i ** 0.5 # чистый Python-код: держит GIL
|
||
return s
|
||
|
||
|
||
def run_threads(n_threads: int, n_per_thread: int) -> float:
|
||
threads = [threading.Thread(target=cpu_worker, args=(n_per_thread,))
|
||
for _ in range(n_threads)]
|
||
t0 = time.perf_counter()
|
||
for t in threads:
|
||
t.start()
|
||
for t in threads:
|
||
t.join()
|
||
return time.perf_counter() - t0
|
||
|
||
|
||
def main():
|
||
TOTAL = 3_000_000
|
||
|
||
t0 = time.perf_counter()
|
||
cpu_worker(TOTAL)
|
||
t_seq = time.perf_counter() - t0
|
||
print(f"1 поток, {TOTAL:,} итераций: {t_seq:.3f} c")
|
||
|
||
t2 = run_threads(2, TOTAL // 2)
|
||
print(f"2 потока, по {TOTAL // 2:,}: {t2:.3f} c "
|
||
f"(ускорение x{t_seq / t2:.2f})")
|
||
|
||
t4 = run_threads(4, TOTAL // 4)
|
||
print(f"4 потока, по {TOTAL // 4:,}: {t4:.3f} c "
|
||
f"(ускорение x{t_seq / t4:.2f})")
|
||
|
||
print("\nУскорения нет (даже хуже!) — GIL. Но тот же код с time.sleep")
|
||
print("ускорился бы почти идеально (демо 01). Разницу изучаем в лабе 3.")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |