[개발] 파이썬

9.2.1. 멀티스레딩과 멀티프로세싱

브랜든정 2024. 12. 30. 13:10
반응형

파이썬 멀티스레딩과 멀티프로세싱: 스레딩 모듈과 프로세싱 모듈의 차이

파이썬은 다양한 멀티스레딩과 멀티프로세싱 기법을 제공하여 병렬 처리를 가능하게 합니다. 이 기법들은 프로그램의 성능을 향상시키고, 효율적인 자원 관리를 가능하게 합니다. 이 글에서는 파이썬의 스레딩 모듈과 프로세싱 모듈의 차이점을 설명하고, 각 모듈의 특징과 사용 방법을 자세히 다루겠습니다.

1. 스레딩 모듈: 파이썬의 스레딩

파이썬의 스레딩은 threading 모듈을 사용하여 구현됩니다. 스레딩은 하나의 프로세스 내에서 여러 스레드를 생성하여 병렬 처리를 가능하게 합니다. 하지만, 파이썬의 스레딩은 Global Interpreter Lock (GIL)로 인해 실제로 병렬 처리가 이루어지지 않는 경우가 많습니다.

1.1 GIL(Global Interpreter Lock)

파이썬의 GIL은 인터프리터가 반드시 하나의 스레드만을 수행하도록 제한하는 메커니즘입니다. 이로 인해 파이썬의 스레딩은 CPU-bound 작업에 적합하지 않습니다. 대신, I/O-bound 작업에 적합합니다. 예를 들어, 네트워크 요청이나 파일 입출력과 같은 작업은 GIL로 인해 스레딩을 사용하여 병렬 처리가 가능합니다.

1.2 스레딩의 장점

  • I/O-bound 작업에 적합: 네트워크 요청, 파일 입출력, 데이터베이스 접근과 같은 작업에서 스레딩을 사용하여 병렬 처리가 가능합니다.
  • 메모리 사용량이 적음: 스레드는 프로세스와 달리 메모리를 공유하므로, 메모리 사용량이 적습니다.
  • 문맥 전환 비용이 낮음: 스레드는 프로세스와 달리 문맥 전환 비용이 낮습니다.

1.3 스레딩의 단점

  • CPU-bound 작업에 적합하지 않음: GIL로 인해 CPU-bound 작업에서는 실제로 병렬 처리가 이루어지지 않습니다.
  • 공유 메모리 동시 접근 경합(Race condition)이 발생할 수 있음: 여러 스레드가 공유 메모리를 접근할 때, 데이터의 일관성을 유지하기 위해 추가적인 동기화가 필요합니다.

2. 프로세싱 모듈: 파이썬의 프로세싱

파이썬의 프로세싱은 multiprocessing 모듈을 사용하여 구현됩니다. 프로세싱은 하나의 프로그램에 다수 프로세스를 생성하여 병렬 처리를 가능하게 합니다. 프로세싱은 GIL의 제한을 받지 않기 때문에, CPU-bound 작업에 적합합니다.

2.1 프로세싱의 장점

  • CPU-bound 작업에 적합: 프로세싱은 GIL의 제한을 받지 않기 때문에, CPU-bound 작업에 적합합니다.
  • 메모리 독립: 각 프로세스는 독립된 메모리 공간을 가집니다.
  • 안정성: 프로세스 간의 메모리 공유가 없기 때문에, 데이터의 일관성을 유지하기가 더 쉽습니다.

2.2 프로세싱의 단점

  • 메모리 사용량이 높음: 프로세스는 독립된 메모리 공간을 가집니다. 따라서, 메모리 사용량이 높습니다.
  • 문맥 전환 비용이 높음: 프로세스는 문맥 전환 비용이 높습니다.

3. 멀티스레딩과 멀티프로세싱의 비교

특징 멀티스레딩 멀티프로세싱
메모리 사용량 적음 많음
안정성 낮음 높음
문맥 전환 비용 낮음 높음
통신 속도 빠름 느림
사용 사례 I/O-bound 작업 CPU-bound 작업

3.1 I/O-bound 작업과 CPU-bound 작업

  • I/O-bound 작업: 네트워크 요청, 파일 입출력, 데이터베이스 접근과 같은 작업에서 스레딩을 사용하여 병렬 처리가 가능합니다.
  • CPU-bound 작업: 계산-intensive 작업, 데이터 압축, 암호화와 같은 작업에서 프로세싱을 사용하여 병렬 처리가 가능합니다.

3.2 예제 코드

스레딩 예제

import threading
import time

def work(id):
    print(f"Thread {id} started")
    time.sleep(2)
    print(f"Thread {id} finished")

threads = []
for i in range(5):
    t = threading.Thread(target=work, args=(i,))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

프로세싱 예제

import multiprocessing
import time

def work(id):
    print(f"Process {id} started")
    time.sleep(2)
    print(f"Process {id} finished")

if __name__ == "__main__":
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=work, args=(i,))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

4. 멀티스레딩과 멀티프로세싱의 활용 사례

4.1 I/O-bound 작업

  • 네트워크 요청: 여러 스레드를 사용하여 병렬로 네트워크 요청을 처리할 수 있습니다.
  • 파일 입출력: 여러 스레드를 사용하여 병렬로 파일 입출력을 처리할 수 있습니다.
  • 데이터베이스 접근: 여러 스레드를 사용하여 병렬로 데이터베이스 접근을 처리할 수 있습니다.

4.2 CPU-bound 작업

  • 계산-intensive 작업: 여러 프로세스를 사용하여 병렬로 계산-intensive 작업을 처리할 수 있습니다.
  • 데이터 압축: 여러 프로세스를 사용하여 병렬로 데이터 압축을 처리할 수 있습니다.
  • 암호화: 여러 프로세스를 사용하여 병렬로 암호화를 처리할 수 있습니다.

5. 결론

파이썬의 스레딩 모듈과 프로세싱 모듈은 각각의 특징과 장단점을 가지고 있습니다. 스레딩은 I/O-bound 작업에 적합하며, 메모리 사용량이 적고 문맥 전환 비용이 낮습니다. 하지만, CPU-bound 작업에는 적합하지 않습니다. 프로세싱은 CPU-bound 작업에 적합하며, 메모리 독립이고 안정성이 높습니다. 하지만, 메모리 사용량이 높고 문맥 전환 비용이 높습니다. 따라서, 프로그램의 성능을 향상시키기 위해 적절한 기법을 선택하는 것이 중요합니다.

반응형

'[개발] 파이썬' 카테고리의 다른 글

10.1. 유닛 테스트  (0) 2024.12.30
9.2.2. 비동기 프로그래밍  (2) 2024.12.30
9.1.2. HTTP 요청 처리  (0) 2024.12.30
9.1.1. 소켓 프로그래밍  (0) 2024.12.30
8.3. REST API 만들기  (4) 2024.12.30