잘못 동작하는 다중 스레드 응용 프로그램의 일반 패턴

개발자는 동시성 시각화 도우미를 사용하여 다중 스레드 응용 프로그램의 동작을 쉽게 시각화할 수 있습니다.이 도구에는 잘못 동작하는 다중 스레드 응용 프로그램의 일반적인 패턴을 모은 갤러리가 포함되어 있습니다.갤러리에는 이 도구를 통해 노출된 일반적이고 인식 가능한 시각적 패턴뿐 아니라, 각 패턴이 나타내는 동작에 대한 설명, 해당 동작의 예상되는 결과 및 가장 일반적인 해결 방법이 포함되어 있습니다.

잠금 경합 및 serialize된 실행

잠금 경합으로 인해 발생하는 serialize된 실행

스레드가 여러 개 있고 컴퓨터의 논리 코어 수가 충분함에도 불구하고 병렬화된 응용 프로그램에서 순차적 실행을 계속하려고 하는 경우가 종종 있습니다.이 경우 첫 번째 증상은 다중 스레드 성능이 저하되는 것이며, 순차적 구현의 경우보다 속도가 다소 느려지기도 합니다.스레드 뷰에서는 병렬로 실행되는 여러 스레드를 볼 수 없으며 대신 언제나 하나의 스레드만 실행되는 것으로 나타납니다.이때 스레드의 동기화 세그먼트를 클릭하면 차단된 스레드에 대한 호출 스택(차단 호출 스택)과 차단 조건을 제거한 스레드에 대한 호출 스택(차단 해제 호출 스택)을 볼 수 있습니다.또한 차단 해체 호출 스택이 분석 중인 프로세스에서 발생한 것이라면 스레드 준비 커넥터가 표시됩니다.이때 차단 호출 스택과 차단 해제 호출 스택에서 코드로 이동하여 serialization의 원인을 세부적으로 조사할 수 있습니다.

다음 그림에 표시된 대로 동시성 시각화 도우미는 여러 스레드가 있음에도 불구하고 응용 프로그램에서 하나의 논리 코어만 소비하고 있는 증상을 CPU 사용률 뷰에 표시할 수도 있습니다.

자세한 내용은 MSDN 블로그 웹 사이트에서 Hazim Shafi의 Parallel Performance Tools For Windows 블로그에 있는 "Performance Pattern 1: Identifying Lock Contention"을 참조하십시오.

잠금 경합

균일하지 않은 작업 부하 분산

균등하지 않은 작업 부하

응용 프로그램의 여러 병렬 스레드 간에 작업 분산이 균일하지 않으면 각 스레드에서 해당 작업을 완료할 때마다 위 그림과 같이 일반적인 계단형 패턴이 나타납니다. 이때 동시성 시각화 도우미는 각 동시 스레드에 대해 매우 가까운 시작 시간을 보여 주는 경우가 가장 많습니다.그러나 이러한 스레드는 일반적으로 동시에 종료되지 않고 각각 다르게 종료됩니다.이 패턴은 여러 병렬 스레드 간에 작업 분산이 균일하지 않아 성능이 저하될 수 있음을 나타냅니다.이러한 문제를 해결하는 가장 좋은 방법은 병렬 스레드 간에 작업을 분산하는 데 사용된 알고리즘을 다시 평가하는 것입니다.

다음 그림에서 보여 주는 것과 같이 동시성 시각화 도우미는 CPU 사용률 뷰에서 이 증상을 CPU 사용률의 점진적인 단계별 감소로 표시할 수도 있습니다.

균등하지 않은 작업 부하

초과 구독

초과 구독

초과 구독이 발생하면 프로세스의 활성 스레드 수가 시스템의 사용 가능한 논리 코어 수보다 많아집니다.위 그림에서는 모든 활성 스레드에 상당한 선점 구간이 있는 초과 구독의 결과를 보여 줍니다.또한 범례에는 선점에 큰 비율(이 예의 경우에는 84%)의 시간이 소요되고 있음이 표시됩니다.이는 프로세스에서 논리 코어 수보다 많은 동시 스레드를 실행하도록 시스템에 요청하고 있음을 나타낼 수 있습니다.그러나 시스템의 다른 프로세스에서 이 프로세스에 사용할 수 있는 것으로 간주된 리소스를 사용하고 있음을 나타낼 수도 있습니다.

이 문제를 확인할 때는 다음 사항을 고려해야 합니다.

  • 전체 시스템이 초과 구독되었을 수 있습니다.시스템의 다른 프로세스에서 스레드를 선점하고 있을 수 있다는 것을 고려하십시오.스레드 뷰에서 선점 세그먼트 위에 마우스를 놓으면 도구 설명에 해당 스레드와 해당 스레드를 선점한 프로세스가 표시됩니다.이 프로세스가 반드시 해당 프로세스가 선점된 전체 시간 내내 실행된 프로세스인 것은 아니지만, 프로세스에서 선점 문제가 발생한 원인에 대한 힌트를 제공해 줍니다.

  • 프로세스에서 이 작업 단계 동안 실행하기에 적절한 스레드 수를 결정하는 방식을 확인하십시오.프로세스에서 활성 병렬 스레드의 수를 직접 계산하는 경우, 시스템의 사용 가능한 논리 코어 수를 효과적으로 반영하도록 이 알고리즘을 수정하는 것이 좋습니다.동시성 런타임, 작업 병렬 라이브러리 또는 PLINQ를 사용하는 경우 이러한 라이브러리는 스레드 수를 계산하는 작업을 수행합니다.

불충분한 I/O

불충분한 I/O

I/O의 과용이나 오용은 응용 프로그램의 비효율성을 초래하는 일반적인 원인입니다.위 그림을 보면표시되는 시간 표시 막대 프로필에서는 표시된 스레드 시간의 42%가 I/O에 의해 소비되고 있음을 보여 줍니다.시간 표시 막대에는 대량의 I/O가 표시되며, 이는 프로파일링된 응용 프로그램이 I/O로 인해 빈번하게 차단되었음을 나타냅니다.I/O의 종류에 대한 세부 정보와 프로그램 차단 위치를 보려면 해당 영역을 확대하고, 표시되는 시간 표시 막대 프로필을 검사한 다음, 특정 I/O 블록을 클릭하여 현재 호출 스택을 확인합니다.

잠금 호송

잠금 호송

잠금 호송은 응용 프로그램에서 선입선출 방식으로 잠금을 획득하는 경우와 잠금에 도달하는 속도가 잠금 획득 속도보다 빠른 경우에 발생합니다.이 두 가지 경우가 함께 발생하면 잠금 요청이 정체되기 시작합니다.이 문제를 해결하는 한 가지 방법은 "불공평한" 잠금을 사용하는 것입니다. 이는 첫 번째 스레드가 잠금을 잠금 해제된 상태로 액세스할 수 있게 하는 잠금을 말합니다.위 그림에서는 이러한 호송 동작을 보여 줍니다.이 문제를 해결하려면 동기화 개체에 대한 경합을 줄여 보고 불공평한 잠금을 사용해 보십시오.

참고 항목

개념

스레드 뷰(병렬 성능)