float-Berechnungen schneller als double?
-
Tachyon schrieb:
hustbaer schrieb:
Ich würde sagen dass dein Tip Blödsinn ist.
Wenn man nicht einen guten Grund hat float zu nehmen, sollte man grundsätzlich double nehmen.
Blubb.Aha, und wieso? Ich kenne da 'ne Aussage von Stroustrup, aber da gabs ebenfalls keine Begründung dazu.
Weil double genauer ist!?!
Wieso sollte ich also ohne wirklich guten Grund das ungenauere float verwenden?Wenns mit float soviel schneller ist, dass es sich wirklich auszahlt, dann kann man ja float nehmen. Das wäre dann nämlich ein "wirklich guter Grund". Oder wenn der Speicherverbrauch zum Problem wird.
Genauso könnte man jetzt Leuten empfehlen "short" oder gar "char" für bestimmte Dinge zu verwenden. Aber wieso, wenn ich genausogut int nehmen kann? Nur damit ich irgendwann das Problem bekomme, dass der Wertebereicht doch nicht ausreicht? Bzw. bei float vs. double: dass die Genauigkeit nichtmehr reicht? Nö, sicher nicht.
-
Siehe doch mal in der Dokumentation des Compilers nach, ob dieser zwischen float und double einen Unterschied macht oder ob er für mehr bytes long double haben will. Ansonsten ist die Fragestellung nach der Geschwindigkeit pow(2,killefitt) oder powl(3,bullshit)!
-
hustbaer schrieb:
Genauso könnte man jetzt Leuten empfehlen "short" oder gar "char" für bestimmte Dinge zu verwenden. Aber wieso, wenn ich genausogut int nehmen kann? Nur damit ich irgendwann das Problem bekomme, dass der Wertebereicht doch nicht ausreicht? Bzw. bei float vs. double: dass die Genauigkeit nichtmehr reicht? Nö, sicher nicht.
Warum genau verwendest du dann nicht long double? oder eine BigFloat klasse?
Wenn float nicht mehr reicht, dann tausche ich den typ aus - ist trivial und idR komplett automatisch möglich.
PS:
ich verwende int wo es sinn macht und char wo es sinn macht.
und nicht überall __int64Typen auszutauschen ist kein Problem solange es nicht teil eines public interfaces zu client code ist. und wenn es das ist, dann typedef und gut ist.
nicht immer aus angst den größten typen nehmen den man finden kann...
-
@Shade Of Mine:
Verwendest du dann bei Schleifen als Zählervariable auch char, wenn du weisst dass die Schleife nie mehr als 10 Durchläufe haben kann?
Also ich nicht, ich verwende da size_t.
Und eben (an anderen Stellen) hauptsächlich int (bzw. unsigned int). Und double. Weil's eben "Standard" ist.
Man muss sich nicht bei jeder Variable überlegen wie gross sie nun sein muss, man muss sich nurmehr überlegen ob ein int reicht, bzw. ob es ganz grobe Verschwändung wäre einen zu grossen Typ zu verwenden. (Ich verwende z.B. NICHT std::basic_string<int>
)
Die Standard-Library hält das im Übrigen auch so, guck dir bloss mal die Returntypen von Funktionen ala strcmp bzw. std::basic_string<T>::compare an. Warum wird da z.B. kein signed char verwendet?ich verwende int wo es sinn macht und char wo es sinn macht.
Das mache ich genauso. Nur vermute ich dass wir unterschiedliche Ansichten darüber haben wo was Sinn macht.
-
hustbaer schrieb:
[...]Und eben (an anderen Stellen) hauptsächlich int (bzw. unsigned int). Und double. Weil's eben "Standard" ist.[...]
size_tist nicht "Standard" sondern Standard.
Das ist aber was ganz anderes als die float <-> double Problematik. Da gibts nicht so etwas wie einen Standard. Und Dein "Standard" ist ebenfalls nicht Standard.
Es hat sich dort aber bewährt, float zu nehmen wenn es geht, und double zu nehmen wenn man muss. In vielen Anwendungsfällen (z.B. Signalverarbeitung) hat sich gezeigt, dass die Ungenauigkeiten hinzunehmen sind. Der Zuwachs an Performance (und je nachdem auch an freiem Speicher) ist jedoch nicht zu verachten.
-
Tachyon schrieb:
In vielen Anwendungsfällen (z.B. Signalverarbeitung) hat sich gezeigt, dass die Ungenauigkeiten hinzunehmen sind. Der Zuwachs an Performance (und je nachdem auch an freiem Speicher) ist jedoch nicht zu verachten.
Dass das in vielen (peziellen) Anwendungsfällen hinnehmbar ist heißt nicht, dass es immer hinnehmbar ist. Pauschal aus vermuteten Performancevorteilen erstmal float zu nehmen und sich dann zu wundern wo denn die Rundungsfehler herkommen ist doch genau der falsche Ansatz. Vielmehr ist es doch wohl sinnvoller anfangs grundsätzlich double zu nehmen und dann erst zu zeigen dass der Performancevorteil ausreichend groß und die Rundungsfehler hinreichend gering sind, bevor man auf float umsteigt.
-
hustbaer schrieb:
Die Standard-Library hält das im Übrigen auch so, guck dir bloss mal die Returntypen von Funktionen ala strcmp bzw. std::basic_string<T>::compare an. Warum wird da z.B. kein signed char verwendet
Weil
inti.d.R. die beste Performance auf der jeweiligen Plattform bietet. Dieses Argument greift aber bei Typen für reelle Zahlen nicht, da hier das Format keine Interpretetion zulässt.Deiner Argumentation nach müsstest Du übrigens immer
long doublenehmen...
-
pumuckl schrieb:
...
Wie gesagt, dieser Argumentation nach müsste man immer
long doublenehmen.Bei der Verwendung von reellen Typen muss man sich i.d.R. ohnehin einiges an Gedanken machen. Die Epsilon-Umgebung bei Vergleichen z.B. oder der zu erwartende Exponent wegen der Denormaisierung. Einfach so double nehmen und dann glauben "passt scho" ist einfach Quark.
Ich hatte bis jetzt einmal die Situation, wo ich glaubte das die Probleme an der mangelnden Genauigkeit von float lagen. War aber nicht so. Das Problem lag immanent im verwendeten Verfahren (adpaptive Filterung/Interpolation zur dynamischen Anpassung zweier Taktraten).
-
Tachyon schrieb:
Wie gesagt, dieser Argumentation nach müsste man immer
long doublenehmen.Jein. Es geht um Erfahrungswerte. Die Erfahrung zeigt, dass die float-Ungenauigkeiten sich bereits nach wenigen Opeartionen in die 5te bis 6te Nachommastelle fortpflanzen können, nach ein paar mehr Operationen bis in die dritte. Das sind Bereiche die für die meisten Anwendungen durchaus relevant sind, so dass float eben für die meisten Anwendungen erstmal nicht ohne nähere Überprüfungen in Frage kommt.
Die Ungenauigkeiten von double spielen sich dagegen einige Stellen weiter hinten ab und ergeben auch nach vielen Rechenoperationen in normalen Anwendungsgebieten keine relevanten Fehler. Damit ist man in den meisten Anwendungsgebieten mit double auf der sicheren Seite.
Ausnahmen sind Bereiche mit hochpräzisen Messungen und numerischen Rechnungen, z.B. Simulationsprogramme in Physik und Ingenieurwissenschaften, wo sich Rundungsfehler zum Teil deutlich schneller fortpflanzen als bei einer simplen Multiplikation. Deshalb nimmt man dort auch eher long double bzw. zeigt durch hinreichend genaue Abschätzungen, dass ein double genügt. (Die Vermeidung von zu großen Rundungsfehlern bei numerischen Berechnungen ist eine Wissenschaft für sich...)
-
Gibt es denn überhaupt Performanceunterschiede?
Die FPU (Annahme: PC, auf DSPs u.ä. sieht das ganze natürlich anders aus) rechnet intern sowieso mit 80 Bit, bleibt also nur der Datentransfer. Wieviel macht das aus?
-
hustbaer schrieb:
Verwendest du dann bei Schleifen als Zählervariable auch char, wenn du weisst dass die Schleife nie mehr als 10 Durchläufe haben kann?
Ich verwende int (eigentlich intfast32_t) oder eben size_type - je nachdem ob ich die größe brauche oder nicht. für einfache schleifen eben intfast32_t und für container iterationen eben size_type des containers.
man beachte: das richtige tool für den richtigen job.
Und eben (an anderen Stellen) hauptsächlich int (bzw. unsigned int). Und double. Weil's eben "Standard" ist.
schlechte argumentation.
Die Standard-Library hält das im Übrigen auch so, guck dir bloss mal die Returntypen von Funktionen ala strcmp bzw. std::basic_string<T>::compare an. Warum wird da z.B. kein signed char verwendet?
weil das der falsche typ für den job wäre.
kannst du mir auch verraten warum?
kleiner tipp: wieviel ist -120-120 und wie gut passt das in einen signed char rein.
mal abgesehen davon dass int oder besser gesagt intfastXY_t immer der ideale typ für soetwas ist.Das mache ich genauso. Nur vermute ich dass wir unterschiedliche Ansichten darüber haben wo was Sinn macht.
nein, du verwendest das was "standard" ist.
ich kann jeden typen den ich verwende argumentieren. ich weiss warum ich hier double und dort float verwendet habe.das ist der punkt.
das heisst nicht dass man immer float nehmen soll, sondern dass man vorher oder auch nachher darüber nachdenken sollte welcher typ der passende ist. uU ist long double nötig.
was ich also sage ist: nachdenken welcher typ passt und den nehmen (uU jetzt einen nehmen und später nachdenken) aber nicht einfach typ X nehmen "weil man das halt so macht".