정보처리기술사/운영체제

프로세스(Process)와 쓰레드

anodos 2024. 3. 1. 20:37

1. 프로세스(Process)

프로그램이 메모리에 올라간 후 운영체제에 의해 실행되는 것

프로세스별 메모리 독립적

프로세스는 운영체제로 부터 독립된 자원을 할당 받으며 한 프로세스가 다른 프로세스의 데이터에 접근불가

2. 쓰레드(Thread)

프로세스의 실행 단위를 쓰레드라고 부름

프로세스는 최소 하나의 쓰레드로 구성되는데 이를 단일 쓰레드라 함

프로세스가 여러 쓰레드를 가질수 있는데 이를 다중 쓰레드라 함

 

3. 스레드 스케줄링

운영체제와 스케줄링

- 운영체제는 여러 프로그램(프로세스)를 아주 잛은 시간마다 실행시켜 동시에 실행되는 것처럼 보임

- 운영체제의 스케줄링 기법은 다양, 스케줄링의 기본 단위로 앞서 설명한 쓰레드 사용

 

3. 메인 프로세스

멀티 프로세싱 모듈 : 프로세스의 이름과 프로세스 아이디

import multiprocessing as mp 
if __name__ == "__main__":
proc = mp.current_process()
print(proc.name)
print(proc.pid)

#MainProcess
#33732

 

3. 메인 스포닝(spawning)

부모 프로세스(Parent Process)가 운영체제에 요청하여 자식프로세스(Child Process)를 생성
작업량이 많은 경우 일부 작업을 자식 프로세스에게 위임하여 처리 가능

def worker():
    proc = mp.current_process()
    print(proc.name)
    print(proc.pid)
    time.sleep(5)
    print("SubProcess End")
    
    
if __name__ == "__main__":
    # 메인 프로세스
    proc = mp.current_process()
    print(proc.name)
    print(proc.pid)
    
    #Processing Sparwing
    p = mp.Process(name="SubProcess", target=worker)
    p.start()
    
    print("MainProcess End")

 

4. 프로세스와 쓰레드

공유자원을 관리하기 특수한 방법을 사용해야 함

import threading

x = 0
def foo():
    global x
    for i in range(1000000):
        x += 1
    
def bar():
    global x
    for i in range(1000000):
        x -= 1
    
t0 = threading.Thread(target=foo)
t1 = threading.Thread(target=bar)
t0.start()
t1.start()
t0.join()
t1.join()
print(x)
더보기

파이썬의 GIL(Global Interpreter Lock)은 파이썬 인터프리터가 한 번에 한 스레드만 파이썬 바이트코드를 실행하도록 제한하는 메커니즘입니다. 이는 멀티스레딩 환경에서 동시에 여러 CPU 코어를 활용하는 것을 제한하고, 파이썬 프로그램의 병렬성을 제한하는 주요 요인 중 하나입니다.

GIL은 CPython, 즉 기본적으로 파이썬으로 작성된 C 언어로 구현된 파이썬 인터프리터에서 발생합니다. CPython의 GIL은 파이썬 바이트코드를 실행하는 동안에만 적용되며, I/O 작업이나 외부 호출 등의 작업은 GIL에 영향을 받지 않습니다.

GIL이 왜 필요한지 이해하기 위해서는 파이썬의 메모리 관리 방식을 이해해야 합니다. 파이썬은 자동으로 메모리를 관리해주는 가비지 컬렉션을 사용합니다. 이 가비지 컬렉션은 여러 스레드가 동시에 메모리를 수정하는 것을 방지하기 위해 GIL을 사용합니다. GIL은 파이썬의 가비지 컬렉션을 단일 스레드로만 실행되도록 보장하며, 이를 통해 메모리 누수나 데이터 손상을 방지합니다.

하지만 GIL은 멀티코어 프로세서의 이점을 제대로 활용하지 못하게 만들기도 합니다왜냐하면 여러 스레드가 병렬로 실행되더라도, 실제로 파이썬 인터프리터는 동시에 하나의 스레드만 실행하도록 GIL을 유지하기 때문입니다. 따라서 CPU 바운드 작업(연산 집약적인 작업)을 수행하는 경우에는 GIL로 인해 멀티코어 환경에서 성능 향상을 기대하기 어렵습니다.

GIL은 특히 CPU 바운드 작업을 수행하는 멀티스레드 파이썬 프로그램의 성능을 제한할 수 있습니다. 그러나 I/O 바운드 작업(입출력 집약적인 작업)의 경우에는 GIL이 큰 영향을 미치지 않습니다. 왜냐하면 I/O 작업을 수행하는 동안에는 대부분의 시간이 대기 상태에 있기 때문에 GIL이 해제되고, 다른 스레드가 파이썬 코드를 실행할 수 있기 때문입니다.

파이썬에서 GIL 문제를 해결하기 위해서는 여러 가지 방법이 있습니다. 대표적으로 다음과 같은 방법들이 있습니다:

1. 멀티프로세스

멀티프로세스 모듈을 사용하여 GIL을 우회하고 별도의 프로세스를 생성하여 병렬 처리를 수행할 수 있습니다.
  
2. C 확장 모듈 사용

C 언어나 Cython 등의 확장 모듈을 사용하여 CPU 바운드 작업을 수행하는 부분을 파이썬 바이트코드가 아닌 네이티브 코드로 실행하여 GIL을 우회할 수 있습니다.
  
3. Jython 또는 IronPython 사용

Jython은 자바 가상 머신 위에서 실행되며, IronPython은 .NET 환경에서 실행됩니다. 이러한 환경에서는 GIL이 존재하지 않기 때문에 멀티스레드 환경에서 성능 향상을 기대할 수 있습니다.
  
4. Asyncio와 같은 비동기 프로그래밍

비동기 프로그래밍을 통해 I/O 바운드 작업을 효율적으로 처리하고, GIL의 영향을 최소화할 수 있습니다.

이러한 방법들을 사용하여 GIL 문제를 해결하거나 우회함으로써 파이썬 프로그램의 성능을 향상시킬 수 있습니다.

반응형