menu
 
버전
2024.1.4.8780

2024.1.4.8780

2023.1.12.8706

2022.1.18.8567

2021.1.14.8108

2019.2.15.7667

2019.1.11.7296

2018.1.11.6987

2017.2.10.6745

2017.1.9.6501

2016.2.6.6153

2015.1.9.5624


menu_open
Wwise SDK 2024.1.4
CPU 사용 최적화하기

오디오 렌더링 스레드

기본적으로 Wwise 사운드 엔진은 모든 명령 처리와 오디오 렌더링을 전용 스레드인 AK::EventManager 에서 처리하며, 이는 AkPlatformInitSettings::threadLEngine 매개 변수로 제어됩니다. AK::SoundEngine::RenderAudio 를 호출하면 게임 프레임이 종료되고 스레드는 이전 RenderAudio 호출 이후 수신된 모든 API 명령을 사용할 수 있습니다.

AkInitSettings::bUseLEngineThreadfalse 로 설정하면 이 스레드가 비활성화되고 RenderAudio 가 동기적으로 실행되어 명령을 처리하고 필요한 경우 오디오를 렌더링합니다. 실제 오디오 출력 레이트는 그대로 오디오 엔드포인트에 의해 제어됩니다. RenderAudio 호출 간격이 AkInitSettings::uNumSamplesPerFrame 에서 정의한 버퍼 시간과 출력 샘플 레이트보다 짧을 경우, 일부 RenderAudio 호출은 오디오 렌더링 부분을 건너뛸 수 있습니다. 반대로, RenderAudio 호출 간격이 출력 버퍼 시간보다 길 경우에는 RenderAudio 가 한 번에 둘 이상의 버퍼를 처리해 CPU 사용률이 갑자기 치솟을 수 있고 결국 오디오가 지직거리는 현상이 발생할 수 있습니다.

오프라인 렌더링을 활성화하면 오디오 스레드에서 비동기 명령 처리 및 오디오 렌더링이 비활성화됩니다. RenderAudio 를 호출할 때마다 렌더링되는 오디오의 양은 AK::SoundEngine::SetOfflineRenderingFrameTime 으로 전송되는 0이 아닌 양수 값에 의해 결정됩니다. 0 또는 음수 값을 사용하면 RenderAudio 가 정확히 하나의 오디오 버퍼를 처리하게 됩니다.

warning경고: 오디오 렌더링 스레드가 비활성화되었거나 오프라인 렌더링이 활성화된 경우, 동기식 AK::SoundEngine::LoadBankAK::SoundEngine::UnloadBank API 호출은 RenderAudio 호출자와 동일한 스레드에서 이루어져서는 안 됩니다. 이러한 호출은 오디오 버퍼가 렌더링되어 Stop 작업을 완료하고 SoundBank 미디어를 해제할 때까지 차단될 수 있는데, 이는 RenderAudio 에 대한 동시 호출 없이는 발생하지 않습니다.

Microsoft 플랫폼에서는 단일 스레드 아파트(single-threaded apartment, STA) 동시성 모델을 사용하기 때문에 AkInitSettings::bUseLEngineThreadfalse 로 설정할 때 AK::SoundEngine::RenderAudio 를 호출하는 동일한 스레드에서 CoInitializeEx() 를 호출해야 합니다.

쿼리 API 함수 사용하기

특정 AK::SoundEngine::Query 함수는 CPU 스파이크를 일으킬 수 있습니다. 낭비되는 CPU 사용률을 최소화하고 최적의 성능을 보장하려면 다음 지침을 따르는 것이 좋습니다.

  • Query 함수를 개발 빌드에서는 사용하되, 정식 제작 빌드에서는 사용하지 마세요.
  • Query 함수를 사용해야 하는 경우 SoundEngine 글로벌 콜백 내부에서 사용합니다( AkGlobalCallbackLocation 참조). 예를 들어, RTPC 값을 읽어야 하는 경우 AkGlobalCallbackLocation_BeginRender 또는 AkGlobalCallbackLocation_EndRender 에 코드를 넣습니다.

