JiYoung Dev πŸ–₯

파이썬 λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ„ ν™œμš©ν•œ 병렬 ν”„λ‘œκ·Έλž˜λ° 방법 λ³Έλ¬Έ

Study/Back-End

파이썬 λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ„ ν™œμš©ν•œ 병렬 ν”„λ‘œκ·Έλž˜λ° 방법

Shinjio 2025. 3. 3. 17:09
λ°˜μ‘ν˜•

πŸ“ 병렬 ν”„λ‘œκ·Έλž˜λ°

병렬 ν”„λ‘œκ·Έλž˜λ°μ€ CPUκ°€ μ‹±κΈ€ μ½”μ–΄κ°€ μ•„λ‹Œ λ©€ν‹° μ½”μ–΄ 컴퓨터 ν™˜κ²½μ—μ„œ μ—¬λŸ¬ 개의 μž‘μ—…μ„ 보닀 빨리 μ‹€ν–‰ν•˜κΈ° μœ„ν•œ λͺ©μ μœΌλ‘œ κ°œλ°œλ˜λŠ” ν”„λ‘œκ·Έλž˜λ°μ΄λ‹€. 

 

πŸ’Ύ 병렬 ν”„λ‘œκ·Έλž˜λ°μ„ κ΅¬ν˜„ν•˜λŠ” 방법

1️⃣ λ©€ν‹°ν”„λ‘œμ„Έμ‹±(Multiprocessing)

μ—¬λŸ¬ 개의 ν”„λ‘œμ„ΈμŠ€λ₯Ό λ™μ‹œμ— μ‹€ν–‰ν•˜μ—¬ 병렬 처리λ₯Ό κ΅¬ν˜„ν•œλ‹€. 각 ν”„λ‘œμ„ΈμŠ€λŠ” λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰λ˜λ©°, μ„œλ‘œ λ©”λͺ¨λ¦¬ 곡간을 κ³΅μœ ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신(IPC)κ°€ ν•„μš”ν•˜λ‹€. 

λ©€ν‹° ν”„λ‘œμ„Έμ‹±μ€ CPU μ½”μ–΄λ₯Ό μ—¬λŸ¬ 개 ν™œμš©ν•  수 μžˆμ–΄ λ©€ν‹°μ½”μ–΄ μ‹œμŠ€ν…œμ—μ„œ μ„±λŠ₯을 크게 ν–₯μƒμ‹œν‚¬ 수 있으며, 각 ν”„λ‘œμ„ΈμŠ€κ°€ λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰λ˜λ―€λ‘œ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ™€ 좩돌 없이 μ•ˆμ „ν•˜κ²Œ μ‹€ν–‰ν•  수 μžˆλ‹€. 

 

2️⃣ λ©€ν‹°μŠ€λ ˆλ”©(Multithreading)

ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ—¬λŸ¬ μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•˜μ—¬ λ³‘λ ¬λ‘œ μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€. μŠ€λ ˆλ“œλŠ” 같은 λ©”λͺ¨λ¦¬ 곡간을 κ³΅μœ ν•˜λ―€λ‘œ, μŠ€λ ˆλ“œ κ°„ 동기화가 ν•„μš”ν•  수 μžˆλ‹€. 주둜 κ²½λŸ‰ν™”λœ 병렬 처리λ₯Ό μœ„ν•΄ μ‚¬μš©ν•˜λ©° ν”„λ‘œμ„ΈμŠ€λ³΄λ‹€ λ©”λͺ¨λ¦¬ λΉ„μš©μ΄ 적고, λΉ λ₯Έ μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­μ΄ κ°€λŠ₯ν•˜λ‹€.

 

3️⃣ 비동기(Asychronous)

