프로그래밍에서 스레드를 올바르게 사용하는 것은 무엇입니까?


13

많은 프로그램이 프로세스 당 최대 100 개를 사용하는 동안 사람들은 프로세서 당 하나의 스레드 만 사용하도록 권장한다고 들었습니다. 예를 들어 일반적인 프로그램

vb.net ide uses about 25 thread when not debugging
System uses about 100
chrome uses about 19
Avira uses more than about 50

스레드 관련 질문을 게시 할 때마다 프로세서마다 하나 이상의 스레드를 사용해서는 안되며, 위에서 언급 한 모든 프로그램은 단일 프로세서로 시스템을 망칠 것입니다.


7
그 추천은 광범위합니다. 프로세서 당 하나의 스레드 제한은 계산 바운드 응용 프로그램에만 적합합니다. 대부분의 프로그램은 네트워크 트래픽, 디스크 액세스 또는 RAM에 관계없이 IO 바인딩됩니다. 그렇기 때문에 웹 서버, 데이터베이스 등에는 프로세서 코어보다 많은 스레드가있는 스레드 풀이 있습니다.
Kilian Foth

2
"프로세서 당 하나 이상의 스레드를 사용해서는 안된다는 사실을 거의 항상 상기시켜줍니다." 링크 나 예제를 게시 할 수 있습니까? 거의 매번 ?
S.Lott

2
"... 사람들은 프로세스 당 하나의 스레드 만 사용하도록 권장합니다." 이 사람들은 누구인가요? 암흑 시대 이후로 일정이 크게 발전했습니다.
Rein Henrichs

2
프로세스 당 둘 이상의 UI 스레드 가 없어야 합니다.
SLaks

3
@ 빌리 오닐 (Billy ONeal), 귀하의 편집으로 질문이 무의미 해졌습니다
SK-logic

답변:


22

프로세서 당 하나의 스레드 만 사용해야합니다.

아마도 최대의 효율성을 원하는 HPC에서 가능할 것입니다.

프로그램 설계에 적합한 스레드 수를 사용해야하며 여전히 허용 가능한 성능을 제공해야합니다.

웹 서버의 경우 들어오는 각 연결마다 스레드를 시작하는 것이 합리적 일 수 있습니다 (물론로드가 많은 서버에는 더 나은 방법이 있지만).

자신의 스레드에서 실행되는 각 도구는 부적절하지 않습니다. .Net IDE에 대해보고 된 많은 스레드가 로깅 및 I / O 작업이 자체 스레드에서 시작되어 차단되지 않은 채 계속 될 수 있다고 생각합니다.


9
이제 당신이 들어 본 것 중에서 가장 어리석은 것이 무엇인지 궁금합니다.
Michael K

3
@Michael-저 학년생을 가르치고 국방 계약을 맺었습니다. 내가들은 가장 멍청한 말은 믿지 않을 것입니다!
Martin Beckett

1
TheDailyWTF.com에서 본 적이 있습니까?
FrustratedWithFormsDesigner

나는 지금 그들을 찾을 수 없지만이 링크를 보십시오 social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/…
Smith

2
대부분의 응용 프로그램에 할당 된 프로세서 당 하나의 CPU에 바인딩 된 스레드를. IO 바운드 스레드는 소비하는 메모리 이외의 큰 문제가 아니며 시스템 CPU의 하위 집합 만 사용하도록 앱을 제한 할 수 있다는 점을 기억해야합니다. 결국, 그것은 (일반적으로) 프로그래머가 아닌 사용자 / 관리자의 컴퓨터입니다.
Donal Fellows

2

코어 당 하나의 스레드 조언은 병렬 실행을 통한 목적이 속도 일 때 적용됩니다.

완전히 다르고 똑같이 유효한 이유는 예측할 수없는 이벤트에 응답해야 할 때 코드가 단순하기 때문입니다. 따라서 프로그램이 100 개의 소켓에서 청취해야하고 각 소켓에 완전히주의를 기울이는 것처럼 보이면 스레딩에 완벽하게 사용됩니다. 또 다른 예는 하나의 스레드가 UI 이벤트를 처리하고 다른 하나는 백그라운드 처리를 처리하는 UI입니다.


1
IO 바운드 처리는 이벤트 소스 당 하나의 스레드로 수행되거나 여러 이벤트 소스가 단일 스레드로 다중화 될 수 있습니다. 다중화 된 코드는 일반적으로 더 복잡하고 효율적입니다.
Donal Fellows

2

