Python

[Python] 파이썬 싱글 쓰레드(Single Thread)와 멀티 쓰레드(multi Thread) 사용 예제 및 개념 이해하기

파이썬은 인터프리터 언어입니다. 파이썬은 싱글 쓰레드(Single Thread)에서 순차적으로 동작합니다. 한번에 하나의 작업밖에 할 수 없는 것입니다. 그럼으로 한 번에 여러 작업을 하기 위해서는 threading 모듈을 사용하여 쓰레드를 구현해야합니다.  한 번에 여러 작업을 처리하는 것을 병렬처리라고 합니다. 파이썬은 전역 인터프리터 락킹(Global Interpreter Lock) 때문에 특정 시점에 하나의 파이썬 코드만을 실행하게 되어 있습니다. 그렇기 때문에 파이썬은 실제 다중 CPU 환경에서 동시에 여러 파이썬 코드를 병렬로 실행할 수 없으며 인터리빙(Interleaving) 방식으로 코드를 분할하여 실행됩니다. 다중 CPU 에서 병렬 실행을 위해서는 다중 프로세스를 이용하는 multiprocessing 모듈을 사용해야 합니다. 

 

파이썬에서 병렬처리를 구현하는 방법은 멀티 쓰레드를 사용하거나 멀티프로세스를 사용합니다.

■threading 모듈을 사용하여 싱글 쓰레드 구현

0부터 1억까지의 합을 구하는 계산 프로그램을 1개의 쓰레드로 동작하도록 만들어서 실행합니다. start()함수로 쓰레드시작합니다. join()함수는 쓰레드가 모든 작업을 마칠 때까지 기다리는 것을 의미합니다.  Thread가 인자로 받는 target은 쓰레드가 실행할 함수를 대입합니다. 그리고 args는 쓰레드가 실행하는 함수의 인자들을 의미합니다.

from threading import Thread
import time


def addition_operation(work_id, start, end, result):
    print(f'작업단위 : {work_id}')
    total = 0
    for i in range(start, end):
        total += i
    result.append(total)
    return


result_list = list()
thread1 = Thread(target=addition_operation, args=(1, 0, 100000000, result_list))
thread1.start()
start_time = time.perf_counter() #스톱워치랑 같은 개념
start_time5 = time.process_time() #코드 효율성비교는 process_time()함수를 사용하는 것이 유용

thread1.join()
print(f"덧셈결과: {sum(result_list)}")
end_time = time.perf_counter() 
end_time5 = time.process_time()

print("스톱워치 : 쓰레드 작업 실행시간(초): ", end_time - start_time)
print("코드 효율성비교 : 프로세스 실행시간: ", end_time5 - start_time5)



#실행결과
작업단위 : 1
덧셈결과: 4999999950000000
스톱워치 : 쓰레드 작업 실행시간(초):  5.6459868
코드 효율성비교 : 프로세스 실행시간:  5.53125

 

■threading 모듈을 사용하여 멀티쓰레드 구현

쓰레드를 하나 더 추가하여 병렬로 동작하도록 멀티 쓰레드를 구현하여 실행하여봅니다. 1억까지의 합을 구하기 위해 2개의 쓰레드로 각각 5천만까지 합을 구합니다.

from threading import Thread
import time


def addition_operation(work_id, start, end, result):
    print(f'작업단위 : {work_id}')
    total = 0
    for i in range(start, end):
        total += i
    result.append(total)
    return


result_list = list()
thread1 = Thread(target=addition_operation, args=(1, 0, 50000000, result_list))
thread2 = Thread(target=addition_operation, args=(2, 50000000, 100000000, result_list))
thread1.start()
start_time = time.perf_counter() #스톱워치랑 같은 개념
start_time5 = time.process_time() #코드 효율성비교는 process_time()함수를 사용하는 것이 유용
thread2.start()
thread1.join()
thread2.join()
print(f"덧셈결과: {sum(result_list)}")

end_time = time.perf_counter()
end_time5 = time.process_time()

print("스톱워치 : 쓰레드 작업 실행시간(초):", end_time - start_time)
print("코드 효율성비교 : 프로세스 실행시간:", end_time5 - start_time5)


#실행결과
작업단위 : 1
작업단위 : 2
덧셈결과: 4999999950000000
스톱워치 : 쓰레드 작업 실행시간(초): 5.3284284
코드 효율성비교 : 프로세스 실행시간: 5.3125

처리결과를 보면, 싱글 쓰레드로 처리한 실행시간과 병렬처리(멀티 쓰레드)로 처리한 실행시간의 차이가 거의 없습니다.

그 이유는 파이썬의 전역 인터프리터 락킹(Global Interpreter Lock) 정책(GIL) 때문입니다. GIL정책이 적용되는 것은 CPU동작에서 입니다. 

하나의 쓰레드가 cpu 작업을 마치고 I/O 작업을 실행하는 동안에는 다른 쓰레드가 cpu 동작을 동시에 실행할 수 있습니다.  그럼으로 cpu작업이 적고 I/O 작업이 많은 병렬처리 프로그램에서 효과를 볼 수 있습니다.

 

반면 다중 프로세스를 이용하는 multiprocessing 모듈를 사용하여 구현하는 경우 멀티프로세스 각자가 고유한 메모리를 할당 받아서 사용하기 때문에 많은 메모리를 필요로 합니다. 그러나 작업을 병렬로 동시에 처리합니다. 분산 처리 시스템을 구현할 수 있습니다. 멀티 프로세스에 대한 구현 예제는 다음 글에서 확인할 수 있습니다.

 

[Python] 파이썬 멀티프로세싱(multiprocessing) 구현 예제 : 멀티 쓰레드(multi-Thread)와 실행시간 차이 분석

 

[Python] 파이썬 멀티프로세싱(multiprocessing) 구현 예제 : 멀티 쓰레드(multi-Thread)와 실행시간 차이 분

파이썬에서 다중 CPU에서 병렬 실행을 위해서는 다중 프로세스를 이용하는 multiprocessing 모듈을 사용해야 합니다. 멀티 쓰레드를 구현하여 실행한 결과 프로세스 처리시간은 동일하였습니다. 그

playground.naragara.com

 

[REFERENCE]

예제로 배우는 파이썬 프로그래밍

monkey3199.github.io/develop/python/2018/12/04/python-pararrel.html

 

[파이썬 더 알아보기]

[프로그래밍/Python] – [Python] 파이썬 코드 실행시간(시:분:초) 측정하는 방법 예제 총정리: time(), timedelta(),process_time(), perf_counter(),default_timer()

[프로그래밍/Python] – [Python] 파이썬 패키지(Package), 모듈(Module) 개념 및 예제 : 패키지, 모듈을 만들고 불러오기(import)

[프로그래밍/Python] – [Python] 파이썬 랜덤 숫자 뽑기 난수 발생(random) 예제 총정리 : randint(), randrange(), uniform(), shuffle(), choice(), choices(), simple()

[프로그래밍/Python] – [Python] 파이썬 클래스(class) 와 생성자(__init__) 사용방법 및 예제 총정리

[프로그래밍/Python] – [Python] 파이썬 기본(기초) 문법 : 예제 및 총정리

 

Leave a Reply

error: Content is protected !!