내용 이전
https://white.seolpyo.com/entry/25/
파이썬 멀티프로세싱 Pool과 Process 차이점 비교 - 하얀설표 블로그
파이썬 멀티프로세싱에 대해 인터넷을 검색해보면 이런 말이 자주 보였다. Pool은 처리할 일을 바닥에 뿌려놓고 알아서 분산 처리를 하게 만드는 방식이고,Process는 각 프로세스별로 할당량을 명
white.seolpyo.com
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
파이썬 멀티프로세싱에 대해 인터넷을 검색해보면 이런 말이 보인다.
Pool 은 처리할 일을 바닥에 뿌려놓고 알아서 분산 처리를 하게 만드는 방식이고,
Process는 각 프로세스별로 할당량을 명시적으로 정해준 뒤 실행되는 방식이다.
(그래서 이게 무슨 뜻이라는 걸까)
아주 틀린 말은 아니겠지만, 개인적으로 위와 같은 설명은 깔끔한 설명이 되지 못한다고 생각한다.(개인적으로 저 설명을 통해 무엇을 할 수 있는 것인지 알 수가 없다고 생각한다.)
제일 답답했던건 위와 같은 문구가 하나가 아니라 멀티프로세싱을 다루는 거의 모든 글에서 위와 같은 설명을 미사여구만 살짝 바꿨을 뿐 그대로 쓰고 있다는 점이다.
그러다 문득, 떠오른 생각이 있어 따로 정리해본다.
사전 설명
먼저, 내가 하려는 것은 단순한 작업 시간 비교이다.
일정 시간 슬립하게 하고, 전체 작업 시간을 출력해서 어떤 차이를 만들 수 있는지를 알아볼 것이다.
Pool
import multiprocessing as redfoxtistory
from time import sleep, time
def f(sec):
sec = int(sec)
print(f'{sec}초 대기')
sleep(sec)
print(f'{sec}초 대기 완료')
if __name__ == '__main__':
t = time()
with redfoxtistory.Pool(processes = 2) as p:
p.map(f, ['1', '3', '5', '7'])
print(f'전체 작업 시간 : {time() - t}초')
>> 1초 대기
3초 대기
1초 대기 완료
5초 대기
3초 대기 완료
7초 대기
5초 대기 완료
7초 대기 완료
전체 작업 시간 : 10.256101846694946초
Process
import multiprocessing as redfoxtistory
from time import sleep, time
def f(sec):
sec = int(sec)
print(f'{sec}초 대기')
sleep(sec)
print(f'{sec}초 대기 완료')
if __name__ == '__main__':
t = time()
p1 = redfoxtistory.Process(target = f, args = ('1'))
p2 = redfoxtistory.Process(target = f, args = ('3'))
p3 = redfoxtistory.Process(target = f, args = ('5'))
p4 = redfoxtistory.Process(target = f, args = ('7'))
p1.start()
p2.start()
p1.join()
p2.join()
p3.start()
p4.start()
p3.join()
p4.join()
print(f'전체 작업 시간 : {time() - t}초')
>> 1초 대기
3초 대기
1초 대기 완료
3초 대기 완료
5초 대기
7초 대기
5초 대기 완료
7초 대기 완료
전체 작업 시간 : 10.393099308013916초
최소 작업시간
위 코드들에서는 2개의 프로세스를 사용하며, 각각 1초, 3초, 5초, 7초의 슬립 시간을 가진다.
여기서 가장 최소 작업시간을 소요하는 방법은 cpu1에서 1초 슬립 후 7초 슬립을, cpu2에서 3초 슬립 후 5초 슬립을 하는 것이다.
그러나 위에 있는 모든 코드들은 10초의 작업시간을 보여주는데, 이는 cpu1에서 1초 슬립 후 5초 슬립을, cpu2에서 3초 슬립 후 7초 슬립을 하고 있기 때문이다.
작업 순서 개선
이번에는 10초가 아닌 8초의 작업 시간을 만들어볼 것이다.
import multiprocessing as redfoxtistory
from time import sleep, time
def f(sec):
sec = int(sec)
print(f'{sec}초 대기')
sleep(sec)
print(f'{sec}초 대기 완료')
if __name__ == '__main__':
t = time()
p1 = redfoxtistory.Process(target = f, args = ('1'))
p2 = redfoxtistory.Process(target = f, args = ('3'))
p3 = redfoxtistory.Process(target = f, args = ('5'))
p4 = redfoxtistory.Process(target = f, args = ('7'))
p1.start()
p2.start()
p1.join()
p4.start()
p2.join()
p3.start()
p3.join()
p4.join()
print(f'전체 작업 시간 : {time() - t}초')
>> 1초 대기
3초 대기
1초 대기 완료
7초 대기
3초 대기 완료
5초 대기
7초 대기 완료
5초 대기 완료
전체 작업 시간 : 8.322612047195435초
차이점
이번에는 Process의 작업 순서를 임의로 조정했다. 코드 실행 부분을 보면 p1작업(1초슬립) 후에 p3(5초슬립)가 아닌 p4작업(7초슬립)을 했고, 그리고 p2작업(3초슬립) 후에 p4(7초슬립)가 아닌 p3(5초슬립) 작업을 실행하게 만들었다.
결론
Pool과 Process의 차이는 단일 프로세스가 아닌 multiProcessing을 사용하는 경우 코드 작성자가 직접 작업 순서를 결정할 수 있는 것에 있다.
Pool 역시 작업 순서를 결정할 수 없는 것은 아니나, 각 프로세스별 작업 시간을 알고 있는 상태에서 작업 순서를 하나씩 지정하는 부분에서는 multiprocessing.Pool보다는 multiprocessing.Process가 좀 더 알아보기 쉬운 편이라고 생각된다.
물론 그만큼 코드가 길어지고 지저분해보이게 되며, Pool 역시 순서를 조정할 수 없는 것은 아니다보니 무엇이 더 좋다고 말하기는 어려울 것 같다.
참고)multiprocessing.Process 작업순서
Process 코드를 보면 p1과 p2 join 후 p3과 p4를 start하거나, p1 join 후 p4 start, p2 join 후 p3 start를 하고 있다.
p1~p4를 한 번에 start한 다음 p1~p4를 한 번에 join하지 않은 이유는, 이 경우 4개의 작업이 동시에 이루어지기 때문이다.
Pool에서는 2개의 프로세스만 사용했는데, 이렇게 되면 2개의 프로세스와 4개의 프로세스 작업 속도를 비교하게 되버린다.
import multiprocessing as redfoxtistory
from time import sleep, time
def f(sec):
sec = int(sec)
print(f'{sec}초 대기')
sleep(sec)
print(f'{sec}초 대기 완료')
if __name__ == '__main__':
t = time()
p1 = redfoxtistory.Process(target = f, args = ('1'))
p2 = redfoxtistory.Process(target = f, args = ('3'))
p3 = redfoxtistory.Process(target = f, args = ('5'))
p4 = redfoxtistory.Process(target = f, args = ('7'))
p1.start()
p2.start()
p3.start()
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
print(f'전체 작업 시간 : {time() - t}초')
>> 1초 대기
5초 대기
3초 대기
7초 대기
1초 대기 완료
3초 대기 완료
5초 대기 완료
7초 대기 완료
전체 작업 시간 : 7.346333742141724초
참고)multiprocessing.Pool 작업순서 조정
multiprocessing.Pool 역시 작업 순서 조정이 가능하다.
이 경우 Process보다 코드도 짧아 깔끔해보이긴 하지만, 사용하는 프로세스 수에 따라 작업 순서가 급변하게 되니 나중에 코드를 수정하게 되었을 때, 전체 작업 시간을 줄이기 위한 순서를 조정하는데에는 Process로 직접 순서를 정해주는 것보다 애를 먹을 것 같다.
이전 코드와 달라진 부분은 args 부분으로, 기존에는 1, 3, 5, 7이었던 순서가 1, 3, 7, 5로 변경되었다.
import multiprocessing as redfoxtistory
from time import sleep, time
def f(sec):
sec = int(sec)
print(f'{sec}초 대기')
sleep(sec)
print(f'{sec}초 대기 완료')
if __name__ == '__main__':
t = time()
with redfoxtistory.Pool(processes = 2) as p:
p.map(f, ['1', '3', '7', '5'])
print(f'전체 작업 시간 : {time() - t}초')
>> 1초 대기
3초 대기
1초 대기 완료
7초 대기
3초 대기 완료
5초 대기
7초 대기 완료
5초 대기 완료
전체 작업 시간 : 8.246297597885132초
'파이썬 > 예제' 카테고리의 다른 글
파이썬 절사평균 구하기 예제 (0) | 2022.01.08 |
---|---|
파이썬 tqdm을 while문에서 사용하기 예제 (1) | 2021.02.27 |
파이썬 네이버 뉴스 API 예제(requests 모듈 사용) (0) | 2021.02.25 |
파이썬 네이버 데이터랩 urllib 예제를 requests 예제로 바꾸기 (0) | 2021.02.24 |
최근댓글