Python은 멀티 스레딩을 지원합니까? 실행 시간을 단축 할 수 있습니까?


95

다중 스레딩이 Python에서 작동하는지 여부에 대해 약간 혼란 스럽습니다.

나는 이것에 대해 많은 질문이 있었고 많은 것을 읽었지만 여전히 혼란 스럽습니다. 나는 내 경험을 통해 알고 있으며 다른 사람들이 여기에 StackOverflow에 자신의 답변과 예제를 게시하는 것을 보았습니다. 그렇다면 모든 사람들이 Python이 GIL에 의해 잠겨 있고 한 번에 하나의 스레드 만 실행할 수 있다고 계속 말하는 이유는 무엇입니까? 분명히 작동합니다. 아니면 내가 여기서 얻지 못하는 차이점이 있습니까?

많은 포스터 / 응답자들은 스레딩이 다중 코어를 사용하지 않기 때문에 제한적이라고 계속 언급합니다. 그러나 동시에 작업을 수행하므로 결합 된 워크로드가 더 빨리 완료되기 때문에 여전히 유용하다고 말할 수 있습니다. 왜 그렇지 않으면 파이썬 스레드 모듈이 있을까요?

최신 정보:

지금까지 모든 답변에 감사드립니다. 내가 이해하는 방식은 멀티 스레딩이 일부 IO 작업에 대해서만 병렬로 실행되지만 CPU 바운드 다중 코어 작업에 대해서는 한 번에 하나씩 만 실행할 수 있다는 것입니다.

이것이 실제적인 측면에서 나에게 어떤 의미인지 완전히 확신 할 수 없으므로 멀티 스레드를 수행하려는 작업의 종류에 대한 예를 들겠습니다. 예를 들어, 매우 긴 문자열 목록을 반복하고 각 목록 항목에 대해 몇 가지 기본 문자열 작업을 수행하고 싶다고 가정 해 보겠습니다. 목록을 분할하고 새 스레드의 루프 / 문자열 코드로 처리 할 각 하위 목록을 보내고 결과를 다시 대기열로 보내면 이러한 워크로드가 대략 동시에 실행됩니까? 가장 중요한 것은 이것이 이론적으로 스크립트를 실행하는 데 걸리는 시간을 단축한다는 것입니다.

또 다른 예는 4 개의 다른 스레드에서 PIL을 사용하여 4 개의 다른 그림을 렌더링하고 저장할 수 있고 그림을 하나씩 처리하는 것보다 더 빠를 수 있습니다. 이 속도 요소는 올바른 용어가 무엇인지 라기보다는 제가 정말로 궁금해하는 것 같습니다.

멀티 프로세싱 모듈에 대해서도 알고 있지만 지금은 중소 규모의 작업로드 (10-30 초)에 주된 관심이 있으므로 하위 프로세스를 시작하는 데 속도가 느릴 수 있으므로 멀티 스레딩이 더 적절할 것이라고 생각합니다.


4
이것은 꽤로드 된 질문입니다. 나는에서 답 거짓말 생각 무엇을 당신이 스레드가 수행 갖고 싶어합니다. 대부분의 상황에서 GIL은 둘 이상의 스레드가 동시에 실행되는 것을 방지합니다. 그러나 병렬로 수행 할 수 있도록 GIL이 릴리스 된 경우 (예 : 파일에서 읽기)가 몇 가지 있습니다. 또한 GIL은 Cpython (가장 일반적인 구현) 의 구현 세부 사항 입니다. 파이썬의 다른 구현 (자이 썬, PyPy 등)는 GIL (AFAIK)이 없습니다
mgilson

2
@mgilson PyPy에는 GIL이 있습니다.

2
@delnan-당신이 옳은 것 같습니다. 감사.
mgilson 2014-01-05

1
"하위 프로세스는 시작 속도가 느릴 수 있습니다."-실행할 준비가 된 작업 풀을 만들 수 있습니다. 오버 헤드는 작업이 작업을 시작하는 데 필요한 데이터를 직렬화 / 역 직렬화하는 데 걸리는 대략적인 시간으로 제한 될 수 있습니다.
Brian Cain

1
@KarimBahgat, 그게 정확히 내가 의미하는 바입니다.
Brian Cain

답변:


132

GIL은 스레딩을 방지하지 않습니다. GIL이하는 일은 한 번에 하나의 스레드 만 Python 코드를 실행하는지 확인하는 것입니다. 제어는 여전히 스레드간에 전환됩니다.

GIL이 방지하는 것은 하나 이상의 CPU 코어 또는 별도의 CPU를 사용하여 스레드를 병렬로 실행하는 것입니다.

이것은 Python 코드에만 적용됩니다. C 확장은 GIL을 릴리스하여 여러 C 코드 스레드와 하나의 Python 스레드가 여러 코어에서 실행되도록 할 수 있습니다. 이것은 select()소켓 읽기 및 쓰기에 대한 호출 과 같이 커널에 의해 제어되는 I / O로 확장 되어 Python이 다중 스레드 다중 코어 설정에서 네트워크 이벤트를 합리적으로 효율적으로 처리하도록합니다.

그런 다음 많은 서버 배포가 수행하는 작업은 둘 이상의 Python 프로세스를 실행하여 OS가 프로세스 간의 일정을 처리하여 CPU 코어를 최대로 활용하도록하는 것입니다. 사용 사례에 적합한 경우 multiprocessing라이브러리 를 사용하여 하나의 코드베이스 및 상위 프로세스에서 여러 프로세스에 걸쳐 병렬 처리를 처리 할 수도 있습니다 .

