W każdym miejscu, w którym spojrzałem, jest napisane, że double
jest lepsze niż float
pod każdym względem. float
został przestarzały double
w Javie, więc dlaczego jest nadal używany?
Dużo programuję w Libgdx, a one zmuszają cię do korzystania float
(deltaTime itp.), Ale wydaje mi się, że double
łatwiej jest pracować z pamięcią i pamięcią.
Przeczytałem również Kiedy używaszfloat
liczby zmiennoprzecinkowej, a kiedy używasz podwójnej , ale jeśli tak naprawdę jest dobry tylko dla liczb z dużą liczbą cyfr po przecinku, to dlaczego nie możemy po prostu użyć jednej z wielu odmian double
?
Czy jest jakiś powód, dla którego ludzie upierają się przy użyciu pływaków, mimo że tak naprawdę nie ma to już żadnych zalet? Czy to zbyt dużo pracy, żeby to wszystko zmienić?
źródło
byte
ishort
aint
kiedy nielong
?Odpowiedzi:
LibGDX to framework wykorzystywany głównie do tworzenia gier.
Podczas opracowywania gier zwykle musisz wykonywać wiele zgniatania liczb w czasie rzeczywistym, a każda wydajność, jaką możesz uzyskać, ma znaczenie. Dlatego twórcy gier zwykle używają liczby zmiennoprzecinkowej, gdy precyzja zmiennoprzecinkowa jest wystarczająca.
Rozmiar rejestrów FPU w CPU nie jest jedyną rzeczą, którą należy wziąć pod uwagę w tym przypadku. W rzeczywistości większość poważnych kryzysów w tworzeniu gier odbywa się za pomocą GPU, a procesory graficzne są zwykle zoptymalizowane pod kątem liczby zmiennoprzecinkowej, a nie podwójnej .
A potem jest jeszcze:
które są cennymi zasobami, które otrzymujesz dwa razy więcej, gdy używasz 32-bitowego float zamiast 64-bitowego double.
źródło
Pływaki zużywają o połowę mniej pamięci niż podwójne.
Mogą mieć mniejszą precyzję niż podwójne, ale wiele aplikacji nie wymaga precyzji. Mają większy zasięg niż jakikolwiek inny format stałego punktu o podobnej wielkości. Dlatego wypełniają niszę, która wymaga szerokiego zakresu liczb, ale nie wymaga wysokiej precyzji i gdzie ważne jest użycie pamięci. Na przykład używałem ich w dużych systemach sieci neuronowych.
Wychodząc poza Javę, są również szeroko stosowane w grafice 3D, ponieważ wiele procesorów graficznych używa ich jako podstawowego formatu - poza bardzo drogimi urządzeniami NVIDIA Tesla / AMD FirePro, zmiennoprzecinkowe podwójnej precyzji jest bardzo wolne na GPU.
źródło
Kompatybilność wsteczna
Jest to najważniejszy powód zachowania zachowania w już istniejącym języku / bibliotece / ISA / itp.
Zastanów się, co by się stało, gdyby zabrali spławiki z Javy. Libgdx (i tysiące innych bibliotek i programów) nie działałby. Będzie to wymagało wiele wysiłku, aby zaktualizować wszystko, a być może nawet lata dla wielu projektów (wystarczy spojrzeć na przechodzące wstecz Python 2 na Python 3, przechodzące pod kątem zgodności). I nie wszystko zostanie zaktualizowane, niektóre rzeczy zostaną zerwane na zawsze, ponieważ opiekunowie porzucili je, być może wcześniej, niż by to zrobili, ponieważ wymagałoby to więcej wysiłku, niż chcieliby zaktualizować, lub ponieważ nie jest już możliwe osiągnięcie tego, co ich oprogramowanie powinno było do zrobienia.
Występ
Podwójne wersje 64-bitowe zajmują dwa razy więcej pamięci i są prawie zawsze wolniejsze w przetwarzaniu niż zmiennoprzecinkowe zmiennoprzecinkowe 32-bitowe (bardzo rzadkimi wyjątkami są sytuacje, w których oczekuje się, że 32-bitowa zmiennoprzecinkowa będzie używana tak rzadko lub wcale, że nie podjęto żadnych wysiłków w celu ich zoptymalizowania O ile nie opracowujesz specjalistycznego sprzętu, nie doświadczysz tego w najbliższej przyszłości.)
Libgdx jest szczególnie odpowiednią dla Ciebie biblioteką gier. Gry mają tendencję do większej wrażliwości na wydajność niż większość programów. Karty graficzne do gier (tj. AMD Radeon i NVIDIA Geforce, a nie FirePro i Quadro) mają zazwyczaj bardzo słabą wydajność zmiennoprzecinkową w wersji 64-bitowej. Dzięki uprzejmości Anandtech, oto jak wydajność podwójnej precyzji porównuje się do wydajności pojedynczej precyzji w niektórych z najlepszych dostępnych kart do gier AMD i NVIDIA (na początku 2016 r.)
Należy pamiętać, że R9 Fury i GTX 900 są nowsze niż R9 200 i GTX 700, więc względna wydajność 64-bitowego zmiennoprzecinkowego spada. Cofnij się wystarczająco daleko, a znajdziesz GTX 580, który miał stosunek 1/8 jak seria R9 200.
1/32 wydajności jest dość dużą karą do zapłacenia, jeśli masz ścisłe ograniczenie czasowe i nie zyskujesz dużo, używając większego podwójnego.
źródło
Operacje atomowe
Oprócz tego, co już powiedzieli inni, wadą specyficzną dla Javy
double
(ilong
) jest to, że przypisania do 64-bitowych pierwotnych typów nie są gwarantowane jako atomowe . Ze specyfikacji języka Java, Java SE 8 Edition , strona 660 (wyróżnienie dodane):Fuj
Aby tego uniknąć, musisz zadeklarować zmienną 64-bitową za pomocą
volatile
słowa kluczowego lub użyć innej formy synchronizacji wokół przypisań.źródło
Wydaje inne odpowiedzi brakowało jeden ważny punkt: SIMD architekturach może przetworzyć mniej / więcej danych w zależności czy działają one na
double
lubfloat
elemencie (na przykład osiem wartości pływak na raz lub cztery podwójne wartości na raz).Podsumowanie rozważań dotyczących wydajności
float
może być szybszy na niektórych procesorach (na przykład na niektórych urządzeniach mobilnych).float
zużywa mniej pamięci, więc w dużych zestawach danych może znacznie zmniejszyć całkowitą wymaganą pamięć (dysk twardy / RAM) i zużyte pasmo.float
może powodować, że procesor zużywa mniej energii (nie mogę znaleźć odniesienia, ale jeśli nie jest to możliwe, przynajmniej wydaje się prawdopodobne) do obliczeń o pojedynczej precyzji w porównaniu do obliczeń o podwójnej precyzji.float
zużywa mniej pasma, a w niektórych aplikacjach ma znaczenie.float
zużywa aż połowę pamięci podręcznej w porównaniu do podwójnej.Podsumowanie względów dokładności
float
wystarczydouble
i tak ma znacznie większą precyzjęZagadnienia dotyczące zgodności
double
(to dlatego, że producenci GPU starają się zwiększyć liczbę rdzeni graficznych, a dlatego starają się zaoszczędzić jak najwięcej obwodów w każdym rdzeniu, więc optymalizacjafloat
pozwala na tworzenie układów GPU z większą liczbą rdzeni w środku)double
formatu wewnętrznego (do operacji renderowania 3D)Ogólne wskazówki
double
zmiennych tymczasowych na stosie daje dodatkową precyzję za darmo (dodatkowa precyzja bez obniżenia wydajności).float
, ale mogą być ograniczone wartości, jeśli używaszdouble
)float
lub tylkodouble
bardzo pomaga kompilatorowi w SIMD-ify instrukcje.Aby uzyskać więcej informacji, zobacz poniższe komentarze PeterCordes.
źródło
double
tymczasowe jest bezpłatne tylko na x86 z FPU x87, nie z SSE2. Automatyczne wektoryzowanie pętli zdouble
tymczasowymi oznacza rozpakowaniefloat
dodouble
, co wymaga dodatkowej instrukcji, a ty przetwarzasz o połowę mniej elementów na wektor. Bez automatycznej wektoryzacji konwersja zwykle może odbywać się w locie podczas ładowania lub przechowywania, ale oznacza to dodatkowe instrukcje podczas mieszania liczb zmiennoprzecinkowych i podwójnych w wyrażeniach.Oprócz innych wymienionych powodów:
Jeśli masz dane pomiarowe, czy to ciśnienia, przepływy, prądy, napięcia, czy cokolwiek innego, często dzieje się tak w przypadku sprzętu wyposażonego w ADC.
ADC zazwyczaj ma 10 lub 12 bitów, 14 lub 16 bitów są rzadsze. Ale trzymajmy się 16-bitowym - jeśli mierzysz w pełnej skali, masz dokładność 1/65535. Oznacza to, że zmiana z 65534/65535 na 65535/65535 to tylko ten krok - 1/65535. To mniej więcej 1,5E-05. Dokładność pływaka wynosi około 1E-07, więc jest o wiele lepsza. Oznacza to, że niczego nie tracisz, używając
float
do przechowywania tych danych.Jeśli wykonujesz nadmierne obliczenia za pomocą pływaków, wykonujesz nieco gorsze wyniki niż
doubles
pod względem dokładności, ale często nie potrzebujesz tej dokładności, ponieważ często nie przejmujesz się, czy właśnie zmierzyłeś napięcie 2 V lub 2,00002 V. Podobnie , jeśli przekształcisz to napięcie w ciśnienie, nie przejmujesz się, czy masz 3 bary lub 3.00003 bary.źródło