다른 계산과 다른 속도로 진행될 수있는 각 계산마다 하나의 스레드가 필요합니다.

대규모 작업 블록으로 제공되는 병렬 CPU 바운드 계산의 경우 일반적으로 CPU 당 하나의 스레드를 원합니다. 일단 스레드가 모두 사용되면 더 많은 스레드가 도움이되지 않고 스케줄러 오버 헤드를 생성하기 때문입니다. 작업 블록의 크기가 불규칙한 크기이거나 런타임에 동적으로 생성되는 경우 (종종 처리 할 복잡한 데이터 구조가 큰 경우) 블록을 많은 스레드에 첨부 할 수 있으므로 스케줄러는 항상 모든 CPU 사용을 유지하기 위해 일부 작업 블록이 완료 될 때 선택하도록 설정합니다.

I / O 바운드 계산의 경우 일반적으로 각 독립 I / O "채널"에 대해 서로 다른 속도로 통신하기 때문에 하나의 스레드를 원하며 채널에서 차단 된 스레드는 다른 스레드가 진행되는 것을 막지 않습니다.


이 스타일의 스레딩은 이상한 아키텍처의 프로그램으로 이어질 수 있습니다. DB 테이블에서 레코드를 읽는 스레드, 변환 된 레코드를 소켓에 쓰는 스레드, 소켓 쓰기에 대한 답변을 읽는 스레드가있는 4 스레드 프로그램을 보았습니다 (순서가 잘못되었습니다) 그리고 비동기식으로)하고 응답으로 원래 DB 레코드를 수정하는 스레드입니다. 직관적이지 않은 오류 조건이 발생했습니다.
Bruce Ediger

한 가지 관점은이 스타일이 이상한 프로그램을 만들어 낸다는 것입니다. 또 다른 견해는 이것이 프로그램이 가져야 할 자연스러운 스타일입니다. "직관적이지 않은"오류 조건에 대한 Dunno; 많은 일이 발생하고 그중 하나가 오류를 겪으면 비동기 계산을 통해 올바르게 전파되는지 확인하는 것이 많은 언어의 문제입니다 (어쨌든 Java 예외는 스레드 경계에서 정의되지 않음). 프로그램 스타일에 문제가 있습니다. (우리의 PARLANSE 프로그래밍 언어 ([참조 : bio] 참조)는 스레드 경계를 넘어 예외를 깨끗하게 처리하므로이 작업을 올바르게 수행 할 수 있습니다.)
Ira Baxter

1

스레드의 경험상 규칙은 컴퓨터에서 사용할 수있는 각 "실행 단위"에 대해 하나 이상의 "활성"(CPU 시간에 따라 명령을 즉시 실행할 수 있음) 작업자 스레드를 원한다는 것입니다. "실행 단위"는 하나의 논리적 명령어 프로세서이므로 쿼드 칩, 쿼드 코어 Xeon 하이퍼 스레딩 서버에는 32 EU (4 개의 칩, 칩당 4 개의 코어, 각 하이퍼 스레드)가 있습니다. 평균 Core i7은 8입니다.

스레드가 항상 실행 상태에있는 경우 EU 당 하나의 스레드가 CPU 성능을 최대한 활용합니다. 스레드는 캐시되지 않은 메모리, 하드 디스크, 네트워크 포트 등에 액세스해야하기 때문에 기다려야하며 CPU의주의가 필요하지 않습니다. 따라서 더 많은 스레드가 대기하고 갈수록 늘어남으로써 전반적인 효율성을 더욱 높일 수 있습니다. 이것은 비용이 든다. CPU가 스레드를 전환 할 때 스레드의 레지스터, 실행 포인터 및 EU의 가장 내부 작업에 일반적으로 유지되고 매우 빠르게 액세스되는 기타 상태 정보를 캐시해야합니다. 따라서 CPU 칩의 다른 EU가이를 가져올 수 있습니다. 또한 전환 할 스레드를 결정하려면 OS의 스레드가 필요합니다. 마지막으로 EU가 스레드를 전환하면 대부분의 프로세서 아키텍처에서 사용하는 파이프 라이닝의 성능 이점을 잃습니다. 스레드를 전환하기 전에 파이프 라인을 플러시해야합니다. 그러나이 모든 것이 여전히 하드 드라이브 나 RAM이 정보를 제공하기를 기다리는 것보다 평균 시간이 훨씬 덜 걸리기 때문에 비용이 든다.

