Względne zalety obliczeń stałoprzecinkowych vs. zmiennoprzecinkowych?

9

Mam system cyfrowego przetwarzania sygnałów, który działa na szybkiej maszynie x86 przy użyciu liczb zmiennoprzecinkowych o podwójnej precyzji . Przyszło mi do głowy, że tak naprawdę nie używam ogromnego zakresu dynamicznego reprezentacji zmiennoprzecinkowej - wszystkie wielkości mieszczą się w zakresie ± 32768.

Moje pytanie: czy jest możliwe, że przejście na obliczenia o stałym punkcie przyniosłoby korzyści w zakresie dokładności numerycznej (wysoki priorytet) lub czasu obliczeń (niski priorytet)?

Oczywiście odpowiedź zależy od liczby bitów dostępnych do obliczenia punktu stałego. Ile bitów precyzji wykorzystuje typowe systemy stałoprzecinkowe? Czy jest możliwe wydajne wykonywanie obliczeń w punkcie stałym z, powiedzmy, 64-bitową ( 16-bitową częścią całkowitą, 48-bitową częścią ułamkową ) na x86-64?

Zawsze myślałem, że obliczenia w punkcie stałym były wykorzystywane tylko w sytuacjach, w których moc procesora jest ograniczona - czy warto stosować obliczenia w punkcie stałym, gdy moc procesora nie ma znaczenia?

nibot
źródło
Czy naprawdę potrzebujesz więcej niż ~ 15 znaczących liczb, które daje wartość zmiennoprzecinkowa podwójnej precyzji? Podczas gdy ogólne uogólnienia są złe, powiedziałbym, że jeśli spojrzeć na agregację wszystkich systemów DSP o stałym punkcie, 16-bitowe liczby całkowite są prawdopodobnie najbardziej rozpowszechnionym formatem.
Jason R

Odpowiedzi:

7

Dokładność liczbowa liczb całkowitych będzie lepsza niż dokładność liczbowa liczb zmiennoprzecinkowych tylko wtedy, gdy lepsza będzie rozdzielczość liczb całkowitych. Podwójne mają 52 bity ułamkowe, więc liczby zmiennoprzecinkowe o podwójnej precyzji mają rozdzielczość gorszą niż w przybliżeniu liczby całkowite252, który jest znacznie większy niż 32768 (215). Więc nie, dokładność liczbowa nie będzie lepsza, jeśli przejdziesz do liczb całkowitych.

Drugi problem to prędkość. Odpowiedź brzmi: to zależy od sprzętu. Jeśli uruchamiasz swój program na cyfrowym procesorze sygnałowym, który ma wiele rdzeni zwielokrotniających / gromadzących rdzenie, wówczas tak, będzie znacznie szybszy w stałym punkcie. Z drugiej strony na układzie x86 prawdopodobnie będzie on wolniejszy w ustalonym punkcie. Zrobiłem dokładnie to, o czym mówisz raz, i zauważyłem, że moje czasy wykonania rosną.

Po przeprowadzeniu kilku wyszukiwań w Internecie dowiedziałem się, że jest to powszechne. Powodem jest to, że ma dedykowany procesor zmiennoprzecinkowy, który nic nie robi, gdy przechodzisz do punktu stałego, podczas gdy sprzęt stałoprzecinkowy jest współdzielony ze zwykłą akcją punktu stałego, taką jak arytmetyka wskaźnika.

Jeśli chcesz przyspieszyć przetwarzanie, sposobem na to jest zmiana z pływaków podwójnej precyzji na pływaki pojedynczej precyzji. To powinno spowodować znaczny wzrost prędkości. To oczywiście zmniejszyłoby dokładność liczbową.