비동기 ν”„λ‘œκ·Έλž˜λ°μ€ μž‘μ—…μ„ λ³‘λ ¬λ‘œ μˆ˜ν–‰ν•˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ μ‹€μ œλ‘œλŠ” 단일 μŠ€λ ˆλ“œμ—μ„œ μž‘μ—…μ„ λΉ„λ™κΈ°μ μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” 방식이닀. μž‘μ—…μ„ λΈ”λ‘œν‚Ή 없이 μˆ˜ν–‰ν•˜λ©° 콜백 λ˜λŠ” ν”„λ‘œλ―ΈμŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ μž‘μ—… μ™„λ£Œ μ‹œ κ²°κ³Όλ₯Ό μ²˜λ¦¬ν•œλ‹€. 주둜 IO μž‘μ—…μ—μ„œ μ„±λŠ₯을 μ΅œμ ν™”ν•  수 있으며 μ—¬λŸ¬ μž‘μ—…μ„ λ™μ‹œμ— 기닀릴 수 μžˆλ‹€. 

 


πŸ“ 파이썬의 병렬 ν”„λ‘œκ·Έλž˜λ°

νŒŒμ΄μ¬μ—μ„œλŠ” μœ„μ˜ 3가지 방식을 ν™œμš©ν•˜μ—¬ 병렬 ν”„λ‘œκ·Έλž˜λ°μ„ κ΅¬ν˜„ν•  수 μžˆλ‹€. 

 

1️⃣ λ©€ν‹°μŠ€λ ˆλ”©

νŒŒμ΄μ¬μ—μ„œ λ©€ν‹°μŠ€λ ˆλ”©μ€ threading λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•œλ‹€. λ©€ν‹°μŠ€λ ˆλ”©μ€ ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ—¬λŸ¬ μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•˜μ—¬ λ™μ‹œμ— μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ” 방식이닀. 각 μŠ€λ ˆλ“œλŠ” λ™μΌν•œ λ©”λͺ¨λ¦¬ 곡간을 κ³΅μœ ν•˜λ©°, CPU μžμ›μ„ λ™μ‹œμ— μ‚¬μš©ν•˜λŠ” κ²ƒμ²˜λŸΌ 보인닀. κ·ΈλŸ¬λ‚˜ νŒŒμ΄μ¬μ€ GIL(Global Interpreter Lock) λ•Œλ¬Έμ— λ©€ν‹° μŠ€λ ˆλ”©μ„ μ‚¬μš©ν•œ 병렬 μ²˜λ¦¬λŠ” CPU λ°”μš΄λ“œ μž‘μ—…μ— λŒ€ν•΄μ„œλŠ” μ„±λŠ₯ ν–₯상이 크지 μ•Šλ‹€. 

GIL은 인터프리터가 μ—¬λŸ¬ 맀 μˆœκ°„ 1개의 μ“°λ ˆλ“œλ§Œ μ‹€ν–‰ν•  수 있게 ν•œλ‹€. κ²°κ΅­ 파이썬의 λ©€ν‹°μŠ€λ ˆλ”©μ€ 병렬적이 μ•„λ‹ˆλΌ λ™μ‹œμ μœΌλ‘œ μ‹€ν–‰λ˜λŠ” 것이닀. λ©€ν‹° μŠ€λ ˆλ”©μ€ 주둜 I/O λ°”μš΄λ“œ μž‘μ—…(예: 파일 읽기/μ“°κΈ°, λ„€νŠΈμ›Œν¬ μš”μ²­ λ“±)에 μ‚¬μš©ν•œλ‹€. 

** 파이썬의 GIL κ΄€λ ¨ μžλ£ŒλŠ” 맨 μ•„λž˜ 참고자료λ₯Ό 톡해 λ‚΄μš©μ„ 확인할 수 μžˆλ‹€. λ‹€μŒμ—λŠ” 파이썬의 GIL에 λŒ€ν•΄ μƒμ„Ένžˆ ν¬μŠ€νŒ…ν•΄ λ³Ό μ˜ˆμ •μ΄λ‹€.

 

2️⃣ λ©€ν‹°ν”„λ‘œμ„Έμ‹±

λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ€ multiprocessing λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜μ—¬ μ—¬λŸ¬ 개의 ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³  병렬 처리λ₯Ό μˆ˜ν–‰ν•œλ‹€. 각 ν”„λ‘œμ„ΈμŠ€λŠ” 독립적인 λ©”λͺ¨λ¦¬ 곡간을 가지고 있기 λ•œλˆ„μ— GIL의 영ν–₯을 받지 μ•ŠλŠ”λ‹€. CPU λ°”μš΄λ“œ μž‘μ—…(λ³΅μž‘ν•œ 계산, 이미지 처리 λ“±)μ—μ„œ μ„±λŠ₯ ν–₯상을 크게 κΈ°λŒ€ν•  수 μžˆλ‹€. 

 

