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.)
한번에 하나의 쓰레드를 사용하기 때문에 멀티쓰레드의 병렬적 동작이 불가능하다.
단순 연산의 멀티쓰레드와 멀티프로세스
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
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번같은 일반적 코드와 성능차이가 거의 없다.
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
멀티프로세스는 병렬적동작을 하기 때문에 단순 연산에 있어서 큰 성능 향상을 기대할 수 있다.