Jim Clay
źródło
Miałem na myśli to, co mówi ta odpowiedź, kiedy napisałem swoją. Ten jest lepszy. Jeśli się nie mylę, przeczytałem też gdzieś, że na niektórych komputerach (może 64-bitowych?) Rodzimy sprzętowy zmiennoprzecinkowy typ jest podwójny, więc użycie liczb zmiennoprzecinkowych o pojedynczej precyzji (cztery bajty) może być w rzeczywistości wolniejsze. W każdym razie należy to wziąć pod uwagę.
heltonbiker
Pływaki pojedynczej precyzji mają 23-bitowe mantysy, podwójne mają 52 bity.
Paul R
Proponuję 16-bitową liczbę całkowitą + 48-bitową frakcję jako alternatywę dla zmiennoprzecinkowej podwójnej precyzji. Wspomniałem o 32768, aby wskazać, że moje wartości z łatwością mieszczą się w tym zakresie. Biorąc pod uwagę ograniczenie tych wartości, myślę, że Q16.48 zapewniłoby większą dokładność numeryczną niż zmiennoprzecinkowa podwójnej precyzji.
nibot
1
@nibot Dobra. Dwójki miałyby lepszą precyzję od -16 do +16, a ułamkowe liczby całkowite miałyby lepszą precyzję gdzie indziej do -32769 i +32768. Nie mogli oczywiście reprezentować niczego poza tym. Byłyby również wolniejsze niż podwójne. Dla mnie ograniczony zasięg i niska prędkość byłyby przełomowe, ale YMMV.
Jim Clay
6

Zalety punktu stałego dotyczą głównie mocy (na przykład, gdy masz wybór sprzętu procesora lub procesor jest dobry w wyłączaniu nieużywanych jednostek funkcjonalnych). Jest tak, ponieważ jednostki o stałym punkcie są zwykle mniejsze (mniej tranzystorów, krótsze druty, mniejsza pojemność do pokonania na MAC) dla danej technologii i stawki emisji, niż zmiennoprzecinkowe.

Jednak ogromna liczba popularnych współczesnych procesorów (serwer, komputer PC, a nawet urządzenia mobilne) ma więcej i szybsze FPU (szczególnie jednostki FP o pojedynczej precyzji) niż mnożniki liczb całkowitych, a większość mocy systemu nie pochodzi z korzystania z FPU, więc używanie stałej -point będzie miał niewielkie lub żadne zalety dla typowych obliczeń DSP na tych produktach i może być wadą pod względem czystej wydajności. Wykorzystując obecną technologię, wszelkie korzyści związane ze stałymi punktami będą głównie gromadzone w małych produktach osadzonych, takich jak urządzenia wielkości przycisków.

Jednak należy również wziąć pod uwagę ślady pamięci podręcznej i procesora. Sprytne użycie mniejszych typów danych (short int i float), aby całkowicie zmieścić duże obliczenia w pamięci podręcznej danych, może zrównoważyć wszelkie zalety przepustowości FPU.

hotpaw2
źródło
2
+1 za wzmiankę o znaczeniu problemów z pamięcią podręczną w odniesieniu do wydajności. W nowoczesnych procesorach x86 projektowanie algorytmu z myślą o buforowaniu może mieć ogromny wpływ na wydajność.
Jason R
5

Wolisz liczbę zmiennoprzecinkową pojedynczej precyzji od liczby podwójnej - spowoduje to zmniejszenie o połowę przepustowości pamięci, powierzchni pamięci podręcznej i wymagań dotyczących pamięci, a także przyspieszy niektóre operacje matematyczne. Otwiera także możliwość 4-kierunkowego SIMD, jeśli konieczna jest dalsza optymalizacja.

Punkt stały jest naprawdę wartościowy tylko wtedy, gdy nie masz FPU - większość współczesnych procesorów x86 ma dwa FPU, więc nie można nic zyskać na używaniu stałego punktu, a wydajność może być nawet znacznie gorsza z ustalonym punktem. (Należy również zauważyć, że punkt stały wymaga dodatkowych instrukcji w porównaniu do zmiennoprzecinkowego dla operacji takich jak mnożenie).

Paul R.
źródło
Jestem zainteresowany zwiększeniem dokładności numerycznej, a nie jej zmniejszaniem.
nibot
Jak widzisz punkt stały poprawiający dokładność liczbową w stosunku do podwójnej, która ma już 52 bity precyzji i ogromny zakres dynamiki?
Paul R
Cóż, mógłbym użyć formatu stałego punktu z więcej niż 52 bitami.
nibot
Ponieważ najwyraźniej potrzebujesz co najmniej 16 bitów na część całkowitą reprezentacji punktu stałego, zajmie ci to znacznie ponad 64 bity, więc prawdopodobnie patrzysz na format, dla którego twój procesor nie ma nawet natywnych instrukcji liczb całkowitych. W takim przypadku równie dobrze możesz użyć istniejącej biblioteki dużej liczby całkowitej lub podobnej. Najważniejsze pytanie, na które należy jednak odpowiedzieć, to: ile naprawdę potrzebujesz precyzji ?
Paul R
3

