float 128 bit

0

Jakieś biblioteki do obliczeń z poczwórną precyzją (z 30 cyfr).

Może coś w stylu podwójnych double - jak complex, ale inaczej:
w górnym double mamy liczbę z precyzją 2^-53, czyli 53 bity, a w dolnym drugie 53.

Przykładowo.
double x = 1.0, y = 1e-25, z;

z = x + y; // z = 1; bo w double jest tylko z 15 cyfr, a tu potrzeba 25.

Ale gdy mam dwa double na liczbę, wtedy jest git.

nawet tak może być:
1.0 + 1e-100 = (1, 1e-100); i tyle, nie muszą tego dodawać...

Chodzi o operacje na takich liczbach, żeby można było normalnie obliczać, o tak:

float128 x(1.58878786565454, 4.34544e-16), y(5, 1e-22), z;

x += y;
x++;
z = xx + yy;

z.sqrt(); // chlastamy pierwiastek z precyzją 107 bitów (53*2 + 1).

Taką precyzję ma ten kalkulator z windows (~32 cyfry dziesiętne).

1
  1. long double
  2. gmplib.org
0

long double jest za krótkie - z 19 cyfr zaledwie.

A te biblioteki są na oparte na całkowitoliczbowych manipulacjach - jakby emulatory FPU?

Takie coś będzie chyba strasznie wolne...
To tak jakby np. mnożyć dwa double: 8 bajtów i 53 bity precyzji, bez koprocesora.
Pewnie z 50 razy wolniej wyjdzie, średnio licząc - arytmetyka, a funkcje ln, exp, sin,... znacznie gorzej.

Używając tej reprezentacji za pomocą dwóch double (czy nawet kilku) mogę używać FPU, np. obliczenie pierwiastka:
procesor obliczy szybko 53 bity (nawet 64, ale to jest zbyteczne), a potem tylko to sobie doprecyzowujemy - wystarczy jeden krok algorytmu Newtona!
Podobnie inne funkcje załatwiamy.

Natomiast proste operacje arytm. będą realizowane z 4 razy dłużej, nie 20, czy 50, bo tu używamy FPU.
Koprocesory numeryczne znacznie szybciej takie rzeczy robią, bo przecież były latami doskonalone specjalnie w celu wykonywania tylko takich operacji.

0

To skoro wiesz to po co się pytasz? Podaliśmy ci rozwiązanie dla liczb praktycznie nieskończenie dużych jeśli chodzi o zmiennoprzecinkowe i całkowite. Więc w czym problem?

1

Jak zwykle kłania się Wujek Google albo bardziej precyzyjnie Wikipedia:

http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format

gcc: __float128 - 128 bitów
gcc: long double - 128 bitów (tylko na PowerPC, Sparc)
gcc: long double - 80 bitów (x86-64)
intel: long double - 80 bitów (x86-64, /Qlong‑double)
intel: _Quad - 128 bitów

W vc++ nie ma prawdziwego long double, ale można sobie to włączyć (otrzyma się wtedy 80 bitów):
http://baumdevblog.blogspot.com/2010/11/high-precision-floating-point.html

W gcc znalazłem procedury do obsługi 128-bitowych obliczeń, ale prawdopodobnie wykorzystują one jakieś inne funkcje z gcc:
http://www.opensource.apple.com/source/gcc/gcc-5646/gcc/config/rs6000/darwin-ldouble.c

Boost wskazuje jeszcze na NTL:
http://shoup.net/ntl/

(robię ten research bo też zajmuję się numerkami w C++)

1

Musisz się zastanowić do czego potrzebujesz takich liczb. Jeżeli do kalkulatora o wysokiej precyzji to dostałeś już odpowiedzi. A jak np. potrzebujesz tego do jakiś obliczeń naukowych, to jak brak precyzji zmienia wynik to spróbuj zmienić algorytm na bardziej numerycznie poprawny, dobrze działający na typie double.

Inna kwestia jest w grafice obliczeniowej, tam często żeby stosować szybkie algorytmy musisz mieć dokładne obliczenia nawet z pierwiastkami, więc stosuje się naprawdę skomplikowane typy liczbowe. Możesz o tym poczytać na stronie CGALa, jednej z dwóch dobrych bibliotek do grafiki obliczeniowej (inna jest LEDA, ale koszty jej są ogromne). W grafice 3d stosuje się liczby o zdecydowanie mniejszej precyzji, często mniejszej niż liczby pojedynczej precyzji, ponieważ wydajność się liczy bardziej niż dokładność. Podstawą jest, żeby nie kumulować błędów.

0
winerfresh napisał(a)

