59. λμμ±μ μν΄ μ€λ λκ° νμν κ²½μ°μλ ThreadpoolExecutor λ₯Ό μ¬μ©νλΌ
1. concurrent.futures μ ThreadpoolExecutor λ΄μ₯ λͺ¨λ
Thread μ Queue λ₯Ό μ¬μ©ν μ κ·Ό λ°©λ²λ€μ μ₯μ μ μ‘°ν©νμ¬ λ³λ ¬ I/O λ¬Έμ ν΄κ²°
ALIVE = '*'
EMPTY = '-'
class Grid :
...
class LockingGrid (Grid ):
...
def count_neighbors (y , x , get ):
...
def game_logic (state , neighbors ):
...
# μ¬κΈ°μ λΈλ‘νΉ# I/Oλ₯Ό μννλ€
data = my_socket .recv (100 )
...
def step_cell (y , x , get , set ):
state = get (y , x )
neighbors = count_neighbors (y , x , get )
next_state = game_logic (state , neighbors )
set (y , x , next_state )
Grid μ κ° μ
μ λν΄ μ Thread μΈμ€ν΄μ€λ₯Ό μμνλ λμ ν¨μλ₯Ό μ€νκΈ°(executor)μ μ λ¬νμ¬ ν¬μμ
μ€νκΈ°λ μ λ¬λ°μ ν¨μλ₯Ό λ³λμ μ€λ λμμ μν
λμ€μ ν¬μΈνκΈ° μν΄ λͺ¨λ μμ
μ κ²°κ³Όλ₯Ό κΈ°λ€λ¦Ό
from concurrent .futures import ThreadPoolExecutor
def simulate_pool (pool , grid ):
next_grid = LockingGrid (grid .height , grid .width )
futures = []
for y in range (grid .height ):
for x in range (grid .width ):
args = (y , x , grid .get , next_grid .set )
future = pool .submit (step_cell , * args ) # ν¬μμ
futures .append (future )
for future in futures :
future .result () # ν¬μΈ
return next_grid
class ColumnPrinter :
...
grid = LockingGrid (5 , 9 )
grid .set (0 , 3 , ALIVE )
grid .set (1 , 4 , ALIVE )
grid .set (2 , 2 , ALIVE )
grid .set (2 , 3 , ALIVE )
grid .set (2 , 4 , ALIVE )
columns = ColumnPrinter ()
with ThreadPoolExecutor (max_workers = 10 ) as pool :
for i in range (5 ):
columns .append (str (grid ))
grid = simulate_pool (pool , grid )
print (columns )
> >>
0 | 1 | 2 | 3 | 4
- - - * - - - - - | - - - - - - - - - | - - - - - - - - - | - - - - - - - - - | - - - - - - - - -
- - - - * - - - - | - - * - * - - - - | - - - - * - - - - | - - - * - - - - - | - - - - * - - - -
- - * * * - - - - | - - - * * - - - - | - - * - * - - - - | - - - - * * - - - | - - - - - * - - -
- - - - - - - - - | - - - * - - - - - | - - - * * - - - - | - - - * * - - - - | - - - * * * - - -
- - - - - - - - - | - - - - - - - - - | - - - - - - - - - | - - - - - - - - - | - - - - - - - - -
μ€νκΈ°λ μ¬μ©ν μ€λ λλ₯Ό 미리 ν λΉ
simulate_pool μ μ€νν λ λ§λ€ μ€λ λ μμ λΉμ© κ°μ
λ³λ ¬ I/O λ¬Έμ ν΄κ²° μν Thread λ‘ μΈν λ©λͺ¨λ¦¬ λΆμ‘± λ¬Έμ λ₯Ό μ€λ λ νμ μ¬μ©ν μ€λ λ μ΅λ κ°μλ₯Ό μ§μ νμ¬ ν΄κ²°
max_workers νλΌλ―Έν° μ¬μ©
**ThreadPoolExecutor μ₯μ **
submit λ©μλκ° λ°ννλ Future μΈμ€ν΄μ€μ λν΄ result λ©μλλ₯Ό νΈμΆνλ©΄ μ€λ λλ₯Ό μ€ννλ μ€μ λ°μν μμΈ μλ propagation
def game_logic (state , neighbors ):
...
raise OSError ('I/O λ¬Έμ λ°μ' )
...
with ThreadPoolExecutor (max_workers = 10 ) as pool :
task = pool .submit (game_logic , ALIVE , 3 )
task .result ()
> >>
Traceback ...
OSError : I / O λ¬Έμ λ°μ
count_neighbors ν¨μμ I/O λ³λ ¬μ±μ μ 곡ν΄μΌ νλ κ²½μ°
ThreadPoolExecutor κ° step_cell μ μΌλΆλΆμΌλ‘ λ ν¨μλ₯Ό μ΄λ―Έ λμμ μ€ννκ³ μμΌλ―λ‘ λ³κ²½ νμ μμ
λ¨μ
ThreadPoolExecutor κ° μ νλ μμ I/O λ³λ ¬μ±λ§ μ 곡ν¨
max_workers λ₯Ό 100μΌλ‘ μ€μ ν΄λ λμ I/O κ° νμν 그리λμ 10000κ° μ΄μμ μ
μ λ£μ κ²½μ° νμ₯ λΆκ°
ThreadPoolExecutor λ λΉλκΈ°μ μΈ ν΄λ²μ΄ μ‘΄μ¬νμ§ μμ μν©μ μ²λ¦¬νλ κ²½μ° μ’μ λ°©λ²
λ§μ κ²½μ° I/O λ³λ ¬μ±μ μ΅λνν μ μλ λ λμ λ°©λ² μ‘΄μ¬(Corutine)