- Anukari는 실시간 3D 물리 신시사이저라 대규모 spring-mass 모델을 GPU에서 계산해야 하지만, Apple silicon macOS에서 GPU 클록이 충분히 오르지 않으면 오디오 지연 조건을 맞추기 어려움
- DAW가 오디오 버퍼 블록마다 플러그인을 호출하는 구조와 macOS의 전력 관리 휴리스틱이 맞물리며, GPU가 블록 사이에 쉬는 것처럼 보여 낮은 성능 상태에 머물 수 있음
- Xcode Instruments의 Metal profiler에서 Performance State를 Maximum으로 두면 정상 동작하고 Minimum에서는 크게 나빠져, 병목의 핵심이 GPU 클록 속도임을 확인함
- 현재는 작은 spin kernel로 GPU 부하를 인위적으로 높이는 “waste makes haste” 우회책을 쓰지만, 일부 Pro/Max Apple 하드웨어에서는 여전히 문제가 남아 있음
- 개발자는 Apple Metal 팀에 Audio Workgroup의 GPU 확장, MTLCommandQueue의 실시간 민감도 옵션, 또는 기존 해결책 안내를 요청하며 Windows에서는 같은 spin loop가 필요 없다고 봄
Anukari가 겪는 macOS GPU 성능 문제
- Anukari 3D Physics Synthesizer는 오디오 생성을 위해 대규모 spring-mass 물리 모델을 실시간으로 시뮬레이션함
- 비중 있는 수의 물리 객체를 지원하려면 GPU가 필요하며, 물리 코드는 메모리보다 ALU 병목에 가까움
- 시뮬레이션의 변경 가능한 상태는 GPU의 threadgroup memory에 저장됨
- 수동 할당 L1 캐시에 가까운 구조라 매우 빠름
- 일반적인 사용 방식은 Pro Tools, Ableton 같은 DAW 안에서 AU 또는 VST3 플러그인으로 실행되는 형태임
- DAW는 오디오 버퍼 블록마다 Anukari를 호출함
- Anukari는 각 블록마다 GPU 물리 시뮬레이션 커널을 실행하고 결과를 기다린 뒤 반환함
- 오디오 버퍼 블록은 GPU 커널 스케줄링 지연을 여러 샘플에 나눠 흡수할 수 있지만, 커널 자체 실행 시간은 여전히 결정적임
macOS 전력 관리와 실시간 오디오의 충돌
- Apple silicon은 전력 절감을 위해 칩의 클록 속도를 낮출 수 있고, macOS는 처리 수요가 낮다고 판단하면 낮은 클록을 유지함
- Anukari의 DAW 내 실행 방식은 macOS가 GPU 수요를 판단하는 방식과 잘 맞지 않음
- GPU는 오디오 버퍼 블록 사이에 유휴 상태가 되므로, 평균 부하가 예컨대 60% 정도로만 보일 수 있음
- macOS의 실제 휴리스틱은 알 수 없지만 load average 같은 방식일 수 있다고 추정함
- 이 부하가 GPU 클록 상승 기준을 넘지 못할 수 있음
- Anukari는 실시간 제약을 맞추기 위해 낮은 지연이 필요하고, 이를 위해 높은 GPU 클록이 필요함
- Apple GPU 클록이 얼마나 낮아질 수 있는지는 알 수 없지만, Anukari를 사용할 수 없게 만들 정도로 낮아질 수 있음
Metal profiler로 확인한 클록 문제
- Xcode에 포함된 Apple Instruments의 Metal profiler로 Anukari가 ALU-bound임을 확인함
- Metal profiler는 프로파일링 중 Metal “Performance State”를 선택할 수 있음
- 이 설정은 profiler 밖에서는 구성할 수 없음
- Maximum performance state에서는 Anukari가 완벽하게 동작함
- Minimum performance state에서는 동작이 크게 나빠짐
- 두 상태의 차이 때문에 GPU 클록 속도가 Anukari 성능 문제의 핵심으로 드러남
“waste makes haste” 우회책과 한계
- macOS가 필요한 시점에 GPU 클록을 올려주지 않기 때문에, Anukari는 별도의 우회책을 사용함
- 오디오 계산 GPU 작업과 병렬로 두 번째 GPU 작업을 실행해 높은 평균 부하를 만들고 macOS가 클록을 올리도록 유도함
- 이 작업은 가능한 적은 GPU 자원을 쓰면서도 클록 휴리스틱을 자극하도록 조정됨
- 실질적으로 GPU를 데우는 spin loop임
- 이 전략은 “waste makes haste”라고 부르며, 관련 devlog에 상세히 기록되어 있음
- 개발자의 MacBook M1에서는 이 방식이 문제를 완전히 해결했고 Anukari가 안정적으로 실행됨
- 하지만 Anukari Beta 출시 후 일부 macOS 사용자에게 문제가 발생함
- 특히 Pro 또는 Max Apple 하드웨어 사용자에게 성능 문제가 많아 보임
- 글에서는 GPU chiplet별 독립 클록 가능성, 더 강력한 GPU에서는 spin workload가 너무 보수적일 가능성을 가설로 듦
Apple에 요청하는 해결 방향
- Apple 엔지니어가 더 잘 알 것이라는 전제에서 몇 가지 가능한 해결책을 제안함
- Solution 1: Audio Workgroup 개념을 GPU 처리까지 확장함
- macOS의 오디오 처리는 Audio Workgroup이라는 스레드 또는 스레드 그룹에서 수행됨
- OS는 이 스레드들이 실시간 제약을 가진다는 점을 이해하고 우선순위를 부여함
- Audio Workgroup 스레드가 관리하는 MTLCommandQueue를 실시간 처리로 간주해 GPU 클록을 조정할 수 있음
- Solution 2: Metal API의 MTLCommandQueue에 실시간 민감도를 표시하는 옵션을 제공함
- 해당 queue를 처리하는 GPU chiplet의 클록을 그에 맞춰 조정할 수 있음
- Solution 3: 이미 원하는 기능을 얻는 방법이 있다면 Apple이 알려주는 것만으로도 충분함
- 글 상단에는 Apple이 연락해 왔으며 관련 내용은 별도 글에 있다고 덧붙어 있음
Game Mode와 Windows 비교
- Apple의 Game Mode는 Anukari가 필요한 것과 비슷해 보이지만 적용하기 어려움
- Game Mode는 프로세스 단위임
- Anukari는 대부분 다른 프로세스 안의 플러그인으로 쓰이며, 해당 프로세스는 Game Mode를 지원하지 않음
- Anukari가 이를 직접 제어할 수 없음
- Game Mode는 fullscreen도 요구하지만 Anukari는 보통 fullscreen이 아님
- Windows에서는 이 문제가 발생하지 않음
- Windows가 사용자에게 성능 상태 제어를 더 많이 주기 때문인지, NVIDIA 드라이버가 전력 소비에 덜 신중한 것인지는 알 수 없음
- Windows에서는 spin loop가 필요 없음
- 성능이 약한 GPU를 가진 Windows PC는 Anukari를 잘 실행하는 반면, 고가의 Mac M4 Max에서는 stutter가 발생할 수 있다고 비교함
파이프라이닝이 맞지 않는 이유
- GPU 코드를 파이프라인화해 GPU를 포화시키는 방식은 처리량 중심 작업에는 적합하지만, Anukari는 지연 민감 작업임
- 여러 물리 시뮬레이션 커널을 미리 스케줄링하면 GPU가 현재 오디오 블록을 처리하는 동안 CPU가 다음 블록을 준비할 수 있음
- 하지만 파이프라이닝은 처리량을 높이는 대신 지연을 늘림
- Anukari의 각 커널 실행은 마이크 입력 같은 실시간 오디오 입력 데이터에 접근해야 함
- 다음 오디오 블록을 미리 처리하는 speculative execution은 필요한 입력 데이터가 없어서 사용할 수 없음
spin kernel을 같은 MTLCommandQueue에 넣는 방식의 문제
- spin kernel과 physics kernel이 서로 다른 GPU chiplet에서 실행되는 것이 실제 원인이라면, 같은 MTLCommandQueue에 넣는 방법이 해결책처럼 보일 수 있음
- 실제로 이 방법을 시도했지만 동작하지 않았음
- 이유는 Anukari가 지연 민감 작업이기 때문임
- spin kernel이 가끔 조금 오래 실행됨
- 그 시간이 physics kernel 실행 시간에 침범함
- 작은 spin kernel과 volatile unified memory를 이용해 CPU가 “exit kernel early” 플래그를 쓰는 방식도 실험함
- 이런 장치에도 spin kernel이 physics kernel 시간을 침범하는 경우가 생김
GPU kernel hedging이 어려운 이유
- 분산 시스템의 request hedging처럼 물리 커널을 여러 복사본으로 실행하고 가장 먼저 끝난 결과를 쓰는 방식도 검토함
- 이 방식은 꼬리 지연과 지연 분산을 줄이고, 동시에 GPU 부하를 만들어 OS가 성능 상태를 올리도록 유도할 수 있음
- 하지만 Anukari에는 여러 문제가 있음
- 한 physics kernel이 오디오 블록 주기 하나보다 오래 걸리면 해당 커널 스트림이 뒤처짐
- 뒤처진 커널 스트림은 미래 블록에서 따라잡아야 하며, 다른 스트림의 내부 상태를 복사하는 fast-forward가 필요함
- 내부 상태 복사는 비쌈
- 가장 큰 내부 상태는 delay line용 오디오 버퍼임
- 마이크마다 1초의 과거 오디오를 저장함
- 크기는
48,000 samples * 50 mics * 2 channels * 16 voices * 4 bytes로 307MB임 - 더 높은 sample rate에서는 더 커짐
- 효율적으로 처리하려면 각 hedged kernel stream의 dirty 영역을 정밀하게 추적하고 그 부분만 복사해야 함
- 하지만 버퍼 메모리 배치는 physics kernel의 읽기 workload에 맞게 최적화되어 있음
- 최소한만 복사해도 전체 버퍼에 흩어진 영역을 복사하게 되어 느림
- 사용자 모델 변경도 모든 hedged kernel에 전파해야 함
- physics kernel은 “waste makes haste” spin kernel보다 GPU footprint가 훨씬 큼
- hedging은 더 많은 불필요한 GPU 부하를 만들고, 병렬로 실행 가능한 Anukari 인스턴스 수를 줄일 수 있음
- hedge kernel끼리 경쟁해 모두 느려질 수도 있음
이미 수행한 최적화와 GPU가 필요한 이유
- Anukari 시뮬레이션은 ALU-bound라서 메모리 접근 패턴 개선 같은 일반적인 최적화 여지가 크지 않음
- 성능을 높이려면 산술 처리량을 최적화해야 함
- 가능한 곳에서는 FP16 연산을 사용해 Apple ALU를 더 잘 포화시킴
- micro-benchmark를 사용해 명령어 순서를 조정함
- 모든 물리 상태를 L1 memory에 둠
- vectorization을 위해 load 순서를 재배치함
- Apple SIMD-group의 스레드들이 대체로 instruction pointer를 공유한다는 점도 활용함
- 서로 다른 물리 객체는 branch path가 크게 갈라짐
- 한 SIMD-group 안에서 두 종류의 객체를 시뮬레이션하면 instruction masking 때문에 느려짐
- 이를 피하려고 물리 객체의 메모리 배치를 동적으로 최적화해 SIMD-group 안에서 실행되는 객체 타입 수를 줄임
- 이 최적화는 the new warp alignment optimizer에 자세히 정리되어 있음
- 추가 산술 최적화 여지는 있지만 한 자릿수 퍼센트포인트 수준의 개선에 그칠 것으로 봄
- 강력한 머신에서 Anukari는 768~1024개 물리 객체를 시뮬레이션할 수 있음
- 각 객체는 다른 객체와 임의로 연결될 수 있음
- 객체는 보통 초당 48,000 샘플의 오디오 sample rate로 implicit Euler integration을 수행함
- 각 객체는 3~10개의 동작 파라미터를 가짐
- 일부 동작에는 vector rotation,
exp(),log()같은 비싼 연산이 포함됨 - polyphony를 위해 전체 물리 시뮬레이션을 최대 16개 병렬 복사본으로 실행함
- CPU로는 이 방식이 가능하지 않았으며, GPU의 많은 ALU, L1 cache layout 제어,
threadgroup_barrier같은 동시성 구조가 필요함 - Anukari는 GPU 처리 없이는 존재할 수 없음
GPU Audio API가 해결책이 아닌 이유
- GPU Audio의 CEO Alexander Talashov는 Anukari가 GPU Audio API를 쓰면 문제가 해결될 수 있다고 말해 왔음
- 개발자는 GPU Audio를 좋은 제품으로 평가하고, GPU를 DSP에 접근 가능하게 만드는 제품이라고 소개함
- 하지만 Anukari에는 GPU Audio가 유용하지 않다고 판단함
- Anukari는 전통적인 DSP 애플리케이션과 달리 수치 미분방정식 적분기에 가까움
- DSP 일부가 있긴 하지만 대부분의 계산은 Eulerian integration임
- 물리 세계의 마이크 압축 같은 DSP는 GPU의 물리 계산 안에서 inline으로 처리됨
- Anukari는 Metal의 낮은 계층에서 GPU를 직접 프로그래밍하고 있음
- 필요한 것은 Apple이 GPU 클록 속도를 안정적으로 올려주는 것임