To skoro wiesz to po co się pytasz? Podaliśmy ci rozwiązanie dla liczb praktycznie nieskończenie dużych jeśli chodzi o zmiennoprzecinkowe i całkowite. Więc w czym problem?

Nie wiem, może jest dobre.
Ile czasu tam trwa mnożenie z precyzją 32 cyfr, czyli ze 110 bitów precyzji?

Zjarek napisał(a)

Musisz się zastanowić do czego potrzebujesz takich liczb. Jeżeli do kalkulatora o wysokiej precyzji to dostałeś już odpowiedzi. A jak np. potrzebujesz tego do jakiś obliczeń naukowych, to jak brak precyzji zmienia wynik to spróbuj zmienić algorytm na bardziej numerycznie poprawny, dobrze działający na typie double.

Głównie do równań różniczkowych.
double jest za krótki w wielu przypadkach.

Np. w symulacji orbit planet wychodzą nieduże błędy r (zgodnie z precyzją double), ale za to błąd fazy jest na poziomie 10^-8, czyli sqrt(1e-16), co znaczy że błąd fazy rośnie z kwadratem czasu obliczeń (bezpośrednio z praw Keplera to wynika).

I tego żaden algorytm nie wyeliminuje - tu błędy są skorelowane ze sobą i tyle.
Dopiero gdy użyjemy liczb z precyzją 10-32, czyli z 32 cyfry, wtedy błąd fazy będzie na poziomie 10-16.

1

To możesz spróbować użyć liczb o bardzo dużej precyzji i sprawdzić, czy wydajność jest akceptowalna. Do tego zastanawiałbym się czy taka precyzja jest potrzebna. Mówisz o ruchu planet, ale czy masz odpowiednio dokładne dane oraz czy wszystkie oddziaływania które bierzesz pod uwagę wystarczają na tak dokładne obliczenia. Z drugiej strony równania różniczkowe szczególnie nie lubią złej precyzji.

1

Tak się troszeczkę pobawiłem gmp i wyszło, że na 3.2 GHz z -O2 mnożenie dwóch liczb mpf_class o precyzji 128 bit milion razy trwa 0.98s, czyli około 1ns na iterację. Taki test to żadna wyrocznia, ale wydaje mi się, że 128 bitów dla gmp to nie problem.

0
Zjarek napisał(a)

To możesz spróbować użyć liczb o bardzo dużej precyzji i sprawdzić, czy wydajność jest akceptowalna. Do tego zastanawiałbym się czy taka precyzja jest potrzebna. Mówisz o ruchu planet, ale czy masz odpowiednio dokładne dane oraz czy wszystkie oddziaływania które bierzesz pod uwagę wystarczają na tak dokładne obliczenia. Z drugiej strony równania różniczkowe szczególnie nie lubią złej precyzji.

W tym przypadku poczwórna precyzja jest koniczna.
Przykładowo: słynna precesja peryhelium Merkurego 570'' / 100 lat,
i w tym jest ponoć około 40'' niezgodne z Newtonem.

Porównajmy to z błędami obliczeń:
40/100 lat < 0.1 / orbitę, orbita to pełny kąt, zatem: 0.1/1296000 < 8e-8;
jak widać na double jest to nierozróżnialne od błędów obliczeń.

0
Endrju napisał(a)

Tak się troszeczkę pobawiłem gmp i wyszło, że na 3.2 GHz z -O2 mnożenie dwóch liczb mpf_class o precyzji 128 bit milion razy trwa 0.98s, czyli około 1ns na iterację. Taki test to żadna wyrocznia, ale wydaje mi się, że 128 bitów dla gmp to nie problem.

Może oblicz to samo na double dla porównania... i long double.

Trochę chyba wolno wychodzi.
Mnożenie na FPU to kilka taktów, plus operacje ładowania... z 20 taktów.
3.2 G / 20 = 160 M, a tam masz 1 M, raczej kiepsko.

0

Ogólnie jak robisz taką symulację to musisz wybrać optimum precyzji i czasu wykonania. Przy mniejszych precyzjach długi czas obliczeń nie ma sensu, bo nic z tego nie wynika, z kolei przy bardzo dużych precyzjach tylko tracisz czas, bo tego nie wykorzystujesz.

Ja bym spróbował określenie sobie jakiegoś sensownego czasu działania programu, np. 4 h i do tego to dostosowywał. Mpf będzie w tym wypadku najlepsze, lub jak koniecznie chcesz rozwiązanie 128 bitowe, to było już to wspomniane dla różnych kompilatorów.

0

