[Python 3.13] GIL을 해제해보자Language/Python2024. 10. 11. 20:28
Table of Contents
드디어 Python 3.13.0 에서 GIL이 해제 되었다.
Python 3.13.0 으로 멀티쓰레딩 성능 테스트를 해보려 했지만, 실패했다.
찾아보니, 일반 CPython 3.13 에선 아직 안되고, GIL을 해제하여 빌드 된 CPython을 사용해야 한다.
pyenv 를 활용하여 GIL이 해제된 CPython을 구해보자
pyenv install 3.13t-dev
pyenv shell 3.13t-dev
python3 --version
# Python 3.13.0+ 형식으로 나오면 성공
GIL이 해제되어 성능이 싱글 쓰레드 < 멀티 프로세싱 < 멀티 쓰레드 순으로 나왔다.
그렇다면 8코어 8쓰레드 M3 기준 CPU를 잘 갈구는지 확인해보자
테스트 코드
import math
import multiprocessing
import sys
import sysconfig
import threading
import time
PYTHON_GIL = 1
# A CPU-bound task: computing a large number of prime numbers
def is_prime(n: int) -> bool:
if n <= 1:
return False
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
def count_primes(start: int, end: int) -> int:
count = 0
for i in range(start, end):
if is_prime(i):
count += 1
return count
def threaded_count_primes(n: int, num_threads: int) -> int:
threads = []
results = [0] * num_threads
def worker(start: int, end: int, index: int) -> None:
results[index] = count_primes(start, end)
step = n // num_threads
for i in range(num_threads):
start = i * step
end = (i + 1) * step if i != num_threads - 1 else n
thread = threading.Thread(target=worker, args=(start, end, i))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
return sum(results)
def multiprocess_count_primes(n: int, num_processes: int) -> int:
with multiprocessing.Pool(processes=num_processes) as pool:
step = n // num_processes
tasks = [
(i * step, (i + 1) * step if i != num_processes - 1 else n)
for i in range(num_processes)
]
results = [pool.apply_async(count_primes, args=task) for task in tasks]
return sum([result.get() for result in results])
def main() -> None:
# print(f"The GIL active: {sys._is_gil_enabled()}")
print(f"Version of python: {sys.version}")
active = sysconfig.get_config_vars().get("Py_GIL_DISABLED")
if active is None:
print("GIL cannot be disabled")
if active == 0:
print("GIL is [active]")
if active == 1:
print("GIL is [disabled]")
N = 3*10**6
start_time = time.time()
single_threaded_result = count_primes(0, N)
single_threaded_time = time.time() - start_time
print(
f"Single-threaded: {single_threaded_result} primes in [{single_threaded_time:.2f}] seconds"
)
for i in range(1, 16):
NUM_THREADS = i
NUM_PROCESSES = i
start_time = time.time()
threaded_result = threaded_count_primes(N, NUM_THREADS)
threaded_time = time.time() - start_time
print(f"{i} Threaded: {threaded_result} primes in [{threaded_time:.2f}] seconds")
start_time = time.time()
multiprocess_result = multiprocess_count_primes(N, NUM_PROCESSES)
multiprocess_time = time.time() - start_time
print(
f"{i} Multiprocessed: {multiprocess_result} primes in [{multiprocess_time:.2f}] seconds"
)
print()
if __name__ == "__main__":
main()
원본 출처 : https://github.com/ArjanCodes/examples/blob/main/2024/gil/main.py
'Language > Python' 카테고리의 다른 글
[Python] 파이썬 개발자 면접 질문 (0) | 2024.05.26 |
---|---|
[Python] GIL이란? 파이썬에서의 멀티쓰레드 (0) | 2024.05.06 |
[Python] Pandas, Numpy 성능 향상 (feat.Pandas vs Numpy) (0) | 2024.05.06 |
Python 3.11 달라진 점 - 업데이트 (0) | 2024.01.15 |
자료구조 - List, Dict, Set, Tuple (0) | 2022.10.27 |