오디오 렌더링 작업의 동시 실행에 Job Manager 활용하기

기본적으로 Wwise 사운드 엔진은 다양한 오디오 렌더링 과제 또는 '작업'을 오디오 렌더링 스레드에서 순차적으로 실행합니다. 이러한 작업에는 버스 및 음성 처리 업무가 포함되지만 이 뿐만은 아닙니다.

이러한 오디오 작업의 동시 실행은 Wwise 사운드 엔진이 게임 관리 스레드에서 CPU 시간을 요청할 수 있도록 하는 콜백을 지정하여 활성화할 수 있습니다. 게임에서 AkJobMgrSettings::fnRequestJobWorker 를 통해 이 콜백에 대한 구현을 제공하는 경우 Wwise 사운드 엔진에서 동시 실행이 활성화됩니다.

info참고: 동시 작업 실행을 활성화하면 일부 AK::SoundEngine 콜백이 동시 작업 작업자 스레드에서 생성됩니다. 일부 플러그인은 동시 작업 실행과 호환되지 않을 수 있습니다.

사운드 엔진의 Job Manager가 작동하는 방식을 이해하려면 두 가지 중요한 콜백의 차이점을 아는 것이 중요합니다.

  1. 작업자 요청 함수게임 엔진에 의해 정의되며 Wwise 사운드 엔진에 의해 호출됩니다.
  2. 작업자 함수Wwise 사운드 엔진에 의해 정의되고 게임 엔진에 의해 호출됩니다.
info참고: Wwise 사운드 엔진은 각 작업자 요청에 대해 정확히 한 번의 작업자 함수 호출을 필요로 합니다. 예를 들어, 작업자 요청 함수가 AkJobType_AudioProcessing 유형의 작업자 3개를 요청하기 위해 한 번 호출되고, AkJobType_Generic 유형의 작업자 2개를 요청하기 위해 다시 호출되는 경우, 사운드 엔진은 게임에서 AkJobType_AudioProcessing 을 사용하여 작업자 함수를 세 번 호출하고, AkJobType_Generic 을 사용하여 두 번 호출할 것으로 예상합니다. 호출은 서로 다른 스레드에서 순차적으로 또는 동시에 어떤 순서로든 발행될 수 있습니다.

작업자 요청 함수가 정의되면 오디오 렌더링 스레드는 다음과 같이 동작합니다.

그림: 작업자 실행의 시퀀스 도표
  1. 오디오 렌더링 스레드가 음성이나 버스 처리와 같이 여러 스레드에서 수행할 수 있는 작업을 식별합니다.
  2. 오디오 렌더링 스레드가 게임의 작업자 요청 함수를 호출하여 다른 스레드의 CPU 시간을 요청합니다. 이 단계에서 게임 엔진은 호출할 작업자 함수의 주소를 수신합니다.
  3. 게임 엔진은 스레드 풀에서 요청을 예약합니다. 이에 따라 여러 개의 작업자 스레드가 깨어납니다.
  4. 게임의 작업자 스레드는 2단계에서 사운드 엔진이 제공한 작업자 함수를 호출합니다.
  5. 작업자 함수에 대한 각 호출은 최소한 하나의 오디오 렌더링 작업을 실행하지만, 가능한 경우 더 많은 작업을 실행할 수 있습니다.
  6. 오디오 렌더링 스레드는 모든 필수 작업이 실행 완료되자마자 처리를 재개합니다.

이 처리 과정은 하나의 오디오 렌더링에서 여러 번 반복될 수 있으며, 오디오 렌더링 스레드는 가능한 한 많은 작업을 파이프라인으로 처리하려고 시도합니다. 예를 들어, 버스 그래프를 렌더링할 때 주어진 버스에 대한 처리 시간은 모든 입력에 대한 처리가 완료되는 즉시 요청되며 다른 버스와 독립적으로 실행될 수 있습니다. 이런 방식으로 Job Manager는 항상 처리량을 극대화하려고 시도합니다.