Przyznaj się jaki algorytm stosujesz do symulacji, bo to może być źródłem błędów.
Mogłeś też zastosować za mały krok czasowy, co prowadzi do dużych błędów numerycznych (mały czas daje małe różnice w pozycji, które mogą być na granicy precyzji i wtedy możesz dostać dziwne wyniki, gorsze niż gdy krok czasowy byłby większy).
Wątpię by do symulacji planet double nie wystarczał, przykładowo orbita ziemi jest znana z dokładnością 9 cyfr wiodących (czyli masz 6 cyfr w zapasie).
Jeśli masz błąd systematyczny (twoje wypowiedzi to sugerują) to na 100% stosujesz zły algorytm lub parametry wejściowe.
Dobrze dobrany algorytm i parametry wejściowe powinny dawać błędy przypadkowe.
Dobrą metodą testowania poprawności algorytmu jest obserwowanie energii całkowitej układu, jeśli energia nie jest statystycznie stała to masz błąd w algorytmie lub doborze parametrów (krok czasowy).

0
wil napisał(a)

(...) raczej kiepsko.

Albo szybkość albo dokładność. Nie można mieć obu.

long double nie jest ani troszeczkę tak dokładny jak wpisana w gmp liczba z 32 cyframi:

1.12345678910111213141516171834 * 1.857362534743929293746546473830

gmp:         2.086666549480117626294158933040704982273
long double: 2.086666549480117855254815428800441168277

Oczywiście gmp ma wynik prawidłowy.

Btw. long double nie ma 128 bitów tylko 80. :-)

0

witam, a może inny język programowania - fortran?

Zjarek napisał(a)

Ogólnie jak robisz taką symulację to musisz wybrać optimum precyzji i czasu wykonania. Przy mniejszych precyzjach długi czas obliczeń nie ma sensu, bo nic z tego nie wynika, z kolei przy bardzo dużych precyzjach tylko tracisz czas, bo tego nie wykorzystujesz.

Ja bym spróbował określenie sobie jakiegoś sensownego czasu działania programu, np. 4 h i do tego to dostosowywał. Mpf będzie w tym wypadku najlepsze, lub jak koniecznie chcesz rozwiązanie 128 bitowe, to było już to wspomniane dla różnych kompilatorów.

Każda metoda ma swój optymalny krok.
Mniejszy krok zwiększa błąd zaokrągleń (więcej obliczeń na dany przedział czasu T), a dłuższy krok daje większy błąd obcięcia (zależny od rzędu metody).

Np. dla RK4 i orbity Merkurego, z obliczeniami na double, najmniejszy błąd otrzymasz dla około dt = ~3000s, prawie = 1 godz.
Dla metody rzędu 8 optymalny krok byłby chyba z 30 razy dłuższy, czyli aż doba.
Dla metody rzędu 2 należałoby skrócić krok poniżej minut, a wtedy będzie bardzo dużo obliczeń, więc i sumaryczny błąd znacznie większy.

0
MarekR22 napisał(a)

Przyznaj się jaki algorytm stosujesz do symulacji, bo to może być źródłem błędów.
Mogłeś też zastosować za mały krok czasowy, co prowadzi do dużych błędów numerycznych (mały czas daje małe różnice w pozycji, które mogą być na granicy precyzji i wtedy możesz dostać dziwne wyniki, gorsze niż gdy krok czasowy byłby większy).
Wątpię by do symulacji planet double nie wystarczał, przykładowo orbita ziemi jest znana z dokładnością 9 cyfr wiodących (czyli masz 6 cyfr w zapasie).
Jeśli masz błąd systematyczny (twoje wypowiedzi to sugerują) to na 100% stosujesz zły algorytm lub parametry wejściowe.
Dobrze dobrany algorytm i parametry wejściowe powinny dawać błędy przypadkowe.
Dobrą metodą testowania poprawności algorytmu jest obserwowanie energii całkowitej układu, jeśli energia nie jest statystycznie stała to masz błąd w algorytmie lub doborze parametrów (krok czasowy).

Najlepsze są prawdopodobnie metody ekstrapolacyjne, podobnie jak w przypadku całek oznaczonych.
Schematy Runge-Kutty wyższych rzędów wykonują zbyt dużo obliczeń.

Nawet ta RK4 to już przesada.
Bierzesz znacznie prostszą metodę rzędu 2, wykonujesz jeden krok ekstrapolacji, i masz rządu 4.
Drugi kroczek i już jest 6, itd.

MiM napisał(a)

witam, a może inny język programowania - fortran?

Wolałby już postscript. );

Endrju napisał(a)

Albo szybkość albo dokładność. Nie można mieć obu.

Ale nie 200 razy wolniej.

Endrju napisał(a)

long double nie ma 128 bitów tylko 80. :-)

long double ma 64 bity precyzji.

0

Ale Ty chciałeś 128, czyż nie? Z tego powodu nie użyjesz żadnego typu na x86 bez bibliotek do arbitralnej precyzji. (__float128 nie liczę, bo ten typ jest jakiś dziwny)