3️⃣ 비동기 ν”„λ‘œκ·Έλž˜λ°

비동기 ν”„λ‘œκ·Έλž˜λ°μ€ asyncio λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜μ—¬ I/O μž‘μ—…μ„ λΉ„λ™κΈ°μ μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆλ‹€. μ΄λŠ” λ©€ν‹°μŠ€λ ˆλ”©μ΄λ‚˜ λ©€ν‹°ν”„λ‘œμ„Έμ‹±κ³ΌλŠ” 달리 단일 μŠ€λ ˆλ“œμ—μ„œ λΉ„λ™κΈ°μ μœΌλ‘œ μ—¬λŸ¬ μž‘μ—…μ„ μ²˜λ¦¬ν•  수 있게 ν•΄μ€€λ‹€. 비동기 μž‘μ—…μ€ 주둜 I/O λ°”μš΄λ“œ μž‘μ—…μ—μ„œ μ„±λŠ₯ ν–₯상이 크닀. 

 


 

πŸ“ 파이썬 λ©€ν‹°ν”„λ‘œμ„Έμ‹±

CPU λ°”μš΄λ“œ μž‘μ—…μ„ 주둜 μ§„ν–‰ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ„ 톡해 병렬 처리 ν•˜μ—¬ μ„±λŠ₯을 λŒμ–΄μ˜¬λ¦¬λ € ν•œλ‹€. 파이썬의 λ©€ν‹°ν”„λ‘œμ„Έμ‹± 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄μž.

 

파이썬의 multiprocessing λͺ¨λ“ˆμ€ threading λͺ¨λ“ˆκ³Ό μœ μ‚¬ν•œ APIλ₯Ό μ‚¬μš©ν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€λ₯Ό 생성할 수 μžˆλ„λ‘ μ§€μ›ν•˜λŠ” νŒ¨ν‚€μ§€μ΄λ‹€. multiprocessing νŒ¨ν‚€μ§€λŠ” 둜컬 및 원격 λ™μ‹œμ„±μ„ μ œκ³΅ν•˜λ©°, μŠ€λ ˆλ“œ λŒ€μ‹  μ„œλΈŒν”„λ‘œμ„ΈμŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ GIL을 μš°νšŒν•œλ‹€. 이둜 인해 multiprocessing λͺ¨λ“ˆμ€ 주어진 λ¨Έμ‹ μ—μ„œ μ—¬λŸ¬ ν”„λ‘œμ„Έμ„œλ₯Ό μ™„μ „νžˆ ν™œμš©ν•  수 있게 ν•΄μ£Όλ©°, Unix와 μœˆλ„μš°μ—μ„œ λͺ¨λ‘ μ‹€ν–‰ κ°€λŠ₯ν•˜λ‹€. 

 

multiprocessing λͺ¨λ“ˆμ€ Pool 객체λ₯Ό μ œκ³΅ν•œλ‹€. Pool κ°μ²΄λŠ” μ—¬λŸ¬ μž…λ ₯ 값에 λŒ€ν•΄ ν•¨μˆ˜ 싀행을 병렬화할 수 μžˆλŠ” νŽΈλ¦¬ν•œ 방법을 μ œκ³΅ν•œλ‹€. μž…λ ₯ 데이터λ₯Ό ν”„λ‘œμ„ΈμŠ€μ— λΆ„λ°°ν•˜μ—¬ 데이터 병렬성을 μ²˜λ¦¬ν•œλ‹€. 

 

β˜‘ Pool을 μ‚¬μš©ν•œ 데이터 λ³‘λ ¬μ„±μ˜ κΈ°λ³Έ μ˜ˆμ‹œ

from multiprocessing import Pool

def f(x):
  return x*x

