파이썬의 GIL

codakcodak·2023년 5월 7일
0

GIL(Global Interpreter Lock)

정의:멀티쓰레드에서 다른 객체에 접근하는 것을 막기 위해 한번에 하나의 바이트코드를 실행하는 것

(In CPython, the global interpreter lock, or GIL, is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecodes at once. This lock is necessary mainly because CPython's memory management is not thread-safe.)

한번에 하나의 쓰레드를 사용하기 때문에 멀티쓰레드의 병렬적 동작이 불가능하다.

단순 연산의 멀티쓰레드와 멀티프로세스

  1. 단순 연산
import time
import os,sys
import threading

sys.set_int_max_str_digits(1000000000)

nums=[50]*5

#3중for문으로 곱을 하는 단순한 cpu연산의 함수
def cpu_bound_func(number:int):
    print(f"{os.getpid()} process | {threading.get_ident()} thread")
    total=1
    arrange=range(1,number+1)
    for i in arrange:
        for j in arrange:
            for k in arrange:
                total*=i*j*k
            
    return total

def main():
    results=[cpu_bound_func(num) for num in nums]    

if __name__=="__main__":
    start = time.time()
    main()
    print("실행시간 :", time.time() - start,"seconds")
$ python multi_thread_cpu_bound.py
22276 process | 27660 thread
22276 process | 27660 thread
22276 process | 27660 thread
22276 process | 27660 thread
22276 process | 27660 thread
실행시간 : 12.075221300125122 seconds
  1. 단순 연산의 멀티 쓰레드
import time
import os,sys
import threading
from concurrent.futures import ThreadPoolExecutor

sys.set_int_max_str_digits(1000000000)

nums=[50]*5

def cpu_bound_func(number:int):
    print(f"{os.getpid()} process | {threading.get_ident()} thread")
    total=1
    arrange=range(1,number+1)
    for i in arrange:
        for j in arrange:
            for k in arrange:
                total*=i*j*k
            
    return total

def multi_thread_main():
    executor=ThreadPoolExecutor(max_workers=10)
    results=list(executor.map(cpu_bound_func,nums))
    
if __name__=="__main__":
    start = time.time()
    multi_thread_main()
    print("실행시간 :", time.time() - start,"seconds")
22276 process | 15044 thread
22276 process | 22280 thread
22276 process | 15848 thread
22276 process | 17496 thread
22276 process | 20252 thread
실행시간 : 12.310534954071045 seconds

동작과정

파이썬의 멀티쓰레드에서는 병렬적 동작이 불가능하기 때문에 1번같은 일반적 코드와 성능차이가 거의 없다.

  1. 단순 연산의 멀티 프로세스
import time
import os,sys
import threading
from concurrent.futures import ProcessPoolExecutor

sys.set_int_max_str_digits(1000000000)

nums=[50]*5

def cpu_bound_func(number:int):
    print(f"{os.getpid()} process | {threading.get_ident()} thread")
    total=1
    arrange=range(1,number+1)
    for i in arrange:
        for j in arrange:
            for k in arrange:
                total*=i*j*k
            
    return total

def multi_process_main():
    executor=ProcessPoolExecutor(max_workers=10)
    results=list(executor.map(cpu_bound_func,nums))

if __name__=="__main__":
    start = time.time()
    multi_process_main()
    print("실행시간 :", time.time() - start,"seconds")
25104 process | 29388 thread
15308 process | 23948 thread
3364 process | 30292 thread
29192 process | 13276 thread
6704 process | 19216 thread
실행시간 : 3.2905492782592773 seconds

동작과정

멀티프로세스는 병렬적동작을 하기 때문에 단순 연산에 있어서 큰 성능 향상을 기대할 수 있다.

profile
숲을 보는 코더

0개의 댓글