작업 큐 및 스레딩 개선 사항

이 항목에서는 Microsoft Media Foundation 플랫폼의 작업 큐 및 스레딩에 대한 Windows 8 향상에 대해 설명합니다.

Windows 7 동작

이 섹션에서는 Windows 7에서 Media Foundation 작업 큐의 동작을 요약합니다.

작업 큐

Media Foundation 플랫폼은 여러 표준 작업 큐를 만듭니다. 두 가지만 일반 애플리케이션용으로 문서화되어 있습니다.

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

애플리케이션 또는 구성 요소는 MFAllocateWorkQueue 또는 MFAllocateWorkQueueEx를 호출하여 새 작업 큐를 할당할 수 있습니다. MFAllocateWorkQueueEx 함수는 두 가지 유형의 작업 큐를 정의합니다.

  • MF_STANDARD_WORKQUEUE 메시지 루프 없이 작업 큐를 만듭니다.
  • MF_WINDOW_WORKQUEUE 메시지 루프를 사용하여 작업 큐를 만듭니다.

작업 항목을 큐에 대기하려면 MFPutWorkItem 또는 MFPutWorkItemEx를 호출합니다. 플랫폼은 IMFAsyncCallback의 호출자 제공 구현을 호출하여 작업 항목을 실행합니다. Windows 7 이하에서는 플랫폼이 작업 큐당 하나의 스레드를 만듭니다.

MMCSS 지원

MMCSS( 멀티미디어 클래스 스케줄러 서비스 )는 우선 순위가 낮은 애플리케이션에 대한 CPU 리소스를 거부하지 않고 멀티미디어 애플리케이션이 CPU 시간의 정기적인 조각을 얻을 수 있도록 스레드 우선 순위를 관리합니다. MMCSS는 CPU 사용률 프로필이 다른 작업 집합을 정의합니다. 스레드가 MMCSS 작업을 조인하는 경우 MMCSS는 다음과 같은 여러 요인에 따라 스레드의 우선 순위를 설정합니다.

  • 레지스트리에 설정된 작업의 기본 우선 순위입니다.
  • AvSetMmThreadPriority를 호출하여 런타임에 설정되는 상대 스레드 우선 순위입니다.
  • 애플리케이션이 포그라운드에 있는지 여부, 각 MMCSS 클래스의 스레드에서 사용하는 CPU 시간 등 다양한 런타임 특성입니다.

애플리케이션은 MFBeginRegisterWorkQueueWithMMCSS를 호출하여 MMCSS에 작업 큐를 등록할 수 있습니다. 이 함수는 작업 큐 ID, MMCSS 클래스(작업 이름) 및 MMCSS 작업 식별자를 사용합니다. 내부적으로 작업 이름 및 작업 ID를 사용하여 AvSetMmThreadCharacteristics 를 호출합니다. 작업 큐가 MMCSS에 등록되면 MFGetWorkQueueMMCSSClassMFGetWorkQueueMMCSSTaskId를 호출하여 클래스 및 작업 ID를 가져올 수 있습니다.

미디어 세션IMFWorkQueueServices 인터페이스를 통해 이러한 API에 대한 다소 높은 수준의 액세스를 제공합니다. 이 인터페이스는 두 가지 기본 메서드를 제공합니다.

메서드 Description
BeginRegisterPlatformWorkQueueWithMMCSS MMCSS 작업에 작업 큐를 등록합니다. 이 메서드는 기본적으로 MFBeginRegisterWorkQueueWithMMCSS에 대한 씬 래퍼이지만 MFASYNC_CALLBACK_QUEUE_ALL 값을 전달하여 모든 플랫폼 작업 큐를 한 번에 등록할 수 있습니다.
BeginRegisterTopologyWorkQueuesWithMMCSS 토폴로지의 분기를 작업 큐에 등록합니다.

 

토폴로지 분기를 등록하려면 다음을 수행합니다.

  1. 분기의 원본 노드에서 MF_TOPONODE_WORKQUEUE_ID 특성을 설정합니다. 애플리케이션 정의 값을 사용합니다.
  2. 필요에 따라 작업 큐를 MMCSS 작업에 조인하도록 MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 설정합니다.
  3. 확인된 토 폴로지에서 BeginRegisterTopologyWorkQueuesWithMMCSS 를 호출합니다.

미디어 세션은 MF_TOPONODE_WORKQUEUE_ID 고유한 각 값에 대해 새 작업 큐를 할당합니다. 각 토폴로지 분기에 대해 비동기 파이프라인 작업은 분기에 할당된 작업 큐에서 수행됩니다.

IMFRealTimeClient