if __name__ == '__main__':
  with Pool(5) as p: # 5개의 ν”„λ‘œμ„ΈμŠ€λ₯Ό 가진 ν”„λ‘œμ„ΈμŠ€ ν’€ 생성
  	# μž…λ ₯ 리슀트 [1,2,3]에 μžˆλŠ” 각 값에 λŒ€ν•΄ fλ₯Ό λ³‘λ ¬λ‘œ μ‹€ν–‰
    # f(1), f(2), f(3)이 각각 λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ‹€ν–‰
    print(p.map(f, [1,2,3])) # [1,4,9] 좜λ ₯

 

β˜‘ Process 생성

λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ—μ„œλŠ” Process 객체λ₯Ό μƒμ„±ν•œ ν›„, κ·Έ 객체의 start() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•œλ‹€.  

from multiprocessing import Process
import os

def info(title):
  print(title)
  print('module name:', __name__)
  print('parent process:', os.getppid())
  print('process id:', os.getpid())

def f(name):
  info('function f')
  print('hello', name)

if __name__ == '__main__':
  info('main line')
  p = Process(target=f, args=('bob',))
  p.start()
  p.join()

 

main line
module name: __main__
parent process: 101488
process id: 101493
function f
module name: __main__
parent process: 101493
process id: 101497
hello bob

 

 

πŸ’Ύ 파이썬 λ©€ν‹°ν”„λ‘œμ„Έμ‹± ν”„λ‘œμ„ΈμŠ€ μ‹œμž‘ 방법

파이썬의 λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ€ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‹œμž‘ν•˜λŠ” μ„Έ 가지 방법을 μ§€μ›ν•œλ‹€. 

 

1️⃣ spawn

λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μƒˆ Python 인터프리터 ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‹œμž‘ν•œλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” ν•΄λ‹Ή ν”„λ‘œμ„ΈμŠ€ 객체의 run() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” 데 ν•„μš”ν•œ λ¦¬μ†ŒμŠ€λ§Œ 상속 λ°›λŠ”λ‹€. 특히 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λΆˆν•„μš”ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°μ™€ 핸듀은 μƒμ†λ˜μ§€ μ•ŠλŠ”λ‹€. 이 방법을 μ‚¬μš©ν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‹œμž‘ν•˜λŠ” 것은 forkλ‚˜ forkserverλ₯Ό μ‚¬μš©ν•˜λŠ” 것보닀 μƒλ‹Ήνžˆ λŠλ¦¬λ‹€. 

Unix와 Windowsμ—μ„œ μ§€μ›λ˜λ©° Windows와 macOSμ—μ„œ κΈ°λ³Έκ°’μœΌλ‘œ μ‚¬μš©λœλ‹€. 

 

2️⃣ fork

λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” os.fork()λ₯Ό μ‚¬μš©ν•˜μ—¬ Python 인터프리터λ₯Ό ν¬ν¬ν•œλ‹€. μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” μ‹œμž‘ν•  λ•Œ 사싀상 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ™€ λ™μΌν•˜λ‹€. λΆ€λͺ¨μ˜ λͺ¨λ“  λ¦¬μ†ŒμŠ€κ°€ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ— μƒμ†λœλ‹€. λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ•ˆμ „ν•˜κ²Œ ν¬ν¬ν•˜λŠ” 것은 λ¬Έμ œκ°€ 될 수 μžˆμŒμ„ μœ μ˜ν•΄μ•Ό ν•œλ‹€. 

Unix μ „μš©μœΌλ‘œ μ‚¬μš©λ˜λ©°, Unixμ—μ„œ κΈ°λ³Έκ°’μœΌλ‘œ μ‚¬μš©λœλ‹€. 

 

3️⃣ forkserver

ν”„λ‘œκ·Έλž¨μ΄ μ‹œμž‘λ˜λ©΄ forkserver μ‹œμž‘ 방법을 μ„ νƒν•˜μ—¬ μ„œλ²„ ν”„λ‘œμ„ΈμŠ€κ°€ μ‹œμž‘λœλ‹€. κ·Έ 이후 μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€κ°€ ν•„μš”ν•  λ•Œλ§ˆλ‹€ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€λŠ” μ„œλ²„μ— μ—°κ²°ν•˜μ—¬ μƒˆλ‘œμš΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό ν¬ν¬ν•˜λ„λ‘ μš”μ²­ν•œλ‹€. 포크 μ„œλ²„ ν”„λ‘œμ„ΈμŠ€λŠ” 단일 μŠ€λ ˆλ“œλ‘œ μ‹€ν–‰λ˜λ―€λ‘œ os.fork()λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ•ˆμ „ν•˜λ‹€. λΆˆν•„μš”ν•œ λ¦¬μ†ŒμŠ€λŠ” μƒμ†λ˜μ§€ μ•ŠλŠ”λ‹€. 

