πŸ’» Programming/Python

[python] λ©€ν‹°ν”„λ‘œμ„Έμ‹± Process μ‚¬μš©λ²• 및 μ½”λ“œ μ˜ˆμ‹œ | multiprocessing.Process | μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€μ— μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ„ ν• λ‹Ή

뭅즀 2024. 1. 7. 19:21
λ°˜μ‘ν˜•
 

[python] λ©€ν‹°ν”„λ‘œμ„Έμ‹± Pool μ‚¬μš©λ²• 및 μ½”λ“œ μ˜ˆμ‹œ | multiprocessing.Pool | python 속도 ν–₯상

λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ€ μ—¬λŸ¬ 개의 독립적인 ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜μ—¬ 각각의 ν”„λ‘œμ„ΈμŠ€κ°€ λ³‘λ ¬λ‘œ μž‘μ—…ν•˜λ„λ‘ ν•˜λŠ” 방식이닀. 각 ν”„λ‘œμ„ΈμŠ€λŠ” 독립적인 λ©”λͺ¨λ¦¬ 곡간을 가지며, ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신 (Inter-Process Co

mvje.tistory.com

 

μœ„ ν¬μŠ€νŒ…μ—μ„œ 파이썬으둜 λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ„ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ multiprocessing.Pool μ‚¬μš©λ²•μ— λŒ€ν•΄ μ‚΄νŽ΄λ΄€λ‹€. μ΄λ²ˆμ—λŠ” multiprocessing.Processλ₯Ό ν™œμš©ν•œ λ©€ν‹°ν”„λ‘œμ„Έμ‹± 방법과 Pool, Process 두 가지 λ°©λ²•μ˜ 차이점에 λŒ€ν•΄ μ•Œμ•„λ³΄κ³ μž ν•œλ‹€.

 

multiprocessing.Poolκ³Ό multiprocessing.ProcessλŠ” 파이썬의 multiprocessing λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜μ—¬ λ©€ν‹°ν”„λ‘œμ„Έμ‹±μ„ κ΅¬ν˜„ν•˜λŠ” 두 가지 λ‹€λ₯Έ λ°©λ²•μœΌλ‘œ, 각각의 μ ‘κ·Ό 방식은 νŠΉμ • 상황에 더 νŽΈλ¦¬ν•˜κ²Œ μ‚¬μš©λ  수 μžˆλ‹€.

 

특히 μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€μ— μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ„ ν• λ‹Ήν•˜κΈ° μœ„ν•΄μ„œλŠ” multiprocessing.Processλ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.


multiprocessing.Pool

 

- νŽΈλ¦¬ν•œ μΈν„°νŽ˜μ΄μŠ€

  • Pool 클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‰½κ²Œ μƒμ„±ν•˜κ³  관리할 수 있으며
  • 각 ν”„λ‘œμ„ΈμŠ€μ— μž‘μ—…μ„ λΆ„λ°°ν•˜κ³  κ²°κ³Όλ₯Ό μˆ˜μ§‘ν•˜λŠ” 데 μœ μš©ν•˜λ‹€
  • λ•Œλ¬Έμ— κ°„λ‹¨ν•˜κ³  λ™μΌν•œ μž‘μ—…μ„ μ—¬λŸ¬ 데이터에 λ³‘λ ¬λ‘œ μ μš©ν•΄μ•Ό ν•  λ•Œ νŽΈλ¦¬ν•˜λ‹€

 

- μž‘μ—… λΆ„λ°°

  • map, imap, apply 등을 톡해 각 ν”„λ‘œμ„ΈμŠ€μ— λ™μΌν•œ μž‘μ—…μ„ λ³‘λ ¬λ‘œ λΆ„λ°°ν•  수 μžˆλ‹€.
  • μž…λ ₯ 데이터λ₯Ό λ‚˜λˆ„μ–΄ μ²˜λ¦¬ν•˜κ³  κ²°κ³Όλ₯Ό μˆ˜μ§‘ν•˜λŠ” 과정이 λ‚΄λΆ€μ μœΌλ‘œ μ²˜λ¦¬λœλ‹€.

 

- ν’€ 크기 μ œμ–΄

  • Pool의 processes λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 생성할 ν”„λ‘œμ„ΈμŠ€μ˜ 개수λ₯Ό μ‘°μ ˆν•  수 μžˆλ‹€.

 

# μ½”λ“œ 예제

from multiprocessing import Pool

def square_number(x):
    return x ** 2

if __name__ == "__main__":
    data = [1, 2, 3, 4, 5]

    with Pool(processes=3) as pool:
        results = pool.map(square_number, data)

    print("Results:", results)

 


multiprocessing.Process

 

- 더 λ§Žμ€ μ œμ–΄

  • Process 클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ 각 ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•΄ 더 λ§Žμ€ μ œμ–΄λ₯Ό ν•  수 μžˆλ‹€.
  • 각 ν”„λ‘œμ„ΈμŠ€λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ‹œμž‘ν•˜κ³  μ’…λ£Œν•  수 μžˆλ‹€.

 

- ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신

  • Queue, Pipe 등을 μ‚¬μš©ν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€ κ°„ 데이터 κ΅ν™˜μ„ 직접 κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.
  • IPC(Inter-Process Communication) λ©”μ»€λ‹ˆμ¦˜μ„ 톡해 데이터λ₯Ό κ³΅μœ ν•  수 μžˆλ‹€.

 

- 더 λ³΅μž‘ν•œ μž‘μ—…μ— 적합

  • λ³΅μž‘ν•œ μž‘μ—…μ΄λ‚˜ μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ„ 각 ν”„λ‘œμ„ΈμŠ€μ— μˆ˜ν–‰ν•˜κ³ μž ν•  λ•Œ μ‚¬μš©λœλ‹€κ³  ν•œλ‹€.

 

# μ½”λ“œ 예제 - κΈ°λ³Έ

from multiprocessing import Process, Queue

def square_numbers(numbers, result_queue):
    squared_numbers = [x ** 2 for x in numbers]
    result_queue.put(squared_numbers)

if __name__ == "__main__":
    data = [1, 2, 3, 4, 5]
    result_queue = Queue()

    # 각 ν”„λ‘œμ„ΈμŠ€κ°€ λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰λ˜λ©°, μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ„ μˆ˜ν–‰
    num_of_processes = 3
    processes = [Process(target=square_numbers, args=(data, result_queue)) for _ in range(num_of_processes)]

    for process in processes:
        process.start()

    for process in processes:
        process.join()

    # κ²°κ³Όλ₯Ό νμ—μ„œ μˆ˜μ§‘
    results = [result_queue.get() for _ in processes]

    print("Results:", results)
  • 이 μ˜ˆμ‹œμ—μ„œλŠ” square_numbers ν•¨μˆ˜κ°€ κ°κ°μ˜ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ‹€ν–‰λ¨
  • 각 ν”„λ‘œμ„ΈμŠ€λŠ” λ…λ¦½μ μœΌλ‘œ data 리슀트의 숫자λ₯Ό μ œκ³±ν•˜κ³ , κ·Έ κ²°κ³Όλ₯Ό result_queue에 λ„£μŒ
  • 메인 ν”„λ‘œμ„ΈμŠ€μ—μ„œλŠ” κ° ν”„λ‘œμ„ΈμŠ€μ˜ κ²°κ³Όλ₯Ό μˆ˜μ§‘ν•˜μ—¬ μΆœλ ₯

 

 

# μ½”λ“œ 예제 - 각 ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ„ μˆ˜ν–‰

from multiprocessing import Process, Queue

def square_numbers(numbers, result_queue):
    squared_numbers = [x ** 2 for x in numbers]
    result_queue.put(squared_numbers)

def cube_numbers(numbers, result_queue):
    cubed_numbers = [x ** 3 for x in numbers]
    result_queue.put(cubed_numbers)

if __name__ == "__main__":
    data = [1, 2, 3, 4, 5]
    result_queue = Queue()

    # 각 ν”„λ‘œμ„ΈμŠ€μ— λ‹€λ₯Έ ν•¨μˆ˜ ν• λ‹Ή
    process1 = Process(target=square_numbers, args=(data, result_queue))
    process2 = Process(target=cube_numbers, args=(data, result_queue))

    # ν”„λ‘œμ„ΈμŠ€ μ‹œμž‘
    process1.start()
    process2.start()

    # ν”„λ‘œμ„ΈμŠ€ μ’…λ£Œ λŒ€κΈ°
    process1.join()
    process2.join()

    # κ²°κ³Όλ₯Ό νμ—μ„œ μˆ˜μ§‘
    results = [result_queue.get(), result_queue.get()]

    print("Squared Results:", results[0])
    print("Cubed Results:", results[1])
  • ν”„λ‘œμ„ΈμŠ€λ₯Ό μ—¬λŸ¬κ°œ λ§Œλ“€κ³  각 ν”„λ‘œμ„ΈμŠ€λ§ˆλ‹€ μ„œλ‘œ λ‹€λ₯Έ ν•¨μˆ˜λ₯Ό target으둜 λ„£μ–΄μ£Όλ©΄ 각 ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ„œλ‘œ λ‹€λ₯Έ ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€.
  • μ˜ˆμ‹œμ—μ„œλŠ” 숫자λ₯Ό μ œκ³±ν•˜λŠ” square_numbers ν•¨μˆ˜μ™€ 숫자λ₯Ό μ„Έμ œκ³±ν•˜λŠ” cube_numbers ν•¨μˆ˜λ₯Ό μ„œλ‘œ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€λ‘œ μ‹€ν–‰

 

λ°˜μ‘ν˜•