동시성과 Queue를 사용하기 위해 코드를 어떻게 리팩토링해야 하는지 이해하라

매일 공부(ML)·2022년 8월 2일
0

이어드림

목록 보기
113/146

queue 내장 모듈의 Queue 클래스를 사용해서 파이프라인을 스레드로 실행하게 구현

아래와 같은 문제 해결

  • Simulate_thread 함수의 방식보다 simulate pipeline함수가 더 따라가기 어렵다

  • 코드의 가독성을 개선하려면 ClosableQueue와 StoppableWorker라는 추가 지원 클래스가 필요하게 되고, 복잡도도 함께 증가한다.

  • 병렬성을 활용하여 필요에 따라서 자동으로 시스템 규모가 확장되지않는다.

    • 미리 부하를 예측하여 잠재적인 병렬성 수준을 지정한다.
  • 디버깅을 활성화하려면 발생한 예외를 작업 스레드에서 수동으로 잡아서 Queue를 통해 전달하고 주 스레드에서 다시 발생 시킨다.


그러나, 결국 요구 사항이 다시 변경했을 때 큰 문제들이 나타나게 된다.


def count_neighbors(y,x,get):
    #여기서 블로킹 I/O를 수행
    data = my_socket.recv(100)


#위의 함수를 병렬화하기 위해서 파이프라인 추가
# 작업자 스레드 사이에서 예외가 제대로 전달하여 주 스레드까지 도달하는지 확인
# 동기화를 위해서 Grid 클래스의 Lock사용


def count_neighbors_thread(item):
    y, x, state, get = item
    try:
        neighbors = count_neighbors(y,x,get)
    except Exception as e:
        neighbors = 3
    return (y,x,state, neighbors)

def game_logic_thread(item):
    y , x, state, neighbors = item
    if isinstance(neighbors, Exception):
        next_state = neighbors
    else:
        try:
            next_state = game_logic(state, neighbors)
        except Exception as e:
            next_state = 0
    return (y, x, next_state)

class LockingGrid(Grid):
#count_neighbors_thread 작업자와 그에 해당하는 Thread 인스턴스를 위해서
#다른 Queue 인스턴스 집합 만들기

in_queue = ClosableQueue()
logic_queue = ClosableQueue()
out_queue = ClosableQueue()

threads = []

for _ in range(5):
    thread = StoppableWorker(count_neighbors_thread, in_queue, logic_queue)
    thread.start()
    threads.append(thread)


for _ in range(5):
    thread = StoppableWorker(game_logic_thread, logic_queue, out_queue)
    thread.start()
    threads.append(thread)

중요 포인트

  • 변경해야할 부분도 많고 코드도 많이 필요하다

  • Queue가 팬아웃과 팬인 문제를 해결하지만 부가 비용이 많다.

  • Thread만 사용하는 방식보다 Queue를 사용하는 방식이 더 좋지만 Queue는 파이썬이 제공하는 다른 도구만큼 좋지 않다>


Summary

  • 작업자 스레드 수를 고정하고 Queue와 함께 사용하면 스레드를 사용할 때 팬인과 팬아웃의 규모 확장성을 개선한다.

  • Queue를 사용하도록 기존 코드를 리팩터링하려면 상당히 많은 작업이 필요한데 다단계로 이뤄진 파이프라인이 필요하면 작업량이 더 늘어난다.

  • 다른 파이썬 내장 기능이나 모듈이 제공하는 병렬 I/O를 가능하게 해주는 다른 기능과 비교 시, Queue는 프로그램이 활용할 수 있는 전체 I/O병렬성의 정도를 제한한다.

profile
성장을 도울 아카이빙 블로그

0개의 댓글