Unix ν”Œλž«νΌ 쀑 Unix  νŒŒμ΄ν”„λ₯Ό 톡해 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ „λ‹¬ν•˜λŠ” κΈ°λŠ₯을 μ§€μ›ν•˜λŠ” ν”Œλž«νΌμ—μ„œ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. 

 

πŸ“Œ fork vs spawn vs forkserver

fork 

λΉ λ₯΄μ§€λ§Œ μ•ˆμ „ν•˜μ§€ μ•Šλ‹€. 

  • ForkλŠ” λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬, λͺ¨λ“ˆ, 객체 등을 κ·ΈλŒ€λ‘œ λ³΅μ‚¬ν•˜μ—¬ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ§Œλ“ λ‹€. 이 덕뢄에 속도가 λΉ λ₯΄λ‹€.
  • ν•˜μ§€λ§Œ λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ μŠ€λ ˆλ“œλŠ” λ³΅μ‚¬λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ—, λΆ€λͺ¨μ—μ„œ μž κΈˆμ„ 가지고 μžˆλŠ” μŠ€λ ˆλ“œκ°€ μžμ‹ ν”„λ‘œμ„ΈμŠ€μ— 영ν–₯을 λ―ΈμΉ  수 μžˆμ–΄ deadlock λ°œμƒ μœ„ν—˜μ΄ μžˆλ‹€. 
  • λ˜ν•œ, λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ 파일 λ””μŠ€ν¬λ¦½ν„°λ‚˜ λ„€νŠΈμ›Œν¬ 포트 등도 μžμ‹μ—κ²Œ μƒμ†λ˜μ–΄ λΆˆν•„μš”ν•œ λ¦¬μ†ŒμŠ€ κ³΅μœ κ°€ λ°œμƒν•  수 μžˆλ‹€. 
  • λ”°λΌμ„œ forkλŠ” λΉ λ₯΄μ§€λ§Œ, μ•ˆμ „μ„±μ΄ 떨어지고 λΆˆν•„μš”ν•˜κ²Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 컀질 수 μžˆλ‹€. 

Spawn

μ•ˆμ €ν•˜μ§€λ§Œ λŠλ¦¬λ‹€.

  • Spawn은 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬, 파일 λ””μŠ€ν¬λ¦½ν„°, μŠ€λ ˆλ“œ 등을 λ³΅μ‚¬ν•˜μ§€ μ•Šκ³  μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ²˜μŒλΆ€ν„° μƒˆλ‘œ μ‹œμž‘ν•œλ‹€. 
  • 기술적으둜 spawn은 λΆ€λͺ¨ ν”„λ‘œμ„ΈμŠ€μ˜ λ³΅μ œλ³Έμ„ μƒμ„±ν•œ ν›„, μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” μƒˆλ‘œμš΄ Python 인터프리터λ₯Ό μ‹œμž‘ν•˜κ³ , ν•„μš”ν•œ λͺ¨λ“ˆμ„ λ‘œλ“œν•œ λ’€ μ§€μ •λœ ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•œλ‹€. 
  • 이 방식은 μ•ˆμ „ν•˜κ³  κ°„κ²°ν•˜μ§€λ§Œ, μ²˜μŒλΆ€ν„° ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‹œμž‘ν•΄μ•Ό ν•˜λ―€λ‘œ λŠλ¦¬λ‹€. ν•˜μ§€λ§Œ μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ ν•˜λŠ” 일이 크지 μ•Šλ‹€λ©΄ 느리게 λŠκ»΄μ§€μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€. 

Forkserver

