Microsoft의 비동기식 접근 방식 은 멀티 스레드 프로그래밍을위한 가장 일반적인 목적, 즉 IO 작업에 대한 응답 성을 향상시키는 좋은 방법 입니다.
그러나 비동기 방식은 성능을 전혀 향상 시키거나 CPU를 많이 사용하지 않는 작업에 대한 응답 성을 향상시킬 수 없다는 것을 인식하는 것이 중요합니다.
응답 성을위한 멀티 스레딩
응답 성을위한 멀티 스레딩은 과도한 IO 작업 또는 많은 계산 작업 중에 프로그램을 응답 적으로 유지하는 전통적인 방법입니다. 백그라운드 스레드에 파일을 저장하면 하드 드라이브가 작업을 완료 할 때까지 기다리지 않고도 작업을 계속할 수 있습니다. IO 스레드는 종종 쓰기의 일부가 완료되기를 기다리는 것을 차단하므로 컨텍스트 전환이 자주 발생합니다.
마찬가지로 복잡한 계산을 수행 할 때 정기적 인 컨텍스트 전환을 허용하여 UI가 응답 상태를 유지하고 사용자가 프로그램이 중단되었다고 생각하지 않도록합니다.
여기서의 목표는 일반적으로 여러 스레드가 다른 CPU에서 실행되도록하는 것이 아닙니다. 대신, 백그라운드 백그라운드 작업이 실행되는 동안 UI를 업데이트하고 사용자에게 응답 할 수 있도록 장기 실행 백그라운드 작업과 UI간에 컨텍스트 전환이 발생하도록하는 데 관심이 있습니다. 일반적으로 UI는 CPU를 많이 사용하지 않으며 스레딩 프레임 워크 또는 OS는 일반적으로 동일한 CPU에서 실행하도록 결정합니다.
컨텍스트 전환 비용이 추가되어 실제로 전체 성능이 저하되지만 CPU 성능이 목표가 아니기 때문에 신경 쓰지 않습니다. 우리는 보통 우리가 필요로하는 것보다 더 많은 CPU 파워를 가지고 있다는 것을 알고 있으므로 멀티 스레딩에 대한 우리의 목표는 사용자의 시간을 낭비하지 않고 사용자를 위해 작업을 수행하는 것입니다.
"비동기"대안
"비동기 방식"은 단일 스레드 내에서 컨텍스트 전환을 활성화하여이 그림을 변경합니다. 이를 통해 모든 작업이 단일 CPU에서 실행될 수 있으며 스레드 생성 / 정리가 줄어들고 스레드 간의 실제 컨텍스트 전환이 줄어든 성능이 약간 향상 될 수 있습니다.
네트워크 리소스의 수신을 기다리는 새 스레드를 만드는 대신 (예 : 이미지 다운로드) 이미지를 사용할 수있게 하는 async
메소드가 사용 await
되며 그 동안 호출 메소드를 생성합니다.
여기서 주요 장점은 잠금 및 동기화를 전혀 사용하지 않기 때문에 교착 상태 방지와 같은 스레딩 문제에 대해 걱정할 필요가 없으며 프로그래머가 백그라운드 스레드를 설정하고 다시 가져 오는 작업이 약간 적다는 것입니다 UI를 안전하게 업데이트하기 위해 결과가 다시 표시되면 UI 스레드에서
기술적 인 세부 사항을 너무 깊이 조사하지는 않았지만 가끔 가벼운 CPU 활동으로 다운로드를 관리하면 별도의 스레드가 아닌 UI 이벤트 대기열의 작업과 같은 작업이됩니다. 다운로드가 완료되면 비동기 메소드가 해당 이벤트 큐에서 재개됩니다. 다시 말해, await
"필요한 결과가 있는지 확인하고, 그렇지 않은 경우이 스레드의 작업 대기열에 다시 넣습니다"와 비슷한 것을 의미합니다.
이 방법은 CPU를 많이 사용하는 작업의 문제를 해결하지 못합니다. 대기 할 데이터가 없으므로 실제 백그라운드 작업자 스레드를 만들지 않고 상황 컨텍스트 전환을 수행 할 수 없습니다. 물론 비동기 방식을 널리 사용하는 프로그램에서 비동기 메소드를 사용하여 백그라운드 스레드를 시작하고 결과를 리턴하는 것이 여전히 편리 할 수 있습니다.
성능을위한 멀티 스레딩
"성능"에 대해 이야기하기 때문에 멀티 스레딩을 성능 향상에 사용하는 방법에 대해서도 논의하고 싶습니다. 단일 스레드 비동기 방식으로는 불가능합니다.
실제로 단일 CPU에 충분한 CPU 전원이없고 성능에 멀티 스레딩을 사용하려는 경우 실제로 수행하기가 어려운 경우가 많습니다. 반면에 하나의 CPU가 충분한 처리 성능을 갖추지 못하면 합리적인 시간 내에 프로그램이 수행하려는 작업을 수행 할 수있는 유일한 솔루션이기도합니다.
사소한 병렬 처리
물론 멀티 스레딩을 통해 실제 속도를 높이는 것이 쉬운 경우도 있습니다 .
많은 독립적 인 계산 집약적 작업 (즉, 결과를 결정하기 위해 수행해야하는 계산과 관련하여 입력 및 출력 데이터가 매우 작은 작업)이 발생하는 경우 종종 다음과 같이 상당한 속도 향상을 얻을 수 있습니다. 스레드 풀 (사용 가능한 CPU 수에 따라 적절하게 크기 조정)을 작성하고 마스터 스레드가 작업을 분배하고 결과를 수집합니다.
성능을위한 실용적인 멀티 스레딩
나는 너무 많은 전문가가되기를 원치 않지만, 일반적으로 요즘 발생하는 성능에 대한 가장 실용적인 멀티 스레딩은 사소한 병렬 처리가있는 응용 프로그램의 위치를 찾고 여러 스레드를 사용한다는 것입니다 혜택을 얻을 수 있습니다.
최적화와 마찬가지로 일반적으로 프로그램 성능을 프로파일 링하고 핫스팟을 식별 한 후에 최적화하는 것이 좋습니다.이 부분은 스레드없이 다른 스레드에서 실행해야한다고 임의로 결정하여 프로그램 속도를 늦추기 쉽습니다. 먼저 두 부분이 CPU 시간의 상당 부분을 차지하는지 확인합니다.
추가 스레드는 더 많은 설정 / 삭제 비용과 더 많은 컨텍스트 스위치 또는 더 많은 CPU 간 통신 비용을 의미합니다. 별도의 CPU를 사용하는 경우 이러한 비용을 보충하기에 충분한 작업을 수행하지 않고 응답 성 이유로 별도의 스레드가 필요하지 않은 경우 이점이 없어 속도가 느려집니다.
상호 종속성이 거의없고 프로그램 런타임의 상당 부분을 차지하는 작업을 찾으십시오.
상호 의존성이 없다면 사소한 병렬 처리의 경우 스레드로 쉽게 설정하고 이점을 누릴 수 있습니다.
상호 의존성이 제한된 작업을 찾을 수있어 정보 교환을위한 잠금 및 동기화로 인해 속도가 크게 느려지지 않으면 멀티 스레딩으로 인해 속도가 향상 될 수 있습니다. 필요할 때 동기화되지 않아 잘못된 결과가 발생합니다.
또는 멀티 스레딩을위한 더 일반적인 응용 프로그램 중 일부는 (일부) 미리 정해진 알고리즘의 속도 향상을 찾는 것이 아니라, 더 많은 예산을 책정하려고합니다. 게임 엔진을 작성하는 경우 AI가 프레임 속도 내에서 결정을 내릴 수 있도록 AI에 자체 CPU를 제공 할 수 있으면 AI에 더 큰 CPU주기 예산을 제공 할 수 있습니다.
그러나 스레드를 프로파일 링하고 어느 시점에서 비용을 보충하기에 충분한 작업을 수행하고 있는지 확인하십시오.
병렬 알고리즘
또한 여러 프로세서를 사용하여 속도를 높일 수있는 문제가 많이 있지만 CPU간에 간단히 분할하기에는 너무 모 놀리 식입니다.
CPU 간 통신 비용으로 인해 여러 CPU를 사용할 때의 이점을 제거하기가 쉽기 때문에 병렬 알고리즘은 사용 가능한 최상의 비 병렬 알고리즘과 관련하여 big-O 런타임에 대해 신중하게 분석해야합니다. 일반적으로 각 CPU에서 계산을 사용하는 것보다 CPU 간 통신이 적어야합니다 (큰 O 용어로).
현재로서는 여전히 복잡한 분석이 필요하기 때문에 여전히 학술 연구를위한 공간입니다. 부분적으로 사소한 병렬 처리가 매우 일반적이기 때문입니다. 부분적으로 아직 컴퓨터에 CPU 코어가 많지 않아서 하나의 CPU에서 합리적인 시간 프레임으로 해결할 수없는 모든 CPU를 사용하여 합리적인 시간 프레임으로 해결할 수 있습니다.