GIL은 CPython 구현에만 적용됩니다. Jython과 IronPython은 서로 다른 스레딩 구현을 사용합니다 (각각 네이티브 Java VM 및 .NET 공통 런타임 스레드).

업데이트를 직접 처리하려면 : 순수 Python 코드를 사용하여 병렬 실행에서 속도 향상을 시도하는 모든 작업은 스레드 된 Python 코드가 한 번에 실행되는 하나의 스레드에 잠겨 있으므로 속도가 향상되지 않습니다. 그러나 C 확장과 I / O를 혼합하면 (예 : PIL 또는 numpy 작업) 모든 C 코드가 하나의 활성 Python 스레드 와 병렬로 실행될 수 있습니다 .

Python 스레딩은 반응 형 GUI를 만들거나 I / O가 Python 코드보다 병목 현상이 더 큰 여러 개의 짧은 웹 요청을 처리하는 데 적합합니다. 계산 집약적 인 Python 코드를 병렬화 multiprocessing하거나 이러한 작업 을 위해 모듈을 고수 하거나 전용 외부 라이브러리에 위임하는 데 적합하지 않습니다 .


@MartijnPieters에게 감사합니다. 그러면 "아니오"인 for 루프와 같은 코드 속도를 높이기 위해 스레딩을 사용할 수 있는지 여부에 대한 내 질문에 대한 명확한 답변이 있습니다. 아마도 당신이나 누군가가 내가 받아 들일 수있는 새로운 답변을 작성할 수있을 것입니다. 이것은 GIL에서 스레딩이 병렬로 실행되도록 허용하는 일반적인 모듈 / 코드 / 작업의 몇 가지 구체적인 예를 제공합니다 (예 : I / O 및 네트워크 / 언급 된 소켓 읽기 작업 및 Python의 멀티 스레딩이 유용한 다른 경우). 가능한 경우 일반적인 다중 스레드 사용 및 일부 프로그래밍 예제의 좋은 목록이 있습니까?
Karim Bahgat 2014 년

4
아니요, 그러한 답변이별로 도움이되지 않을 것 같습니다. 솔직히. 완전한 목록을 만들 수는 없지만, 경험상의 규칙은 모든 I / O (파일 읽기 및 쓰기, 네트워크 소켓, 파이프)가 C로 처리되고 많은 C 라이브러리도 해당 GIL을 릴리스한다는 것입니다. 그러나이를 문서화하는 것은 라이브러리에 달려 있습니다.
Martijn Pieters

1
내 잘못은 지금까지 업데이트 된 답변을 보지 못했으며 스레드 사용에 대한 좋은 예를 제공했습니다. 이러한 포함 (올바른 내게 임 잘못된 경우) 네트워크 프로그래밍 (예 urllib.urlopen()?)는 파이썬 GUI 내에서 하나의 파이썬 스크립트를 호출하는 여러 PIL (예 : 전화 Image.transform())와 NumPy와 (예를 들어 numpy.array()스레드) 작업을. 그리고 여러 스레드를 사용하여 파일을 읽는 것과 같은 몇 가지 예제를 주석에 추가했습니다 (예 : f.read()?). 완전한 목록이 불가능하다는 것을 알고 있으며 업데이트에서 제공 한 예제 유형을 원했습니다. 어느 쪽이든, 귀하의 답변을 수락했습니다. :)
Karim Bahgat 2014 년

2
@KarimBahgat : 예, urllib.urlopen()네트워크 소켓을 호출합니다. 소켓 I / O를 기다리는 것은 스레드를 전환하고 다른 작업을 수행 할 수있는 훌륭한 기회입니다.
Martijn Pieters

4
이 문제와 직접적인 관련이 없지만 때때로 스레딩이 성능에 관한 것이 아님을 주목할 가치가 있습니다. 코드를 여러 개의 독립적 인 실행 스레드로 작성하는 것이 더 간단 할 수 있습니다. 예를 들어, 하나의 스레드가 배경 음악을 재생하고, 하나는 UI를 서비스하고, 다른 하나는 결국 수행해야하지만 서두르지 않는 계산에 집중할 수 있습니다. UI runloop로 다음 오디오 버퍼 재생을 시퀀싱하거나 상호 작용을 방해하지 않도록 계산을 작은 조각으로 나누는 것은 스레드를 사용하는 것보다 훨씬 어려울 수 있습니다.
abarnert

4

예. :)

하위 수준 스레드 모듈과 상위 수준 스레드 모듈이 있습니다. 그러나 단순히 멀티 코어 머신을 사용하고 싶다면 멀티 프로세싱 모듈 을 사용 하면됩니다.

문서 에서 인용 :

CPython에서는 Global Interpreter Lock으로 인해 한 번에 하나의 스레드 만 Python 코드를 실행할 수 있습니다 (특정 성능 지향 라이브러리가이 제한을 극복 할 수 있음에도 불구하고). 애플리케이션이 멀티 코어 머신의 계산 리소스를 더 잘 활용하도록하려면 멀티 프로세싱을 사용하는 것이 좋습니다. 그러나 여러 I / O 바인딩 작업을 동시에 실행하려는 경우 스레딩은 여전히 ​​적절한 모델입니다.


3

파이썬에서 스레딩이 허용됩니다. 유일한 문제는 GIL이 한 번에 하나의 스레드 만 실행되도록한다는 것입니다 (병렬 처리 없음).

따라서 기본적으로 계산 속도를 높이기 위해 코드를 다중 스레드하려는 경우 한 번에 하나의 스레드 만 실행되는 것처럼 속도가 빨라지지는 않지만 예를 들어 데이터베이스와 상호 작용하는 데 사용하면 속도가 빨라집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.