GIL (Global Interpreter Lock)은 파이썬에서 스레딩 (threading) 등이 터치하기 까다로운 주요 이유로 자주 인용되는 것 같습니다. "처음에 왜 그랬습니까?"라는 질문이 제기됩니다.
프로그래머가 아니기 때문에 그 이유가 무엇인지 전혀 알지 못합니다. GIL을 도입 한 논리는 무엇입니까?
GIL (Global Interpreter Lock)은 파이썬에서 스레딩 (threading) 등이 터치하기 까다로운 주요 이유로 자주 인용되는 것 같습니다. "처음에 왜 그랬습니까?"라는 질문이 제기됩니다.
프로그래머가 아니기 때문에 그 이유가 무엇인지 전혀 알지 못합니다. GIL을 도입 한 논리는 무엇입니까?
답변:
CPython, IronPython, RPython 등과 같은 몇 가지 Python 구현이 있습니다.
그들 중 일부는 GIL을 가지고 있으며 일부는 그렇지 않습니다. 예를 들어 CPython에는 GIL이 있습니다.
에서 http://en.wikipedia.org/wiki/Global_Interpreter_Lock
GIL을 사용하여 프로그래밍 언어로 작성된 응용 프로그램은 별도의 프로세스를 사용하여 완전한 병렬 처리를 달성하도록 설계 할 수 있습니다. 각 프로세스에는 고유 한 인터프리터가 있고 고유 한 GIL이 있기 때문입니다.
GIL의 장점
파이썬 (CPython 및 기타)이 GIL을 사용하는 이유
CPython에서 전역 인터프리터 잠금 (GIL)은 여러 원시 스레드가 한 번에 Python 바이트 코드를 실행하지 못하게하는 뮤텍스입니다. 이 잠금은 주로 CPython의 메모리 관리가 스레드로부터 안전하지 않기 때문에 필요합니다.
GIL은 특정 상황에서 멀티 스레드 CPython 프로그램이 멀티 프로세서 시스템을 최대한 활용하지 못하기 때문에 논란의 여지가 있습니다. I / O, 이미지 처리 및 NumPy 번호 크 런칭과 같은 잠재적으로 차단되거나 오래 실행되는 작업은 GIL 외부에서 발생합니다. 따라서 GIL 내부에서 많은 시간을 보내고 CPython 바이트 코드를 해석하여 GIL이 병목 현상이되는 것은 멀티 스레드 프로그램에서만 가능합니다.
파이썬에는 몇 가지 이유로 세밀한 잠금과 달리 GIL이 있습니다.
단일 스레드의 경우 더 빠릅니다.
i / o 바운드 프로그램의 멀티 스레드 케이스에서는 더 빠릅니다.
C 라이브러리에서 계산 집약적 인 작업을 수행하는 CPU 바인딩 프로그램의 경우 멀티 스레드 경우가 더 빠릅니다.
C 확장을 더 쉽게 작성할 수 있습니다 .Py_BEGIN_ALLOW_THREADS와 Py_END_ALLOW_THREADS 매크로 사이에서 허용되는 위치를 제외하고는 파이썬 스레드 전환이 없습니다.
C 라이브러리를보다 쉽게 래핑 할 수 있습니다. 스레드 안전성에 대해 걱정할 필요가 없습니다. 라이브러리가 스레드로부터 안전하지 않은 경우 호출하는 동안 GIL을 잠금 상태로 유지하면됩니다.
GIL은 C 확장으로 해제 할 수 있습니다. Python의 표준 라이브러리는 각 차단 I / O 호출 주위에 GIL을 릴리스합니다. 따라서 GIL은 i / o 바운드 서버의 성능에 영향을 미치지 않습니다. 따라서 프로세스 (포크), 스레드 또는 비동기식 I / O를 사용하여 Python에서 네트워킹 서버를 작성할 수 있으며 GIL은 방해가되지 않습니다.
C 또는 Fortran의 숫자 라이브러리는 GIL 릴리스와 유사하게 호출 할 수 있습니다. C 확장이 FFT가 완료되기를 기다리는 동안 인터프리터는 다른 Python 스레드를 실행합니다. 따라서 GIL은이 경우 세밀한 잠금보다 쉽고 빠릅니다. 이것은 대량의 수치 작업을 구성합니다. NumPy 확장 프로그램은 가능할 때마다 GIL을 해제합니다.
스레드는 일반적으로 대부분의 서버 프로그램을 작성하는 나쁜 방법입니다. 부하가 적 으면 포크가 더 쉽습니다. 부하가 높으면 비동기식 I / O 및 이벤트 중심 프로그래밍 (예 : Python의 Twisted 프레임 워크 사용)이 더 좋습니다. 스레드를 사용하는 유일한 이유는 Windows에서 os.fork가 부족하다는 것입니다.
GIL은 순수 파이썬에서 CPU 집약적 인 작업을 수행하는 경우에만 문제가됩니다. 여기서 프로세스 및 메시지 전달 (예 : mpi4py)을 사용하여보다 깔끔한 디자인을 얻을 수 있습니다. 파이썬 치즈 샵에는 스레드와 동일한 인터페이스를 제공하는 '프로세싱'모듈도 있습니다 (예 : threading.Thread를 processing.Process로 대체).
스레드는 GIL에 관계없이 GUI의 응답 성을 유지하는 데 사용될 수 있습니다. GIL이 성능을 손상시키는 경우 (위의 설명 참조) 스레드가 프로세스를 생성하고 완료 될 때까지 기다릴 수 있습니다.
s/RPython/PyPy/g
. @MichaelBorgwardt 프로 GIL이 그 이유 중 하나 인 이유는 무엇입니까? 나는이 답변의 내용 중 일부 (즉, 대안에 대한 토론)가 요점에 있음에 동의하지만. 그리고 더 나은 또는 더 나쁜 것을 위해, 재계 산은 이제 거의 불가능하다. 전체 API와 코드베이스에 깊이 뿌리 내리고있다. 코드 절반을 다시 작성하지 않고 모든 외부 코드를 손상시키지 않으면 코드를 제거하는 것이 거의 불가능 합니다.
multiprocessing
2.6 이후 표준 라이브러리를 잊지 마십시오 . 워커 풀은 단순한 병렬 처리 유형에 대한 매우 매끄러운 추상화입니다.
우선 파이썬에는 GIL이 없습니다. 파이썬은 프로그래밍 언어입니다. 프로그래밍 언어는 일련의 추상 수학 규칙 및 제한 사항입니다. Python Language Specification에는 GIL이 있어야한다고 말하는 것은 없습니다.
파이썬에는 여러 가지 구현이 있습니다. 일부는 GIL이 있고 일부는 없습니다.
GIL을 갖는 간단한 설명은 동시 코드 작성이 어렵다는 것입니다. 코드 주위에 거대한 잠금을 설정하면 코드가 항상 연속적으로 실행됩니다. 문제 해결됨!
CPython에서 특히 중요한 한 가지 목표는 C로 작성된 플러그인으로 인터프리터를 쉽게 확장하는 것입니다. 다시 한 번, 동시 코드 작성은 어렵 기 때문에 동시성이 없음을 보장하여 확장 성을보다 쉽게 작성할 수 있습니다. 통역사. 또한 이러한 확장 중 다수는 동시성을 염두에두고 작성되지 않았을 수있는 기존 라이브러리 주변의 얇은 래퍼 일뿐입니다.
GIL의 목적은 무엇입니까?
CAPI 문서에는 다음과 같은 주제가 있습니다.
파이썬 인터프리터는 완전히 스레드 안전하지 않습니다. 다중 스레드 파이썬 프로그램을 지원하기 위해 전역 인터프리터 잠금 또는 GIL이라고하는 전역 잠금이있어 파이썬 객체에 안전하게 액세스하려면 현재 스레드가 보유해야합니다. 잠금이 없으면 가장 간단한 조작으로도 멀티 스레드 프로그램에서 문제가 발생할 수 있습니다. 예를 들어, 두 개의 스레드가 동일한 객체의 참조 카운트를 동시에 증가 시키면 참조 카운트는 두 번이 아니라 한 번만 증가 할 수 있습니다.
즉, GIL은 상태의 손상을 방지합니다. 메모리 안전 작업 만 허용되므로 Python 프로그램은 세그먼트 오류를 발생시키지 않아야합니다. GIL은 이러한 보증을 다중 스레드 프로그램으로 확장합니다.
대안은 무엇입니까?
GIL의 목적이 국가를 부패로부터 보호하는 것이라면, 한 가지 확실한 대안은 훨씬 더 미세한 곡물에 고정하는 것입니다. 아마도 객체 별 수준 일 것입니다. 이 문제는 멀티 스레드 프로그램의 성능을 향상시키는 것으로 입증되었지만 더 많은 오버 헤드가 있으며 단일 스레드 프로그램으로 인해 어려움을 겪습니다.