info참고: 작업자 요청 함수는 사운드 엔진 코드를 실행하는 모든 스레드에서 호출될 수 있으며, 반드시 스레드로부터 안전한 방식으로 구현되어야 합니다.

게임 엔진의 기존 작업 스케줄러와 통합하기

Wwise 사운드 엔진의 Job Manager는 기존 작업 스케줄러와 함께 작동하여 협력적 멀티태스킹을 달성하도록 설계되었습니다. 이미 작업 스케줄러가 있는 게임 엔진은 기존 작업 시스템 내에서 작업자 함수의 실행을 스케줄링하는 방식으로 작업자 요청 함수를 구현해야 합니다.

작업자 함수를 호출할 때, 게임 엔진의 작업 스케줄러는 마이크로초 단위로 시간 초과를 지정할 수 있습니다. 이는 사운드 엔진이 호출 스레드에서 너무 많은 CPU 사용률을 차지하지 않도록 방지하기 위한 것입니다. 이 제한 시간을 지나면 작업자 함수는 중지되고, 실행할 수 있는 작업이 더 있는 경우 추가 작업자를 요청합니다. 그러면 이 스레드에서 다른, 우선 순위가 더 높은 게임 엔진 작업을 실행할 수 있습니다.

info참고: 작업자 함수의 실행을 지연하거나 사운드 엔진 작업의 실행 시간을 제한하는 경우 보이스 고갈 상태가 발생할 수 있으므로 주의해야 합니다. 기존 작업 스케줄러에 사운드 엔진 작업을 통합할 때 오디오 렌더링 작업을 높은 우선순위 작업으로 처리하는 것이 좋습니다.

아직 작업 스케줄러가 없는 게임 엔진의 경우 해당 스케줄러의 예제 구현은 SDK 예제의 SDK/samples/SoundEngine/Common/AkJobWorkerMgr.[h,cpp]에서 제공됩니다. 이 예제는 오디오 렌더링 작업의 동시 실행을 위한 좋은 시작점이 될 것입니다. 또한, IntegrationDemo는 이 예제 구현이 실제 최종 사용자 애플리케이션에 어떻게 통합될 수 있는지 보여주는 코드를 제공합니다.

Job Manager를 사용하는 모범 사례

Job Manager를 가장 잘 활용하는 방법에 대한 몇 가지 권장 사항은 다음과 같습니다.

  1. 필요한 스레드를 새로운 작업자 요청이 들어올 때 생성하지 마세요. 대부분의 시스템에서 새로운 스레드를 만드는 것은 비용이 많이 드는 작업입니다. 대신, 사운드 엔진이 초기화되기 전에 미리 결정된 수의 스레드를 미리 할당하고, 작업자 요청을 해당 스레드들에 분산하세요.
  2. 사운드 엔진 작업의 충분한 병렬화를 달성하는 데 필요한 것보다 많은 작업자 스레드를 사용하지 마세요. 어떤 경우에는 작업자를 요청하는 오버헤드로 인해 다른 작업에 더 효과적으로 쓰일 있는 CPU 사용률을 잃어버릴 수 있습니다. 또한, 작업자 수를 늘리면 사운드 엔진의 메모리 할당자나 다른 시스템에서 스레드 로컬 캐시를 사용하기 때문에 사운드 엔진이 요청하는 총 메모리 양이 늘어날 수 있습니다.
  3. 작업 실행을 지원하는 게임 엔진 작업자 스레드에서 스레드를 초기화하고 종료할 때 AK::MemoryMgr::InitForThreadAK::MemoryMgr::TermForThread 를 호출하는 것이 좋습니다. 이렇게 하면 스레드 로컬 메모리 리소스의 적절한 초기화 및 종료가 보장됩니다. 작업자 함수를 실행한 후 비활성 기간에 들어가면 AK::MemoryMgr::TrimForThread 를 호출하여 가까운 미래에 다시 활용되지 않을 스레드 로컬 메모리 리소스를 해제하는 것이 좋습니다.
  4. CPU 코어 수가 고정되어 미리 알려진 플랫폼에서는 각 스레드가 동일한 CPU 코어에 유지되도록 작업자 스레드 친화성을 설정합니다. 스레드가 다른 코어로 마이그레이션될 때 CPU 캐시가 새로 고쳐지는 것을 방지하기 위해, 실행 중에 오디오 작업이 CPU 코어 사이를 이동하지 않도록 하는 것이 바람직합니다.
  5. 여러 Cluster 또는 Core Complex(CCX)가 있는 시스템에서는 작업자 스레드와 오디오 렌더링 스레드가 모두 동일한 CCX에서 실행되도록 스레드 친화성을 설정하여 코어 간 캐시 일관성을 향상시킵니다.
  6. 동시 멀티 스레딩(Simultaneous Multi-Threading, SMT)을 탑재한 시스템에서 CPU 리소스 경쟁을 줄이기 위해 작업자 스레드가 동일한 코어를 공유하는 대신, 별도의 물리적 코어에서 실행되도록 스레드 친화성을 설정합니다.
  7. 사운드 엔진을 다시 초기화하지 않고 사운드 엔진이 요청할 수 있는 최대 작업자 수를 변경하려면 AK::SoundEngine::SetJobMgrMaxActiveWorkers 를 사용하면 됩니다. 이는 타이틀의 작업 조건의 변화에 동적으로 대응하거나 멀티스레드 작업에 대한 다양한 구성을 보다 쉽게 실험하고 프로파일링하는 데 유용할 수 있습니다.