그러나 일반적으로 EU로서 "활성"스레드 수의 두 배를 넘어 서면 OS는 EU의 시간 스케줄링 스레드보다 더 많은 시간을 소비하기 시작하고 EU는 실제로 활성 스레드를 실행하는 데 소비되는 것보다 더 많은 시간을 소비합니다. 프로그램의. 이것은 규모의 경제의 비결입니다. 이 시점에서 추가 스레드를 추가하는 경우 멀티 스레드 알고리즘을 실행하는 데 실제로 시간이 더 걸립니다.

따라서 전반적으로 컴퓨터에 EU가있는 것보다 최소한 스레드를 프로그램에 유지하려고하지만 대기하거나 잠자 지 않는 수보다 두 배 이상 많은 수의 스레드를 피하고 싶습니다.


N이 스레드 수이고 U가 단위 수이면 OP는 "N = U"규칙에 의문을 제기했습니다. "U <= N <= 2 U"규칙으로 완화하고 있습니다. 조금 더 나아가서 "합리적으로 작은"상수 (프로그래머에게 알려진) c에 대한 "N <= c U"c를 사용할 수 있다고 말합니다 (벤치 마크가 합리적인 성능을 보이는 경우). 스레드 수가 잠재적으로 무제한으로 늘어날 수 있는지는 매우 우려됩니다.
5gon12eder

1

하나의 스레드를 사용해야합니다.

바쁘게 유지해야하는 각 프로세서.

각각의 I / O는 비 차단 방식으로는 수행 할 수 없도록 유용하게 동시에 보류 할 수 있습니다. 예를 들어 로컬 디스크에서 읽습니다.

비 차단 인터페이스가 없거나 비 차단 인터페이스가 적합하지 않은 라이브러리를 호출하는 것과 같이 전용 스레드가 필요한 각 작업. 여기에는 시스템 시계 모니터링, 발사 타이머 등과 같은 작업이 포함됩니다.

페이지 결함과 같은 예기치 않은 차단으로부터 보호하기위한 추가 기능.

예를 들어 중요하지 않은 코드에서 최적화 할 가치가없는 예상 차단으로부터 보호하기위한 추가 기능. 예를 들어, DNS 요청을 거의 할 필요가없는 경우 DNS 요청을 비동기 적으로 수행하려는 노력이 필요하지 않을 수 있습니다. 몇 개의 추가 스레드를 작성하고보다 쉽게 ​​생활 할 수 있습니다.

"프로세서 당 하나의 스레드"규칙을 따르는 경우 모든 코드가 성능에 중요합니다. 어떤 이유로 든 차단되는 코드는 프로세스가 해당 프로세서를 사용할 수 없음을 의미합니다. 그럴만한 이유없이 프로그래밍이 훨씬 어려워집니다.


0

단일 프로그램에 멀티 코어 / 멀티 프로세서 시스템을 사용할 수 있도록 프로세스와 스레드를 생성 할 수 있으며,이 경우 코어보다 스레드 / 프로세스가 더 많아도 단일 프로그램에는 이점이 없습니다.

또는 일반적으로 추가 실행을 차단하는 이벤트를 폴링하는 루틴을 가질 수 있습니다. CPU를 폴링으로 묶는 대신 적절한 이벤트가 발생할 때까지 유휴 상태로 유지되는 스레드를 만들 수 있습니다. 이 방법은 웹 서버 및 GUI 이벤트 큐에서 매우 일반적으로 사용됩니다. 대부분의 프로그램은 모든 스레드가 액세스 할 수있는 일종의 중앙 데이터 저장소 (프로그램 실행 코드가 있더라도)를 원하므로 프로세스에서 스레딩을 사용하는 것 같습니다.


0

언급 한 앱이 수십 개의 스레드를 동시에 실행 하는 경우는 거의 없습니다 . 스레드 풀 에 있기 때문에 대부분 거기에 앉아 있습니다 . 앱은 대기열에 다양한 작업을 보내고 스레드 풀의 스레드에 의해 제거됩니다.

수영장 크기가 왜 그렇게 큰가요? 스레드는 종종 디스크, 네트워크, 사용자, 다른 스레드 등과 같은 다른 리소스 를 기다려야 하기 때문에 스레드가 대기하는 동안 프로세서를 완전히 활용하려면 다른 스레드를 실행하는 것이 좋습니다. 풀의 크기를 적절하게 조정하는 것은 쉽지 않습니다. 스레드가 너무 적 으면 무언가를 기다리는 동안 프로세서가 완전히 활용되지 않으므로 성능이 저하됩니다. 스레드가 너무 많으면 스레드 간 전환으로 인해 성능이 저하됩니다.

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