파이썬으로 멀티프로세싱 vs 멀티 스레딩
조회수 16816회
1 답변
-
threading은 스레드를 여러개, multiprocessing은 프로세스를 여러개 쓰는걸 의미하고
하나의 프로세스 안에는 여러개 스레드가 있을 수 있기 때문에 프로세스가 스레드보다 더 큽니다.
스레드는 프로세스 내에서 스레드끼리 같은 메모리 공간을 쓰고, 프로세스는 서로 다른 메모리 공간을 씁니다.
따라서 멀티프로세싱을 쓰는 경우 프로세스 간에 같은 객체를 공유하는 게 어렵습니다 항상 객체를 공유하는 게 좋지만은 않은데요, 동시에 여러 개의 스레드가 같은 자원을 쓸 때는 race condition이 발생해 예상치 못한 결과가 날 수 있습니다.
예를 들어 리스트에 원소를 하나씩 append해 mylist = [1,2,3,...,300]을 만들려고 할 때, 스레드를 여러 개 만들어 속도를 높이는 코드를 다음과 같이 만들었다고 하면
import thread, time mylist = [[0,1]] def listTo300Elem(id): while len(mylist) < 300: #원소가 300개 이상이 되면 멈춤 mylist.append([id, mylist[-1][1]+1]) #어느스레드가 append했는지 마크 thread.start_new_thread(listTo300Elem, (1,)) #스레드 id 1 thread.start_new_thread(listTo300Elem, (2,)) #스레드 id 2 thread.start_new_thread(listTo300Elem, (3,)) #스레드 id 3 thread.start_new_thread(listTo300Elem, (4,)) #스레드 id 4 thread.start_new_thread(listTo300Elem, (5,)) #스레드 id 5 thread.start_new_thread(listTo300Elem, (6,)) #스레드 id 6 thread.start_new_thread(listTo300Elem, (7,)) #스레드 id 7 time.sleep(5) #충분히 기다려줌 print mylist
결과 :
[[0, 1], [1, 2], [1, 3], [1, 4], [1, 5], ..., [7, 222], [7, 223], [3, 224], [3, 225], [3, 226], [3, 227], [3, 228], [3, 229], [3, 230], [3, 231], [3, 232], [3, 233], [3, 234], [3, 235], [3, 236], [3, 237], [3, 238], [3, 239], [3, 240], [3, 241], [3, 242], [3, 243], [3, 244], [3, 245], [3, 246], [3, 247], [3, 248], [6, 249], [6, 250], [6, 251], [6, 252], [6, 253], [6, 254], [6, 255], [6, 256], [6, 257], [6, 258], [6, 259], [6, 260], [6, 261], [6, 262], [6, 263], [6, 264], [6, 265], [6, 266], [6, 267], [6, 268], [6, 269], [6, 270], [6, 271], [6, 272], [6, 273], [6, 274], [6, 275], [6, 276], [6, 277], [6, 278], [6, 279], [6, 280], [6, 281], [6, 282], [6, 283], [6, 284], [6, 285], [6, 286], [6, 287], [6, 288], [6, 289], [6, 290], [6, 291], [6, 292], [6, 293], [6, 294], [6, 295], [6, 296], [6, 297], [6, 298], [3, 299], [3, 300], [7, 224], [6, 225], [1, 107]]
예상대로라면 마지막 원소는
[어떤 id, 300]
이 돼야 하지만300
이 아니라107
이 나왔습니다. 심지어 이 코드는 실행할 때마다 다른 결과가 나옵니다.이렇게 실행할 때마다 다른 결과를 내는 이유는, thread가 같은 자원을 동시에 접근하기 때문입니다.
thread7
가mylist
에 접근해[7,223]
을 출력한 후 block되어[7, 224]
을 출력하기 전, 그 사이에 다른 스레드들이 mylist에 접근해mylist
의 값을 바꿔버립니다. 하지만thread7
은 더 이상233
이 마지막 원소가 아닌걸 모르기 때문에[7, 224]
를 출력한 후mylist
의 길이가 300이상이므로 함수를 종료합니다.이렇듯 동시에 같은 메모리를 쓰는 상황은 문제가 발생할 수 있기 때문에 이런 상황을 방지하기 위해 자원에 접근을 제한해주는 GIL(global interpreter lock)이 필요합니다.
제가 생각하는 둘의 장단점은
멀티프로세싱
장점
- 메모리를 공유하지 않음
- 코드 흐름이 명확함
- 멀티코어/CPU 의 장점을 쓸 수 있음
- shared memory를 쓰지 않는 이상 동기화가 필요 없음
- 자식 프로세스를 interrupt/kill할수 있음
- 파이썬의 multiprocessing모듈이 제공하는 다양한 interface기능
단점
- IPC(Inter Process Communication)에서 오버헤드가 좀 더 큼
- 메모리가 더 많이 필요함
스레딩
장점
- 메모리가 적게 필요함
- 메모리를 공유함 - 서로 상태를 공유하기 쉬움
- GIL을 이용해 병렬 처리가 가능
- I/O bound 어플리케이션에 옵션이 많음
단점
- interrupt/kill 할 수 없음
- command queue/message pump 모델을 따르지 않는 경우 동기화해야 함
- race condition이 발생할 수 있음
댓글 입력