IMFRealTimeClient 인터페이스는 자체 스레드를 만들거나 비동기 작업에 작업 큐를 사용하는 파이프라인 구성 요소를 위한 것입니다. 미디어 세션은 다음과 같이 이 인터페이스를 사용하여 파이프라인 구성 요소에 올바른 동작을 알립니다.

  • 파이프라인 구성 요소가 작업자 스레드를 만드는 경우 IMFRealTimeClient::RegisterThreads 메서드는 조인할 MMCSS 클래스를 구성 요소에 알릴 수 있습니다.
  • 파이프라인 구성 요소가 작업 큐를 사용하는 경우 IMFRealTimeClient::SetWorkQueue 메서드는 사용할 작업 큐를 구성 요소에 알려줍니다.

일반적으로 파이프라인 구성 요소는 스레드 또는 작업 큐를 사용하여 비동기 작업을 수행하지만 둘 다 수행하지는 않습니다.

Windows 8 개선 사항

다중 스레드 작업 큐

Windows 8 Media Foundation은 다중 스레드 큐라는 새로운 유형의 작업 큐를 지원합니다. 다중 스레드 큐는 시스템 스레드 풀을 사용하여 작업 항목을 디스패치합니다. 다중 스레드 큐는 이전의 단일 스레드 큐보다 더 잘 확장됩니다. 예를 들면 다음과 같습니다.

  • 여러 구성 요소는 서로 차단하지 않고 다중 스레드 큐를 공유할 수 있으므로 스레드 수가 줄어듭니다.

  • 이벤트가 이미 설정된 경우 컨텍스트 전환을 방지하기 위해 작업 항목이 최적화됩니다. 이는 이벤트를 기다리는 자체 스레드를 만드는 것보다 더 효율적입니다.

IMFRealTimeClientEx를 사용하는 경우 애플리케이션은 스레드 회전을 방지하고 대신 작업 큐를 사용해야 합니다. 이를 위해 애플리케이션은 SetWorkQueueEx 를 구현해야 하며 RegisterThreadsUnregisterThreads를 사용하지 않아야 합니다.

Media Foundation 플랫폼이 초기화되면 식별자 MFASYNC_CALLBACK_QUEUE_MULTITHREADED 있는 다중 스레드 큐를 만듭니다.

다중 스레드 큐는 작업 항목을 직렬화하지 않습니다. 스레드 풀의 스레드를 사용할 수 있게 될 때마다 큐의 다음 작업 항목이 디스패치됩니다. 호출자는 작업이 올바르게 직렬화되었는지 확인해야 합니다. 이를 더 쉽게 하기 위해 Media Foundation은 직렬 작업 큐를 정의합니다. 직렬 큐는 다른 작업 큐를 래핑하지만 완전히 직렬화된 실행을 보장합니다. 큐의 다음 항목은 이전 항목이 완료될 때까지 디스패치되지 않습니다.

다음 코드는 플랫폼 다중 스레드 큐를 통해 serializer 큐를 만듭니다.

DWORD workQueueID;
hr = MFAllocateSerialWorkQueue(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, &workQueueID); 

둘 이상의 직렬 큐는 동일한 다중 스레드 큐를 래핑할 수 있습니다. 그런 다음 직렬 큐는 동일한 스레드 풀을 공유하고 직렬화된 실행은 각 큐 내에서 적용됩니다.

Windows 8 이전에 존재했던 표준 작업 큐는 이제 플랫폼 다중 스레드 큐를 래핑하는 직렬 작업 큐로 구현됩니다. 이 변경 내용은 이전 버전과의 호환성을 유지합니다.

공유 작업 작업 큐

커널 스케줄러를 올바르게 사용하려면 사용하는 각 MMCSS 작업에 대해 하나의 다중 스레드 작업 큐가 있어야 합니다. Media Foundation 플랫폼은 필요에 따라 프로세스당 MMCSS 작업당 최대 1개를 할당합니다. 특정 MMCSS 작업에 대한 공유 작업 큐를 가져오려면 MFLockSharedWorkQueue 를 호출하고 작업 이름을 지정합니다. 함수는 테이블의 작업 이름을 조회합니다. 이 작업에 대한 작업 큐가 아직 없는 경우 함수는 새 MT 작업 큐를 할당하고 MMCSS 작업에 즉시 조인합니다. 해당 작업에 대한 작업 큐가 이미 있는 경우 함수는 기존 작업 큐의 식별자를 반환합니다.

대기 큐

대기 큐는 신호가 전송될 이벤트를 기다리는 특별한 플랫폼 작업 큐입니다. 구성 요소가 이벤트가 신호를 받을 때까지 기다려야 하는 경우 작업자 스레드를 만드는 대신 대기 큐를 사용하여 이벤트를 대기할 수 있습니다.