Oprócz podanych tutaj bardzo dobrych odpowiedzi, warto dodać kilka rzeczy:

  • Są sytuacje, w których nawet jeśli masz bardzo podstawowe wymagania dotyczące zakresu dynamicznego przetwarzanych danych, nadal będziesz potrzebować bardzo dobrej precyzji dla niektórych operacji na nich wykonywanych - na przykład będziesz chciał zastosować filtr IIR, który wymaga stosunkowo małych współczynników; ich obcięcie spowoduje niestabilność. Gdy tylko twój system otrzyma informację zwrotną, istnieje duża szansa, że ​​problemy z kwantyzacją / obcięciem cię ugryzą podczas korzystania z ustalonego punktu - musisz być znacznie bardziej ostrożny w takich kwestiach, jak topologia filtrów i schematy obcięcia / oszczędzania ułamków.
  • W przeciwieństwie do wielu architektur DSP / DSC, x86 nie ma nasyconych operacji na liczbach całkowitych (cóż, jest w SSE, a nie na standardowym kodzie skalarnym). Oznacza to, że w przypadku przepełnienia mogą się zdarzyć złe rzeczy - wartości zmieniające znaki i „zawijanie”. Musisz być bardzo ostrożny z przepełnieniami i zakresem dynamicznym lub zraszać testy zakresów operandóww całym kodzie. Może to poważnie zaszkodzić wydajności. Dla porównania, zmiennoprzecinkowa jest bardziej odporna na te problemy, ponieważ duży zakres dynamiczny zapewnia więcej „rezerwy”, a przepełnienia nie doprowadzą do katastrofalnych awarii. Większość kodu przetwarzania sygnału audio działającego na komputerach stacjonarnych używa zakresu -1,0 .. 1,0, pojedynczej lub podwójnej precyzji; daje to ponad setki dB nadwyżki. Napisałem kod przetwarzania sygnału audio dla obu podejść, a gdy używam liczb zmiennoprzecinkowych, jest tylko kilka miejsc, w których muszę jawnie przyciąć / nasycić sygnał - zwykle tylko na końcu łańcucha przetwarzania sygnału lub w miejscach, gdzie występuje sprzężenie zwrotne.
fenenety
źródło
1

Kilka punktów do rozważenia:

  • Większość współczesnych procesorów od wielu lat optymalizuje kroczenie liczb zmiennoprzecinkowych, a nawet procesory graficzne są do tego bardzo skutecznie wykorzystywane;
  • Obliczenia stałoprzecinkowe uszkadzają dane i mogą powodować poważne problemy, gdy operacje arytmetyczne nie są dobrze uwarunkowane (dlatego liczby stałoprzecinkowe zostały zastąpione liczbami zmiennoprzecinkowymi);
  • Nawet jeśli używasz podpisanych skrótów do ZAWIERANIA swoich danych (wiele rejestratorów danych używa 16-bitowej precyzji), OBLICZENIA należy wykonać w liczbach zmiennoprzecinkowych, a następnie przekonwertować z powrotem na liczby całkowite, w przeciwnym razie mogą wystąpić artefakty, takie jak kwantyzacja i aliasing.

W ostatecznym rozrachunku uważam, że nasze dane z prawdziwego świata są cenne, a ślepe numerowanie komputera to skromna robota służąca. Komputer musi zostać obciążony ciężką pracą na rzecz twoich danych i ciebie, a nie traktowany tak, jakby był prawdziwą gwiazdą serialu.

heltonbiker
źródło
Nie chciałem sugerować, że użyję 16-bitowych skrótów do przechowywania moich ilości, ale raczej coś w rodzaju 64-bitowego formatu stałego punktu z 16-bitową częścią całkowitą i 48-bitową częścią ułamkową. Motywacja jest taka, że ​​jeśli i tak nie używam większości bitów wykładnikowych w formacie zmiennoprzecinkowym, czy moja dokładność numeryczna poprawiłaby się, gdyby zamiast tego użyć tych bitów w celu zapewnienia dodatkowych cyfr znaczących?
nibot
Do pierwotnego pytania należy dodać 16-bitową liczbę całkowitą + 48-bitowy ułamek. To wygląda jak215powoduje zamieszanie.
Christopher Felton
Jeszcze jedno: wydaje mi się, że StackOverflow (zamiast DSP.SE tutaj) byłby idealnym miejscem do uzyskania głębszych powodów zalet i wad jednego formatu w stosunku do drugiego.
heltonbiker