Przyczyny opóźnienia dźwięku

Ta strona skupia się na czynnikach wpływających na opóźnienie wyjściowe, ale podobne omówienie dotyczy opóźnienia wejściowego.

Zakładając, że obwody analogowe nie mają znaczącego udziału, głównymi powierzchniowymi czynnikami wpływającymi na opóźnienie dźwięku są:

  • Aplikacja
  • Całkowita liczba buforów w potoku
  • Rozmiar każdego bufora w ramkach
  • Dodatkowe opóźnienie po procesorze aplikacji, na przykład z procesora DSP

Choć powyższa lista autorów może być dokładna, jest również myląca. Powodem jest to, że liczba buforów i rozmiar buforów są bardziej skutkiem niż przyczyną . Zwykle dzieje się tak, że dany schemat bufora jest wdrażany i testowany, ale podczas testowania niedopełnienie lub przekroczenie poziomu dźwięku jest słyszalne jako „kliknięcie” lub „trzask”. Aby to zrekompensować, projektant systemu zwiększa następnie rozmiary buforów lub liczbę buforów. Daje to pożądany rezultat w postaci eliminacji niedomiarów lub przekroczeń, ale ma również niepożądany efekt uboczny w postaci zwiększenia opóźnień. Więcej informacji na temat rozmiarów buforów można znaleźć w filmie Opóźnienie dźwięku: rozmiary buforów .

Lepszym podejściem jest zrozumienie przyczyn niedomiarów i przekroczeń, a następnie ich skorygowanie. Eliminuje to słyszalne artefakty i może pozwolić na jeszcze mniejsze lub mniejsze bufory, a tym samym zmniejszyć opóźnienia.

Z naszego doświadczenia wynika, że ​​najczęstszymi przyczynami przekroczeń i niedomiarów są:

  • Linux CFS (całkowicie uczciwy harmonogram)
  • wątki o wysokim priorytecie z planowaniem SCHED_FIFO
  • odwrócenie priorytetu
  • długie opóźnienie planowania
  • długotrwałe procedury obsługi przerwań
  • długi czas wyłączenia przerwań
  • zarządzanie energią
  • jądra bezpieczeństwa

Harmonogramowanie CFS i SCHED_FIFO w systemie Linux

Linux CFS został zaprojektowany tak, aby był sprawiedliwy w stosunku do konkurencyjnych obciążeń korzystających ze wspólnego zasobu procesora. Ta sprawiedliwość jest reprezentowana przez ładny parametr na wątek. Wartość nice waha się od -19 (najmniej przyjemny lub najwięcej przydzielonego czasu procesora) do 20 (najfajniejszy lub najmniej przydzielonego czasu procesora). Ogólnie rzecz biorąc, wszystkie wątki z daną wartością nice otrzymują w przybliżeniu równy czas procesora, a wątki z liczbowo niższą wartością nice powinny spodziewać się większego czasu procesora. Jednakże CFS jest „sprawiedliwy” tylko w przypadku stosunkowo długich okresów obserwacji. W krótkoterminowych oknach obserwacji CFS może alokować zasoby procesora w nieoczekiwany sposób. Na przykład może przenieść procesor z wątku o niskiej dokładności numerycznej do wątku o wysokiej jakości liczbowej. W przypadku dźwięku może to skutkować niedopełnieniem lub przekroczeniem.

Oczywistym rozwiązaniem jest unikanie CFS w przypadku wątków audio o wysokiej wydajności. Począwszy od Androida 4.1, takie wątki używają teraz zasad planowania SCHED_FIFO zamiast zasad planowania SCHED_NORMAL (zwanych także SCHED_OTHER ) zaimplementowanych przez CFS.

Priorytety SCHED_FIFO

Chociaż wątki audio o wysokiej wydajności korzystają teraz SCHED_FIFO , nadal są podatne na inne wątki SCHED_FIFO o wyższym priorytecie. Są to zazwyczaj wątki robocze jądra, ale może istnieć również kilka wątków użytkowników innych niż audio z polityką SCHED_FIFO . Dostępne priorytety SCHED_FIFO mieszczą się w zakresie od 1 do 99. Wątki audio działają z priorytetem 2 lub 3. Dzięki temu priorytet 1 jest dostępny dla wątków o niższym priorytecie, a priorytety od 4 do 99 dla wątków o wyższym priorytecie. Zalecamy używanie priorytetu 1, gdy tylko jest to możliwe, i rezerwowanie priorytetów od 4 do 99 dla tych wątków, które gwarantują zakończenie w określonym czasie, wykonanie z okresem krótszym niż okres wątków audio i wiadomo, że nie kolidują z harmonogramem wątków audio.

Planowanie monotoniczne z szybkością

Więcej informacji na temat teorii przypisywania stałych priorytetów można znaleźć w artykule w Wikipedii Planowanie monotoniczne szybkościowe (RMS). Kluczową kwestią jest to, że stałe priorytety powinny być przydzielane ściśle na podstawie okresu, przy czym wyższe priorytety powinny być przypisywane wątkom o krótszych okresach, a nie na podstawie postrzeganej „ważności”. Wątki nieokresowe można modelować jako wątki okresowe, stosując maksymalną częstotliwość wykonywania i maksymalną liczbę obliczeń na wykonanie. Jeśli wątku nieokresowego nie można modelować jako wątku okresowego (na przykład mógłby on być wykonywany z nieograniczoną częstotliwością lub nieograniczonymi obliczeniami na wykonanie), wówczas nie należy mu przypisywać stałego priorytetu, ponieważ byłoby to niezgodne z planowaniem prawdziwych wątków okresowych .