위의 권장 사항은 게임의 다른 요구 사항과 비교하여 검토되어야 합니다. 일부 권장 사항을 따르지 않더라도 Job Manager는 사운드 엔진의 전체 처리량을 높이는 좋은 방법입니다.

Android

Android 플랫폼에서는 Job Manager에 대해 2개 이상의 활성 작업자 스레드를 사용하는 것이 권장되지 않습니다. AK::SoundEngine::SetJobMgrMaxActiveWorkers 로 설정합니다. Android 기기에서 작업자 스레드가 많으면 CPU 사용률이 높아지고 전반적인 사운드 엔진 성능이 저하될 수 있습니다.

Job Manager 메모리 사용 최적화하기

작업을 할당할 때 메모리가 부족하면 심각한 오류로 간주되어 오디오 렌더링의 논리적 흐름이 중단되고 다시 시작할 수 없게 됩니다. 이는 정의되지 않은 결과와 리소스 누출로 이어질 것입니다.

이를 방지하기 위해 Job Manager는 사운드 엔진이 종료될 때까지 유지되고 재사용될 메모리 슬랩을 할당합니다. 이러한 슬랩의 대부분은 사운드 엔진 초기화 중에 미리 할당되지만, 필요에 따라 그때그때 할당될 수도 있습니다.

AkInitSettings::settingsJobManager 를 이용해 메모리 슬랩의 크기와 초기화 시 미리 할당되는 메모리 슬랩의 수를 제어할 수 있습니다.

info참고: 렌더링 중에 AK::MemoryMgr::Malloc 이 새로운 메모리 슬랩을 할당하지 못하면 Job Manager는 성공할 때까지 할당을 계속 시도합니다. 메모리 부족 상황에서 사운드 엔진이 멈춘다면 초기화 설정에서 미리 할당된 슬랩 수를 늘리세요.

이 페이지가 도움이 되었나요?

지원이 필요하신가요?

질문이 있으신가요? 문제를 겪고 계신가요? 더 많은 정보가 필요하신가요? 저희에게 문의해주시면 도와드리겠습니다!

지원 페이지를 방문해 주세요

작업하는 프로젝트에 대해 알려주세요. 언제든지 도와드릴 준비가 되어 있습니다.

프로젝트를 등록하세요. 아무런 조건이나 의무 사항 없이 빠른 시작을 도와드리겠습니다.

Wwise를 시작해 보세요