Hallo, einige Prozessoren haben ja Additionsbefehle, die automatisch sättigen. Das ist sehr toll bei Filter und Regelungen. Aber wie benutze ich in C eine sättigende Addition ? Mr L. Lafer
mrlaferlafer schrieb: > Aber wie benutze ich in C eine sättigende Addition ? Indem du die entsprechenden Compiler-Intrisics suchst, findest und verwendest.
> Aber wie benutze ich in C eine sättigende Addition ?
Gar nicht, schliesslich soll das C-Programm auf jedem Prozessor laufen,
nicht nur auf denjenigen, die solche Befehle kennen.
unsigned int a,b,c;
c = ( b<65535-a ? a+b : 65535 );
Wenn der Compiler das als sättigende Addition erkennt, kann er ja selbst
den passenen Befehl einbauen (ich bin sicher, daß er es nicht erkennt).
Also bleibt nur die Verwendung von asm{ } und damit ein nicht mehr
portbales Programm.
Sättigende Additiln?! Ok, MaWin ich sehe Deine mathematische Definition. Aber der Begriff ist mir neu. Woher kommt der, und wozu braucht man sowas? Ich habe schon Google bemüht, aber die Ergebnisse sind eher nicht vorhanden.
Decius schrieb: > Aber der Begriff ist mir neu. Woher kommt der, und wozu braucht man > sowas? Ist typisch für DSP-Arithmetik und Computergraphik. Wenn du Audio- und Video-Prozesse digital rechnest, dann wärs blöd, wenn beim Überlauf Vorzeichen und Wert ins Gegenteil umkippen. Clipping ist weit weniger störend. http://de.wikipedia.org/wiki/Sättigungsarithmetik
MaWin schrieb: > (ich bin sicher, daß er es nicht erkennt) Ich frage mich, woher du diese deine Sicherheit nimmst. Kann mich nicht erinnern, dass du in der Vergangenheit großartig mit Kompetenz im Compilerbau geglänzt hättest. (Ich auch nicht, aber ich würde auch nicht sowas behaupten. Ich halt's nämlich sehr wohl für möglich, dass er es erkennt.)
Man kann sowas in Compilern schon erkennen, wenn man sich die Mühe macht. Allerdings schätze auch ich die Chancen gering ein. Die dominanten Anwendungen mit saturierender Arithmetik rechnen keine Skalare, sondern gepackte Vektoren. SIMD eben (MMX, SSE, NEON usw). Und da ist im ersten Ansatz der Programmierer gefragt, nicht der C-Compiler. Um sowas sinnvoll per Compiler abzuwickeln ist die C-Sprache wenig geeignet, da brauchts eine andere Sprachdefinition. Die Intrinsics sind zwischen Architekturen natürlich notorisch unportabel, weil man stark an der verwendeten Hardware hängt. 128-Bit Vektoren auf Befehle mit 64-Bit Vektoren umzustellen stellt zwangsläufig das ganze Programm auf den Kopf. Bei den Compilern für eine bestimmte Architektur hat man dagegen gewisse Chancen, dass sich ein de-fakto Standard für die Intrinics ergibt.
MaWin schrieb: > c = ( b<65535-a ? a+b : 65535 ); > > Wenn der Compiler das als sättigende Addition erkennt, kann er ja selbst > den passenen Befehl einbauen (ich bin sicher, daß er es nicht erkennt). > > Also bleibt nur die Verwendung von asm{ } und damit ein nicht mehr > portbales Programm. Natürlich kann man das Programm trotzdem portabel gestalten. Man bastelt sich einfach ein Makro, wo per default die von dir angegebene Operation durchgeführt wird, und per #ifdef dann speziell auf diesem Compiler dann die asm-Variante stattdessen verwendet wird.
Ich bin mir nicht sicher, aber ich vermute (und ein Kollege, der nichts anderes macht, als DSP zu programmieren, hat das aus seiner Sicht bestätigt), dass der Compiler wohl wirklich nicht genug klug ist für das. Er arbeitet in diesen Fällen immer mit Intrinsics. Das hat bei mir folgende Frage aufgeworfen: Warum zum Geier gibt es eigentlich keinen "Type qualifier", so wie z.B. volatile dafür? Also z.B. saturating int x = 30000; saturating int y = 30000; ... y = x + y; Und jetzt sollte das aufgtund der qualifier eben NICHT überlaufen, sondern saturieren. Portabel könnte man das problemlos machen. Ich denke, jeder Prozi hat ein Overflow-Flag. Beim Datentyp float geht's ja auch. Jeder Prozi kann ein C-Programm laufen lassen, das floats braucht. Auch wenn er keine FPU hat. Der Compiler muss einfach wissen, ob da eine ist, und die libc muss wissen, was sie bei den entprechenden Aufrufen tun soll. Und genau so könnte man das in C/C++ machen. Wenn saturierende Arithmetik nicht unterstützt wird, muss libc halt einfach selber prüfen, ob es einen Overflow gegeben hat und entsprechend sättigen. Und wenn eine da ist, nimmt sie eben den entsprechenden Befehl, je nach DSP, für den sie kompiliert wurde. Wie es im Detail, v.a. typübergreifend gehen soll, diese Details müssten halt noch geklärt werden. Der Bedarf ist m.E. durchaus vorhanden! Wenn auch mein Kollege gerade wieder einen Gegenbeweis erbracht hat, sagen die DSP-Hersteller (resp. -Vertreter) ja dauernd, dass man Assembler heute auch im DSP nicht mehr braucht, sondern alles in C machen kann. Aber wenn man dann alles mit intrinsics machen muss, ist das ja auch nicht so sexy! Ich finde: Es ist Zeit für C++1x :-)) (nein, ernsthaft, ich sehe keinen Grund, das NICHT in den Standard einzuführen. Habe ich etwas übersehen?) Gruäss Simon
Simon Huwyler schrieb: > (nein, ernsthaft, ich sehe keinen Grund, das NICHT in den Standard > einzuführen. Habe ich etwas übersehen?) Das ging sehr wohl. Man könnte vorzeichenbehaftete Arithmetik sogar fest so definieren - immerhin war deren Verhalten bei Überlauf noch nie anderweitig definiert. ;-) Allerdings fehlt C die geeignete Notation für die erwähnte dabei wesentliche Vektorrechnung. Und da wird auch nichts mehr draus, jedenfalls nicht mit den gewohnten Operatoren, denn die Bedeutung von int a[], b[]; ... = b - a; ist bereits vorgegeben, entspricht aber nicht dem, was man bei Vektorarithmetik bräuchte.
Es gibt auch einen Artikel hier... http://www.mikrocontroller.net/articles/AVR_Arithmetik/Saturierung
Genau diese in Assembler geschriebenen Arithmetikfunktionen könnte man jetzt eben standardisieren, und voilà, jeder Prozi kann saturierend rechnen. Kostet halt etwas overhead, aber er kann's. Und mit den exakt gleichen Aufrufen kann eine libc für einen DSP nun eben dessen Harware verwenden, um das zu erreichen. Und der Compiler muss natürlich wissen, dass er nicht einfach einen ADD befehl einfügen darf, sonden einen Call zur libc machen muss. Resp. um wirklich performant zu sein (was ja bei DSP nicht sooo unwichtig ist ;-), sollte der Compiler gar nicht erst einen Aufruf machen, der nur wiederum ein ADD_SAT macht, sondern diesen selber machen. A. K. schrieb: > Allerdings fehlt C die geeignete Notation für die erwähnte dabei > wesentliche Vektorrechnung. Das ist wieder eine andere Baustelle. Klar, das könnte man sich auch schöner vorstellen. A. K. schrieb: > immerhin war deren Verhalten bei Überlauf noch nie > anderweitig definiert. ;-) echt?? Ich dachte, es sei genau definiert, wie ein Überlauf aussehen soll. Bin mir sogar recht sicher. Aus diesem Grund ist es ja auch subobtimal, in einem 32bit-System einer Funktion einen 16Bit-Wert zu übergeben (aus Sicht der Performanz, selbst wenn nur 16 Bit gebraucht werden). Denn der compiler muss dann eben das Überlaufverhalten einer 16-Bit-Variable nachbilden. Gruäss Simon
Simon Huwyler schrieb: > echt?? Ich dachte, es sei definiert, DASS es überläuft. Bin mir sogar > recht sicher. Na dann schau mal nach und zeig mit die Stelle. Wohlgemerkt: Ich schrieb ausschliesslich von Arithmetik mit Vorzeichen. Nicht grundlos.
A. K. schrieb: > Na dann schau mal nach und zeig mit die Stelle. Wohlgemerkt: Ich schrieb > ausschliesslich von Arithmetik mit Vorzeichen. Nicht grundlos. http://bytes.com/topic/c/answers/134631-signed-int-overflow Verdammt, Du hast recht! Das wusste ich nicht!
Simon Huwyler schrieb: > Warum zum Geier gibt es eigentlich keinen "Type qualifier", > so wie z.B. volatile dafür? Du meinst _Sat aus ISO/IEC DTR 18037 ? http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1275.pdf
Aus obigem Link kopiert: edit: Ups, wurde überholt, jetzt ist es der vor-vorige. :-) Interessantes Dokument, btw! Actually, the overflow behavior is always undefined, in theory even for unsigned integers. But that could never happen because the standard says that unsigned integers don't overflow at all. Wenn man dem glaubt, dann DARF laut C Standard ein Überlauf also gar nicht stattfinden, und der Compiler darf den Computer sprengen, wenn es doch passiert. Wow.... Tatsache ist aber (das habe ich a)in Büchern gelesen und b)selber ausprobiert), dass, wenn man einer Funktion einen 16-Bit-Wert übergibt (ich glaube, egal ob signed oder unsigned), dann wird auf einem 32-Bit-System in der Funktion immer zuerst auf 16-Bit gekürzt (gelesen, dass das alle Compiler machen, getestet, dass es GCC macht), um JA sicherzustellen, dass, wenn ich ihn in einen 32-Bit Wert rüberkopiere, die oberen 16Bit auch wirklich 0 sind (was einen Overhead bedeutet). Das ist also sozusagen vorauseilender Gehorsam? Der Compiler könnte auch sagen: "Selber schuld! Wenn Du mir einen 16-Bit Wert gibst, der halt doch grösser als 65535 ist (was ja passt, er hockt ja physikalisch in einer 32bit-Speicherzelle), dann ist's halt so! Schliesslich hast Du Dich nicht an die Regeln gehalten!"
Simon Huwyler schrieb: > Wenn man dem glaubt, dann DARF laut C Standard ein Überlauf also gar > nicht stattfinden, und der Compiler darf den Computer sprengen, wenn es > doch passiert. Wow.... Nö, bloss hilft es, wenn man die Originalstelle liest, nicht den von irgendwem verwursteten Kram. C99: "Acomputation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type." Das "can never overflow" besagt eben gerade, dass die Kiste nicht aufgrund von Bitknappheit platzen darf, sondern sich definiert gemäss Modulo-Arithmetik verhält und somit ein numerisch innerhalb des Wertebereichs liegendes Ergebnis liefern muss.
> Warum zum Geier gibt es eigentlich keinen "Type qualifier", > so wie z.B. volatile dafür? saturating int x = 30000; Weil du dabei ja voraussetzt, welche Grenze dein int hat, nämlich daß es ein 16 bit Wert ist damit er bei 32767 sättigt. Portiert man diesen Code auf eine Maschine mit 32 bit ints, ist deine Sättigung bei 2147483647 und dein Algorithmus wird nicht mehr wie vorgesehen funktionieren Ein int saturating at (-32768,32767) x = 30000; würde klarer sein.
A. K. schrieb: > Nö, bloss hilft es, wenn man die Originalstelle liest, nicht den von > irgendwem verwursteten Kram. Wäre hilfreich gewesen, hast recht. So gesehen mach das wiederum einen gaaaaaanz anderen Sinn. MaWin schrieb: > Weil du dabei ja voraussetzt, welche Grenze dein int hat, > nämlich daß es ein 16 bit Wert ist damit er bei 32767 sättigt. Ok. int ist auch so ziemlich das blödeste Beispiel, das ich wählen konnte. :-) Hast natürlich recht, genau DER ist ja nicht definiert, wie gross er ist. Andererseits: OHNE das "saturating" ist es ja genau gleich undefiniert. Das ist halt so 'ne Krücke in C/C++...
Simon Huwyler schrieb: > Tatsache ist aber (das habe ich a)in Büchern gelesen und b)selber > ausprobiert), dass, wenn man einer Funktion einen 16-Bit-Wert übergibt > (ich glaube, egal ob signed oder unsigned), dann wird auf einem > 32-Bit-System in der Funktion immer zuerst auf 16-Bit gekürzt Allerdings ist auch hier bei einem Parameter mit 16-Bits mit Vorzeichen nicht definiert, welcher Wert dabei herauskommt, wenn das Argument da nicht reinpasst. Es darf knallen, d.h. eine Exception auslösen, oder irgendeinen beliebigen Wert liefern. Das reale Verhalten von Compilern erlaubt keinen Schluss auf den Standard. Nur andersrum.
A. K. schrieb: > Das reale Verhalten von Compilern erlaubt keinen Schluss auf den > Standard. Nur andersrum. Das stimmt natürlich (naja, das zweite ist zumindest zu hoffen. ;-) Also eigentlich könnte man jetzt sehr frech sein, und einen Compiler so bauen, dass er signed Variablen IMMER saturiert. Und wer dann flucht, dass sein Programm merkwürdige Dinge macht, kann auf den Standard verwiesen werden. Immerhin besser als die Kiste explodieren zu lassen. ;-)
Simon Huwyler schrieb: > Also eigentlich könnte man jetzt sehr frech sein, und einen Compiler so > bauen, dass er signed Variablen IMMER saturiert. Ja. Genau das schrieb ich ja oben.
genau. :-) Also brauchen wir tatsächlich keinen neuen Standard. Cool. Und das unsigned Zeug ist ja eh bei DSP nicht zu gebrauchen. :-) Also, wer patched den GCC? ;-)
Simon Huwyler schrieb: > wenn man einer Funktion einen 16-Bit-Wert übergibt [...], dann wird > wird auf einem 32-Bit-System in der Funktion immer zuerst auf 16-Bit > gekürzt [...], um JA sicherzustellen, dass, wenn ich ihn in einen > 32-Bit Wert rüberkopiere, die oberen 16Bit auch wirklich 0 sind. > > Das ist also sozusagen vorauseilender Gehorsam? Nein. Einen 16-Bit Wert als 32-Bit Wert zu übergeben ist eine reine Optimierung, die nix mit dem Standard zu tun hat bzw. nur soweit, daß die Behandlung von Funktionsparametern durch die Implementierung, d.h. durch das ABI festgelegt wird. Das ABI wiederum wird i.d.R so gestaltet, daß es die Systemeigenheiten optimal ausnutzt anstatt zu ineffizientem Code zu führen.
Simon Huwyler schrieb: > Und das unsigned Zeug ist ja eh bei DSP nicht zu gebrauchen. :-) > > Also, wer patched den GCC? ;-) Olle Kamellen: Siehe -fno-strict-overflow oder -fwrapv Guckst du: http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fwrapv-2246 http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fstrict_002doverflow-853
Johann L. schrieb: >> Also, wer patched den GCC? ;-) > > Olle Kamellen: Siehe -fno-strict-overflow oder -fwrapv Nicht ganz. Er will ja eine Version, die bei signed stets saturiert. Das tun die beiden Varianten nicht. Die eine wirft statt dessen eine Exception, die nutzt bei signed eben die erwähnte Freiheit, die der Standard gibt.
Johann L. schrieb: > Nein. Einen 16-Bit Wert als 32-Bit Wert zu übergeben ist eine reine > Optimierung, die nix mit dem Standard zu tun hat bzw. nur soweit, daß > die Behandlung von Funktionsparametern durch die Implementierung, d.h. > durch das ABI festgelegt wird. Jaja, das weiss ich schon. Aber den "fake 16Bit-Wert", der aus von Dir genanntem Grund in einer 32-Bit Speicherzelle übergeben wird, dann wirklich auf 16 Bit zu stutzen, DAS meinte ich. Das MUSS der compiler im unsigned Fall machen, um "16-Bit-Variablen-Verhalten" zu garantieren. Und im Signed-Fall, muss er es, wie ich eben gelernt habe, theoretisch nicht machen, weil ein INT16, in dem plötzlich 800'000 drinsteht (weil's ja 32 Bit sind, ist das möglich) zu undefiniertem Verhalten führt.
Simon Huwyler schrieb: > Und im Signed-Fall, muss er es, wie ich eben gelernt habe, theoretisch > nicht machen, weil ein INT16, in dem plötzlich 800'000 drinsteht (weil's > ja 32 Bit sind, ist das möglich) zu undefiniertem Verhalten führt. Er muss nicht die unteren 16 Bits liefern, sondern kann auch etwas anderes liefern. Das heisst aber nicht zwangsläufig, dass er in dem 16-Bit Parameter einen Wert ausserhalb des zulässigen Wertebereichs deponieren darf. Dieser Aspekt wird im Standard zwar m.W. nicht ausdrücklich behandelt, aber die viralen Konsequenzen einer diesbezüglichen Freigabe sprechen dagegen. Denn das hiesse, das weiter hinten im Code eine für sich allein perfekt korrekte Rechnung, die nie selbst überlaufen kann, aufgrund vorgehender Operationen doch auf die Schnauze fallen oder sogar eine Exception werfen dürfte. Das wär dann doch etwas problematisch. Nur bei Fliesskommaarithmetik gemäss ISO 754 ist das so definiert, aber da hat man ja auch explizit NaNs eingebaut.
A. K. schrieb: > Er will ja eine Version, die bei signed stets saturiert. Das werden nur die meisten Nutzer als Pessimierung empfinden und daher nicht wollen.
Jörg Wunsch schrieb: > Das werden nur die meisten Nutzer als Pessimierung empfinden und > daher nicht wollen. Klar. Aber das ist hier ja nur ein Spiel darüber, was theoretisch ginge. Andererseits könnte man eine Maschine definieren, die sich so verhält. Da wäre dann keine Pessimierung mehr. Zwar braucht man dann getrennte Befehle für Additionen mit und ohne Vorzeichen, aber eine entsprechende Unterscheidung gibts beispielsweise bei PowerPC ohnehin schon.
Das geht ja doch recht elegant. Ich dachte schon, man müsste das in C programmieren und erst die Optimierer erkennt das, was ich machen will, und ersetzt dass dann gegen die entsprechenden Befehle. Danke schön für die vielen Antworten.
A. K. schrieb: > Andererseits könnte man eine Maschine definieren, die sich so verhält. Dann doch lieber das von Johann genannte _Sat implementieren. Hmm, grad nochmal nachgesehen: das ist nur für fixed-point vorgesehen.
Sättigungsarithmetik in den C-Standard einzuführen, halte ich nicht für sinnvoll. Überläufe in Arithmetikoperationen sind in den allermeisten Fällen Bugs, weil sich der Entwickler bei der Festlegung der Datentypen zu wenig Gedanken über die Wertebereiche gemacht hat. Sättigungsarithmetik kann zwar die negativen Effekte von Überläufen vermindern, aber fehlerhaft bleiben die Ergebnisse trotzdem. Eine entsprechende Erweiterung des Standards würde somit erst einmal nur die schlampige Programmierung fördern. Es gibt sicher Fälle, in denen auf Grund von fixen Randbedingungen Überläufe unvermeidbar sind und deswegen bewusst in Kauf genommen werden. In diesen Fällen sollte sich der Entwickler aber im Klaren darüber sein, in welchen Situationen die Überläufe wie stark auftreten, und ob eine Gegenmaßnahme wie die Sättigungsarithmetik das Problem wirklich zufriedenstellend löst. Ist dies der Fall, kann es angebracht sein sein, die Sättigung an wenigen kritischen Stellen im Programm anzuwenden. Andere Stellen, an denen kein Überlauf erwartet wird, sollten stattdessen durch Asserts abgesichert werden, um ggf. mögliche Fehleinschätzung der Wertebereiche aufzudecken. Eine Variable pauschal als sättigend zu deklarieren, käme aber aber einem Rundumschlag gleich, der möglicherweise wirkliche Programmfehler kaschiert und auf Rechnern ohne Hardwareunterstützung für die Sättigung die Pogrammlaufzeiten unnötig verlängert.
Yalu X. schrieb: > Überläufe in Arithmetikoperationen sind in den allermeisten Fällen Bugs, > weil sich der Entwickler bei der Festlegung der Datentypen zu wenig > Gedanken über die Wertebereiche gemacht hat. Helligkeitseinstellung bei Bildaten auch?
A. K. schrieb: > Yalu X. schrieb: > >> Überläufe in Arithmetikoperationen sind in den allermeisten Fällen Bugs, >> weil sich der Entwickler bei der Festlegung der Datentypen zu wenig >> Gedanken über die Wertebereiche gemacht hat. > > Helligkeitseinstellung bei Bildaten auch? ja, dort auch. das erhöhen der helligkeit / kontrastes führt dann zum verlust von information. Macht sich der entwickler mehr gedanken über wertebereiche wird eine helligkeitsgrenze erreicht, bzw der helligkeitsverlauf nichtlinnear dargestellt, bzw wertebereich erhöht -> aber mit erhalt aller informationen (reversibel).
bildbearbeitung schrieb: > ja, dort auch. das erhöhen der helligkeit / kontrastes führt dann zum > verlust von information. Ja, ist in diesem Falle aber beispielsweise einfach vom Nutzer explizit so gewollt: er dreht den Helligkeitsregler auf und nimmt damit billigend in Kauf, dass die hellen Stellen des Bilds in die Sättigung laufen (weißer wäscht keiner, auch nicht Rainer ;-), weil er vielleicht dadurch in den dunklen Bereichen sein gewünschtes Detail besser erkennen kann.
bildbearbeitung schrieb: >> Helligkeitseinstellung bei Bildaten auch? > > ja, dort auch. das erhöhen der helligkeit / kontrastes führt dann zum > verlust von information. Natürlich tut es das. Sollten deshalb die diversen Bildregler bei Fernsehern präventiv abgeschafft werden, weil sich unter den Millionen Pixeln pro Frame garantiert irgendwann eines befinden wird, dass dann aus dem Wertebereich läuft? Klar ist das Informationsverlust. Na und? Sollte ein Gerät vorsorglich den Betrieb einstellen, wenn sich doch mal ein Extremwert einstellt? Oder wärs dir nicht doch lieber, wenn die Heizung auch bei -15°C an der Kante weiter läuft, statt sämtliche Leitungen einfrieren zu lassen, auf den Software-Update wartend? Sättigungsarithmetik bei der Kontoverwaltung wär wohl problematisch. Aber es gibt beliebig viele Fälle, in denen nicht in jedem Fall alle letzten Bits von Bedeutung sind, ein gradueller Verlust an Genauigkeit einem Totalverlust oder gar einer Umkehrung der Funktion vorzuziehen ist. Was Programmier- und Konzeptfehler angeht: Obzwar es wünschenswert ist, stets und immerdar nur mit perfekten Programme zu leben, wissen wir alle, dass dies nicht realistisch ist. Da sind mir dann fehlertolerante Konzepte lieber als solche, die beim kleinsten Anlass mit assert() den Betrieb einstellen.
Yalu X. schrieb: > Überläufe in Arithmetikoperationen sind in den allermeisten Fällen Bugs, > weil sich der Entwickler bei der Festlegung der Datentypen zu wenig > Gedanken über die Wertebereiche gemacht hat. Da bin ich gar nicht einverstanden. In MANCHEN Fällen: Jup. In den MEISTEN Fällen: ..... ..... ja. In den ALLERMEISTEN Fällen: .... Rein quantitativ wohl schon. Aber es gibt halt eben eine - wohl kleine, aber doch existierende, und recht gut definierte Teilmenge von Applikationen, wo diese Aussage nicht zutrifft: Nämlich eben die DSP und (gehören ja eigentlich auch dazu) Regelungstechnik. Beispiel: Ich will einen schnellen Regler implementieren. Da kann ich durchaus - und das ist auch üblich - diesen Regler absichtlich so dimensionieren, dass er durchaus in die Sättigung gehen kann und auch soll. Und genau deswegen bieten wohl alle DSP Sättigungsarithmetik an. Wenn ich nämlich auch für die Fälle, wo er einfach VOLLGAS nach links drücken soll, garantieren will, dass JA JA JA JA NIIIIIIIIIIIIIIIIIIIIIIE ein Überlauf passiert (was katastrophal wäre, da reden wir nämlich u.U. tatsächlich von einer Explosion ;-), verschenke ich wertvolle Wertedynamik.
A. K. schrieb: > Simon Huwyler schrieb: > >> Und im Signed-Fall, muss er es, wie ich eben gelernt habe, theoretisch >> nicht machen, weil ein INT16, in dem plötzlich 800'000 drinsteht (weil's >> ja 32 Bit sind, ist das möglich) zu undefiniertem Verhalten führt. > > Er muss nicht die unteren 16 Bits liefern, sondern kann auch etwas > anderes liefern. Das heisst aber nicht zwangsläufig, dass er in dem > 16-Bit Parameter einen Wert ausserhalb des zulässigen Wertebereichs > deponieren darf. Dieser Aspekt wird im Standard zwar m.W. nicht > ausdrücklich behandelt, aber die viralen Konsequenzen einer > diesbezüglichen Freigabe sprechen dagegen. Das hat was.... also war auch die etwas pointierte Aussage oben, dass "nicht definiertes Verhalten" auch hessen kann, dass der computer explodieren darf, argumentatorisch falsch. :-)
A. K. schrieb: > Yalu X. schrieb: > >> Überläufe in Arithmetikoperationen sind in den allermeisten Fällen Bugs, >> weil sich der Entwickler bei der Festlegung der Datentypen zu wenig >> Gedanken über die Wertebereiche gemacht hat. > > Helligkeitseinstellung bei Bildaten auch? Siehe "allermeisten" und dritter Absatz in meinem obigen Beitrag. Und wieviel Prozent (oder besser Promille) aller C-Programme befassen sich mit Bildbe- bzw. -verarbeitung? Und um wieviel werden in diesen Fällen die Entwicklungszeit verringert oder die Softwarequalität ver- bessert, wenn die Programmiersprache die Stättigungsarithmetik nativ verfügbar macht? Wenn der Sprachumfang von C schon erweitert werden muss, dann besser um solche Dinge wie Interrupthandling, bei denen der Kreis der Nutznießer deutlich größer sein dürfte. Aber wie gesagt: Ich bin kein Gegner der Sättigungsarithmetik als solche, nur der C-Standard sollte damit nicht aufgebläht werden.
Yalu X. schrieb: > Und wieviel Prozent (oder besser Promille) aller C-Programme befassen > sich mit Bildbe- bzw. -verarbeitung? Bezogen auf die Menge der verarbeiteten Daten ist der Anteil mittlerweile ziemlich beträchtlich. ;-) > Aber wie gesagt: Ich bin kein Gegner der Sättigungsarithmetik als > solche, nur der C-Standard sollte damit nicht aufgebläht werden. Die _Sat Erweiterung steht in einem Zusatz, der Erweiterungen für embedded Systems vereinheitlichen soll. Zum verpflichtenden Standard wird das nicht.
A. K. schrieb: > Bezogen auf die Menge der verarbeiteten Daten ist der Anteil > mittlerweile ziemlich beträchtlich. ;-) Das ist halt alles immer eine Frage der Perspektive ;-) > Die _Sat Erweiterung steht in einem Zusatz, der Erweiterungen für > embedded Systems vereinheitlichen soll. Zum verpflichtenden Standard > wird das nicht. Deswegen ist die Welt ja noch in Ordnung :)
Ich denke natürlich auch nicht, dass man in C/C++ vorzeichenbehaftete Arithmetik ZWINGEND saturierend machen soll. Allerdings habe ich meine heutige Erkenntnis, die mich aus allen Wolken fallen liess, gleich einigen Kollegen erzählt. Die meisten wussten nicht, dass das Verhalten nicht definiert ist. Und einer hat die Augen sehr weit aufgerissen und entgegnet, dass er und auch andere häufig als "einfachen Trick" Timer mit signed Variablen implementieren und dann auf negativ testen. Und mit sowas kann man im jetztigen Status Quo ja gewaltig auf die Schnauze fallen! Aber gegen eine Erweiterung (die, wie sich herausstellt, ja eben gar nicht nötig ist. Ein ANSI-C-Compiler rechnet ja jetzt schon sättigend (irgendwo gibt es sicher einen, der das tut, und das ist dann eben durchaus ein dem Standard gehorchender ANSI-C-Compiler) - spricht ja wirklich nicht viel, weil sie ja auch nicht "teuer" wäre. Edit: Mann, diesen Satz habe ich vergeigt.... stack overflow! :-) Die Erweiterung des Standards würde ja folgendes bedeuten: WENN ich eine Variable mit "saturating" qualifiziere, dann bedeutet das, dass ich davon ausgehen DARF, dass sie sättigt. Wenn ich es nicht mache, dann KANN sie sättigen oder auch nicht. Und das ist der Status Quo, C-Standard. Sie KANN sättigen, sie KANN wieder bei 0 anfangen, sie KANN auf -max zurückfallen... Das halte ich für viel Gefährlicher. Und ich will gar nicht wissen, wieviele Programme sich darauf verlassen, dass der C-Compiler genau das tut, was er gemäss Standard tun DARF (wohl auch meistens TUT), aber nicht tun MUSS.
Simon Huwyler schrieb: > Aber gegen eine Erweiterung [...] spricht ja > wirklich nicht viel, weil sie ja auch nicht "teuer" wäre. Aber sie ist eben auch überflüssig. Zugegeben, es wäre sicherlich sinnvoller, als der Unfug von wegen _Complex und so. Aber nicht ohne Grund möchte man die Programmiersprache selbst ja knapp halten, ohne überflüssiges Zeug. Und sättigende Arithmetik kann man problemlos mit den vorhandenen Digen realisieren. Praktisch teilt sich das Feld aber wohl in zwei Hälften: Die einen brauchen ganz wenig sättigende Arithmetik. Kann man also bequem selbst programmieren. Die anderen betreiben intensiv DSP und brauchen jeden Menge davon. Die wollen dann aber meistens auch gleich Vektoroperationen (SSE, MMX und so weiteR), also erübrigt sich die Plattformunabhägigkeit schon wieder. Unterm Strich wäre sättigende Arithmetik also m.M.n. etwas, das wunderbar in eine Programmbibliothek gehört. > Das halte ich für viel Gefährlicher. Und ich will gar nicht wissen, > wieviele Programme sich darauf verlassen, dass der C-Compiler genau das > tut, was er gemäss Standard tun DARF (wohl auch meistens TUT), aber > nicht tun MUSS. Tja.
Sven P. schrieb: > Unterm Strich wäre sättigende Arithmetik also m.M.n. etwas, das > wunderbar in eine Programmbibliothek gehört. Und wenn man dafür C++ verwendet, dann merkt es ausserdem keiner.
Sven P. schrieb: > Unterm Strich wäre sättigende Arithmetik also m.M.n. etwas, das > wunderbar in eine Programmbibliothek gehört. A. K. schrieb: > Und wenn man dafür C++ verwendet, dann merkt es ausserdem keiner. Grundsätzlich bin ich mit Euch einverstanden. Es war ja auch nur so'ne Idee. Aber einfach mit einer Bibliothek kann man das Ziel schon nicht wirklich erreichen. Denn wir wollen ja Performant sein, d.h. wir wollen eben keinen Bibliotheksaufruf, sondern, dass der Compiler quasi alle "ADD" Befehle durch "ADDSAT"-Befehle ersetzt etc. Aber eben: Ich gebe Euch recht. Ach ja, und noch was: Viele DSPs haben für sättigend und nicht sättigend eh keine unterschiedlichen Befehle, sondern die ALU wird entsprechend konfiguriert. Da würde es also ein abgeändertes crt0 tun. Ich dachte halt, dass das gegen alle Religionen verstösst, aber jetzt weiss ich ja sogar, dass das absolut regelkonform ist. :-) Edit: Ups, nein, eben NICHT, er darf es ja nur bei signed Typen machen! Grrr.... :-) Hey, ich habe heute gewaltig was gelernt!
Simon Huwyler schrieb: > (nein, ernsthaft, ich sehe keinen Grund, das NICHT in den Standard > einzuführen. Habe ich etwas übersehen?) Was ist mit Maschinen die das nicht unterstützen ? Gibt es für keine konformen C-Compiler mehr ?
Simon Huwyler schrieb: > Denn wir wollen ja Performant sein, d.h. wir wollen > eben keinen Bibliotheksaufruf, sondern, dass der Compiler quasi alle > "ADD" Befehle durch "ADDSAT"-Befehle ersetzt etc. Es hat ja niemand gefordert, dass es bei der Bibliothek um Funktionsaufrufe gehen muss. Könnte ja auch eine Makrobibliothek sein oder schlicht Inline-Funktionen. Genaugenommen ist beim GCC zum Beispiel eine komplette Fließkommarecheneinheit in Makros realisiert, für Prozessoren, die keine Hardware dafür haben.
Yalu X. schrieb: > Überläufe in Arithmetikoperationen sind in den allermeisten Fällen Bugs, > weil sich der Entwickler bei der Festlegung der Datentypen zu wenig > Gedanken über die Wertebereiche gemacht hat. Wenn dadurch der Akku von meinen mobilen Device länger läuft, solls mir recht sein.
Simon Huwyler schrieb: > dass der Compiler quasi alle "ADD" Befehle durch "ADDSAT"-Befehle ersetzt etc. Was bedeutet hier "quasi" ? Kannst du das genauer beschreiben ? Was ist mit dazugelinkten Funktionen ?
D++ schrieb: > Simon Huwyler schrieb: >> (nein, ernsthaft, ich sehe keinen Grund, das NICHT in den Standard >> einzuführen. Habe ich etwas übersehen?) > > Was ist mit Maschinen die das nicht unterstützen ? Gibt es für keine > konformen C-Compiler mehr ? Es gibt ja auch Compiler für Prozessoren, die keine 32-Bit-Arithmetik unterstützen, oder z.B. Floating-Point, obwohl die Sprache entsprechende Datentypen zwingend voraussetzt. Das wird halt auf solchen Prozessoren emuliert.
A. K. schrieb: > Natürlich tut es das. Sollten deshalb die diversen Bildregler bei > Fernsehern präventiv abgeschafft werden, weil sich unter den Millionen > Pixeln pro Frame garantiert irgendwann eines befinden wird, dass dann > aus dem Wertebereich läuft? Klar ist das Informationsverlust. Na und? > > Sollte ein Gerät vorsorglich den Betrieb einstellen, wenn sich doch mal > ein Extremwert einstellt? Oder wärs dir nicht doch lieber, wenn die > Heizung auch bei -15°C an der Kante weiter läuft, statt sämtliche > Leitungen einfrieren zu lassen, auf den Software-Update wartend? In der Natur gibt es keine unendliche Dynamik.
D++ schrieb: > Simon Huwyler schrieb: >> (nein, ernsthaft, ich sehe keinen Grund, das NICHT in den Standard >> einzuführen. Habe ich etwas übersehen?) > > Was ist mit Maschinen die das nicht unterstützen ? Gibt es für keine > konformen C-Compiler mehr ? Gegenfrage: Können nur Prozessoren mit einer FPU floating point Zahlen verwenden? ;-) Wenn man saturating WILL, und das HW-mässig nicht unterstützt wird, muss es eben durch SW (sprich: libc) gerechnet werden. Sven P. schrieb: > Es hat ja niemand gefordert, dass es bei der Bibliothek um > Funktionsaufrufe gehen muss. Könnte ja auch eine Makrobibliothek sein > oder schlicht Inline-Funktionen. Hast schon recht. Aber ich sehe - nein, sähe - das halt wirklich sehr ähnlich wie mit mit floating point. Da muss ja auch dem Compiler gesagt werden, ob er eine FPU zur Verfügung hat. Zumindest im GCC ist das so, oder? Aber eben: So genau kenne ich mich mit diesem Mechanismus nicht aus. Ach, sehe gerade: Sven P. schrieb: > Genaugenommen ist beim GCC zum Beispiel eine komplette > Fließkommarecheneinheit in Makros realisiert, für Prozessoren, die keine > Hardware dafür haben. > Ok, das ist dann alles in Makros programmiert? Wusste ich nicht. D++ schrieb: > Simon Huwyler schrieb: >> dass der Compiler quasi alle "ADD" Befehle durch "ADDSAT"-Befehle ersetzt etc. > > Was bedeutet hier "quasi" ? Kannst du das genauer beschreiben ? Was ist > mit dazugelinkten Funktionen ? Mit denen ist's genau gleich, wie mit Floating point. Klar, libraries müssen entsprechend kompiliert sein. Aber eben: Du wirst auch nie eine Library zum laufen bringen, die für 'nen Prozi mit FPU compiliert wurde, wenn Du keine FPU hast. Das ist also sicher kein Argument.
Rolf Magnus schrieb: > Es gibt ja auch Compiler für Prozessoren, die keine 32-Bit-Arithmetik > unterstützen, oder z.B. Floating-Point, obwohl die Sprache entsprechende > Datentypen zwingend voraussetzt. Das wird halt auf solchen Prozessoren > emuliert. Aber C hat einen Typ dafür, und Regeln für die Konvertirung von Typen.
Ja, eben, das war ja die Frage, ob man das einführen könnte. Einen Typ, resp. eher einen qualifier, der die entsprechenden Regeln definiert. Warum sollte das dann bei Prozis ohne Saturation nicht mehr funktionieren?
D++ schrieb: > In der Natur gibt es keine unendliche Dynamik. Richtig. Aber was willst Du damit sagen? Es geht nicht um unendliche Dynamik, sondern darum, dass es in vielen Bereichen viel wichtiger ist, in 80% der Fälle seinen Wertebereich sinnvoll zu nutzen, als in den 0.00001% der Fälle, in denen der Wert extrem wird, den auch noch korrekt und ohne Informationsverlust abbilden zu können. Und genau deswegen wurde sättigende Arithmetik erfunden. Nicht als Schadensbegrenzung bei dummen/faulen Programmierern. Natürlich kann man auf andere Weise aufpassen, dass solche katastrophalen Dinge bei einem Überlauf nicht passieren. Genau durch zwei Massnahmen: 1) Overflows selber abfangenn. --> teuer, kostet Zyklen. Viele Zyklen. 2) Wertebereich anpassen, so dass sie nicht auftreten können. (NIE NIE NIE!) --> kostet Dynamik des Wertebereichs. u.U. sehr viel davon..
Simon Huwyler schrieb: > Sven P. schrieb: >> Genaugenommen ist beim GCC zum Beispiel eine komplette >> Fließkommarecheneinheit in Makros realisiert, für Prozessoren, >> die keine Hardware dafür haben. > > Ok, das ist dann alles in Makros programmiert? Wusste ich nicht. Vergiss es. Das ist Käse.
D++ schrieb: > Simon Huwyler schrieb: >> (nein, ernsthaft, ich sehe keinen Grund, das NICHT in den Standard >> einzuführen. Habe ich etwas übersehen?) > > Was ist mit Maschinen die das nicht unterstützen ? Gibt es für keine > konformen C-Compiler mehr ? D++ schrieb: > Rolf Magnus schrieb: >> Es gibt ja auch Compiler für Prozessoren, die keine 32-Bit-Arithmetik >> unterstützen, oder z.B. Floating-Point, obwohl die Sprache entsprechende >> Datentypen zwingend voraussetzt. Das wird halt auf solchen Prozessoren >> emuliert. > > Aber C hat einen Typ dafür, und Regeln für die Konvertirung von Typen. Irgendwie diskutierst du im Kreis rum. Wenn man Regeln für saturierende Arithmetik in C definieren würde, hätte es die auch, womit wir wieder am Anfang wären. Ich zitiere mal zur Referenz nochmal alle relevanten Teile der Diskussion.
Johann L. schrieb: > Simon Huwyler schrieb: >> Sven P. schrieb: > >>> Genaugenommen ist beim GCC zum Beispiel eine komplette >>> Fließkommarecheneinheit in Makros realisiert, für Prozessoren, >>> die keine Hardware dafür haben. >> >> Ok, das ist dann alles in Makros programmiert? Wusste ich nicht. > > Vergiss es. Das ist Käse. Dann schau doch z.B. in der glibc-Version 2.7 ins soft-fp-Verzeichnis. Gut, das beschränkt sich erstmal auf arithmetische Funktionen (+-*/) und die Wurzel, der Rest ist dann schon in Funktionen verpackt. Die Bitpfriemelei ist (oder war) zumindest wirklich in Makros gepackt.
Die glibc ist Teil von GCC? Aha. Das ist mir bislang entgangen.
Sven P. schrieb: > Dann schau doch z.B. in der glibc-Version 2.7 ins soft-fp-Verzeichnis. > Gut, das beschränkt sich erstmal auf arithmetische Funktionen (+-*/) und > die Wurzel, der Rest ist dann schon in Funktionen verpackt. Die Funktionen für die Grundrechenarten verwenden zwar intensiv Makros, sind aber selbst normale C-Funktionen (z.B. __adddf3 für die Double-Addition). Das geht auch gar nicht anders, weil man den Compiler m.W. nicht dazu bringen kann, bei dem Ausdruck x+y automatisch ein Makro (z.B ADDDF(x,y)) anstelle von einer Funktion anzuwenden. Und selbst wenn das ginge, hätte man die üblichen Probleme von Makroexpansionen.
Yalu X. schrieb: > Das geht auch gar nicht anders, weil man den Compiler > m.W. nicht dazu bringen kann, bei dem Ausdruck x+y automatisch ein Makro > (z.B ADDDF(x,y)) anstelle von einer Funktion anzuwenden. (das geht jetzt nicht an Dich, Yalu, ist mir klar, dass Dir das klar ist) Ausser natürlich, der Compiler "weiss" selber, dass er eben keinen Library-Aufruf machen muss, sondern direkt Maschinenbefehle verwenden kann. GCC kann man deshalb per Parameter dazu bewegen, hard-float oder soft-float zu verwenden. Und bei soft-float macht er dann eben den entsprechenden Library call, während er bei hard-float direkt mit der FPU schwatzt. Deswegen meinte ich ja eben, dass die Argumentation, man könne die Verwendung nativ saturierender Arithmetik alleine mit Bibliotheken realisieren, falsch ist. Denn ein Compiler wird sicher nie dafür: int x = 12; int y = 34; y = x + y; eine Bibliotheksfunktion aufrufen. (Bitte jetzt nicht argumentieren, dass der Compiler hier y einfach mit 46 initialisiert, was natürlich wohl stimmt, wenn er optimiert ;-) D.h. selbst WENN man den Overhead des Library calls in Kauf nähme (was man sicher nicht täte), hätte man keine Möglichkeit, den ADD-Aufruf entsprechend "umzubiegen".
Yalu X. schrieb: > Die Funktionen für die Grundrechenarten verwenden zwar intensiv > Makros, sind aber selbst normale C-Funktionen (z.B. __adddf3 für die > Double-Addition). Ja sicher. Ich wollte damit nur nahelegen, dass man sowas durchaus auch als Makrobibliothek machen kann. Der Schritt dahin ist ja wirklich nur noch winzig. > Das geht auch gar nicht anders, weil man den Compiler > m.W. nicht dazu bringen kann, bei dem Ausdruck x+y automatisch ein Makro > (z.B ADDDF(x,y)) anstelle von einer Funktion anzuwenden. Und selbst > wenn das ginge, hätte man die üblichen Probleme von Makroexpansionen. Das weiß ich nicht, ich kenne die Interna des GCC nicht allzu genau. Aber bei deisen Fließkomma-Funktionen geht es ja auch nicht darum, sie etwa mit Operatorüberladung oder sonstwie einzubauen. Der ganze Kram da ist ja nur Ersatz für Compiler-Intrinsics, insofern wird der Compiler selbst sich da schon entsprechend bedienen. Johann: Ich würde schon sagen, dass die C-Bibliothek zum Compilersatz gehört. Siehst du doch auch eigentlich gleich: Die Soft-FP-Implementierung ist wohl kaum für den Endbenutzer gedacht. Auch solche Dinge wie longjmp.h oder stdint.h lassen sich kaum vom Compiler trennen.
Simon Huwyler schrieb: > Deswegen meinte ich ja eben, dass die Argumentation, man könne die > Verwendung nativ saturierender Arithmetik alleine mit Bibliotheken > realisieren, falsch ist. Denn ein Compiler wird sicher nie dafür: > > int x = 12; > int y = 34; > y = x + y; > > eine Bibliotheksfunktion aufrufen. Dafür nicht. Aber zum Beispiel dafür:
1 | class satint { |
2 | ...
|
3 | satint operator+(satint other) { ... } |
4 | }
|
5 | |
6 | satint x = 12; |
7 | satint y = 34; |
8 | y = x + y; |
Das wäre dann so eine Bibliothek, die ich mir vorstellen könnte. Ist so natürlich nicht nativ. Nativ wäre dann aber mitunter die Implementierung von operator+(). Und wenn der Compiler das dann als inline übersetzt, hast du deine echte sättigende Arithmetik.
Sven P. schrieb: > Dafür nicht. Aber zum Beispiel dafür: Wenn die Methoden inline sind und nur mit Konstanten beschickt werden, dann faltet er das genauso zu einer abschliessenden Konstanten zusammen. Der ARM Compiler berechnet auch Intrinsics mit Konstanten selber, wie beispielsweise __builtin_clz (count leading zeroes). Das hatte mich dann doch etwas überrascht.
Sven P. schrieb: > Ist so > natürlich nicht nativ. Richtig. Aber darum geht es ja. Dass man es nicht-nativ in einer Bibliothek zur Verfügung stellen kann, ist ja klar. Sven P. schrieb: > Aber bei deisen Fließkomma-Funktionen geht es ja auch nicht darum, sie > etwa mit Operatorüberladung oder sonstwie einzubauen. Eben! FPU-Nutzung kann man sogar alleine durch Anpassen der Bibliothek erreichen. Mit dem Nachteil, dass es halt immer einen zusätzlichen Call gibt in eine Bibliotheksfunktion, die dann wiederum nur einen Maschinbefehl ausführt. (Ich gehe hier davon aus, dass bei floats-Ops IMMER die Bibliothek zu Hilfe genommen wird. Vielleicht ist das nicht mal so, weiss nicht...) Und dennoch hat man sich entschieden, dem GCC dafür einen Parameter zu spendieren. Wenn man aber zwei integers hat, wird kein Compiler der Welt einer Bibliothek die Chance geben, diese Addition "umzubiegen". Weil es der Compiler eben selber kann und keine Bibliothek benötigt. Edit: Ok, sehe gerade: Mit oben genanntem Nachteil könnnte man das mit Operator Overloading tatsächlich machen, hast recht, Sven. Aber eben: Dieser Nachteil ist in einer Reglerschlaufe frappant. Bei jeder Addition wird dann ein Bibliotheksaufruf gemacht, der dann einen einzelnen Befehl ausführt. Und der EINZIGE Zweck der nativen Nutzung saturierender Arithmetik, wäre ja Performanz in den Fällen, wo diese Art der Arithmetik eben gewünscht wird, Resp. zu verhindern, dass man mit intrinsics etc. arbeiten muss, weil eben Performanz wichtig ist. und leider geht sat. Arith. halt allermeistens mit hohen Performanzanforderungen einher (DSP). Sven P. schrieb: > insofern wird der Compiler > selbst sich da schon entsprechend bedienen. Aber man muss ihm eben beibringen: - Dass es etwas gibt, das sich saturierende Arithmetik schimpft - Dass er dazu eben nicht die Maschinenbefehle ADD, SUB etc. verwenden darf, sondern eben andere. Mit einer Bibliothek alleine ist das unmöglich.
A. K. schrieb: > Wenn die Methoden inline sind Hmmmmmm............ moment mal.........Wenn man eine Klasse (satuating_int oder so) definiert, und deren Operationen alle inline definiert... Dann sollte das vielleicht sogar gehen, oder? Ist das realistisch, dass der Comiler dann den ganzen Plunder auf einen einzelnen ADDSAT oder dergleichen runterbricht? Dass also: x = x + y; übersetzt wird in ADDSAT x,y
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.