대기 큐를 사용하려면 MFPutWaitingWorkItem을 호출합니다. 매개 변수에는 이벤트 핸들 및 IMFAsyncResult 포인터가 포함됩니다. 이벤트가 신호를 받으면 대기 큐가 콜백을 호출합니다. 단일 플랫폼 대기 큐가 있습니다. 애플리케이션은 자체 대기 큐를 만들 수 없습니다.

MMCSS 지원에 대한 향상된 기능

다음 새로운 Media Foundation 플랫폼 함수는 MMCSS와 관련이 있습니다.

함수 Description
MFBeginRegisterWorkQueueWithMMCSSEx MMCSS에 작업 큐를 등록합니다. 이 함수에는 상대 스레드 우선 순위를 지정하는 매개 변수가 포함되어 있습니다. 내부적으로 이 값은 AvSetMmThreadPriority 호출로 변환됩니다.
MFGetWorkQueueMMCSSPriority 작업 큐의 우선 순위를 쿼리합니다.
MFRegisterPlatformWithMMCSS 모든 플랫폼 작업 큐를 MMCSS 작업에 등록합니다. 이 함수는 IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS 메서드와 유사하지만 미디어 세션의 instance 만들지 않고도 사용할 수 있습니다. 또한 함수에는 기본 스레드 우선 순위를 지정하는 매개 변수가 포함됩니다.

 

미디어 세션을 사용하는 애플리케이션은 오디오 렌더링 분기의 MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 특성을 "오디오"로 설정해야 합니다. 특성을 비디오 렌더링 분기의 "재생"으로 설정합니다.

IMFRealTimeClientEx

IMFRealTimeClientEx 인터페이스는 비동기 작업을 수행하는 파이프라인 구성 요소에 대해 IMFRealTimeClient를 대체합니다.

메서드 Description
RegisterThreadsEx 구성 요소에 MMCSS에 스레드를 등록하도록 알 수 있습니다. 이 메서드는 IMFRealTimeClient::RegisterThreads와 동일하지만 기본 스레드 우선 순위에 대한 매개 변수를 추가합니다.
SetWorkQueueEx 구성 요소에 특정 작업 큐를 사용하도록 알 수 있습니다. 이 메서드는 IMFReadTimeClient::SetWorkQueue와 동일하지만 작업 항목 우선 순위에 대한 매개 변수를 추가합니다.
UnregisterThreads 구성 요소에 MMCSS에서 해당 스레드의 등록을 취소하도록 알 수 있습니다. 이 메서드는 IMFRealTimeClient::UnregisterThreads 메서드와 동일합니다.

 

파이프라인 구성 요소는 작업 큐를 사용해야 하며 다음과 같은 이유로 작업자 스레드를 만들지 않아야 합니다.

  • 작업 큐는 OS 스레드 풀을 사용하기 때문에 더 잘 확장됩니다.
  • 플랫폼은 MMCSS에 작업 큐를 등록하는 세부 정보를 처리합니다.
  • 작업자 스레드는 쉽게 디버그하기 어려운 교착 상태를 일으킬 수 있습니다.

또한 비동기 작업을 직렬화해야 하는 경우 serializer 작업 큐를 사용하는 것이 좋습니다.

토폴로지 분기

MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 특성이 MMCSS에 토폴로지 분기를 등록하는 경우 Windows 8 미디어 세션에서 공유 MT 작업 큐를 사용합니다. 이전 버전의 Windows에서는 미디어 세션에서 새 작업 큐를 할당했습니다.

MMCSS를 사용하여 토폴로지 분기를 등록하기 위해 두 개의 새 특성이 정의됩니다.

attribute Description
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY 기본 스레드 우선 순위를 지정합니다.
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY 작업 항목 우선 순위를 지정합니다.

 

권장 사항

  • 미디어 세션을 사용하는 애플리케이션은 MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 오디오 렌더링 분기의 경우 "오디오"로, 비디오 렌더링 분기의 경우 "재생"으로 설정해야 합니다.
  • 미디어 세션을 사용하는 애플리케이션은 토폴 로지에서 IMFWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS 를 호출해야 합니다.
  • 파이프라인 구성 요소의 경우 작업자 스레드 대신 작업 큐를 사용하는 것이 좋습니다. 구성 요소가 작업 큐 또는 작업자 스레드를 사용하는 경우 IMFRealTimeClientEx를 구현합니다.
  • 이렇게 하면 플랫폼 작업 큐의 목적이 무효화하므로 프라이빗 작업 큐를 만들지 마세요. 플랫폼 다중 스레드 큐 또는 플랫폼 다중 스레드 큐를 래핑하는 직렬 큐를 사용합니다.
  • 비동기 작업을 직렬화해야 하는 경우 직렬 큐를 사용합니다.

요약

스레드 및 작업 큐와 관련된 다음 Media Foundation 플랫폼 API는 Windows 8 새로운 기능입니다.

작업 큐