λΉ λ₯΄κ³  μ•ˆμ „ν•˜μ§€λ§Œ λ³΅μž‘ν•˜λ‹€.

  • ForkserverλŠ” μ²˜μŒμ— 'fork server'λΌλŠ” νŠΉλ³„ν•œ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ§Œλ“€μ–΄ 놓고, κ·Έ ν”„λ‘œμ„ΈμŠ€κ°€ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό ν¬ν¬ν•œλ‹€. 이λ₯Ό 톡해 λͺ¨λ“  μžμ‹ ν”„λ‘œμ„ΈμŠ€λŠ” κ°„κ²°ν•˜κ³  μ•ˆμ „ν•˜κ²Œ μ‹œμž‘λœλ‹€. 
  • μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‹œμž‘ν•  λ•Œλ§ˆλ‹€ forkserver에 μš”μ²­ν•΄μ„œ μžμ‹ ν”„λ‘œμ„ΈμŠ€λ₯Ό ν¬ν¬ν•œλ‹€. 이 방식은 λΉ λ₯΄κ³  μ•ˆμ „ν•˜μ§€λ§Œ, λ³΅μž‘ν•˜κ³  λ¬Έμ„œν™”κ°€ λΆ€μ‘±ν•΄ μ‚¬μš©ν•˜κΈ° μ–΄λ ΅λ‹€. 
  • ForkserverλŠ” 잠금 문제λ₯Ό 방지할 수 있고, μžμ‹ ν”„λ‘œμ„ΈμŠ€κ°€ 컀지지 μ•ŠμœΌλ©° μ „μ²΄μ μœΌλ‘œ νš¨μœ¨μ μ΄λ‹€. 

 

Unixμ—μ„œ spawn λ˜λŠ” forserver μ‹œμž‘ 방법을 μ‚¬μš©ν•˜λ©΄ λ¦¬μ†ŒμŠ€ 좔적기 ν”„λ‘œμ„ΈμŠ€κ°€ μ‹œμž‘λœλ‹€. 이 ν”„λ‘œμ„ΈμŠ€λŠ” ν”„λ‘œκ·Έλž¨μ˜ ν”„λ‘œμ„ΈμŠ€κ°€ μƒμ„±ν•œ λ§ν¬λ˜μ§€ μ•Šμ€ λͺ…λͺ…λœ μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€(예: λͺ…λͺ…λœ μ„Έλ§ˆν¬μ–΄λ‚˜ SharedMemory 객체)λ₯Ό μΆ”μ ν•œλ‹€. λͺ¨λ“  ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œλ˜λ©΄ λ¦¬μ†ŒμŠ€ μΆ”μ κΈ°λŠ” 좔적 쀑인 객체λ₯Ό 언링크 ν•œλ‹€. 일반적으둜 좔적할 객체가 μ—†μ–΄μ•Ό ν•˜μ§€λ§Œ, ν”„λ‘œμ„ΈμŠ€κ°€ μ‹ ν˜Έλ‘œ μ’…λ£Œλ˜μ—ˆμ„ 경우 λˆ„μˆ˜λœ λ¦¬μ†ŒμŠ€κ°€ μžˆμ„ 수 μžˆλ‹€. 

 

μ‹œμž‘ 방법을 μ„ νƒν•˜λ €λ©΄ main λͺ¨λ“ˆμ˜ if __name__ ==  '__main__' λΈ”λ‘μ—μ„œ set_start_method()λ₯Ό μ‚¬μš©ν•œλ‹€. 

 

import multiprocessing as mp

def foo(q):
  q.put('hello')

if __name__ == '__main__':
  mp.set_start_method('spawn')
  q = mp.Queue()
  p = mp.Process(target=foo, args=(q,))
  p.start()
  print(q.get())
  p.join()

 

set_start_method()λŠ” ν”„λ‘œκ·Έλž¨μ—μ„œ ν•œ 번만 μ‚¬μš©ν•œλ‹€. 


πŸ“– 참고자료

https://teus-kiwiee.tistory.com/entry/PythonMultiProcessing-%ED%83%90%EA%B5%AC 

 

[Python]MultiProcessing 탐ꡬ