Odwrócenie priorytetów

Odwrócenie priorytetów to klasyczny tryb awarii systemów czasu rzeczywistego, w którym zadanie o wyższym priorytecie jest blokowane przez nieograniczony czas w oczekiwaniu na zadanie o niższym priorytecie, które zwolni zasób, taki jak (stan współdzielony chroniony przez) mutex . Zobacz artykuł „ Unikanie odwracania priorytetów ”, aby zapoznać się z technikami łagodzenia tego problemu.

Planowanie opóźnienia

Opóźnienie planowania to czas pomiędzy momentem, w którym wątek staje się gotowy do działania, a zakończeniem wynikającego z tego przełączenia kontekstu, tak że wątek faktycznie działa na procesorze. Im krótsze opóźnienie, tym lepiej, a wszystko powyżej dwóch milisekund powoduje problemy z dźwiękiem. Długie opóźnienia w planowaniu najprawdopodobniej wystąpią podczas przejść między trybami, takich jak uruchamianie lub wyłączanie procesora, przełączanie między jądrem zabezpieczającym a normalnym jądrem, przełączanie z trybu pełnej mocy do trybu niskiego poboru mocy lub dostosowywanie częstotliwości i napięcia zegara procesora .

Przerywa

W wielu projektach CPU 0 obsługuje wszystkie przerwania zewnętrzne. Zatem długo działająca procedura obsługi przerwań może opóźniać inne przerwania, w szczególności przerwania zakończenia bezpośredniego dostępu do pamięci audio (DMA). Zaprojektuj procedury obsługi przerwań, aby szybko kończyły się i odkładały długą pracę na wątek (najlepiej wątek CFS lub wątek SCHED_FIFO o priorytecie 1).

Równoważnie, wyłączenie przerwań na CPU 0 na długi okres ma ten sam skutek w postaci opóźnienia obsługi przerwań audio. Długie czasy wyłączenia przerwań zwykle mają miejsce podczas oczekiwania na blokadę obrotu jądra. Przejrzyj te blokady obrotowe, aby upewnić się, że są ograniczone.

Zarządzanie mocą, wydajnością i temperaturą

Zarządzanie energią to szerokie pojęcie, które obejmuje wysiłki mające na celu monitorowanie i zmniejszanie zużycia energii przy jednoczesnej optymalizacji wydajności. Zarządzanie ciepłem i chłodzenie komputera są podobne, ale mają na celu pomiar i kontrolę ciepła, aby uniknąć uszkodzeń spowodowanych nadmiarem ciepła. W jądrze Linuksa administrator procesora jest odpowiedzialny za politykę niskiego poziomu, podczas gdy tryb użytkownika konfiguruje politykę wysokiego poziomu. Stosowane techniki obejmują:

  • dynamiczne skalowanie napięcia
  • dynamiczne skalowanie częstotliwości
  • umożliwienie dynamicznego rdzenia
  • przełączanie klastrów
  • bramkowanie mocy
  • hotplug (hotswap)
  • różne tryby uśpienia (zatrzymanie, zatrzymanie, bezczynność, zawieszenie itp.)
  • migracja procesów
  • powinowactwo procesora

Niektóre operacje zarządzania mogą skutkować „przerwami w pracy” lub okresami, w których procesor aplikacji nie wykonuje użytecznej pracy. Te przerwy w pracy mogą zakłócać dźwięk, dlatego też takie zarządzanie powinno zostać zaprojektowane tak, aby zapewnić akceptowalne najgorsze przestoje w pracy, gdy dźwięk jest aktywny. Oczywiście, gdy nieuchronna jest utrata ciepła, unikanie trwałych uszkodzeń jest ważniejsze niż dźwięk!

Jądra bezpieczeństwa

Jądro zabezpieczające do zarządzania prawami cyfrowymi (DRM) może działać na tym samym rdzeniu procesora aplikacji, co rdzeń głównego systemu operacyjnego i kod aplikacji. Za każdym razem, gdy na rdzeniu aktywna jest operacja jądra zabezpieczającego, w rzeczywistości następuje zatrzymanie zwykłej pracy, która normalnie przebiegałaby na tym rdzeniu. W szczególności może to obejmować prace dźwiękowe. Z natury wewnętrzne zachowanie jądra bezpieczeństwa jest nie do odgadnięcia z warstw wyższego poziomu, dlatego wszelkie anomalie w wydajności spowodowane przez jądro bezpieczeństwa są szczególnie szkodliwe. Na przykład operacje jądra zabezpieczeń zazwyczaj nie pojawiają się w śladach przełączania kontekstu. Nazywamy ten czas „ciemnym czasem” — czasem, który upływa, a którego nie można zaobserwować. Jądra zabezpieczeń powinny być zaprojektowane tak, aby możliwe było zatrzymanie pracy w najgorszym przypadku, gdy dźwięk jest aktywny.