Nie rozumiem czego od nas oczekujesz? GMP i inne takie biblioteki są pisane przez ludzi którzy raczej się na tym znają, szybciej nie będzie. Jeżeli masz 486 i 66 MHz to faktycznie masz problem, jeżeli masz jakikolwiek normalny sprzęt, to każda z tych bibliotek będzie wystarczająco szybka. Liczysz położenie planet co 1ns czy jak?

0
Endrju napisał(a)

__float128 nie liczę, bo ten typ jest jakiś dziwny

A co ma dziwnego (oprócz nazwy)?
Poza tym jest jeszcze _Quad.

0
Endrju napisał(a)

Ale Ty chciałeś 128, czyż nie? Z tego powodu nie użyjesz żadnego typu na x86 bez bibliotek do arbitralnej precyzji. (__float128 nie liczę, bo ten typ jest jakiś dziwny)

Chodzi mi o poczwórną precyzję:
http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format

Endrju napisał(a)

GMP i inne takie biblioteki są pisane przez ludzi którzy raczej się na tym znają, szybciej nie będzie. Jeżeli masz 486 i 66 MHz to faktycznie masz problem, jeżeli masz jakikolwiek normalny sprzęt, to każda z tych bibliotek będzie wystarczająco szybka. Liczysz położenie planet co 1ns czy jak?

Chyba trochę przesadziłeś z tymi fachowcami od algorytmiki.

Na moim marnym Celeronie 2.53GHz, obliczenia na tablicach double w stylu: c[i] = a[i] * b[i];
dodawanie: 150 mln / s
mnożenie: 150 mln / s
dzielenie: 50 mln / s

liczby w tablicach były losowe.

Procesor oblicza to i tak z pełną precyzją - long double.
Na 3.2 GHz powinno być z 200 mnożeń 64 bits, zatem 128 bits można załatwić bez problemu 10 razy wolniej = 20 mln /s.
1 mln / s ? Studenci takie algorytmy produkują na ćwiczeniach.

0

...

Wyraźnie napisałem, że czas który sobie zmierzyłem to żaden benchmark, pokazuje tylko, że gmp jest całkiem szybkie.

Tu masz benchmark:

endrju@kormoran ~/gmpbench-0.2 $ ./multiply 128 128                                                                                          
Calibrating CPU speed...done                                                                                                                 
Multiplying 128-bit number with 128-bit number 696150042 times...done!                                                                       
RESULT: 71246550 operations per second 

71 milionów na sekundę. Nie 1 ani 20.

Tu masz cały wynik: http://4programmers.net/Pastebin/1351

PS.

Z cyklu "Czy wiesz że?": Mathematica używa GMP.

0
Endrju napisał(a)

...
Wyraźnie napisałem, że czas który sobie zmierzyłem to żaden benchmark, pokazuje tylko, że gmp jest całkiem szybkie.

Zgadza się, to żaden benchmark. Zapomniałeś że benchmarki podaje się w celach porównawczych a nie dla samego ich istnienia, w związku z czym masz dwa wyjścia:
a) albo podajesz dla tej samej maszyny wyniki także dla double, long double 80-bit i _Quad
b) albo podajesz kompletną definicję maszyny, w tym CPU (model, wersja, częstotliwość pracy), RAM (częstotliwość, opóźnienie), OS, wersja kompilatora, wersja GMP

To co teraz podałeś nie jest nawet ciekawostką, bo nie ma do czego tego porównać.

Jeszcze raz zapytam (także autora wątku), dlaczego nie gcc / __float128 ?

http://gcc.gnu.org/onlinedocs/libquadmath.pdf
http://stackoverflow.com/questions/5451447/quadruple-precision-in-c-gcc

0

Kolejny czepialski. :-(

Niech sobie autor wątku sam sprawdzi, to jego problem jest, nie mój. Ja tylko zaznaczyłem, że wbrew jego oczekiwaniom gmp nie jest tak wolne jak myśli. Benchmark gmp jest do pobrania z ich strony, dla double już sobie napisał.

__float128 jest nieprzenośny ale powinien być szybki...

0

Za wolne - dobre na kalkulator.

Zresztą nawet nie znam tego gcc, ale z tego co zdążyłem zauważyć jest to jakieś kolejne cudo od wszystkiego, czyli do niczego...
Robię na windows.

0

Tu jest coś lepszego:
http://web.mit.edu/tabbott/Public/quaddouble-debian/qd-2.3.4-old/docs/qd.pdf

double double i jeszcze quad double - 211 bitów.

http://mrob.com/pub/math/f161.html

Jak widać nie potrzeba do tego 2MB kodu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1