μ•ˆλ…•ν•˜μ„Έμš”. Teusμž…λ‹ˆλ‹€.이번 ν¬μŠ€νŒ…μ€ Python의 Multiprocessing을 μ‚¬μš©ν•˜λŠ” κ³Όμ •μ—μ„œ λ°œμƒν•˜λŠ” λ¬Έμ œμ λ“€μ„ νƒκ΅¬ν•˜λŠ” ν¬μŠ€νŒ… μž…λ‹ˆλ‹€.0. Python의 Multiprocessingμ˜ˆμ „λΆ€ν„° 이야기 ν•˜μ§€λ§Œ, Python의 GIL λ•Œλ¬Έμ—, P

teus-kiwiee.tistory.com

https://docs.python.org/3.10/library/multiprocessing.html#contexts-and-start-methods

 

multiprocessing — Process-based parallelism — Python 3.10.16 documentation

Source code: Lib/multiprocessing/ Introduction multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping the G

docs.python.org

https://stackoverflow.com/questions/64095876/multiprocessing-fork-vs-spawn

 

multiprocessing fork() vs spawn()

I was reading the description of the two from the python doc: spawn The parent process starts a fresh python interpreter process. The child process will only inherit those resources necessary to r...

stackoverflow.com

https://velog.io/@xxhaileypark/Python-%EB%A9%80%ED%8B%B0%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%93%9C

 

[Python] λ©€ν‹°ν”„λ‘œμ„ΈμŠ€ & λ©€ν‹°μŠ€λ ˆλ“œ

νŒŒμ΄μ¬μ€ 인터프리터 언어이기 λ•Œλ¬Έμ— 컴파일 언어보닀 느리고 λ”°λΌμ„œ μ‹€μ‹œκ°„ 거래 μ‹œμŠ€ν…œμ²˜λŸΌ 맀우 짧은 μ‘λ‹΅μ‹œκ°„μ„ ν•„μš”λ‘œ ν•˜λŠ”λ° μ‚¬μš©ν•  수 μ—†λ‹€. νŒŒμ΄μ¬μ€ λ™μ‹œλ‹€λ°œμ μΈ λ©€ν‹°μŠ€λ ˆλ“œλ₯Ό 처

velog.io

https://only-wanna.tistory.com/entry/Python-Global-Interpreter-LockGIL%EC%9D%80-%EC%99%9C-%EB%8F%84%EC%9E%85%EB%90%90%EA%B3%A0-%EC%96%B4%EB%96%A4-%ED%8A%B9%EC%A7%95%EC%9D%B4-%EC%9E%88%EB%82%98%EC%9A%94

 

[Python] Global Interpreter Lock(GIL)은 μ™œ λ„μž…λκ³ , μ–΄λ–€ νŠΉμ§•μ΄ μžˆλ‚˜μš”?

Global Interpreter Lock(GIL)? GIL은 문자 κ·ΈλŒ€λ‘œ 인터프리터에 λŒ€ν•œ Lock이닀. Lock은 인터프리터가 μ—¬λŸ¬ μŠ€λ ˆλ“œλ₯Ό λ³‘λ ¬μ μœΌλ‘œ(Parallel) μ‹€ν–‰ν•˜μ§€ μ•Šλ„λ‘ λ§‰λŠ”λ‹€. νŒŒμ΄μ¬μ—” GIL이 있기 λ•Œλ¬Έμ—, 인터프리터가

only-wanna.tistory.com

https://seoyeonhwng.medium.com/python-global-interpreter-lock-gil-%EC%9D%B4%EB%9E%80-2e519d4491a1

 

Python Global Interpreter Lock(GIL)μ΄λž€?

파이썬 μ–Έμ–΄ μžμ²΄μ— λŒ€ν•΄ κ³΅λΆ€ν•˜λ‹€ 보면 GIL을 마주치게 λœλ‹€. GIL이 무엇인지 λŒ€λž΅ μ•Œκ³  μžˆμ§€λ§Œ, 쑰금 더 깊게 μ΄ν•΄ν•˜κ³  싢은 λ§ˆμŒμ— κ΄€λ ¨ 글을 읽고 μ΄ν•΄ν•œ λ°”λ₯Ό μ •λ¦¬ν•΄λ³΄μ•˜λ‹€.

seoyeonhwng.medium.com

 

λ°˜μ‘ν˜•