Discussion:
Syntax: Wahl der Zahlenbasis
(zu alt für eine Antwort)
Helmut Schellong
2016-08-24 12:29:45 UTC
Permalink
Hallo,

ich bin der Meinung, der nächste C-Standard sollte mal einführen:

0o37745 für Oktal
0d10011 für Dual

Oktal per führender 0 ist für viele Programmierer eine Falle.
Und es ist nicht systematisch, wie es gemeinsam mit 0xFFA
und 0o377 sein könnte.

0d10011 wäre sinnvoll, weil man es in manchen Bereichen
massenweise braucht.
Ich habe da schon Makros zusammengefrickelt...

Solch eine Einführung wäre konfliktfrei.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Claus Reibenstein
2016-08-24 13:04:48 UTC
Permalink
Post by Helmut Schellong
0o37745 für Oktal
Das dürfte massive Probleme mit existierendem Quellcode geben. Außerdem
finde ich das schlecht lesbar.
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
Kommt darauf an, was Du unter "viele" verstehst. Alle mir bekannten
C-Programmierer hatten damit nie ein Problem, und ich wüsste auch nicht,
was daran problematisch sein soll.
Post by Helmut Schellong
Und es ist nicht systematisch, wie es gemeinsam mit 0xFFA
und 0o377 sein könnte.
Was ist denn daran Deiner Meinung nach "nicht systematisch"?
Post by Helmut Schellong
0d10011 wäre sinnvoll, weil man es in manchen Bereichen
massenweise braucht.
Wobei vermutlich "viele" Programmierer damit ein Problem haben dürften,
weil "viele" Programmierer mit "d" eher Dezimal als Dual assoziieren
dürften. "0b" wäre da sinnvoller.
Post by Helmut Schellong
Solch eine Einführung wäre konfliktfrei.
Nein, wäre sie nicht, wie ich eingangs schon dargelegt habe.

Gruß
Claus
Helmut Schellong
2016-08-24 13:42:25 UTC
Permalink
Post by Claus Reibenstein
Post by Helmut Schellong
0o37745 für Oktal
Das dürfte massive Probleme mit existierendem Quellcode geben. Außerdem
finde ich das schlecht lesbar.
Wieso das denn?
Du verstehst offenbar alles falsch.
Ich schrieb nicht, daß die alte Form verschwinden soll!

Ein großes 0O377 wäre schwer lesbar, 0o377 jedoch nicht.
Post by Claus Reibenstein
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
Kommt darauf an, was Du unter "viele" verstehst. Alle mir bekannten
C-Programmierer hatten damit nie ein Problem, und ich wüsste auch nicht,
was daran problematisch sein soll.
Auch ich habe kein Problem damit, andere, weniger professionelle schon.
Post by Claus Reibenstein
Post by Helmut Schellong
Und es ist nicht systematisch, wie es gemeinsam mit 0xFFA
und 0o377 sein könnte.
Was ist denn daran Deiner Meinung nach "nicht systematisch"?
'0x' besteht aus einer Null und einem Buchstaben.
'0' besteht aus einer Null und - nichts weiter.
Wo ist denn da das Systematische?
Post by Claus Reibenstein
Post by Helmut Schellong
0d10011 wäre sinnvoll, weil man es in manchen Bereichen
massenweise braucht.
Wobei vermutlich "viele" Programmierer damit ein Problem haben dürften,
weil "viele" Programmierer mit "d" eher Dezimal als Dual assoziieren
dürften. "0b" wäre da sinnvoller.
Dezimal ist bisher Default.
Und Dezimal hat keine Base-Syntax.
Wer kommt denn darauf, daß '0d' nun erforderlich ist, um dezimal
zu notieren, oder daß beides gilt?

Das 'b' in '0b' heißt 'Bit'.
Das fällt leider aus dem System: dezimal, hex, dual, oktal, ...
Post by Claus Reibenstein
Post by Helmut Schellong
Solch eine Einführung wäre konfliktfrei.
Nein, wäre sie nicht, wie ich eingangs schon dargelegt habe.
Du verstehst offenbar alles falsch.
Die alte Syntax muß bestehen bleiben.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
David Seppi
2016-08-24 14:42:42 UTC
Permalink
Post by Helmut Schellong
Ich schrieb nicht, daß die alte Form verschwinden soll!
Dann verstehe ich nicht, was Du mit ...
Post by Helmut Schellong
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
... gemeint hast. Die "Falle" (jemand schreibt 042, meint damit aber
dezimal 42, nicht dezimal 34) bestünde dann ja weiterhin.

[0d0101 für Binärzahlen]
Post by Helmut Schellong
Post by Helmut Schellong
Solch eine Einführung wäre konfliktfrei.
d ist bereits ein Trenner zwischen Mantisse und Exponenten
bei Gleitkommazahlen.
--
David Seppi
1220 Wien
Claus Reibenstein
2016-08-24 15:00:22 UTC
Permalink
Post by David Seppi
d ist bereits ein Trenner zwischen Mantisse und Exponenten
bei Gleitkommazahlen.
In C?

Gruß
Claus
David Seppi
2016-08-24 22:46:50 UTC
Permalink
Post by David Seppi
d ist bereits ein Trenner zwischen Mantisse und Exponenten
bei Gleitkommazahlen.
In C?
*örgs*, das war ja in Fortran. Danke für die Korrektur.
--
David Seppi
1220 Wien
Helmut Schellong
2016-08-24 19:16:39 UTC
Permalink
Post by David Seppi
Post by Helmut Schellong
Ich schrieb nicht, daß die alte Form verschwinden soll!
Dann verstehe ich nicht, was Du mit ...
Post by Helmut Schellong
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
... gemeint hast. Die "Falle" (jemand schreibt 042, meint damit aber
dezimal 42, nicht dezimal 34) bestünde dann ja weiterhin.
Nein, wer sich unsicher wähnt, kann die neue Syntax verwenden.
Post by David Seppi
[0d0101 für Binärzahlen]
Post by Helmut Schellong
Post by Helmut Schellong
Solch eine Einführung wäre konfliktfrei.
d ist bereits ein Trenner zwischen Mantisse und Exponenten
bei Gleitkommazahlen.
In C gibt es solche Darstellungen nicht.
12.3e-6
0X1P-23F
Vorstehend eine Gleitkommazahl in Hex-Darstellung.
Es gibt nur pP für den Exponenten anstelle von eE.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
David Seppi
2016-08-24 22:48:03 UTC
Permalink
Post by Helmut Schellong
Post by David Seppi
Post by Helmut Schellong
Ich schrieb nicht, daß die alte Form verschwinden soll!
Dann verstehe ich nicht, was Du mit ...
Post by Helmut Schellong
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
... gemeint hast. Die "Falle" (jemand schreibt 042, meint damit aber
dezimal 42, nicht dezimal 34) bestünde dann ja weiterhin.
Nein, wer sich unsicher wähnt, kann die neue Syntax verwenden.
Wer sich unsicher wähnt, der hat selten das Problem.
Sowas taucht ja eher bei Leuten auf, die nicht wissen, daß 042 *keine*
gültige Dezimalschreibweise ist.
--
David Seppi
1220 Wien
Claus Reibenstein
2016-08-24 15:12:58 UTC
Permalink
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
0o37745 für Oktal
Das dürfte massive Probleme mit existierendem Quellcode geben. Außerdem
finde ich das schlecht lesbar.
Wieso das denn?
Du verstehst offenbar alles falsch.
Ich schrieb nicht, daß die alte Form verschwinden soll!
Also ändert die Einführung nichts an der Falle. Wozu soll sie dann gut
sein? Was gewinnen wir dadurch?

Im Übrigen ist die C-Schreibweise von oktalen Zahlen seit ca. 45 Jahren
definiert und auch in anderen Sprachen gebräuchlich (Java z.B.). Ich
habe noch nie gehört, dass irgendjemand damit Probleme hätte. Du bist
der erste.
Post by Helmut Schellong
Ein großes 0O377 wäre schwer lesbar, 0o377 jedoch nicht.
Ich finde beides schlecht lesbar und noch dazu überflüssig.
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
Kommt darauf an, was Du unter "viele" verstehst. Alle mir bekannten
C-Programmierer hatten damit nie ein Problem, und ich wüsste auch nicht,
was daran problematisch sein soll.
Auch ich habe kein Problem damit, andere, weniger professionelle schon.
Dann sollen sie es lernen. Wer ein Werkzeug benutzen möchte, sollte
wissen, wie er damit umzugehen hat.
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Und es ist nicht systematisch, wie es gemeinsam mit 0xFFA
und 0o377 sein könnte.
Was ist denn daran Deiner Meinung nach "nicht systematisch"?
'0x' besteht aus einer Null und einem Buchstaben.
'0' besteht aus einer Null und - nichts weiter.
Wo ist denn da das Systematische?
0 gefolgt von einer der Ziffern 0-7 --> oktal
0 gefolgt von x oder X --> hexadezimal

Für mich ist das systematisch genug, und für andere auch.
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
0d10011 wäre sinnvoll, weil man es in manchen Bereichen
massenweise braucht.
Wobei vermutlich "viele" Programmierer damit ein Problem haben dürften,
weil "viele" Programmierer mit "d" eher Dezimal als Dual assoziieren
dürften. "0b" wäre da sinnvoller.
Dezimal ist bisher Default.
Und Dezimal hat keine Base-Syntax.
Wer kommt denn darauf, daß '0d' nun erforderlich ist, um dezimal
zu notieren, oder daß beides gilt?
Wer kommt denn darauf, dass '0o' nun erforderlich ist, um oktal zu
notieren, oder dass beides gilt?
Post by Helmut Schellong
Das 'b' in '0b' heißt 'Bit'.
Das 'b' in '0b' heißt 'Binär'.
Post by Helmut Schellong
Das fällt leider aus dem System: dezimal, hex, dual, oktal, ...
Finde ich nicht: dezimal, hex, binär, oktal, ...
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Solch eine Einführung wäre konfliktfrei.
Nein, wäre sie nicht, wie ich eingangs schon dargelegt habe.
Du verstehst offenbar alles falsch.
Die alte Syntax muß bestehen bleiben.
Womit nichts gewonnen ist.

Gruß
Claus
Helmut Schellong
2016-08-24 19:37:11 UTC
Permalink
Post by Claus Reibenstein
Post by Helmut Schellong
Ich schrieb nicht, daß die alte Form verschwinden soll!
Also ändert die Einführung nichts an der Falle. Wozu soll sie dann gut
sein? Was gewinnen wir dadurch?
Daß man eine neue, alternative Syntax verwenden kann, die für viele
sicherer und 'angenehmer' ist.
Post by Claus Reibenstein
Ich
habe noch nie gehört, dass irgendjemand damit Probleme hätte. Du bist
der erste.
Ich schrieb, daß ich keine Probleme damit habe.
Aber andere.

[...]
Post by Claus Reibenstein
Post by Helmut Schellong
'0x' besteht aus einer Null und einem Buchstaben.
'0' besteht aus einer Null und - nichts weiter.
Wo ist denn da das Systematische?
0 gefolgt von einer der Ziffern 0-7 --> oktal
0 gefolgt von x oder X --> hexadezimal
Für mich ist das systematisch genug, und für andere auch.
Es ist definitiv nicht systematisch.

[...]
Post by Claus Reibenstein
Post by Helmut Schellong
Dezimal ist bisher Default.
Und Dezimal hat keine Base-Syntax.
Wer kommt denn darauf, daß '0d' nun erforderlich ist, um dezimal
zu notieren, oder daß beides gilt?
Wer kommt denn darauf, dass '0o' nun erforderlich ist, um oktal zu
notieren, oder dass beides gilt?
Man muß nicht 'darauf kommen', der Standard definiert es entsprechend.
Post by Claus Reibenstein
Post by Helmut Schellong
Das 'b' in '0b' heißt 'Bit'.
Das 'b' in '0b' heißt 'Binär'.
Post by Helmut Schellong
Das fällt leider aus dem System: dezimal, hex, dual, oktal, ...
Finde ich nicht: dezimal, hex, binär, oktal, ...
Dann findest Du eindeutig falsch.
Hex ist zum Beispiel auch ein Binär-Code.
BCD-Code ebenso.
Dual-Code ist der am häufigsten verwendete Binär-Code.

Binär bedeutet, daß es zwei Komponenten gibt.
Dual(zahl) bedeutet, daß eine Komponente zwei Zustände haben kann.
Das sind grundlegende Unterschiede.
Post by Claus Reibenstein
Post by Helmut Schellong
Du verstehst offenbar alles falsch.
Die alte Syntax muß bestehen bleiben.
Womit nichts gewonnen ist.
Doch: Es kann die neue Syntax verwendet werden.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-25 08:46:37 UTC
Permalink
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Das 'b' in '0b' heißt 'Bit'.
Das 'b' in '0b' heißt 'Binär'.
Post by Helmut Schellong
Das fällt leider aus dem System: dezimal, hex, dual, oktal, ...
Finde ich nicht: dezimal, hex, binär, oktal, ...
Dann findest Du eindeutig falsch.
Hex ist zum Beispiel auch ein Binär-Code.
Solange man um so sinnfreie Terminologiefragen noch streiten kann,
scheint es ja kein großes Problem zu sein.

Ansonsten meint Wikipedia, das Pendant zu "Dualsystem" sei "Binary
number"; "dual number" ist was anderes. C++14 hat "0b1111". gcc hat
ebenfalls schon seit längerer Zeit "0b1111". Das sind mehr als genug
Gründe, dass, sofern der C-Standard Binärliterale enthalten wird, "0b"
werden wird.


Stefan
Helmut Schellong
2016-08-25 17:15:47 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Das 'b' in '0b' heißt 'Bit'.
Das 'b' in '0b' heißt 'Binär'.
Post by Helmut Schellong
Das fällt leider aus dem System: dezimal, hex, dual, oktal, ...
Finde ich nicht: dezimal, hex, binär, oktal, ...
Dann findest Du eindeutig falsch.
Hex ist zum Beispiel auch ein Binär-Code.
Solange man um so sinnfreie Terminologiefragen noch streiten kann,
scheint es ja kein großes Problem zu sein.
Es geht darum, daß Binär übergeordnet ist.
Eine Dualzahl (eine binäre Zahl) hat 2 Zustände pro Stelle.
Eine Oktalzahl (eine binäre Zahl) hat 8 Zustände pro Stelle.
Eine Hexzahl (eine binäre Zahl) hat 16 Zustände pro Stelle.
...
Binäre Operatoren mit 2 Operanden, Binärbaum, etc.

dezimal, hex, _binär_, oktal, ...
Die vorstehende Aufzählung ist falsch.

Duo, Trio, Bintett, Quartett, Sextett, Septett, Oktett.
Welches Wort gehört da nicht hin?
Post by Stefan Reuther
Ansonsten meint Wikipedia, das Pendant zu "Dualsystem" sei "Binary
number"; "dual number" ist was anderes. C++14 hat "0b1111". gcc hat
ebenfalls schon seit längerer Zeit "0b1111". Das sind mehr als genug
Gründe, dass, sofern der C-Standard Binärliterale enthalten wird, "0b"
werden wird.
Ich empfehle 'Binärcode' in Wikipedia.

'0b' sehe ich als 'bit-weise' an.
Auf gar keinen Fall als 'binär'.
Es heißt Logarithmus dualis, nicht jedoch Logarithmus binaris.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-26 09:13:33 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Das 'b' in '0b' heißt 'Bit'.
Das 'b' in '0b' heißt 'Binär'.
Post by Helmut Schellong
Das fällt leider aus dem System: dezimal, hex, dual, oktal, ...
Finde ich nicht: dezimal, hex, binär, oktal, ...
Dann findest Du eindeutig falsch.
Hex ist zum Beispiel auch ein Binär-Code.
Solange man um so sinnfreie Terminologiefragen noch streiten kann,
scheint es ja kein großes Problem zu sein.
Es geht darum, daß Binär übergeordnet ist.
[...schnipp...]
Post by Helmut Schellong
Ich empfehle 'Binärcode' in Wikipedia.
Das ist alles völlig egal, solange die Sprache, in der C definiert ist,
Englisch ist, denn im Englischen kennt man unter "dual numbers" keine
Dualzahlen (und auch im Deutschen ist "Binärzahl" gefühlt einfach
häufiger; bei Dualsystem dürften die meisten an grüne Punkte denken).

Jahrzehntelang gewachsene Terminologie zu korrigieren ist aussichtslos.
Du hast in der Garage vermutlich auch weder ein Ipsomobil, noch ein
Autokinet stehen.

Und davon abgesehen gibt es halt für "0b" ausreichend Präzedenzfälle.


Stefan
Helmut Schellong
2016-08-26 10:33:52 UTC
Permalink
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Es geht darum, daß Binär übergeordnet ist.
[...schnipp...]
Post by Helmut Schellong
Ich empfehle 'Binärcode' in Wikipedia.
Das ist alles völlig egal, solange die Sprache, in der C definiert ist,
Englisch ist, denn im Englischen kennt man unter "dual numbers" keine
Dualzahlen (und auch im Deutschen ist "Binärzahl" gefühlt einfach
häufiger; bei Dualsystem dürften die meisten an grüne Punkte denken).
'Dual number' ist englisch etwas ganz Anderes, nämlich 'Doppelzahl'.
Vom 'Dualsystem' schrieb ich hier auch nicht.

Mit Gefühlen kommt man hier nicht weit!

Schau bei Wikipedia 'Binärcode' mal unter 'English' nach.
Der Artikel 'Binary code' ist praktisch identisch.

Es gibt da auch 'List of binary codes' und 'Binary number':
Da steht:
=====================================================================
This is a list of some binary codes that are (or have been) used
to represent text as a sequence of binary digits "0" and "1".
..................................................................
a binary number is a number expressed in the binary numeral system
or base-2 numeral system which represents numeric values using
two different symbols: typically 0 (zero) and 1 (one).
The base-2 system is a positional notation with a radix of 2.
..................................................................
The octal numeral system, or oct for short, is the base-8 number
system, and uses the digits 0 to 7.
Octal numerals can be made from binary numerals by grouping
consecutive binary digits into groups of three
(starting from the right).
..................................................................
A numeral system (or system of numeration) is a writing system
for expressing numbers; that is, a mathematical notation
for representing numbers of a given set, using digits
or other symbols in a consistent manner.
It can be seen as the context that allows the symbols "11"
to be interpreted as the binary symbol for three, the decimal
symbol for eleven, or a symbol for other numbers in different bases.
=====================================================================

Hier wird eindeutig das beschrieben, was ich hier schon die ganze Zeit
beschreibe, was jedoch niemand zu begreifen scheint.
Offenbar hat hier niemand außer mir die Fähigkeit (oder will sie
gar nicht haben), Zusammenhänge klar analysieren zu können.

Alles, was irgendwie auf Bits mit 0 und 1 zurückführbar ist, ist
binär, ist eine Binärzahl.
Wenn nun Bits gruppiert werden, liegt eine Binärkodierung vor.
Beispielsweise bei Hexadezimal werden Ziffern und Buchstaben
Gruppen von je 4 Bit zugeordnet.
Es handelt sich um eine Binärzahl, die hexadezimal kodiert wurde.

Eine Aufzählung: dual, binär, hex, oktal, ...
ist schlicht falsch!
Eine 'binäre Binärzahl' ist unsinnig!
Eine oktal kodierte Binärzahl ist hingegen nicht unsinnig.
Post by Stefan Reuther
Jahrzehntelang gewachsene Terminologie zu korrigieren ist aussichtslos.
Das will ich gar nicht, weil die offizielle Terminologie korrekt ist.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-27 09:00:45 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Es geht darum, daß Binär übergeordnet ist.
[...schnipp...]
Post by Helmut Schellong
Ich empfehle 'Binärcode' in Wikipedia.
Das ist alles völlig egal, solange die Sprache, in der C definiert ist,
Englisch ist, denn im Englischen kennt man unter "dual numbers" keine
Dualzahlen (und auch im Deutschen ist "Binärzahl" gefühlt einfach
häufiger; bei Dualsystem dürften die meisten an grüne Punkte denken).
'Dual number' ist englisch etwas ganz Anderes, nämlich 'Doppelzahl'.
Vom 'Dualsystem' schrieb ich hier auch nicht.
Das deutsche Wort für "Dual number" ist "Duale Zahl", meint die
Wikipedia. Und damit ist mitnichten gemeint, dass die Zahl im
Zweiersystem dargestellt wird.
Post by Helmut Schellong
=====================================================================
This is a list of some binary codes that are (or have been) used
to represent text as a sequence of binary digits "0" and "1".
..................................................................
a binary number is a number expressed in the binary numeral system
or base-2 numeral system which represents numeric values using
two different symbols: typically 0 (zero) and 1 (one).
Also genau das, was man mit "0b" schreiben will.
Post by Helmut Schellong
Eine Aufzählung: dual, binär, hex, oktal, ...
ist schlicht falsch!
[...]
Post by Helmut Schellong
Das will ich gar nicht, weil die offizielle Terminologie korrekt ist.
Die "offizielle" Terminologie ist "decimal, octal, hexadecimal, binary".

integer-literal:
decimal-literal integer-suffix_opt
octal-literal integer-suffix_opt
hexadecimal-literal integer-suffix_opt
binary-literal integer-suffix_opt

Quelle: WG21 N3472 "Binary Literals in the C++ Core Language",
Bestandteil von C++14. Case closed.


Stefan
Helmut Schellong
2016-08-27 10:40:11 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
'Dual number' ist englisch etwas ganz Anderes, nämlich 'Doppelzahl'.
Vom 'Dualsystem' schrieb ich hier auch nicht.
Das deutsche Wort für "Dual number" ist "Duale Zahl", meint die
Wikipedia. Und damit ist mitnichten gemeint, dass die Zahl im
Zweiersystem dargestellt wird.
Eben, genau wie im Englischen.
Post by Stefan Reuther
Post by Helmut Schellong
=====================================================================
This is a list of some binary codes that are (or have been) used
to represent text as a sequence of binary digits "0" and "1".
..................................................................
a binary number is a number expressed in the binary numeral system
or base-2 numeral system which represents numeric values using
two different symbols: typically 0 (zero) and 1 (one).
Also genau das, was man mit "0b" schreiben will.
Ja, stimmt, was ich als 'bit-weise' deutete.
Trotzdem ist die Aufzählung:
dual, binär, hex, oktal, ...
falsch.
Post by Stefan Reuther
Post by Helmut Schellong
Das will ich gar nicht, weil die offizielle Terminologie korrekt ist.
Die "offizielle" Terminologie ist "decimal, octal, hexadecimal, binary".
decimal-literal integer-suffix_opt
octal-literal integer-suffix_opt
hexadecimal-literal integer-suffix_opt
binary-literal integer-suffix_opt
Quelle: WG21 N3472 "Binary Literals in the C++ Core Language",
Bestandteil von C++14. Case closed.
Anm.:
Alle Bestandteile dieser Aufzählung sind also 'Binary Literals'.

Du greift hier beliebig zu einer Aufzählung der Syntax
zu 'Integer-Literal'.
Das ist falsch, weil es nicht dem Gegenstand meiner Aufzählung
entspricht.
Meine Aufzählung: dual, oktal, hex
nennt ausnahmslos verschieden kodierte Binärzahlen, oder auch
Binärcodes, ohne irgendwie auf die Syntax einzugehen.
Man kann auch von verschiedenen binären Zahlensystemen
mit jeweils durch den Bezeichner bestimmter Zahlenbasis reden.
Das ist Mathematik, jedoch keine Syntax.

Wert = S_(n−1) ∗ B^(n−1) + ... + S_2 ∗ B^2 + S_1 ∗ B^1 + S_0 ∗ B^0

Mir geht es um das generelle Zahlensystem mit beliebiger Basis, wie
vorstehend.
Und um Bezeichner für Basen: log2 log10 hex oktal dual ...

404] bc
obase=200
2345^958
001 157 020 121 164 039 075 178 179 018 151 040 029 097 080 146 164\
094 077 124 018 051 183 193 002 047 118 078 091 013 050 034 102 087\
012 062 126 084 054 045 171 051 111 005 052 170 149 141 020 093 137\

Die einzelnen Stellen einer Zahl mit beliebiger Basis werden im
Kommando bc durch Dezimalzahlen dargestellt, mangels Zeichen.
Hier, bei Basis=200 durch 000 .. 199, wobei führende Nullen
keine Oktal-Zahl anzeigen.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Claus Reibenstein
2016-08-25 12:11:45 UTC
Permalink
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Ich schrieb nicht, daß die alte Form verschwinden soll!
Also ändert die Einführung nichts an der Falle. Wozu soll sie dann gut
sein? Was gewinnen wir dadurch?
Daß man eine neue, alternative Syntax verwenden kann, die für viele
sicherer und 'angenehmer' ist.
Schon wieder dieses unqualifizierte "viele". Wo nimmst Du nur die
Sicherheit her, dass es wirklich viele sind? Und was sind für Dich
überhaupt "viele"?
Post by Helmut Schellong
Post by Claus Reibenstein
Ich
habe noch nie gehört, dass irgendjemand damit Probleme hätte. Du bist
der erste.
Ich schrieb, daß ich keine Probleme damit habe.
Aber andere.
Auch das ist eine unbewiesene und durch nichts belegte Behauptung.

Wie ich schon schrieb: Du bist der erste, der von Problemen damit berichtet.
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Wo ist denn da das Systematische?
0 gefolgt von einer der Ziffern 0-7 --> oktal
0 gefolgt von x oder X --> hexadezimal
Für mich ist das systematisch genug, und für andere auch.
Es ist definitiv nicht systematisch.
Dann hast Du definitiv eine andere Definition von "systematisch" als ich.
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Wer kommt denn darauf, daß '0d' nun erforderlich ist, um dezimal
zu notieren, oder daß beides gilt?
Wer kommt denn darauf, dass '0o' nun erforderlich ist, um oktal zu
notieren, oder dass beides gilt?
Man muß nicht 'darauf kommen', der Standard definiert es entsprechend.
Das ist bei Dezimal ebenfalls der Fall.
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Das 'b' in '0b' heißt 'Bit'.
Das 'b' in '0b' heißt 'Binär'.
Post by Helmut Schellong
Das fällt leider aus dem System: dezimal, hex, dual, oktal, ...
Finde ich nicht: dezimal, hex, binär, oktal, ...
Dann findest Du eindeutig falsch.
Hex ist zum Beispiel auch ein Binär-Code.
Definitiv nicht.
Post by Helmut Schellong
BCD-Code ebenso.
Da geht es um die interne Darstellung von Dezimalzahlen. Hat mit
Binärcode nichts zu tun.
Post by Helmut Schellong
Dual-Code ist der am häufigsten verwendete Binär-Code.
Dual-Code und Binär-Code sind dasselbe.
Post by Helmut Schellong
Binär bedeutet, daß es zwei Komponenten gibt.
Kommt auf den Kontext an.
Post by Helmut Schellong
Dual(zahl) bedeutet, daß eine Komponente zwei Zustände haben kann.
Dual oder Binär sind bei Zahlen äquivalent und stehen für Zahlen zur
Basis 2, also mit Ziffern 0 und 1.
Post by Helmut Schellong
Das sind grundlegende Unterschiede.
Du konstruierst hier Unterschiede, die es nicht gibt.

Gruß
Claus
Helmut Schellong
2016-08-25 17:52:07 UTC
Permalink
Post by Claus Reibenstein
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Ich schrieb nicht, daß die alte Form verschwinden soll!
Also ändert die Einführung nichts an der Falle. Wozu soll sie dann gut
sein? Was gewinnen wir dadurch?
Daß man eine neue, alternative Syntax verwenden kann, die für viele
sicherer und 'angenehmer' ist.
Schon wieder dieses unqualifizierte "viele". Wo nimmst Du nur die
Sicherheit her, dass es wirklich viele sind? Und was sind für Dich
überhaupt "viele"?
Dir ist klar, daß 'viele' undefinierbar ist?!
Du arbeitest mit altbekannten Methoden, nämlich mit Beweisforderungen,
die gar nicht erfüllbar sind.
Post by Claus Reibenstein
Post by Helmut Schellong
Post by Claus Reibenstein
Ich
habe noch nie gehört, dass irgendjemand damit Probleme hätte. Du bist
der erste.
Ich schrieb, daß ich keine Probleme damit habe.
Aber andere.
Auch das ist eine unbewiesene und durch nichts belegte Behauptung.
Wie ich schon schrieb: Du bist der erste, der von Problemen damit berichtet.
MISRA-C
caxapa.ru/thumbs/468328/misra-c-2004.pdf
=============================================================================
Rule 7.1 (required):
Octal constants (other than zero) and octal escape sequences
shall not be used.
..................................................................
Any integer constant beginning with a “0” (zero) is treated as octal.
So there is a danger, for example, with writing fixed length constants.
For example, the following array initialisation for 3-digit bus messages
would not do as expected (052 is octal, i.e. 42 decimal):
code[1] = 109;
code[2] = 100;
code[3] = 052; /* equivalent to decimal 42 */
code[4] = 071; /* equivalent to decimal 57 */
Octal escape sequences can be problematic because the inadvertent
introduction of a decimal digit ends the octal escape and introduces
another character.
=============================================================================
Es dürften schon 'viele' gewesen sein, die Fehler wegen Oktaldarstellung
in C begangen haben.
Hexadezimal wird übrigens nicht kritisiert in MISRA-C.
Post by Claus Reibenstein
Post by Helmut Schellong
Post by Claus Reibenstein
Post by Helmut Schellong
Wo ist denn da das Systematische?
0 gefolgt von einer der Ziffern 0-7 --> oktal
0 gefolgt von x oder X --> hexadezimal
Für mich ist das systematisch genug, und für andere auch.
Es ist definitiv nicht systematisch.
Dann hast Du definitiv eine andere Definition von "systematisch" als ich.
Offensichtlich.

<0><buchstabe><zahl>

Vorstehend eine Definition.
Die Oktal-Definition in C ist hier nicht anwendbar.
Wohl aber 0x 0b 0d 0o ...

Jetzt müßtest Du begriffen haben, was systemisch ist, und was nicht.
Post by Claus Reibenstein
Post by Helmut Schellong
Dann findest Du eindeutig falsch.
Hex ist zum Beispiel auch ein Binär-Code.
Definitiv nicht.
Post by Helmut Schellong
BCD-Code ebenso.
Da geht es um die interne Darstellung von Dezimalzahlen. Hat mit
Binärcode nichts zu tun.
[usw]
Post by Claus Reibenstein
Du konstruierst hier Unterschiede, die es nicht gibt.
Schau z.B. Wikipedia 'Binärcode'.
https://de.wikipedia.org/wiki/Binärcode#Beispiele_von_Binärcodes
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-26 09:19:53 UTC
Permalink
Post by Helmut Schellong
Post by Claus Reibenstein
Wie ich schon schrieb: Du bist der erste, der von Problemen damit berichtet.
MISRA-C
caxapa.ru/thumbs/468328/misra-c-2004.pdf
=============================================================================
Octal constants (other than zero) and octal escape sequences
shall not be used.
[...]
Post by Helmut Schellong
=============================================================================
Es dürften schon 'viele' gewesen sein, die Fehler wegen Oktaldarstellung
in C begangen haben.
Es gibt Untersuchungen, die besagen, dass MISRA-Regeln gar nicht bis
positiv mit tatsächlichen Softwaredefekten korrellieren. Sprich: es
macht im besten Fall keinen Unterschied, ob man der Regel folgt, oder
die Regel macht die Software schlechter.

Um mit Oktalkonstanten auf die Nase zu fallen, muss sich jemand die Mühe
machen, Dezimalzahlen mit führenden Nullen einzugeben. Wenn nicht gerade
jemand die Ausgabe von 'date' parsen will, passiert das eher nicht.

In meiner Realität ist es da deutlich häufiger, das jemand mit einer in
Excel generierten Tabelle ankommt, die mittendrin an unerwarteten
Stellen mal eine Null stehen hat, weil Excel die Eingabe '0E32' als
Floating-Point-Zahl mit dem Wert 0 interpretiert, wenn man es nicht
explizit daran hindert, auch, wenn man sie explizit mit 'HEXINDEZ'
auswertet.


Stefan
Helmut Schellong
2016-08-26 10:53:18 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Post by Claus Reibenstein
Wie ich schon schrieb: Du bist der erste, der von Problemen damit berichtet.
MISRA-C
caxapa.ru/thumbs/468328/misra-c-2004.pdf
=============================================================================
Octal constants (other than zero) and octal escape sequences
shall not be used.
[...]
Post by Helmut Schellong
=============================================================================
Es dürften schon 'viele' gewesen sein, die Fehler wegen Oktaldarstellung
in C begangen haben.
Es gibt Untersuchungen, die besagen, dass MISRA-Regeln gar nicht bis
positiv mit tatsächlichen Softwaredefekten korrellieren. Sprich: es
macht im besten Fall keinen Unterschied, ob man der Regel folgt, oder
die Regel macht die Software schlechter.
Das stimmt, und ich bin ein Massiv-Gegner von MISRA-C.

Aber die MISRA-Regeln wurden aufgrund von real gemachten Fehlern
in signifikanter Anzahl aufgesetzt.
Und es gibt ~150 Regeln, die unterschiedlich bewertet werden müssen.

MISRA-C reduziert C auf etwa ein Drittel und zerstört damit C.

malloc, realloc, calloc, free, errno, offsetof, setjmp, longjmp,
<signal.h>, <stdio.h>, atof, atoi, atol, abort, exit, getenv, system,
<time.h>
sind z.B. verboten.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-08-26 14:07:33 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Post by Helmut Schellong
Post by Claus Reibenstein
Wie ich schon schrieb: Du bist der erste, der von Problemen damit berichtet.
MISRA-C
caxapa.ru/thumbs/468328/misra-c-2004.pdf
=============================================================================
Octal constants (other than zero) and octal escape sequences
shall not be used.
[...]
Post by Helmut Schellong
=============================================================================
Es dürften schon 'viele' gewesen sein, die Fehler wegen Oktaldarstellung
in C begangen haben.
Es gibt Untersuchungen, die besagen, dass MISRA-Regeln gar nicht bis
positiv mit tatsächlichen Softwaredefekten korrellieren. Sprich: es
macht im besten Fall keinen Unterschied, ob man der Regel folgt, oder
die Regel macht die Software schlechter.
Das stimmt, und ich bin ein Massiv-Gegner von MISRA-C.
Aber die MISRA-Regeln wurden aufgrund von real gemachten Fehlern
in signifikanter Anzahl aufgesetzt.
Das Verfahren ist unsinnig: Wenn man Leute zwingt, anstatt X Y zu tun,
weil X in der Vergangheit haeufig falsch gemacht wurde, dann werden
'Leute' in Zukunft Y anstelle von X falsch machen.
Helmut Schellong
2016-08-26 17:05:35 UTC
Permalink
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
Das stimmt, und ich bin ein Massiv-Gegner von MISRA-C.
Aber die MISRA-Regeln wurden aufgrund von real gemachten Fehlern
in signifikanter Anzahl aufgesetzt.
Das Verfahren ist unsinnig: Wenn man Leute zwingt, anstatt X Y zu tun,
weil X in der Vergangheit haeufig falsch gemacht wurde, dann werden
'Leute' in Zukunft Y anstelle von X falsch machen.
Ja, es ist sogar noch viel schlimmer.

Die Leute müssen statt X YZKLMBER__ tun, um das Verbotene
frickelnd zu ersetzen.

http://www.schellong.de/htm/beisp.html
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-27 08:51:37 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
Das stimmt, und ich bin ein Massiv-Gegner von MISRA-C.
Aber die MISRA-Regeln wurden aufgrund von real gemachten Fehlern
in signifikanter Anzahl aufgesetzt.
Das Verfahren ist unsinnig: Wenn man Leute zwingt, anstatt X Y zu tun,
weil X in der Vergangheit haeufig falsch gemacht wurde, dann werden
'Leute' in Zukunft Y anstelle von X falsch machen.
Ja, es ist sogar noch viel schlimmer.
Die Leute müssen statt X YZKLMBER__ tun, um das Verbotene
frickelnd zu ersetzen.
Diese (leider verbreitete) Herangehensweise ist einer der Gründe, warum
"wir machen jetzt MISRA" oft weder sozial akzeptiert wird, noch
technischen Gewinn bringt.

Die korrekte Herangehensweise ist "wir überlegen uns, warum genau wir X
brauchen, und dokumentieren das im deviation process". Wenn dabei
rauskommt, dass wir malloc, errno, setjmp, abort usw. benötigen, dann:
gern! Dann ist auch sichergestellt, dass verstanden wird, was passiert,
wenn der Mikrocontroller abort macht. Dass das malloc nicht nur gemacht
wird, weil der Coder zu faul war, sich von vornherein Gedanken über den
statischen Buffer zu machen.

Diese Vorgehensweise macht halt leider Arbeit und wird von den Tools
nicht sonderlich gut unterstützt.
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Hier würde ich dir im Normalfall beide "Beispiele" um die Ohren hauen.
Beim ersten Pärchen bleistiftsweise:

int idx = 0;
while ((p[idx] != '\0') && F_DIG(p[idx])) {
i = 10*i + (p[idx] - '0');
++idx;
}
return (m ? -i : i);

MISRA-konform. Ein Drittel so lang wie deine goto-Wüste.


Stefan
Helmut Schellong
2016-08-27 11:18:24 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Ja, es ist sogar noch viel schlimmer.
Die Leute müssen statt X YZKLMBER__ tun, um das Verbotene
frickelnd zu ersetzen.
Diese (leider verbreitete) Herangehensweise ist einer der Gründe, warum
"wir machen jetzt MISRA" oft weder sozial akzeptiert wird, noch
technischen Gewinn bringt.
Die korrekte Herangehensweise ist "wir überlegen uns, warum genau wir X
brauchen, und dokumentieren das im deviation process". Wenn dabei
gern! Dann ist auch sichergestellt, dass verstanden wird, was passiert,
wenn der Mikrocontroller abort macht. Dass das malloc nicht nur gemacht
wird, weil der Coder zu faul war, sich von vornherein Gedanken über den
statischen Buffer zu machen.
Dynamische Speicherverwaltung wird in vielen Programmen
unbedingt vorausgesetzt - unbedingt!

Dazu gibt es das englische Wort 'arbitrary'.
Post by Stefan Reuther
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Hier würde ich dir im Normalfall beide "Beispiele" um die Ohren hauen.
int idx = 0;
while ((p[idx] != '\0') && F_DIG(p[idx])) {
i = 10*i + (p[idx] - '0');
++idx;
}
return (m ? -i : i);
MISRA-konform. Ein Drittel so lang wie deine goto-Wüste.
Du hast nicht begriffen, worum es in dem Code überhaupt geht!

Dein Schleifenkode ist vielleicht 10-fach langsamer als mein
Originalkode.
Rate doch mal, warum ich _nicht_ die Standard-Schleife
verwendete, die Du hier nun zeigst?

Es geht darum, möglichst zu 100% einen nicht misra-konformen
Originalcode misra-konform umzuformen.
Die Statements und deren Abfolge müssen dabei gleich bleiben.

Und diese Forderung hast Du an meiner Beispielsammlung nicht erkannt!

Die von Dir gezeigte Schleife verwende ich auch vielfach.
Dort, wo ein- zweimal eine atoi-Umformung gebraucht wird.
Beispielsweise bei Regulären Ausdrücken.

Jedoch gibt es auch Code, der solche atoi-s millionenfach braucht.
Da braucht es unbedingt effizientere Lösungen.
Du gehörst auch zu denjenigen, die CPU-Power wegwerfen?
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-27 21:55:30 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Die korrekte Herangehensweise ist "wir überlegen uns, warum genau wir X
brauchen, und dokumentieren das im deviation process". Wenn dabei
gern! Dann ist auch sichergestellt, dass verstanden wird, was passiert,
wenn der Mikrocontroller abort macht. Dass das malloc nicht nur gemacht
wird, weil der Coder zu faul war, sich von vornherein Gedanken über den
statischen Buffer zu machen.
Dynamische Speicherverwaltung wird in vielen Programmen
unbedingt vorausgesetzt - unbedingt!
Dazu gibt es das englische Wort 'arbitrary'.
Ich weiß zwar nicht, was du mir damit sagen wolltest, aber: es ist
keinesfalls eine positive Eigenschaft eines Programmteils, dynamische
Speicherverwaltung zu benötigen.
Post by Helmut Schellong
Post by Stefan Reuther
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Hier würde ich dir im Normalfall beide "Beispiele" um die Ohren hauen.
int idx = 0;
while ((p[idx] != '\0') && F_DIG(p[idx])) {
i = 10*i + (p[idx] - '0');
++idx;
}
return (m ? -i : i);
MISRA-konform. Ein Drittel so lang wie deine goto-Wüste.
Du hast nicht begriffen, worum es in dem Code überhaupt geht!
Dein Schleifenkode ist vielleicht 10-fach langsamer als mein
Originalkode.
"vielleicht".

Ich kann auf die Schnelle keinen Unterschied messen, und wenn, dann ist
das eher ein subtiler Vorteil für die Schleife (300 Millionen Aufrufe:
Schleife: 2.48 Sekunden, goto-Wüste: 2.63 Sekunden; gcc 4.9.3 i386 -O2,
Core i5).
Post by Helmut Schellong
Rate doch mal, warum ich _nicht_ die Standard-Schleife
verwendete, die Du hier nun zeigst?
Weil du irgendjemandem imponieren wolltest?

Sorry, im Codereview würdest du bei mir damit trotzdem abblitzen. Es sei
denn, du kannst das "10-fach" irgendwie belegen. Dann würde ich aber
eher mal auf Fehlersuche beim Compiler gehen. Und auch dann müsste atoi
noch ein Hotspot sondersgleichen sein, dass eine Optimierung da was fürs
Gesamtsystem bringt. Dann, und nur dann, würde ich darüber nachdenken,
für Code wie diesen eine MISRA deviation auszustellen.

Ja, ich habe auch Rechenkerne optimiert. Aber an Stellen, wo es wirklich
messbar über die gesamte Systemlast was bringt. goto war dafür nicht
notwendig, nur Makros, und: ja, dafür hab ich eine MISRA deviation bekommen.
Post by Helmut Schellong
Es geht darum, möglichst zu 100% einen nicht misra-konformen
Originalcode misra-konform umzuformen.
Die Statements und deren Abfolge müssen dabei gleich bleiben.
Und diese Forderung hast Du an meiner Beispielsammlung nicht erkannt!
Das ist eine unsinnige Forderung.

Die reale Welt fordert normalerweise nicht Programme, die "Statements"
in bestimmter Reihenfolge ausführen, sondern Programme, die bei
bestimmten Eingaben bestimmte Ergebnisse liefern. Dieses Ergebnis kann
man auch mit MISRA durchaus erreichen.
Post by Helmut Schellong
Du gehörst auch zu denjenigen, die CPU-Power wegwerfen?
Ich gehöre zumindest zu denjenigen, die (durchaus aus schmerzhafter
Erfahrung) gelernt haben, dass man durchaus eine nennenswerte Menge
Hirnschmalz darein investieren sollte, Code einfach wartbar und schwer
fehlverwendbar zu machen.

"Je mehr Zeilen ein Code umfasst, desto unsicherer ist er" hast du ja
schon selbst erkannt. Die Schleife ist halt kürzer...


Stefan
Helmut Schellong
2016-08-28 08:52:43 UTC
Permalink
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Dynamische Speicherverwaltung wird in vielen Programmen
unbedingt vorausgesetzt - unbedingt!
Dazu gibt es das englische Wort 'arbitrary'.
Ich weiß zwar nicht, was du mir damit sagen wolltest, aber: es ist
keinesfalls eine positive Eigenschaft eines Programmteils, dynamische
Speicherverwaltung zu benötigen.
Richtig, eine negative jedoch auch nicht.

Software wird in professionellen Bereichen gemäß genau festgelegter
Forderungen entwickelt.
Wenn da eine Software ist, die Datenbehälter bereitstellt, die
in der Regel 0 bis 5000 Byte an Daten aufnehmen können sollen, jedoch
im Grenzfall auch 1000000000 Byte aufnehmen können sollen, wie macht
man das denn? Richtig, mit dynamischer Speicherverwaltung!

Es kann eine strikte Forderung sein, daß eine Software stets soviel
Arbeitsspeicher verwenden können soll, wie _nötig_ und _möglich_ ist.
Erst danach soll sie mit Fehlermeldung aufgeben.

[...]
Post by Stefan Reuther
Post by Helmut Schellong
Rate doch mal, warum ich _nicht_ die Standard-Schleife
verwendete, die Du hier nun zeigst?
Weil du irgendjemandem imponieren wolltest?
Nein.
Ich wollte sicherstellen, daß meine Funktionen keine Schleife
und keine Multiplikation verwenden und ohne Kompromisse
maximal schnell sind.

[...]
Post by Stefan Reuther
Post by Helmut Schellong
Es geht darum, möglichst zu 100% einen nicht misra-konformen
Originalcode misra-konform umzuformen.
Die Statements und deren Abfolge müssen dabei gleich bleiben.
Und diese Forderung hast Du an meiner Beispielsammlung nicht erkannt!
Das ist eine unsinnige Forderung.
Nein.
Offenbar kennst Du nicht die streng wissenschaftliche und saubere
Arbeitsweise von programmierenden Ingenieuren.

Eine Forderung, _bestehende_ Quellen, die nicht misra-konform sind,
umzuformen, indem alle in MISRA verbotenen Konstrukte durch erlaubte
ersetzt werden, ist absolut vernünftig und korrekt.

Hingegen einen Rückschritt zu machen und die Quellen neu zu entwickeln,
um danach auf Misra-Konformität zu prüfen, ist überhaupt nicht korrekt.
Post by Stefan Reuther
Die reale Welt fordert normalerweise nicht Programme, die "Statements"
in bestimmter Reihenfolge ausführen, sondern Programme, die bei
bestimmten Eingaben bestimmte Ergebnisse liefern. Dieses Ergebnis kann
man auch mit MISRA durchaus erreichen.
Das stimmt.
Aber in der Datei http://www.schellong.de/htm/beisp.html geht es um eine
Demonstration, die aufzeigt, wie Code aussieht, den man den MISRA-Regeln
unterworfen hat.
Es ist dabei zwingend notwendig, den Code hinsichtlich der einzelnen
Anweisungen und deren Abfolge möglichst unverändert zu belassen.
Andernfalls wäre es eine unsaubere, manipulierte Demonstration.
Post by Stefan Reuther
Post by Helmut Schellong
Du gehörst auch zu denjenigen, die CPU-Power wegwerfen?
Ich gehöre zumindest zu denjenigen, die (durchaus aus schmerzhafter
Erfahrung) gelernt haben, dass man durchaus eine nennenswerte Menge
Hirnschmalz darein investieren sollte, Code einfach wartbar und schwer
fehlverwendbar zu machen.
Dagegen kann man nichts haben.
Post by Stefan Reuther
"Je mehr Zeilen ein Code umfasst, desto unsicherer ist er" hast du ja
schon selbst erkannt. Die Schleife ist halt kürzer...
Es geht aber in der Datei um den Unterschied vorher --> nachher:
=========================================================================
Es ist eindeutig erkennbar, daß der misra-konforme Code wesentlich größer
und unübersichtlich ist. Er ist mehrfach verschachtelt und muß Code
mehrfach verwenden. Allein die drei Schlußzeilen sind ein erzwungener
Krampf. Insbesondere, wenn der Zahlenbereich von 5 auf 10 oder 19 Stellen
erweitert wird, steigt die Größe des Code überproportional an.
Die Größe ist eine Potenz der Stellenanzahl.

Hingegen der nicht-konforme Code ist wesentlich kürzer und kompakter und
garnicht verschachtelt.
Seine Größe ist stets etwa das dreifache der Stellenanzahl.
Codeteile werden nicht mehrfach verwendet und es liegt eine übersichtliche
tabellarische Ordnung vor. Zusätzlich ermöglichen die goto-Label
sprechende Label-Bezeichner.

Der misra-konforme Code ist keineswegs sicherer - nein, er ist eindeutig
unsicherer! Je mehr Zeilen ein Code umfaßt, desto unsicherer ist er.
Das ist ein absolut unerschütterlicher und bekannter Fakt.
Und misra-konformer Code ist - falls Regeln zur Wirkung kommen -
grundsätzlich größer, unübersichtlicher, umständlicher, oft fragwürdig
verkrampft, abscheulich verhunzt, bis hin zu Idiotie, und damit ganz klar
unsicherer!

Weiterhin entsteht unter anderen die Frage, wieso goto verboten werden muß?
Eine goto-Anweisung (goto A; ... A:...;) ist die primitivste Anweisung, die
es gibt.
Eine einfache Zuweisung (a=b;) ist bereits wesentlich problematischer.
=========================================================================
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-08-28 20:32:13 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Dynamische Speicherverwaltung wird in vielen Programmen
unbedingt vorausgesetzt - unbedingt!
Dazu gibt es das englische Wort 'arbitrary'.
Ich weiß zwar nicht, was du mir damit sagen wolltest, aber: es ist
keinesfalls eine positive Eigenschaft eines Programmteils, dynamische
Speicherverwaltung zu benötigen.
Richtig, eine negative jedoch auch nicht.
Kann je nach Umgebung sehr stark negativ sein.

Wenn du für deine Aufgabe nur eine bestimmte Speichermenge zur
Verfügung hast, sei es ein paar Kilobyte für ein embedded -
System oder ein paar Gigabyte auf dem Knoten deines HPC-Rechners
(oder deiner Grafikkarte...) oder damals auf dem alten MVS-System,
wo du eine harte Speicherobergrenze auf der JOB-Karte in JCL angeben
musstest und dein Job erst loslief, wenn der Hauptspeicher auch
wirklich da war...

In all diesen Fällen fährt man nicht schlecht mit einer Obergrenze
für den Speicher, den man benötigt. Dynamische Speicherverwaltung
macht das viel einfacher, so eine Obergrenze anzugeben. Unter solchen
Umständen ist dynamische Speicherverwaltung durchaus negativ zu sehen.
Thomas Koenig
2016-08-28 21:03:37 UTC
Permalink
Post by Helmut Schellong
Dynamische Speicherverwaltung
macht das viel einfacher, so eine Obergrenze anzugeben.
s/einfacher/schwieriger/
Stefan Reuther
2016-08-28 20:37:57 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Dynamische Speicherverwaltung wird in vielen Programmen
unbedingt vorausgesetzt - unbedingt!
Dazu gibt es das englische Wort 'arbitrary'.
Ich weiß zwar nicht, was du mir damit sagen wolltest, aber: es ist
keinesfalls eine positive Eigenschaft eines Programmteils, dynamische
Speicherverwaltung zu benötigen.
Richtig, eine negative jedoch auch nicht.
Doch, denn es fügt eine neue Abhängigkeit und neue Fehlermodi hinzu.
Post by Helmut Schellong
Software wird in professionellen Bereichen gemäß genau festgelegter
Forderungen entwickelt.
Wenn da eine Software ist, die Datenbehälter bereitstellt, die
in der Regel 0 bis 5000 Byte an Daten aufnehmen können sollen, jedoch
im Grenzfall auch 1000000000 Byte aufnehmen können sollen, wie macht
man das denn? Richtig, mit dynamischer Speicherverwaltung!
Oder durch Verwendung von Algorithmen, die mit konstantem Speicher
auskommen.

Nicht mehr und nicht weniger als den Schritt zurück und die Frage "kann
ich das auch anders machen als es mir intuitiv aus den Fingern fließt"
verlangt MISRA.
Post by Helmut Schellong
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Rate doch mal, warum ich _nicht_ die Standard-Schleife
verwendete, die Du hier nun zeigst?
Weil du irgendjemandem imponieren wolltest?
Nein.
Ich wollte sicherstellen, daß meine Funktionen keine Schleife
und keine Multiplikation verwenden
Das sind Ziele, auf die hat man schon vor 30 Jahren auf dem Z80 nicht
mehr optimiert, weil sie einfach keinen Sinn haben.
Post by Helmut Schellong
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Es geht darum, möglichst zu 100% einen nicht misra-konformen
Originalcode misra-konform umzuformen.
Die Statements und deren Abfolge müssen dabei gleich bleiben.
Und diese Forderung hast Du an meiner Beispielsammlung nicht erkannt!
Das ist eine unsinnige Forderung.
Nein.
Offenbar kennst Du nicht die streng wissenschaftliche und saubere
Arbeitsweise von programmierenden Ingenieuren.
Doch. Das was du beschreibst ist keine. Das ist vielleicht das, was ein
Programmierergeselle tut, aber nichts, was ein Softwareingenieur tun sollte.
Post by Helmut Schellong
Eine Forderung, _bestehende_ Quellen, die nicht misra-konform sind,
umzuformen, indem alle in MISRA verbotenen Konstrukte durch erlaubte
ersetzt werden, ist absolut vernünftig und korrekt.
Nein, denn das ist eine Forderung, die im Normalfall unsinnigen Code
erzeugt (deine Beispiele zeigen es aufs beste) und genau deswegen
abzulehnen ist.
Post by Helmut Schellong
Hingegen einen Rückschritt zu machen und die Quellen neu zu entwickeln,
um danach auf Misra-Konformität zu prüfen, ist überhaupt nicht korrekt.
Doch, natürlich. Es gibt sogar einen Begriff dafür, nennt sich dann
"Refactoring".

Und dass man damit nichts kaputtmacht, weist am Ende der Unittest nach.
Du hast doch Unittests?
Post by Helmut Schellong
Post by Stefan Reuther
Die reale Welt fordert normalerweise nicht Programme, die "Statements"
in bestimmter Reihenfolge ausführen, sondern Programme, die bei
bestimmten Eingaben bestimmte Ergebnisse liefern. Dieses Ergebnis kann
man auch mit MISRA durchaus erreichen.
Das stimmt.
Aber in der Datei http://www.schellong.de/htm/beisp.html geht es um eine
Demonstration, die aufzeigt, wie Code aussieht, den man den MISRA-Regeln
unterworfen hat.
Es ist dabei zwingend notwendig, den Code hinsichtlich der einzelnen
Anweisungen und deren Abfolge möglichst unverändert zu belassen.
Andernfalls wäre es eine unsaubere, manipulierte Demonstration.
Du demonstrierst nur, dass Unsinn dabei rauskommt, wenn man dem
Schreinergesellen sagt "nimm den Hammer und den Fuchsschwanz, mit dem du
mir eben diesen Steg gezimmert hast, und bau mir nun mit genau dem
gleichen Werkzeug und Material eine Autobahnbrücke".
Post by Helmut Schellong
Post by Stefan Reuther
"Je mehr Zeilen ein Code umfasst, desto unsicherer ist er" hast du ja
schon selbst erkannt. Die Schleife ist halt kürzer...
=========================================================================
Es ist eindeutig erkennbar, daß der misra-konforme Code wesentlich größer
und unübersichtlich ist.
Das ist mir einfach zu blöd. Niemand, der bei Verstand ist, arbeitet so.


Stefan
Rainer Weikusat
2016-08-27 16:12:54 UTC
Permalink
Stefan Reuther <***@arcor.de> writes:

[...]
Dass das malloc nicht nur gemacht wird, weil der Coder zu faul war,
sich von vornherein Gedanken über den statischen Buffer zu machen.
Es gibt Mengen von C-Code, der grundsaetzlich nichts mit Daten macht,
ohne die vorher in einen eigens fuer diesen Zweck via malloc
angeforderten Puffer zu kopieren ...
Rainer Weikusat
2016-08-27 15:59:00 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
Das stimmt, und ich bin ein Massiv-Gegner von MISRA-C.
Aber die MISRA-Regeln wurden aufgrund von real gemachten Fehlern
in signifikanter Anzahl aufgesetzt.
Das Verfahren ist unsinnig: Wenn man Leute zwingt, anstatt X Y zu tun,
weil X in der Vergangheit haeufig falsch gemacht wurde, dann werden
'Leute' in Zukunft Y anstelle von X falsch machen.
Ja, es ist sogar noch viel schlimmer.
Die Leute müssen statt X YZKLMBER__ tun, um das Verbotene
frickelnd zu ersetzen.
http://www.schellong.de/htm/beisp.html
Ich wuerde das mit weniger Herumgehuepfe ausdruecken (Vorzeichen aus
religioesen Gruenden nicht unterstuetzt):

----------------
#include <stdio.h>

static unsigned factors[5][10] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 },
{ 0, 100, 200, 300, 400, 500, 600, 700, 800, 900 },
{ 0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000 },
{ 0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000 }
};

unsigned a2n_unrolled(char *s)
{
char *p;
unsigned *f, x;

p = s;
while (p[1]) ++p;

f = factors[0];
x = 0;
switch (p - s) {
case 4:
x += f[*p-- - '0'];
f += 10;

case 3:
x += f[*p-- - '0'];
f += 10;

case 2:
x += f[*p-- - '0'];
f += 10;

case 1:
x += f[*p-- - '0'];
f += 10;

case 0:
x += f[*p - '0'];
}

return x;
}

unsigned a2n(char *s)
{
char *p;
unsigned *f, x;

p = s;
while (p[1]) ++p;

f = factors[0];
x = 0;
while (p > s) x += f[*p-- - '0'], f += 10;
return x + f[*p - '0'];
}

int main(int argc, char **argv)
{
unsigned long x;

printf("%u\n", a2n_unrolled(argv[1]));
printf("%u\n", a2n(argv[1]));

/* x = 1000000000;
do a2n(argv[1]); while (--x);*/

return 0;
}
Helmut Schellong
2016-08-27 19:12:32 UTC
Permalink
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Ich wuerde das mit weniger Herumgehuepfe ausdruecken (Vorzeichen aus
----------------
#include <stdio.h>
[...]

8.470u 0.007s 0:08.50 99.6% 501+329k 0+0io 0pf+0w
9.025u 0.000s 0:09.04 99.7% 502+330k 0+0io 0pf+0w
6.637u 0.000s 0:06.65 99.6% 504+330k 0+0io 0pf+0w
7.538u 0.000s 0:07.55 99.7% 502+329k 0+0io 0pf+0w
a2n()
a2n_unrolled()
atoi_F()
for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');

Der gcc5 kompiliert die normale Schleife
mit Multiplikation erstaunlich gut.
Er verwendet
leal (%rax,%rax,4), %eax
leal -48(%rdx,%rax,2), %eax
zwecks Multiplikation mit 10.

Meine atoi_F() hatte mal einen viel größeren Abstand
zu anderen Code-Lösungen.
Aber die schnellste ist sie immer noch.
Der 16-Bit-Zahlenbereich ist hier allerdings gering.

unsigned Y;

x = 1000000000;
do y+=atoi_F(argv[1]); while (--x);
Y=y;
printf("%d\n", y);

Übrigens optimiert clang die vorstehende Schleife weg.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-08-27 22:05:25 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Ich wuerde das mit weniger Herumgehuepfe ausdruecken (Vorzeichen aus
----------------
#include <stdio.h>
[...]
8.470u 0.007s 0:08.50 99.6% 501+329k 0+0io 0pf+0w
9.025u 0.000s 0:09.04 99.7% 502+330k 0+0io 0pf+0w
6.637u 0.000s 0:06.65 99.6% 504+330k 0+0io 0pf+0w
7.538u 0.000s 0:07.55 99.7% 502+329k 0+0io 0pf+0w
a2n()
a2n_unrolled()
atoi_F()
for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');
Was soll mir das jetzt mitteilen? Eine Schleife braucht weniger Zeit als
zwei Schleifen? Das ist wenig ueberraschend. Multiplikationen sind teuer
denn trotzdem die eine Schleife weniger Zeit braucht als zwei Schleifen
ist sie weit davon entfernt, doppelt so schnell zu sein?
Geschwindigkeitsvorteil durch kreuz-und-quer goto im Bereich
'Messfehler'? Experiment mit unbekannten Eingabedaten und unbekannter
Rainer Weikusat
2016-08-27 22:06:00 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Ich wuerde das mit weniger Herumgehuepfe ausdruecken (Vorzeichen aus
----------------
#include <stdio.h>
[...]
8.470u 0.007s 0:08.50 99.6% 501+329k 0+0io 0pf+0w
9.025u 0.000s 0:09.04 99.7% 502+330k 0+0io 0pf+0w
6.637u 0.000s 0:06.65 99.6% 504+330k 0+0io 0pf+0w
7.538u 0.000s 0:07.55 99.7% 502+329k 0+0io 0pf+0w
a2n()
a2n_unrolled()
atoi_F()
for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');
Was soll mir das jetzt mitteilen? Eine Schleife braucht weniger Zeit als
zwei Schleifen? Das ist wenig ueberraschend. Multiplikationen sind teuer
denn trotzdem die eine Schleife weniger Zeit braucht als zwei Schleifen
ist sie weit davon entfernt, doppelt so schnell zu sein?
Geschwindigkeitsvorteil durch kreuz-und-quer goto im Bereich
'Messfehler'? Experiment mit unbekannten Eingabedaten und unbekannter
Hardware hatte ein Ergebnis?
Helmut Schellong
2016-08-28 08:09:19 UTC
Permalink
Post by Rainer Weikusat
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Ich wuerde das mit weniger Herumgehuepfe ausdruecken (Vorzeichen aus
----------------
#include <stdio.h>
[...]
8.470u 0.007s 0:08.50 99.6% 501+329k 0+0io 0pf+0w
9.025u 0.000s 0:09.04 99.7% 502+330k 0+0io 0pf+0w
6.637u 0.000s 0:06.65 99.6% 504+330k 0+0io 0pf+0w
7.538u 0.000s 0:07.55 99.7% 502+329k 0+0io 0pf+0w
a2n()
a2n_unrolled()
atoi_F()
for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');
Was soll mir das jetzt mitteilen?
Daß der Zeitbedarf der Funktionen
a2n a2n_unrolled atoi_F atoim_F
8.47 9.03 6.64 7.54 Sekunden
beträgt.
Wobei atoi_F die goto-Wüste ist und atoim_F eine Schleife
mit Multiplikation verwendet.

Nachreichung clang:
7.821u 0.000s 0:07.84 99.7% 501+329k 0+0io 0pf+0w
7.953u 0.000s 0:07.97 99.7% 499+328k 0+0io 0pf+0w
6.284u 0.000s 0:06.29 99.8% 503+330k 0+0io 0pf+0w
9.390u 0.000s 0:09.41 99.7% 501+328k 0+0io 0pf+0w
Gleiche Funktionenzuordnung wie oben.
Post by Rainer Weikusat
Eine Schleife braucht weniger Zeit als
zwei Schleifen? Das ist wenig ueberraschend.
Multiplikationen sind teuer
denn trotzdem die eine Schleife weniger Zeit braucht als zwei Schleifen
ist sie weit davon entfernt, doppelt so schnell zu sein?
Geschwindigkeitsvorteil durch kreuz-und-quer goto im Bereich
'Messfehler'? Experiment mit unbekannten Eingabedaten und unbekannter
Hardware hatte ein Ergebnis?
Soll man nun nie wieder Messungen zum Zeitbedarf von Software machen?
Vor den Messungen kennt man als Nichthellseher die Resultate nicht.
Falls die Resultate einen Meßfehler haben, dann den gleichen bei
jeder der getesteten Funktionen.
Der Parameterwert betrug gestern wie heute 27777.
Die Resultate liegen bis zum Faktor 1,5 auseinander.
Das ist kein Meßfehlerergebnis.

Die vorstehenden Resultate sind sehr interessant, denn ich habe da
schon Unterschiede von 1:14 in der Vergangenheit gemessen.
Es überrascht etwas, daß a2n_unrolled langsamer als a2n ist.
Eine Multiplikation ist teuer, wenn der Compiler sie einkompiliert.
Wenn er sie trickreich ersetzt durch Instruktionen, die etwa 1,5 Takte
brauchen, ist eine Multiplikation in der Quelle nicht teuer.
Es gibt aber keine Garantie, daß ein Compiler stets eine Multiplikation
durch schnellere Instruktionen ersetzt. Deshalb meine goto-Wüste.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
G.B.
2016-08-28 10:41:15 UTC
Permalink
Post by Helmut Schellong
Soll man nun nie wieder Messungen zum Zeitbedarf von Software machen?
Die insunuierte, auf alle Schleifen verallgemeinernde Schlussfolgerung
hin zur Handoptimierung grenzt natürlich ans Absurde. Sie würde auch
allzu offenkundige Ziele von Sollvorgaben an Softwarepraxis sachlich
verfehlen.

Softwarepraxis (Programmierung einfacher while-Schleifen vs.
Programmierung komplex "verdrahteter" Zustandsautomaten),
die im besonderen Fall(!) durch Abweichung von der Regel (MISRA-C)
ihr Ziel besser verwirklicht, darf das augenscheinlich tun,
wenn aus sachlogischen Gründen aus der Regelabweichung ein Profit
resultiert. Kompetente Manager wissen das vielleicht. Vielleicht
entsteht sogar ein doppelter Profit.

Beispiel einer Regel (nicht aus MISRA-C):

Schreibe so, dass nach Möglichkeit einfache, leicht durchschaubare
Lösungen entstehen, die das bestimmte Ziel in der zur Verfügung stehenden
Rechenzeit lösen. Aber auch so lösen, dass keine weiteren Vorgaben
verletzt werden, wie z.B.
- bezahlte Programmierzeit, oder
- geplante Portierbarkeiten, oder
- Ersetzbarkeit für den durch Unfall ausgefallenen Autor.

Eine Software, deren Herstellung gewohnheitsmäßig von so einer Regel abweicht,
weil das Produkt zwar richtig arbeitet, aber im Besonderen jedesmal ein
hochspezialisiertes, clever gemachtes, Applaus wohlfeil forderndes
Kunsthandwerk symbolisiert, einer handgemachten Kuckucksuhr gleicht,
diese Software, wenn sie als verallgemeinerungsfähiges Beispiel
angeführt wird, erzwingt die Frage, warum allgemeine Regeln zur
Softwareherstellung dem Sonderfall aus dem Beispiel unterzuorden sein sollen.

Also: Warum und wann sollte sich verantwortliches Management bei der Wahl
des Algorithmus an kunstvoller Komplexität orientieren?

Insofern dadurch den kunstfertigen Software-Handwerkern ein hohes Maß an
Arbeitszufriedenheit zu Teil wird? Die Berichte über den frustrierenden,
schnöden aber fordernden Arbeitsalltag erfahrener Programmierer
mehren sich. Die Antwort wäre also schon mal nicht leichtfertig ein Ja
oder Nein, das sich nur auf technische Aspekte der Schleifenoptimierung
stützt.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Rainer Weikusat
2016-08-28 11:45:27 UTC
Permalink
Post by Helmut Schellong
Post by Rainer Weikusat
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Post by Helmut Schellong
http://www.schellong.de/htm/beisp.html
Ich wuerde das mit weniger Herumgehuepfe ausdruecken (Vorzeichen aus
----------------
#include <stdio.h>
[...]
8.470u 0.007s 0:08.50 99.6% 501+329k 0+0io 0pf+0w
9.025u 0.000s 0:09.04 99.7% 502+330k 0+0io 0pf+0w
6.637u 0.000s 0:06.65 99.6% 504+330k 0+0io 0pf+0w
7.538u 0.000s 0:07.55 99.7% 502+329k 0+0io 0pf+0w
a2n()
a2n_unrolled()
atoi_F()
for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');
Was soll mir das jetzt mitteilen?
Daß der Zeitbedarf der Funktionen
a2n a2n_unrolled atoi_F atoim_F
8.47 9.03 6.64 7.54 Sekunden
beträgt.
Wobei atoi_F die goto-Wüste ist und atoim_F eine Schleife
mit Multiplikation verwendet.
Dh die in diesem Fall schnellste Konvertierung benoetigt ungefaehr
6.64E-9s pro Ausfuerhrung, die langsamste 9.03E-9s, ein Unterschied von
2.39E-9, 0.00000000238s. Das ist nun allerdings Welterschuetternd[tm].
Uebrigens bekomme ich da mit einem richtigen Profile nicht wirklich
stabile Ergebnisse.

"Im Namen der graesslichen Zeitverschwendung",

unsigned a2n_unrolled(char *s)
{
char *p;
unsigned x, disp;

disp = s[1] ? s[2] ? s[3] ? s[4] ? 4 : 3 : 2 : 1 : 0;
p = s + disp;
x = 0;
switch (disp) {
case 4:
x += factors[4][p[-4] - '0'];

case 3:
x += factors[3][p[-3] - '0'];

case 2:
x += factors[2][p[-2] - '0'];

case 1:
x += factors[1][p[-1] - '0'];

case 0:
x += *p - '0';
}

return x;
}

Hier abgebildet, weil tatsaechlich bei drei Testlaeufen schneller als die
Schellong'sche Springprozession (der ich nicht absprechen moechte,
clever ausgedacht zu sein). (gcc 4.7.2, AMD A10-5700).

[...]
Post by Helmut Schellong
Post by Rainer Weikusat
Eine Schleife braucht weniger Zeit als
zwei Schleifen? Das ist wenig ueberraschend.
Multiplikationen sind teuer
denn trotzdem die eine Schleife weniger Zeit braucht als zwei Schleifen
ist sie weit davon entfernt, doppelt so schnell zu sein?
Geschwindigkeitsvorteil durch kreuz-und-quer goto im Bereich
'Messfehler'? Experiment mit unbekannten Eingabedaten und unbekannter
Hardware hatte ein Ergebnis?
Soll man nun nie wieder Messungen zum Zeitbedarf von Software machen?
Vor den Messungen kennt man als Nichthellseher die Resultate nicht.
Falls die Resultate einen Meßfehler haben, dann den gleichen bei
jeder der getesteten Funktionen.
Der Parameterwert betrug gestern wie heute 27777.
Die Resultate liegen bis zum Faktor 1,5 auseinander.
Das ist kein Meßfehlerergebnis.
Leute, die sich fuer normal halten, werden schon einen Zeitgewinn von 2.4s
als Spinnerei abtun. Hier hatten wir (pro Operation) 2.4
Milliardstelsekunden. Praktisch ist das dasselbe wie 0 oder 5E-9s oder
1E-9s. Deswegen 'Messfehler'.
Helmut Schellong
2016-08-28 17:59:31 UTC
Permalink
Post by Rainer Weikusat
Post by Helmut Schellong
Post by Rainer Weikusat
Was soll mir das jetzt mitteilen?
Daß der Zeitbedarf der Funktionen
a2n a2n_unrolled atoi_F atoim_F
8.47 9.03 6.64 7.54 Sekunden
beträgt.
Wobei atoi_F die goto-Wüste ist und atoim_F eine Schleife
mit Multiplikation verwendet.
Dh die in diesem Fall schnellste Konvertierung benoetigt ungefaehr
6.64E-9s pro Ausfuerhrung, die langsamste 9.03E-9s, ein Unterschied von
2.39E-9, 0.00000000238s. Das ist nun allerdings Welterschuetternd[tm].
Uebrigens bekomme ich da mit einem richtigen Profile nicht wirklich
stabile Ergebnisse.
Wenn man solch eine Funktion oft genug aufruft (millionenfach), wirkt
eine Steigerung der Effizienz der Funktion von 50% nicht selten als eine
Steigerung der Effizienz des gesamten Programms von 30%.

Genau dies Problem hatte ich, weshalb ich kompromißlos eine maximal
schnelle Funktion entwickelte.
Das zeigte Erfolg, indem ich mit der bsh ähnlich schnell bin
wie das intern kompilierende perl.

Aktuell habe ich ein ähnliches Problem mit:
http://www.schellong.de/htm/rpar.bsh.html

Dieses bsh-Skript braucht bis zu etwa 10 Sekunden, weil eine innere
Schleife millionen-fach durchlaufen wird und Zahlen unablässig
zwischen string<-->long hin und her konvertiert werden.
Bei Integer verwende ich meine schnellen goto-Wüsten, aber für
Gleitkomma habe ich nichts Eigenes entwickelt.


Ich habe vor langer Zeit den Taktbedarf einzelner Instruktionen
genau gemessen - ganz genau.

Dazu machte ich einen mathematischen Ansatz:
2t+s - (t+s) = t
Das bedeutet, man hat zwei Schleifen, eine mit zwei Instruktionen
darin, die andere mit einer Instruktion.
Ungenauigkeiten werden dadurch eliminiert, so ähnlich wie beim
Dual-Slope-Verfahren bei Meßgeräten.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-08-28 21:02:10 UTC
Permalink
Post by Helmut Schellong
Wenn man solch eine Funktion oft genug aufruft (millionenfach), wirkt
eine Steigerung der Effizienz der Funktion von 50% nicht selten als eine
Steigerung der Effizienz des gesamten Programms von 30%.
Die atoi - Implementierung als Bottleneck eines gesamten Programms?

Da habe ich Schwierigkeiten, mit das unter vernünftigen
Rahmenbedingungen vorzustellen - kannst du da mal ein Beispiel
nennen?
Helmut Schellong
2016-08-28 21:30:45 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Wenn man solch eine Funktion oft genug aufruft (millionenfach), wirkt
eine Steigerung der Effizienz der Funktion von 50% nicht selten als eine
Steigerung der Effizienz des gesamten Programms von 30%.
Die atoi - Implementierung als Bottleneck eines gesamten Programms?
Da habe ich Schwierigkeiten, mit das unter vernünftigen
Rahmenbedingungen vorzustellen - kannst du da mal ein Beispiel
nennen?
Das habe ich bereits gepostet.
Ein gutes Beispiel ist: http://www.schellong.de/htm/rpar.bsh.html
Es muß nur Integer statt Gleitkomma angenommen werden.

Die Konversionen hin und zurück werden dort millionen-fach vorgenommen
und sorgen u.a. für eine Laufzeit von 1 .. 10 s und mehr.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-08-28 22:03:03 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Post by Helmut Schellong
Wenn man solch eine Funktion oft genug aufruft (millionenfach), wirkt
eine Steigerung der Effizienz der Funktion von 50% nicht selten als eine
Steigerung der Effizienz des gesamten Programms von 30%.
Die atoi - Implementierung als Bottleneck eines gesamten Programms?
Da habe ich Schwierigkeiten, mit das unter vernünftigen
Rahmenbedingungen vorzustellen - kannst du da mal ein Beispiel
nennen?
Das habe ich bereits gepostet.
Ein gutes Beispiel ist: http://www.schellong.de/htm/rpar.bsh.html
Es muß nur Integer statt Gleitkomma angenommen werden.
Die Konversionen hin und zurück werden dort millionen-fach vorgenommen
und sorgen u.a. für eine Laufzeit von 1 .. 10 s und mehr.
Berechnen von parallel geschalteten Widerständen mit einer Shell?
Und dabei verwendet man die meisten CPU-Zyklen dazu, Zahlen von
Dezimal nach Binär und umgekehrt?

Ehrlich gesagt, das scheint mir kaum sinnvoll. Wenn ich
Berechnungen machen möchte und Performance irgendeine Rolle spielt,
dann sollte man das mit einer Sprache machen, die kompiliert wird -
C oder Fortran oder wasauchimmer. Wenn die meisten Rechenzeit in
kompilierten Routinen verbraten wird, kann man natürlich auch
Matlab oder Python oder ... nehmen.

Hast du noch ein anderes Beispiel, was vielleicht mehr überzeugt?
Helmut Schellong
2016-08-29 07:33:53 UTC
Permalink
[...]
Post by Thomas Koenig
Post by Helmut Schellong
Die Konversionen hin und zurück werden dort millionen-fach vorgenommen
und sorgen u.a. für eine Laufzeit von 1 .. 10 s und mehr.
Berechnen von parallel geschalteten Widerständen mit einer Shell?
Ja, hast Du was dagegen?
Interpreter haben viele Vorteile.
Die Shells, APL, BASIC, Forth, Perl, Python, Ruby, PHP
erfahren regen Zuspruch.
Post by Thomas Koenig
Und dabei verwendet man die meisten CPU-Zyklen dazu, Zahlen von
Dezimal nach Binär und umgekehrt?
Nein, nicht den überwiegenden Teil, aber viel.
Post by Thomas Koenig
Ehrlich gesagt, das scheint mir kaum sinnvoll. Wenn ich
Berechnungen machen möchte und Performance irgendeine Rolle spielt,
Performance spielt kaum eine Rolle.
Wenn man alle paar Jahre mal einige frequenzbestimmende Widerstände
ausrechnen muß, so ist die Laufzeit des per Menü bedienbaren
Skriptes fast egal.
Trotzdem hat man den Ehrgeiz, idealerweise eine Laufzeit von
0,5 bis 1 s zu erreichen.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-08-29 16:54:03 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Thomas Koenig
Post by Helmut Schellong
Die Konversionen hin und zurück werden dort millionen-fach vorgenommen
und sorgen u.a. für eine Laufzeit von 1 .. 10 s und mehr.
Berechnen von parallel geschalteten Widerständen mit einer Shell?
Ja, hast Du was dagegen?
Interpreter haben viele Vorteile.
Die Shells, APL, BASIC, Forth, Perl, Python, Ruby, PHP
erfahren regen Zuspruch.
Erläuterung hast du gesnippt - Wenn ich keine Performance brauche,
kann ich das natürlich machen. Wenn ich Performance brauche, dann
muss ich mich drum kümmern, das das funktioniert, z.B. über
eine kompilierte Sprache oder Aufruf von kompilierten Routinen
(siehe Matlab oder Python).
Post by Helmut Schellong
Performance spielt kaum eine Rolle.
Dann ist das aber kein besonders gutes Beispiel dafür, dass
du an atoi herumschraubst, weil du Performance brauchst :-)

Und wenn es eher eine intelektuelle Übung zum eigenen Vergnügen
ist (da spricht ja wirklich rein gar nichts dagegen, sowas mache
ich auch gerne): Schon mal ans Parallelisieren gedacht? :-)
Stefan Reuther
2016-08-29 09:45:21 UTC
Permalink
Post by Helmut Schellong
Post by Thomas Koenig
Die atoi - Implementierung als Bottleneck eines gesamten Programms?
Da habe ich Schwierigkeiten, mit das unter vernünftigen
Rahmenbedingungen vorzustellen - kannst du da mal ein Beispiel
nennen?
Das habe ich bereits gepostet.
Ein gutes Beispiel ist: http://www.schellong.de/htm/rpar.bsh.html
Es muß nur Integer statt Gleitkomma angenommen werden.
Die Konversionen hin und zurück werden dort millionen-fach vorgenommen
und sorgen u.a. für eine Laufzeit von 1 .. 10 s und mehr.
Interessant ist nicht, das eine "Laufzeit von 1 .. 10 s" erzeugt wird
(Laufzeit wofür eigentlich? Das ganze Skript? Nur die atoi? Und warum
ist die angegebene Laufzeit eine ganze Zehnerpotenz?).

Interessant ist der Laufzeitanteil der atoi auf die Gesamtzeit des
Programms.

Gerade bei einem Skriptinterpreter kann man da durch kleverere
Gestaltung der Datenstrukturen deutlich mehr reißen als mit einer
atoi-Wandlung. Ich werfe mal Dinge in den Raum wie "gescheiter AST",
"Vermeidung von Kopien", "Vorberechnung von Hashwerten für
Symbol-Lookups". Das sind die Dinge, die in meinen Scriptinterpretern
die Geschwindigkeit gebracht haben. Dazu musste ich natürlich Jahrzehnte
alten Code auch mal neu machen.


Stefan
Helmut Schellong
2016-08-29 13:51:31 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Post by Thomas Koenig
nennen?
Das habe ich bereits gepostet.
Ein gutes Beispiel ist: http://www.schellong.de/htm/rpar.bsh.html
Es muß nur Integer statt Gleitkomma angenommen werden.
Die Konversionen hin und zurück werden dort millionen-fach vorgenommen
und sorgen u.a. für eine Laufzeit von 1 .. 10 s und mehr.
Interessant ist nicht, das eine "Laufzeit von 1 .. 10 s" erzeugt wird
(Laufzeit wofür eigentlich? Das ganze Skript? Nur die atoi? Und warum
ist die angegebene Laufzeit eine ganze Zehnerpotenz?).
Das ganze Skript erzeugt die angegebene Laufzeit.
Die Laufzeit ist so unterschiedlich, weil das Skript intelligent
entwickelt wurde. Darin stecken mehrere optimierende Verfahren.

Beispielsweise ergibt eine Parallelschaltung von Widerständen (oder eine
Reihenschaltung von Kondensatoren) grundsätzlich einen Resultatwert,
der kleiner ist als der kleinste Ausgangswert.
Kandidaten, die <= dem Zielwert sind, brauchen also gar nicht erst
probiert zu werden.

Das Skript wird also überproportional schneller, je größer der
Zielwert ist.
Post by Stefan Reuther
Interessant ist der Laufzeitanteil der atoi auf die Gesamtzeit des
Programms.
Es ist fraglich, ob ich solch einen Aufwand treiben sollte, um dies
festzustellen, da es ohnehin darauf hinauslaufen muß, daß ich eigene
Funktionen wie strtold() entwickle, die deutlich schneller sein müssen
als die Originale, weil der Aufwand andernfalls komplett sinnlos wird.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-08-29 16:48:59 UTC
Permalink
Post by Helmut Schellong
Die Laufzeit ist so unterschiedlich, weil das Skript intelligent
entwickelt wurde. Darin stecken mehrere optimierende Verfahren.
Beispielsweise ergibt eine Parallelschaltung von Widerständen (oder eine
Reihenschaltung von Kondensatoren) grundsätzlich einen Resultatwert,
der kleiner ist als der kleinste Ausgangswert.
Kandidaten, die <= dem Zielwert sind, brauchen also gar nicht erst
probiert zu werden.
Jetzt bin ich verwirrt. Was genau macht dein Skript?

Der Kommentar im Kopf von http://www.schellong.de/htm/rpar.bsh.html
lautet

"Das Skript ist per Menü (s.u.) gesteuert.
Es errechnet den Gesamtwert von parallel geschalteten Widerständen."

Den Widerstand von Paralellschaltungen von Widerständen rechne
ich mit (pardon my LaTeX)

R_{ges} = \left( \sum_{i=1}^n R_{i}^{-1}\right)^{-1}

aus, da muss ich doch nichts ausprobieren. Und das entsprechende
Programm ist logischerweise ziemlich trivial.
Post by Helmut Schellong
Das Skript wird also überproportional schneller, je größer der
Zielwert ist.
Von Zielwert steht in der Dokumentation nichts. Vielleicht solltest
du die mal ein bisschen besser formulieren :-)
Helmut Schellong
2016-08-30 02:48:27 UTC
Permalink
Post by Thomas Koenig
Post by Helmut Schellong
Die Laufzeit ist so unterschiedlich, weil das Skript intelligent
entwickelt wurde. Darin stecken mehrere optimierende Verfahren.
Beispielsweise ergibt eine Parallelschaltung von Widerständen (oder eine
Reihenschaltung von Kondensatoren) grundsätzlich einen Resultatwert,
der kleiner ist als der kleinste Ausgangswert.
Kandidaten, die <= dem Zielwert sind, brauchen also gar nicht erst
probiert zu werden.
Jetzt bin ich verwirrt. Was genau macht dein Skript?
Der Kommentar im Kopf von http://www.schellong.de/htm/rpar.bsh.html
lautet
"Das Skript ist per Menü (s.u.) gesteuert.
Es errechnet den Gesamtwert von parallel geschalteten Widerständen."
Den Widerstand von Paralellschaltungen von Widerständen rechne
ich mit (pardon my LaTeX)
R_{ges} = \left( \sum_{i=1}^n R_{i}^{-1}\right)^{-1}
aus, da muss ich doch nichts ausprobieren. Und das entsprechende
Programm ist logischerweise ziemlich trivial.
Post by Helmut Schellong
Das Skript wird also überproportional schneller, je größer der
Zielwert ist.
Von Zielwert steht in der Dokumentation nichts. Vielleicht solltest
du die mal ein bisschen besser formulieren :-)
Brauche ich eigentlich nicht, weil es ein Menü hat.
Bei Aufruf sieht man alles von ganz allein.
Im Skript selbst ist auch alles lesbar.
Und wer es nicht aufrufen will, der interessiert sich halt nicht dafür.

Es wird ein Zielwert innerhalb +-Toleranz gesucht.
Anders kann es doch wohl kaum sein.

Diverse Ausgaben des Skripts:
====================================================================
414] rpar.bsh
Startwert-Faktor: 10.0
Puffergroesse: 2880
Puffergroesse: 144 Einträge
Einträge: 121
Pufferwerte gelöscht: 1
Einträge: 120

Startwert=10.0 Endwert=1e6
Reihe=E24 Zielwert-Toleranz=0.3
Wahl E6 : e6
Wahl E12 : e12
Wahl E24 : e24
Wahl E48 : e48
Zeilen max: z # [12]
Toleranz : t # (t 0.5)
Zielwert : zahl (123 12.3 12e3 ...)
Beenden : E
: 12.5

0 : 12.5 : 12.5 = 15 | 75
583 : 12.5 : 12.5072886 = 13 | 330

0 : 12.5 : 12.5 = 30 | 30 | 75
0 : 12.5 : 12.5 = 16 | 75 | 240
0 : 12.5 : 12.5 = 24 | 30 | 200
0 : 12.5 : 12.5 = 15 | 150 | 150
0 : 12.5 : 12.5 = 15 | 120 | 200
0 : 12.5 : 12.5 = 15 | 100 | 300
14 : 12.5 : 12.4998283 = 15 | 75 | 910000
15 : 12.5 : 12.5001821 = 13 | 330 | 22000
15 : 12.5 : 12.4998095 = 15 | 75 | 820000
17 : 12.5 : 12.4997917 = 15 | 75 | 750000
18 : 12.5 : 12.4997702 = 15 | 75 | 680000
20 : 12.5 : 12.499748 = 15 | 75 | 620000

Startwert=10.0 Endwert=1e6
Reihe=E24 Zielwert-Toleranz=0.3
Wahl E6 : e6
Wahl E12 : e12
Wahl E24 : e24
Wahl E48 : e48
Zeilen max: z # [12]
Toleranz : t # (t 0.5)
Zielwert : zahl (123 12.3 12e3 ...)
Beenden : E
: _
E24
1761 : 2534 : 2538.46154 = 3300 | 11000
1992 : 2534 : 2539.04762 = 4300 | 6200
2558 : 2534 : 2540.4814 = 2700 | 43000

24 : 2534 : 2534.05995 = 6200 | 7500 | 10000
64 : 2534 : 2534.16149 = 3000 | 24000 | 51000
67 : 2534 : 2533.83132 = 3300 | 13000 | 68000
96 : 2534 : 2533.75777 = 4700 | 5600 | 300000
112 : 2534 : 2533.71572 = 2700 | 47000 | 330000
124 : 2534 : 2534.31373 = 4700 | 11000 | 11000
151 : 2534 : 2533.61656 = 2700 | 75000 | 91000
162 : 2534 : 2533.58925 = 3300 | 20000 | 24000
162 : 2534 : 2533.58925 = 3300 | 12000 | 120000
223 : 2534 : 2533.43523 = 5100 | 5100 | 390000
233 : 2534 : 2533.40879 = 2700 | 43000 | 910000
277 : 2534 : 2534.70218 = 2700 | 51000 | 220000
E6
1308 : 2534 : 2537.31343 = 6800 | 6800 | 10000
1761 : 2534 : 2538.46154 = 3300 | 22000 | 22000
E24
0 : 9 : 9.0 = 18 | 18
0 : 9 : 9.0 = 12 | 36
1100 : 9 : 9.00990099 = 10 | 91

0 : 9 : 9.0 = 27 | 27 | 27
0 : 9 : 9.0 = 24 | 24 | 36
0 : 9 : 9.0 = 20 | 30 | 36
0 : 9 : 9.0 = 18 | 36 | 36
0 : 9 : 9.0 = 18 | 20 | 180
0 : 9 : 9.0 = 15 | 24 | 360
0 : 9 : 9.0 = 10 | 120 | 360
0 : 9 : 9.0 = 10 | 180 | 180
1 : 9 : 9.00001206 = 10 | 91 | 8200
10 : 9 : 8.99991099 = 12 | 36 | 910000
10 : 9 : 8.99991099 = 18 | 18 | 910000
11 : 9 : 8.99990122 = 18 | 18 | 820000
E24
0 : 8.4 : 8.4 = 12 | 56 | 56
28 : 8.4 : 8.40023497 = 13 | 24 | 2200
67 : 8.4 : 8.39944004 = 16 | 18 | 1000
81 : 8.4 : 8.39932127 = 11 | 36 | 2700
190 : 8.4 : 8.39840637 = 12 | 51 | 62
230 : 8.4 : 8.40193499 = 11 | 36 | 3000
244 : 8.4 : 8.39795172 = 10 | 56 | 820
346 : 8.4 : 8.4029087 = 13 | 24 | 2400
349 : 8.4 : 8.39707079 = 16 | 30 | 43
354 : 8.4 : 8.39702874 = 13 | 24 | 2000
364 : 8.4 : 8.39694656 = 10 | 100 | 110
465 : 8.4 : 8.40390879 = 12 | 30 | 430
0.5% Damit nun auch 2 Werte:
3040 : 8.4 : 8.42553191 = 11 | 36
3861 : 8.4 : 8.43243243 = 13 | 24
4684 : 8.4 : 8.36065574 = 10 | 51
====================================================================

Ich finde die Ausgaben interessant.
Bei Verwendung E24 findet man fast immer einen beliebigen Zielwert
durch Parallelschaltung von nur zwei E-Reihen-Werten.
Oft ohne Abweichung vom gewünschten Zielwert.

Es ist auch erkennbar, daß eine Parallelschaltung von mehr als
3 Werten nicht nötig ist.
Reihenschaltung ist weit unterlegen.

Bei kleinen Zielwerten läuft das Skript maximal lange.
Bei mir etwa 10 Sekunden.
Das liegt daran, daß bis etwa 1800000 Rechendurchläufe gemacht werden.
Bei größeren Werten vergeht z.B. nur 1 Sekunde.
(Zwischen 120^3 und 50^3 besteht ein gewaltiger Unterschied.)

Der Wert links ist die Abweichung in ppm, 3000 entspricht der
Default-Toleranz von +-0.3 %.

Das Skript unternimmt sehr viele Prüfungen der Datenbasis, die die
Grundlage aller Berechnungen ist.
Das ist nachlesbar an: Err "Fehlertext"

Err "Falsche E-Reihe: E$E"
Err "Startwert<1: $Beg"
Err "Startwert>=Endwert: $Beg $End"
Err "Falsche Anzahl Werte $er: $a"
Err "$er-Wert < 1: $r"
Err "$er-Wert nicht streng monoton steigend: $r"
Err "$er-Wert-Faktor vom Vorwert her unpassend: $r/$r0"
Err "Endwert unpassend: $End"
Err "$er-Wert < 1: $r"
Err "Startwert unpassend: $Beg"
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-29 20:53:22 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Interessant ist der Laufzeitanteil der atoi auf die Gesamtzeit des
Programms.
Es ist fraglich, ob ich solch einen Aufwand treiben sollte, um dies
festzustellen, da es ohnehin darauf hinauslaufen muß, daß ich eigene
Funktionen wie strtold() entwickle, die deutlich schneller sein müssen
als die Originale, weil der Aufwand andernfalls komplett sinnlos wird.
Du hast hier in vielen Worten also gesagt, dass dich Messungen nicht
interessieren, weil du sowieso deine kryptisch-optimierten Funktionen
schreiben willst, deren Überlegenheit du von vornherein proklamierst
(der libc-Autor ist schließlich eine Flasche) und der Messaufwand
folglich überflüssig sei?

Ich beginne ja mit einer Lösung, die erstmal möglichst simpel gestrickt
ist, und probiere dann anhand von Messungen Optimierungen aus. Da kommt
dann halt z.B. raus, dass im Lexer fast nichts zu holen ist, und die
Kryptizität den Gewinn nicht wettmacht. Wie gesagt, in meinen
Interpretern kam der Gewinn z.B. vom AST oder von überflüssigen Kopien;
und mit deinen atoi-Fragmenten konnte ich bisher keinen Gewinn überhaupt
nachweisen.

Hat deine Shell überhaupt einen AST? ((Ältere) Erlebnisberichte im Netz
lassen vermuten, dass nicht.) Wenn nicht, ist atoi-Performance dein
kleinstes Problem.


Stefan
Helmut Schellong
2016-08-30 03:03:54 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Post by Stefan Reuther
Interessant ist der Laufzeitanteil der atoi auf die Gesamtzeit des
Programms.
Es ist fraglich, ob ich solch einen Aufwand treiben sollte, um dies
festzustellen, da es ohnehin darauf hinauslaufen muß, daß ich eigene
Funktionen wie strtold() entwickle, die deutlich schneller sein müssen
als die Originale, weil der Aufwand andernfalls komplett sinnlos wird.
Du hast hier in vielen Worten also gesagt, dass dich Messungen nicht
interessieren, weil du sowieso deine kryptisch-optimierten Funktionen
schreiben willst, deren Überlegenheit du von vornherein proklamierst
(der libc-Autor ist schließlich eine Flasche) und der Messaufwand
folglich überflüssig sei?
Ich habe das Gegenteil gesagt.
Ich bezweifle, daß mir die Funktionen deutlich schneller gelingen.
Und genau deshalb ist alles sinnlos.
Da brauche ich doch Messungen gar nicht erst vorzunehmen.

Außerdem habe ich, wie ich mehrfach berichtete, einen durchschlagenden
Erfolg erreicht, mit meinen Funktionen.
Das reicht doch!
Da muß man nicht weiter rummessen.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Helmut Schellong
2016-08-28 18:48:27 UTC
Permalink
[...]
Post by Rainer Weikusat
Hier abgebildet, weil tatsaechlich bei drei Testlaeufen schneller als die
Schellong'sche Springprozession (der ich nicht absprechen moechte,
clever ausgedacht zu sein). (gcc 4.7.2, AMD A10-5700).
Ich ermittle mit clang 6,19 s, was schneller ist als 6,28 s für atoi_F().

Allerdings enthält die komplette atoi_F mehr:

fSTATIC int atoi_F(register const byte *a)
{
register int i;
int m=0;
if (*a<='0') {
if (a[0]==0||a[1]==0) return (0);
while (*a==' '||*a=='\t') ++a;
if (*a=='-'&&(m=1,1)||*a=='+') ++a;
while (*a=='0') ++a;
}
i=0;
if (!F_DIG(a[0])) goto ADD0;
if (!F_DIG(a[1])) goto ADD1;
if (!F_DIG(a[2])) goto I2;
//...
return (m?-i:i);
}
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Helmut Schellong
2016-08-28 19:28:06 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Hier abgebildet, weil tatsaechlich bei drei Testlaeufen schneller als die
Schellong'sche Springprozession (der ich nicht absprechen moechte,
clever ausgedacht zu sein). (gcc 4.7.2, AMD A10-5700).
Ich ermittle mit clang 6,19 s, was schneller ist als 6,28 s für atoi_F().
Wenn ich die atoi_F anpasse an die spartanische a2n_unrolled2, ergibt
sich eine Zeit von 5,41 s, was wiederum der kleinste Wert ist.

Es kann sein, daß ich die welt-schnellste atoi() in C entwickelt habe.
Für die Umkehrkonversion habe ich ähnliche Funktionen.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-08-28 19:40:02 UTC
Permalink
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Hier abgebildet, weil tatsaechlich bei drei Testlaeufen schneller als die
Schellong'sche Springprozession (der ich nicht absprechen moechte,
clever ausgedacht zu sein). (gcc 4.7.2, AMD A10-5700).
Ich ermittle mit clang 6,19 s, was schneller ist als 6,28 s für atoi_F().
Nicht die Variante, mit der ich das verglichen habe. Im uebrigen ist das
Huepfburgwunder durchaus nicht jedesmal schnellste Funktion gewesen. In
einem realen Programm muesste man auch noch die Zeit, die dadurch
verloren geht, etwas sinnvolles wieder in den Cache zu laden, nachdem
die Faktorentabelle es verdraengt hat und andere damit zusammenhaenge
Effekte beruecksichtigen.

Du solltest Dir (bei Interesse) auch mal die glibc-Implementierung von
strchr fuer einen netten Trick, wie man extrem billig das Ende eines
nullterminierten Strings findet, ansehen. Letzen Endes sind solche
'Experimente' in C sinnlos, weil man zu wenig nuetzliched Features der
Ziel-CPU ausnutzen kann.
Helmut Schellong
2016-08-28 20:41:55 UTC
Permalink
Post by Rainer Weikusat
Post by Helmut Schellong
[...]
Post by Rainer Weikusat
Hier abgebildet, weil tatsaechlich bei drei Testlaeufen schneller als die
Schellong'sche Springprozession (der ich nicht absprechen moechte,
clever ausgedacht zu sein). (gcc 4.7.2, AMD A10-5700).
Ich ermittle mit clang 6,19 s, was schneller ist als 6,28 s für atoi_F().
Nicht die Variante, mit der ich das verglichen habe. Im uebrigen ist das
Huepfburgwunder durchaus nicht jedesmal schnellste Funktion gewesen. In
einem realen Programm muesste man auch noch die Zeit, die dadurch
verloren geht, etwas sinnvolles wieder in den Cache zu laden, nachdem
die Faktorentabelle es verdraengt hat und andere damit zusammenhaenge
Effekte beruecksichtigen.
Du solltest Dir (bei Interesse) auch mal die glibc-Implementierung von
strchr fuer einen netten Trick, wie man extrem billig das Ende eines
nullterminierten Strings findet, ansehen.
# define SZUL sizeof(unsigned long)

static void re_inv32(register byte *cre)
{
register unsigned n= _32;
while ((unsigned long)cre&SZUL-1) *cre++ ^= 255, --n;
if (SZUL == 4) {
((unsigned long*)cre)[0] ^= ~(0ul);
((unsigned long*)cre)[1] ^= ~(0ul);
((unsigned long*)cre)[2] ^= ~(0ul);
((unsigned long*)cre)[3] ^= ~(0ul);
((unsigned long*)cre)[4] ^= ~(0ul);
((unsigned long*)cre)[5] ^= ~(0ul);
((unsigned long*)cre)[6] ^= ~(0ul);
n-=4*7; cre+=4*7;
}
if (SZUL == 8) {
((unsigned long*)cre)[0] ^= ~(0ul);
((unsigned long*)cre)[1] ^= ~(0ul);
((unsigned long*)cre)[2] ^= ~(0ul);
n-=8*3; cre+=8*3;
}
while (n) *cre++ ^= 255, --n;
return;
}
#undef SZUL


Die atoi_F() ist übrigens vollkommen portabel.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-08-28 21:04:26 UTC
Permalink
[...]
Post by Helmut Schellong
Post by Rainer Weikusat
Du solltest Dir (bei Interesse) auch mal die glibc-Implementierung von
strchr fuer einen netten Trick, wie man extrem billig das Ende eines
nullterminierten Strings findet, ansehen.
# define SZUL sizeof(unsigned long)
static void re_inv32(register byte *cre)
{
register unsigned n= _32;
while ((unsigned long)cre&SZUL-1) *cre++ ^= 255, --n;
if (SZUL == 4) {
((unsigned long*)cre)[0] ^= ~(0ul);
((unsigned long*)cre)[1] ^= ~(0ul);
((unsigned long*)cre)[2] ^= ~(0ul);
((unsigned long*)cre)[3] ^= ~(0ul);
((unsigned long*)cre)[4] ^= ~(0ul);
((unsigned long*)cre)[5] ^= ~(0ul);
((unsigned long*)cre)[6] ^= ~(0ul);
n-=4*7; cre+=4*7;
}
if (SZUL == 8) {
((unsigned long*)cre)[0] ^= ~(0ul);
((unsigned long*)cre)[1] ^= ~(0ul);
((unsigned long*)cre)[2] ^= ~(0ul);
n-=8*3; cre+=8*3;
}
while (n) *cre++ ^= 255, --n;
return;
}
#undef SZUL
"Hoffnungslos".
Post by Helmut Schellong
Die atoi_F() ist übrigens vollkommen portabel.
Das ist uebrigens vollkommen uninteressant. Falls es Dir Vergnuegen
bereitet, Zeit auf solche Kinkerlitzchen zu verwenden, und Dir diese
Zeit zur Verfuegung steht, ist dagegen nichts einzuwenden ausser dass Du
damit Michel Universitaetsclown jedenfalls das Fuerchten lehrst.

Aber mir stuende im Fall des Falles nicht die Zeit zur Verfuegung, sowas
auseinanderzupuzzlen, deswegen wuerde ich es schlicht durch eine
einfache Implementierung ersetzen, die ich stattdessen benutzen wuerde,
ausser es gibt einen realenn, technischen Grund, der dagegen spricht.

ZB ignoriere ich mehr als 90% aller 'CPAN Perl module' weil Code immer
Fehler hat und mir Zeit und Motivation fehlen, irgendjemandes
'handoptimiertes C' zu reparieren. Wer sowas tut (oder direkt
'handoptimierten [x86] Machinencode' schreibt), hat den Sinn hoeherer
Programmiersprachen nicht verstanden.
Helmut Schellong
2016-08-28 21:17:44 UTC
Permalink
Post by Rainer Weikusat
"Hoffnungslos".
Post by Helmut Schellong
Die atoi_F() ist übrigens vollkommen portabel.
Das ist uebrigens vollkommen uninteressant. Falls es Dir Vergnuegen
bereitet, Zeit auf solche Kinkerlitzchen zu verwenden, und Dir diese
Zeit zur Verfuegung steht, ist dagegen nichts einzuwenden ausser dass Du
damit Michel Universitaetsclown jedenfalls das Fuerchten lehrst.
[...]

Du scheinst einfach davon auszugehen, daß Quellen, die ich hier zeige,
ein paar Wochen oder Monate alt sind.

Nein, sie sind mehrere Jahrzehnte alt!
Das wirft ein ganz anderes Licht auf die Sache.
...
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-08-28 17:45:43 UTC
Permalink
On 2016-08-28 08:09, Helmut Schellong <***@schellong.biz> wrote:

[Diverse handoptimierte atoi-Varianten]
Post by Helmut Schellong
Die vorstehenden Resultate sind sehr interessant, denn ich habe da
schon Unterschiede von 1:14 in der Vergangenheit gemessen.
Es überrascht etwas, daß a2n_unrolled langsamer als a2n ist.
Eine Multiplikation ist teuer, wenn der Compiler sie einkompiliert.
Nicht einmal dann notwendigerweise. Das hängt von der CPU ab.

Auf den meisten aktuellen CPUs ist eine Multiplikation deutlich
schneller als ein Zugriff aufs RAM und möglicherweise sogar schneller
als ein Zugriff auf den L1-Cache. Eine Multiplikation durch einen
Table-Lookup zu ersetzen ist also häufig eher kontraproduktiv (auf einer
VAX war es das schon vor 30 Jahren), selbst wenn der Compiler nicht in
der Lage ist, die Multiplikation durch eine einfachere Operation zu
ersetzen.

Auf 16-Bit-Microcontrollern mag das anders aussehen.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Helmut Schellong
2016-08-28 18:20:13 UTC
Permalink
Post by Peter J. Holzer
Nicht einmal dann notwendigerweise. Das hängt von der CPU ab.
Auf den meisten aktuellen CPUs ist eine Multiplikation deutlich
schneller als ein Zugriff aufs RAM und möglicherweise sogar schneller
als ein Zugriff auf den L1-Cache. Eine Multiplikation durch einen
Table-Lookup zu ersetzen ist also häufig eher kontraproduktiv (auf einer
VAX war es das schon vor 30 Jahren), selbst wenn der Compiler nicht in
der Lage ist, die Multiplikation durch eine einfachere Operation zu
ersetzen.
Meine goto-Wüste ist allerdings bewiesenermaßen mit etwa 6,3 s
deutlich schneller als eine mit 'imul' durch clang-Compiler
auf 'intel64' mit etwa 9,6 s.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Peter J. Holzer
2016-08-28 21:48:16 UTC
Permalink
Post by Helmut Schellong
Post by Peter J. Holzer
Nicht einmal dann notwendigerweise. Das hängt von der CPU ab.
Auf den meisten aktuellen CPUs ist eine Multiplikation deutlich
schneller als ein Zugriff aufs RAM und möglicherweise sogar schneller
als ein Zugriff auf den L1-Cache. Eine Multiplikation durch einen
Table-Lookup zu ersetzen ist also häufig eher kontraproduktiv (auf einer
VAX war es das schon vor 30 Jahren), selbst wenn der Compiler nicht in
der Lage ist, die Multiplikation durch eine einfachere Operation zu
ersetzen.
Meine goto-Wüste ist allerdings bewiesenermaßen mit etwa 6,3 s
deutlich schneller als eine mit 'imul' durch clang-Compiler
auf 'intel64' mit etwa 9,6 s.
Verblüffenderweise ja. Andererseits habe ich Code, bei dem eine innere
Schleife mit einem imull, 2 addl und mehreren movl auf einem Core i5 in
ca. 1,4 Taktzyklen durchlaufen wird. Es ist also offensichtlich möglich,
ca. ein imull pro Taktzyklus abzusetzen. Andererseits braucht Deine
Misra-C-Variante (ja, die ist bei mir am Core i5 mit Abstand die
schnellste) im Durchschnitt insgesamt nur 10 Taktzyklen - da machen ein
paar Taktzyklen mehr gleich einiges aus.

Auf einem CoreDuo (32-Bit-Modus) ist übrigens Stephans Variante (mit gcc
compiliert) die schnellste.

Wobei die Benchmarks vermutlich die Varianten mit Lookup-Tables
bevorzugen: Wenn man 65 Millionen mal die gleiche Funktion
hintereinander aufruft, wird die Lookup-Tabelle immer im L1-Cache sein.
In echtem Code (der ja wahrscheinlich noch was anderes tut als atoi
aufzurufen) ist das nicht gesichert - da kann atoi dann statt 10
Taktzyklen schnell ein paar hundert brauchen ...

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Stefan Reuther
2016-08-28 20:54:26 UTC
Permalink
Post by Helmut Schellong
Post by Rainer Weikusat
Eine Schleife braucht weniger Zeit als
zwei Schleifen? Das ist wenig ueberraschend.
Multiplikationen sind teuer
denn trotzdem die eine Schleife weniger Zeit braucht als zwei Schleifen
ist sie weit davon entfernt, doppelt so schnell zu sein?
Geschwindigkeitsvorteil durch kreuz-und-quer goto im Bereich
'Messfehler'? Experiment mit unbekannten Eingabedaten und unbekannter
Hardware hatte ein Ergebnis?
Soll man nun nie wieder Messungen zum Zeitbedarf von Software machen?
Wer wissenschaftlich arbeitet legt zum Beginn vor allem erstmal
nachvollziehbare Messbedingungen fest. Z.B. in Form einer kompletten
Funktion und "die ruf ich jetzt X mal auf".

Sofern dein Array keine 500 Gigabyte groß ist, ist jedenfalls die
Aussage, "for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');" brauchte
7.54 Sekunden auf Rechnern neuer als einem Zuse Z3 nicht nachvollziehbar
Post by Helmut Schellong
Die vorstehenden Resultate sind sehr interessant, denn ich habe da
schon Unterschiede von 1:14 in der Vergangenheit gemessen.
Es überrascht etwas, daß a2n_unrolled langsamer als a2n ist.
Eine Multiplikation ist teuer, wenn der Compiler sie einkompiliert.
Wenn er sie trickreich ersetzt durch Instruktionen, die etwa 1,5 Takte
brauchen, ist eine Multiplikation in der Quelle nicht teuer.
Wer wissenschaftlich arbeitet schaut hinterher nach, was der Compiler
generiert und warum.

Einen, der für eine Multiplikation mit der Konstanten '10' eine
Multiplikationsinstruktion generiert, habe ich unter
https://gcc.godbolt.org/ jedenfalls nicht gefunden.[1]
Post by Helmut Schellong
Es gibt aber keine Garantie, daß ein Compiler stets eine Multiplikation
durch schnellere Instruktionen ersetzt. Deshalb meine goto-Wüste.
Es gibt auch keine Garantie, dass der Compiler für die goto-Wüste
effizienten Code generiert. Da ist zum einen der Sprung an sich: bei
einer Schleife geht der Compiler normalerweise davon aus, dass der
Rücksprung genommen wird und instruiert den Branch-Prediktor
entsprechend. Bei goto weiß man das nicht.

Zum anderen ist der Speicherzugriff. Das braucht Speicher und vernichtet
teuren L1-Cache. Es braucht extra Zugriffszyklen. Es braucht ggf. extra
Code für positionsunabhängige Adressierung (teuer auf i386). Es braucht
ggf. extra Adressregister. Hingegen braucht eine Multiplikation schon
auf solchen Methusalems wie K8 oder Pentium II nur einen Takt. [2]


Stefan


[1] Getesteter Code:
int foo(char* a)
{
int i;
for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');
return i;
}

[2] http://www.agner.org/optimize/instruction_tables.pdf
"Reciprocal throuput = 1".
Peter J. Holzer
2016-08-28 23:46:25 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Post by Rainer Weikusat
Eine Schleife braucht weniger Zeit als
zwei Schleifen? Das ist wenig ueberraschend.
Multiplikationen sind teuer
denn trotzdem die eine Schleife weniger Zeit braucht als zwei Schleifen
ist sie weit davon entfernt, doppelt so schnell zu sein?
Geschwindigkeitsvorteil durch kreuz-und-quer goto im Bereich
'Messfehler'? Experiment mit unbekannten Eingabedaten und unbekannter
Hardware hatte ein Ergebnis?
Soll man nun nie wieder Messungen zum Zeitbedarf von Software machen?
Wer wissenschaftlich arbeitet legt zum Beginn vor allem erstmal
nachvollziehbare Messbedingungen fest. Z.B. in Form einer kompletten
Funktion und "die ruf ich jetzt X mal auf".
Sofern dein Array keine 500 Gigabyte groß ist, ist jedenfalls die
Aussage, "for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');" brauchte
7.54 Sekunden auf Rechnern neuer als einem Zuse Z3 nicht nachvollziehbar
Das bezog sich offensichtlich auf einen Benchmark, der die Funktion oft
aufruft, nicht auf einen einzigen Aufruf. Die von Helmut zitierten
Einzellaufzeiten waren in der Gegend von ein paar Nanosekunden.
Post by Stefan Reuther
Post by Helmut Schellong
Die vorstehenden Resultate sind sehr interessant, denn ich habe da
schon Unterschiede von 1:14 in der Vergangenheit gemessen.
Es überrascht etwas, daß a2n_unrolled langsamer als a2n ist.
Eine Multiplikation ist teuer, wenn der Compiler sie einkompiliert.
Wenn er sie trickreich ersetzt durch Instruktionen, die etwa 1,5 Takte
brauchen, ist eine Multiplikation in der Quelle nicht teuer.
Wer wissenschaftlich arbeitet schaut hinterher nach, was der Compiler
generiert und warum.
Einen, der für eine Multiplikation mit der Konstanten '10' eine
Multiplikationsinstruktion generiert, habe ich unter
https://gcc.godbolt.org/ jedenfalls nicht gefunden.[1]
Wie Helmut geschrieben hat; Clang.

clang -O9 -Wall -g (clang 3.5.0 für x86_64):

.LBB0_2: # %.lr.ph
# =>This Inner Loop Header: Depth=1
#DEBUG_VALUE: my_atoi:m <- 1
#DEBUG_VALUE: my_atoi:idx <- 0
#DEBUG_VALUE: my_atoi:i <- 0
movzbl %al, %edx
.Ltmp4:
.loc 1 12 3 discriminator 2 # reuther.c:12:3
addl $-48, %edx
.Ltmp5:
.loc 1 12 3 discriminator 3 # reuther.c:12:3
cmpl $9, %edx
jg .LBB0_3
.Ltmp6:
# BB#4: # in Loop: Header=BB0_2 Depth=1
#DEBUG_VALUE: my_atoi:m <- 1
#DEBUG_VALUE: my_atoi:idx <- 0
#DEBUG_VALUE: my_atoi:i <- 0
.loc 1 13 6 # reuther.c:13:6
imull $10, %edi, %eax
addl %eax, %edx
.Ltmp7:
#DEBUG_VALUE: my_atoi:i <- EDX
.loc 1 12 3 discriminator 1 # reuther.c:12:3
movb (%rcx), %al
incq %rcx
testb %al, %al
movl %edx, %edi
jne .LBB0_2
jmp .LBB0_5

(Für x86 praktisch identisch)

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Thomas Koenig
2016-08-29 06:01:05 UTC
Permalink
Post by Peter J. Holzer
Post by Stefan Reuther
Einen, der für eine Multiplikation mit der Konstanten '10' eine
Multiplikationsinstruktion generiert, habe ich unter
https://gcc.godbolt.org/ jedenfalls nicht gefunden.[1]
Wie Helmut geschrieben hat; Clang.
imull $10, %edi, %eax
Dann wird es wohl Zeit für einen bug report / enhancement request
für clang. Oder gibt es den schon? Ein (für mich) erster Blick
in die Bug List bei clang hat nichts gefunden.
Helmut Schellong
2016-08-29 07:04:51 UTC
Permalink
Post by Thomas Koenig
Post by Peter J. Holzer
Post by Stefan Reuther
Einen, der für eine Multiplikation mit der Konstanten '10' eine
Multiplikationsinstruktion generiert, habe ich unter
https://gcc.godbolt.org/ jedenfalls nicht gefunden.[1]
Wie Helmut geschrieben hat; Clang.
imull $10, %edi, %eax
Dann wird es wohl Zeit für einen bug report / enhancement request
für clang. Oder gibt es den schon? Ein (für mich) erster Blick
in die Bug List bei clang hat nichts gefunden.
Vor einiger Zeit hatte ich ein weit schlimmeres Merkmal zu clang
gefunden.
Clang optimiert switch() nicht!
Wenn man 100 'case:' hat, schaltet er 100 if-Bedingungen
hintereinander!
Das ergab, daß ein ganzes Programm halb so schnell lief, wie
mit gcc kompiliert, der switch() großartig optimiert.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
G.B.
2016-08-29 08:08:57 UTC
Permalink
Post by Helmut Schellong
Clang optimiert switch() nicht!
Damit nicht noch eine fragwürdige Verallgemeinerung zu
falschen Annahmen über Clang führt, wäre möglicherweise eine
präzisierende Formulierung angmessen gewesen. "Ich habe
mal ein Programm gehabt, für das Clang wie folgt ..."

Ansonsten verfolgt auch Clang eine Strategie für die
Optimierung von switch, von deren Funktionsweise man
sich ein Bild machen kann. Und Sprungtabellen sind darin
eingeschlossen.

Z.B. einen Test, der einige Formen von switches
durchspielt, in verschiedenen Arrangements.

Da fängt schon damit an, dass in C u.U. erlaubt ist, der
untersuchten Variablen in einem Zweig der Fallunterscheidung
einen Wert zuzuweisen. C-Formalisten: Was ist dann mit
der Sprungtabelle und wie weit kann die Analyse des compilers
reichen?

Für Clang spielt derzeit die Reihenfolgen der case-Liste eine
Rolle. Ich würde angesichts des eben gesagtem sogar vermuten,
dass Clang damit fallwise den Vorgaben von C folgt: Deklariert
man die Schalter-Variable const, ist die Ausgangslage jedenfalls
eine andere.

Für eine einfache Fallunterscheidung, die z.B. die Konstanten
in absteigender Folge auflistet, sehe ich sehr wohl eine
Sprungtabelle nach der Übersetzung. Varianten in anderen Fällen.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Helmut Schellong
2016-08-29 12:21:11 UTC
Permalink
Post by G.B.
Post by Helmut Schellong
Clang optimiert switch() nicht!
Damit nicht noch eine fragwürdige Verallgemeinerung zu
falschen Annahmen über Clang führt, wäre möglicherweise eine
präzisierende Formulierung angmessen gewesen. "Ich habe
mal ein Programm gehabt, für das Clang wie folgt ..."
Ansonsten verfolgt auch Clang eine Strategie für die
Optimierung von switch, von deren Funktionsweise man
sich ein Bild machen kann. Und Sprungtabellen sind darin
eingeschlossen.
Wenn clang nur eine Sprungtabelle generiert, wenn die case #:
um je 1 steigen, so ist das für mich keine Optimierung,
sondern ein stumpfes Nachmachen der Quelle.
Post by G.B.
Z.B. einen Test, der einige Formen von switches
durchspielt, in verschiedenen Arrangements.
Hatte ich letztes Jahr gemacht.
Post by G.B.
Da fängt schon damit an, dass in C u.U. erlaubt ist, der
untersuchten Variablen in einem Zweig der Fallunterscheidung
einen Wert zuzuweisen. C-Formalisten: Was ist dann mit
der Sprungtabelle und wie weit kann die Analyse des compilers
reichen?
Das hat aber nichts mit 'Sprungtabelle: Ja|Nein' zu tun.
Post by G.B.
Für Clang spielt derzeit die Reihenfolgen der case-Liste eine
Rolle. Ich würde angesichts des eben gesagtem sogar vermuten,
dass Clang damit fallwise den Vorgaben von C folgt: Deklariert
man die Schalter-Variable const, ist die Ausgangslage jedenfalls
eine andere.
Das finde ich mehrfach abstrus.

Für gcc ist die Reihenfolge nur nicht egal, wenn durchgefallen wird.
Der Verlauf gelangt ja durch 'break;' stets hinter das Ende
des 'switch() {}'.
Daher ist die Reihenfolge egal.

Auch die Schalter-Steuervariable muß hinsichtlich der oben
angesprochenen Eigenschaften egal sein.
Hier: 'switch (jump)' muß der Integer signed char bis
unsigned long long verwertet/abgegriffen werden.
Alles andere muß egal sein.

selection-statement:
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
If a converted value matches that of the promoted controlling expression,
control jumps to the statement following the matched case label.

Ich lese im C11 nichts über unterschiedliche Behandlung, wegen
nachträglicher Veränderung des Wertes von 'switch (jump)'
oder wegen 'const' oder ...
Es ist ein beliebig großer Ausdruck, dessen Wert an einem
bestimmten Ort und Zeitpunkt festgestellt und nur zu einem Sprung
(in Quelle) verwertet werden soll. Nach dem Sprung ist alles egal.
Post by G.B.
Für eine einfache Fallunterscheidung, die z.B. die Konstanten
in absteigender Folge auflistet, sehe ich sehr wohl eine
Sprungtabelle nach der Übersetzung. Varianten in anderen Fällen.
Ich hatte 24.06.2015 einen Thread "clang zeigt auch Negativa"
begonnen:
============================================================
Zwei Dinge kann ich berichten:

Die Doku zu clang ist sehr dünn.
Auch das Handbuch auf der Webseite.
Auch clang --help hilft da nicht.
Ich bin dazu übergegangen, die gcc-Doku zu lesen,
um clang-Optionen herauszufinden.

clang verwendet KEINE Sprungtabelle, falls die
case 3: case 4: case 5: .. case 66: case 67:
nicht um 1 steigend sind, sondern beispielsweise
alle(!) um 4 steigend sind.

jmpq *.LJTI4_0(,%rcx,8)

Vorstehend ein Tabellensprung - nur bei 1er-Steigung.
Vor etlichen Jahren (vielleicht 15) hat gcc schon
in Fällen von 2 4 8 etc. %rcx 1 2 3 Bit >>geshiftet, um
die Distanz zu normieren.
clang zieht es leider vor, 50 Vergleiche zu machen,
if (s==11) ...
if (s==12) ...
...
if (s==54) ...
if (s==55) ...
bis die richtige Stelle erreicht ist.
Stärkere Optimierung ändert nichts daran.
Ich hatte einen 4er-Abstand, um bei 3 Werten
evtl. Bits 1 2 3 hinzuzufügen: case HULKO|2:
Dies Konzept kann ich mir abschminken.

.........................................................

Dann ist das Optimierungsverhalten bei 'switch () { ...' enorm
wichtig!
Es gibt Compiler, die mehrere Optionen zur Verfügung stellen, um
speziell die Optimierung von 'switch ...' zu steuern.
Die Information, die ich gab, kann folglich wichtig bis sehr wichtig
für so manchen sein.

.........................................................

Ernstzunehmende C-Programmierer sollten sich auch dafür interessieren.

Eigenschaften von Compilern können auf die C-Ebene zurückschlagen
und andere Konzepte gestatten oder erzwingen.
(Beispielsweise habe ich einen anderen Wertabstand wählen müssen.)
Insofern ist dieser Zusammenhang OnTopic.

clang scheint 'switch' gar nicht zu optimieren.
Eine Sprungtabelle in jedem Fall ist meiner Meinung nach Standard.

Ich kenne clang aus zwei speziellen Gründen:
o In meinem C-Buch 3.Auflage gibt es ein großes Kapitel C11.
Das ist mit clang gemeinsam erarbeitet worden, denn der
kann C11.
o Ich arbeite seit etwa 2000 mit FreeBSD.
Dort ist seit Release 10.0 clang der Standard-Compiler,
der gcc ablöste.

Man sprach von dem großen Vorteil(?) des clang, nämlich daß der
sehr schnell kompiliert.
Ich weiß/ahne jetzt auch, warum.

Als Ersatz eines switch() kann ein Array aus Funktionspointern dienen.
Etwa [100] reichen aus für z.B. einen Parser.
Es gibt da interessante Aspekte:
Beispielsweise können Funktionen auf einigen Positionen
die Funktionspointer dynamisch austauschen.

..........................................................

Ich habe mir gcc5 installiert.
Und siehe da, er macht grundsätzlich Sprungtabellen.
Auch bei abgeschalteter Optimierung -O0 !
So muß es auch sein.

clang machte bei 8 switches null Sprungtabellen.
Auch bei -O2 nicht.
Er zog gigantische cmp-jx-jmp-Gefrickel vor.
Eine einzige Tabelle machte clang, nachdem ich einen
durchgehenden case-Wertabstand von 1 herstellte.
Ein durchgehender Wertabstand von 4 genügte ihm nicht.
gcc macht da einfach sw>>=2; vor dem *jump.

Ich bewerte dieses Verhalten von clang quasi als Bug.

..........................................................

Ich habe jetzt Geschwindigkeitsmessungen gemacht.
Beispiel:
3.460u 0.000s 0:03.47 99.7% 759+469k 0+0io 0pf+0w
Loop 10000000

Sehr interessant!:
gcc5 4.98 3.70 3.54 3.4 bei -O0 -O1 -O2 -O3
clang 6.85 3.45 3.76 3.7 bei -O0 -O1 -O2 -O3

clang ist also in der Summe besser, bei -O1,
meiner Standard-Opt seit Jahrzehnten.
Aber nur, wenn man bei switch() die Konzepte so
wählt, daß die case-Werte je um 1 steigen!

7.024u 0.000s 0:07.03 99.8% 757+467k 0+0io 0pf+0w

Das Tempo halbiert sich, wenn das nicht getan wird!
(Ich habe hier alle case-Werte um 4 steigen lassen.)

Ich hatte also absolut Recht mit meiner Meckerei.
Sprungtabellen wegzulassen ergibt ganz miserable
Programm-Performance!

..........................................................

Es geht weiter:

C-Quelle:
memset(&o, 0, sizeof(o)); //size=32

gcc5:
movq $0, 136(%rsp)
movq $0, 128(%rsp)
movq $0, 144(%rsp)
movq $0, 152(%rsp)

clang:

xorl %eax, %eax
movq %rax, -869392(%rbp)
movq %rax, -869352(%rbp)
movl $0, %eax
movq %rax, -869408(%rbp)
movl $0, %eax
movq %rax, -869368(%rbp)
movl $0, %eax
movq %rax, -869512(%rbp)
movl $0, %eax
movq %rax, -869568(%rbp)
movl $0, %eax
movq %rax, -869432(%rbp)
movl $0, %edx
movl $0, %eax
movq %rax, -869448(%rbp)
movl $0, %eax
movq %rax, -869552(%rbp)
movl $0, %eax
movq %rax, -869400(%rbp)
movl $0, %eax
movq %rax, -869560(%rbp)
movl $0, %eax
movq %rax, -869416(%rbp)
movl $0, %eax
movq %rax, -869480(%rbp)

Es geht mir um die unsinnigen Wiederholungen von 'mov 0,eax'.
gcc macht das nicht, hat das noch nie getan.

Warum nimmt er nicht xor edx,edx ?
Zu Beginn macht er es doch optimal.
Die Konstanten brauchen viel Platz und dauern oft länger.

Ein Compiler von Fujitsu hatte das Jahrzehnte lang getan.
Fujitsu war stolz, eine entsprechende Optimierung zu berichten.
==============================================================
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Juergen Ilse
2016-08-29 14:00:00 UTC
Permalink
Hallo,
Post by Helmut Schellong
Post by G.B.
Für Clang spielt derzeit die Reihenfolgen der case-Liste eine
Rolle. Ich würde angesichts des eben gesagtem sogar vermuten,
dass Clang damit fallwise den Vorgaben von C folgt: Deklariert
man die Schalter-Variable const, ist die Ausgangslage jedenfalls
eine andere.
Das finde ich mehrfach abstrus.
Für gcc ist die Reihenfolge nur nicht egal, wenn durchgefallen wird.
Der Verlauf gelangt ja durch 'break;' stets hinter das Ende
des 'switch() {}'.
Daher ist die Reihenfolge egal.
Es muss aber nicht zwingend hinter jedem case auch ein break folgen und
ein break koennte auch (auch wenn es schlechter Stil waere) z.B. durch
ein goto uebersprungen werden ... Es ist nicht immer trivial zu beurteilen,
ob ein "umsortieren" tatsaechlich ein aequivalentes Programm erzeugen wuerde
(und nur in dem Fall waere das umsortieren fuer den Compiler erlaubt).
Mir ist es lieber, wenn der Compiler nicht zu aggressiv zu optimieren
versucht, solange nicht absolut sicher gestellt ist, dass die Optimierung
nicht in irgend welchen (vielleicht auch exotischen) Faellen zu falschen
Ergebnissen fuehrt. Schon mit den laut Standard erlaubten Optimierungen
gibt es durchaus Quelltexte, die damit ggfs. zu falschem Programmcode
kommen. Insbesondere bei Quelltexten, die zu "Optimierungszwecken" viel
mit goto hantieren ...

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Thomas Koenig
2016-08-29 16:32:51 UTC
Permalink
Post by G.B.
Da fängt schon damit an, dass in C u.U. erlaubt ist, der
untersuchten Variablen in einem Zweig der Fallunterscheidung
einen Wert zuzuweisen. C-Formalisten: Was ist dann mit
der Sprungtabelle und wie weit kann die Analyse des compilers
reichen?
Hmm... was genau meinst du damit? Bei meinem Blick in C89 (ok, uralt)
kann ich da keine Falle feststellen.
G.B.
2016-08-29 16:57:51 UTC
Permalink
Post by Thomas Koenig
Post by G.B.
Da fängt schon damit an, dass in C u.U. erlaubt ist, der
untersuchten Variablen in einem Zweig der Fallunterscheidung
einen Wert zuzuweisen. C-Formalisten: Was ist dann mit
der Sprungtabelle und wie weit kann die Analyse des compilers
reichen?
Hmm... was genau meinst du damit? Bei meinem Blick in C89 (ok, uralt)
kann ich da keine Falle feststellen.
Wie Helmut geschrieben hat, ist auf den ersten Blick
das Sprungziel klar, sobald der Ausdruck hinter "switch"
ausgewertet ist, und was danach mit den ("vormaligen")
Bestandteilen des Ausdrucks passiert, ist soweit einerlei.
Allerdings schien mir zu dämmern, was Juergen ausgeführt hat,
nämlich dass die Wahl einer geeigneten Übersetzung von switch
weniger klar ist, sobald eine "innere Kontrollstruktur" mit
goto zu bewerten wäre. Die Zuweisung an eine Variable des
steuernden Ausdrucks verwirrt vielleicht am ehesten den
Leser. Ich stelle mir aber vor, dass auch eine "knallharte"
Herstellung von Sprungtabellen nicht automatisch immer günstig
ist. Die woanders fehlenden Skandalmeldungen lassen immerhin den
Schluss zu, dass die Wahl im Alltag nicht ganz so bedeutsam ist.

Es kam mir eher darauf an, eine allgemein negierende
Behauptung über Sprungtabellen in Clang zu relativieren.

(Da ich zudem mit internalisiertem Frühstück geschrieben
hatte, kann um so mehr verwirrt haben, dass ich vorher
goto, computed goto (ist das jetzt drin in C?), fallthrough,
Zuweisungen, Verschachtelte Schaltungen usf. mitverdauen
wollte.)
Thomas Koenig
2016-08-29 18:01:05 UTC
Permalink
Post by G.B.
Wie Helmut geschrieben hat, ist auf den ersten Blick
das Sprungziel klar, sobald der Ausdruck hinter "switch"
ausgewertet ist, und was danach mit den ("vormaligen")
Bestandteilen des Ausdrucks passiert, ist soweit einerlei.
Das würde ich auch so sehen.

Zitat aus der C89-Norm:

# The integral promotions are perfomed on the controlling expression.
# The constant expression in each case label is converted to the
# promoted type of the controlling expression. If a converted value
# matches that of the prmoted controlling expression, control jumps
# to the labeled statement.
Post by G.B.
Allerdings schien mir zu dämmern, was Juergen ausgeführt hat,
nämlich dass die Wahl einer geeigneten Übersetzung von switch
weniger klar ist, sobald eine "innere Kontrollstruktur" mit
goto zu bewerten wäre. Die Zuweisung an eine Variable des
steuernden Ausdrucks verwirrt vielleicht am ehesten den
Leser.
Das auf jeden Fall :-)

Die controlling expression (die, die in den Klammern hinter
dem Schlüsselwort switch steht), muss aber keine Variable sein,
sondern ist allgemein ein Ausdruck.
Post by G.B.
Ich stelle mir aber vor, dass auch eine "knallharte"
Herstellung von Sprungtabellen nicht automatisch immer günstig
ist.
Natürlich können auch andere Konstrukte besser sein, z.B. wenn die
Fälle eher spärlich gesät sind, beispielsweise so:

switch(myfun())
{
case -50000: printf("Hui "); break;
case 42: printf("Philosophy "); break;
default: printf("Buh "); break;
}

Das würde ich eher mit if-Abfragen erledigen.
Post by G.B.
Die woanders fehlenden Skandalmeldungen lassen immerhin den
Schluss zu, dass die Wahl im Alltag nicht ganz so bedeutsam ist.
Naja, bei gcc gibt es noch einiges Optmierungspotenzial, siehe
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70861

Was das allerdings mit goto zu tun hat, ist mir nicht so ganz klar
Ist aber auch nicht so fürchterlich wichtig.
Stefan Reuther
2016-08-29 09:33:42 UTC
Permalink
Post by Peter J. Holzer
Post by Stefan Reuther
Post by Helmut Schellong
Post by Rainer Weikusat
Eine Schleife braucht weniger Zeit als
zwei Schleifen? Das ist wenig ueberraschend.
Multiplikationen sind teuer
denn trotzdem die eine Schleife weniger Zeit braucht als zwei Schleifen
ist sie weit davon entfernt, doppelt so schnell zu sein?
Geschwindigkeitsvorteil durch kreuz-und-quer goto im Bereich
'Messfehler'? Experiment mit unbekannten Eingabedaten und unbekannter
Hardware hatte ein Ergebnis?
Soll man nun nie wieder Messungen zum Zeitbedarf von Software machen?
Wer wissenschaftlich arbeitet legt zum Beginn vor allem erstmal
nachvollziehbare Messbedingungen fest. Z.B. in Form einer kompletten
Funktion und "die ruf ich jetzt X mal auf".
Sofern dein Array keine 500 Gigabyte groß ist, ist jedenfalls die
Aussage, "for (i=0; *a>='0'&&*a<='9'; ++a) i=i*10+(*a-'0');" brauchte
7.54 Sekunden auf Rechnern neuer als einem Zuse Z3 nicht nachvollziehbar
Das bezog sich offensichtlich auf einen Benchmark, der die Funktion oft
aufruft, nicht auf einen einzigen Aufruf. Die von Helmut zitierten
Einzellaufzeiten waren in der Gegend von ein paar Nanosekunden.
Nichtsdestotrotz hab ich in diesem Thread noch keine vollständigen
Funktionen gesehen, die man in eine Messschleife hätte knoten und messen
können. Ich kann mir halt was basteln und hoffen, dass ich dabei in etwa
das behauptete tue.
Post by Peter J. Holzer
Post by Stefan Reuther
Post by Helmut Schellong
Die vorstehenden Resultate sind sehr interessant, denn ich habe da
schon Unterschiede von 1:14 in der Vergangenheit gemessen.
Es überrascht etwas, daß a2n_unrolled langsamer als a2n ist.
Eine Multiplikation ist teuer, wenn der Compiler sie einkompiliert.
Wenn er sie trickreich ersetzt durch Instruktionen, die etwa 1,5 Takte
brauchen, ist eine Multiplikation in der Quelle nicht teuer.
Wer wissenschaftlich arbeitet schaut hinterher nach, was der Compiler
generiert und warum.
Einen, der für eine Multiplikation mit der Konstanten '10' eine
Multiplikationsinstruktion generiert, habe ich unter
https://gcc.godbolt.org/ jedenfalls nicht gefunden.[1]
Wie Helmut geschrieben hat; Clang.
OK, in der Tat, auch bei https://gcc.godbolt.org/ tut der clang 3.5 das.
Der clang 3.8 nicht.

(Und selbst wenn, stehen die Chancen gut, dass der Compiler Grund zu der
Annahme hat, das sei ausreichend schnell. Dass der x86-64-Code jemals
auf einem Intel 8088 mit 128-154 Takten für IMUL läuft halte ich mal für
ausgeschlossen.


Stefan
Helmut Schellong
2016-08-29 11:05:25 UTC
Permalink
Post by Stefan Reuther
Nichtsdestotrotz hab ich in diesem Thread noch keine vollständigen
Funktionen gesehen, die man in eine Messschleife hätte knoten und messen
können. Ich kann mir halt was basteln und hoffen, dass ich dabei in etwa
das behauptete tue.
Ich sehe hier gleich mehrere vollständige Funktionen.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Helmut Schellong
2016-08-29 07:20:17 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Es gibt aber keine Garantie, daß ein Compiler stets eine Multiplikation
durch schnellere Instruktionen ersetzt. Deshalb meine goto-Wüste.
Es gibt auch keine Garantie, dass der Compiler für die goto-Wüste
effizienten Code generiert. Da ist zum einen der Sprung an sich: bei
einer Schleife geht der Compiler normalerweise davon aus, dass der
Rücksprung genommen wird und instruiert den Branch-Prediktor
entsprechend. Bei goto weiß man das nicht.
Zum anderen ist der Speicherzugriff. Das braucht Speicher und vernichtet
teuren L1-Cache. Es braucht extra Zugriffszyklen. Es braucht ggf. extra
Code für positionsunabhängige Adressierung (teuer auf i386). Es braucht
ggf. extra Adressregister. Hingegen braucht eine Multiplikation schon
auf solchen Methusalems wie K8 oder Pentium II nur einen Takt. [2]
Meine gezeigten Quellen sind mehrere Jahrzehnte alt.
Damals brauchte eine IMUL 19 Takte, eine IDIV 40 Takte.

Im Laufe der Zeit wurde u.a. IMUL immer schneller:
19 -> 5 -> 3 -> 1 Takte, so daß sich heute Assembler
und viele Handoptimierungen nicht mehr lohnen.

IDIV braucht aber auch heute noch 25 | 100 Takte.
Und meine schnellen Konversionsfunktionen gibt es für beide Richtungen.

Zur Zeit derer Entstehung brachten meine schnellen Funktionen, die
Schleifen und Multiplikation und Division vermeiden, einen absolut
durchschlagenden Erfolg.
Und heute sind sie immer noch die schnellsten.
Das sind die schnöden Fakten.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-08-29 09:26:09 UTC
Permalink
Helmut Schellong <***@schellong.biz> writes:

[...]
Post by Helmut Schellong
Zur Zeit derer Entstehung brachten meine schnellen Funktionen, die
Schleifen und Multiplikation und Division vermeiden, einen absolut
durchschlagenden Erfolg.
Und heute sind sie immer noch die schnellsten.
Das sind die schnöden Fakten.
Die schnoeden Fakten sind ungefaehr wie folgt: Jeder, der Zeit und Lust
dazu hat, kann fuer jede beliebige, ihm zur Verfuegung stehende Hardware,
eine mehr oder minder zufaellig in einer bestimmten Situation schneller
ablaufende "C Funktion" schreiben, in den meisten Faellen wahrscheinlich
sogar ohne wirren Spaghetticode zu produzieren, in dem man es dem
Compiler leichter macht, diesen wirren Spaghetticode aus einer
hochsprachlichen 'Anforderungsdefinition' heraus automatisch abzuleiten.

Das Ergebnis diese Verfahrens ist bestenfalls harmlos.
Helmut Schellong
2016-08-29 11:18:46 UTC
Permalink
Post by Rainer Weikusat
Post by Helmut Schellong
Das sind die schnöden Fakten.
Die schnoeden Fakten sind ungefaehr wie folgt: Jeder, der Zeit und Lust
dazu hat,[...] aus einer
hochsprachlichen 'Anforderungsdefinition' heraus automatisch abzuleiten.
Das Ergebnis diese Verfahrens ist bestenfalls harmlos.
Das stimmt heutzutage.

Verkündet hatte ich das schon:
=======================================================
Im Laufe der Zeit wurde u.a. IMUL immer schneller:
19 -> 5 -> 3 -> 1 Takte, so daß sich heute Assembler
und viele Handoptimierungen nicht mehr lohnen.
=======================================================
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-29 09:39:30 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Zum anderen ist der Speicherzugriff. Das braucht Speicher und vernichtet
teuren L1-Cache. Es braucht extra Zugriffszyklen. Es braucht ggf. extra
Code für positionsunabhängige Adressierung (teuer auf i386). Es braucht
ggf. extra Adressregister. Hingegen braucht eine Multiplikation schon
auf solchen Methusalems wie K8 oder Pentium II nur einen Takt. [2]
Meine gezeigten Quellen sind mehrere Jahrzehnte alt.
Auch das ist kein Qualitätsmerkmal.
Post by Helmut Schellong
Damals brauchte eine IMUL 19 Takte, eine IDIV 40 Takte.
19 -> 5 -> 3 -> 1 Takte, so daß sich heute Assembler
und viele Handoptimierungen nicht mehr lohnen.
IDIV braucht aber auch heute noch 25 | 100 Takte.
Dieses Wissen ist in Compilern ganz gut aufgehoben, nicht in Quelltext.

Deswegen generieren diese zum Beispiel für eine Division durch eine
Konstante üblicherweise eine Multiplikation mit dem Inversen.


Stefan
Rainer Weikusat
2016-08-29 10:35:02 UTC
Permalink
[...]
Post by Stefan Reuther
Post by Helmut Schellong
Damals brauchte eine IMUL 19 Takte, eine IDIV 40 Takte.
19 -> 5 -> 3 -> 1 Takte, so daß sich heute Assembler
und viele Handoptimierungen nicht mehr lohnen.
IDIV braucht aber auch heute noch 25 | 100 Takte.
Dieses Wissen ist in Compilern ganz gut aufgehoben, nicht in Quelltext.
"Begrenzt". ZB ist die Idee, vorausberechnete Konstanten fuer
Dezimalstring-nach-Zahl-Umwandlung zu benutzen, die dann nur noch
addiert werden muessen, grundsaetzlich nicht schlecht falls die
entsprechenden Tabellen-Nachschlageoperationen weniger Zeit brauchen,
als es die Multiplikationen andernfalls wuerden. ZB weil sie - ARM9 -
durch Unterroutinen durchgefuert werden muessten. Das ist eine
algorithmische Verbesserung (unter geeigneten Umstaenden) die ein
Compiler nicht durchfuehren kann. Auch wenn das gegebenenfalls
irgendwelchen "Ich will aber nicht dadrueber
nachdenken!"-Heulsusen sauer aufstoesst (die vermutlich ihr
ganz persoenliches Objektmodell in C implementieren weil sie sehr wohl
komplizierte Loesungen fuer einfache Problem haben wollen, bloss keine,
die von anderen Leuten geschrieben wurden).

Unvernuenftig wird das erst an dem Punkt, an dem man die nicht mehr
sinnvolle Idee durch wildes Herumgehacke mit dem Ziel, ein paar
Machineninstruktionen weniger generiert zu bekommen, kuenstlich am Leben
zu erhalten versucht (und das unter Umstaenden noch nicht mal erreicht).
Helmut Schellong
2016-08-29 11:16:08 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Meine gezeigten Quellen sind mehrere Jahrzehnte alt.
Auch das ist kein Qualitätsmerkmal.
Weder hier noch woanders habe ich das behauptet.
Post by Stefan Reuther
Post by Helmut Schellong
Damals brauchte eine IMUL 19 Takte, eine IDIV 40 Takte.
19 -> 5 -> 3 -> 1 Takte, so daß sich heute Assembler
und viele Handoptimierungen nicht mehr lohnen.
IDIV braucht aber auch heute noch 25 | 100 Takte.
Dieses Wissen ist in Compilern ganz gut aufgehoben, nicht in Quelltext.
Deswegen generieren diese zum Beispiel für eine Division durch eine
Konstante üblicherweise eine Multiplikation mit dem Inversen.
Bei der Umkehrfunktion itoa_F verwendet man
standard-mäßig:
do *op-- = (byte)(i%10+'0'); while (i/=10, i);
Also Restwertdivision plus Division.
Das ist jedenfalls teuer.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Stefan Reuther
2016-08-29 20:32:09 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Post by Helmut Schellong
19 -> 5 -> 3 -> 1 Takte, so daß sich heute Assembler
und viele Handoptimierungen nicht mehr lohnen.
IDIV braucht aber auch heute noch 25 | 100 Takte.
Dieses Wissen ist in Compilern ganz gut aufgehoben, nicht in Quelltext.
Deswegen generieren diese zum Beispiel für eine Division durch eine
Konstante üblicherweise eine Multiplikation mit dem Inversen.
Bei der Umkehrfunktion itoa_F verwendet man
do *op-- = (byte)(i%10+'0'); while (i/=10, i);
Also Restwertdivision plus Division.
Das ist jedenfalls teuer.
In etwa diesen Code habe ich unter https://gcc.godbolt.org/ in mehrere
Compiler gesteckt und, soweit ich das erkennen kann, erzeugt keiner
dafür eine Division, wenn man ihn optimieren lässt.

void itoa(char* p, int n)
{
do {
*--p = '0' + (n%10);
n /= 10;
} while (n != 0);
}


Stefan
Helmut Schellong
2016-08-29 13:35:08 UTC
Permalink
Post by Stefan Reuther
Es gibt auch keine Garantie, dass der Compiler für die goto-Wüste
effizienten Code generiert. Da ist zum einen der Sprung an sich: bei
einer Schleife geht der Compiler normalerweise davon aus, dass der
Rücksprung genommen wird und instruiert den Branch-Prediktor
entsprechend. Bei goto weiß man das nicht.
Absolute Sprünge sind doch ideal!
Da wird gar keine Verzweigungsvorhersage benötigt.
Desweiteren kann danach pauschal Padding stehen.

Der Compiler kann doch nicht die Branch prediction instruieren.
Post by Stefan Reuther
Zum anderen ist der Speicherzugriff. Das braucht Speicher und vernichtet
teuren L1-Cache. Es braucht extra Zugriffszyklen. Es braucht ggf. extra
Code für positionsunabhängige Adressierung (teuer auf i386). Es braucht
ggf. extra Adressregister.
Du machst das irgendwie alles 'sehr schlimm'.
Ich habe von Intel developer-manuals, mit bis über 4600 Seiten,
in denen das alles nicht so schlimm aussieht.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-08-29 14:11:53 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Es gibt auch keine Garantie, dass der Compiler für die goto-Wüste
effizienten Code generiert. Da ist zum einen der Sprung an sich: bei
einer Schleife geht der Compiler normalerweise davon aus, dass der
Rücksprung genommen wird und instruiert den Branch-Prediktor
entsprechend. Bei goto weiß man das nicht.
Absolute Sprünge sind doch ideal!
Da wird gar keine Verzweigungsvorhersage benötigt.
Desweiteren kann danach pauschal Padding stehen.
Der Compiler kann doch nicht die Branch prediction instruieren.
Fuer x86 allerdings nicht. Hier scheint etwas mit dem Intel
'static branch prediction algorithm' durcheinandergekommen zu sein (in
Abwesenheit von anderer Information werden Rueckwaertspruenge als
'ausgefuehrt' vorhergesagt und Vorwaertsspruenge als 'nicht
ausgefuerht'). IA-64 hat sogenannte 'branch predictions hints'.
Stefan Reuther
2016-08-29 20:44:16 UTC
Permalink
Post by Helmut Schellong
Post by Stefan Reuther
Es gibt auch keine Garantie, dass der Compiler für die goto-Wüste
effizienten Code generiert. Da ist zum einen der Sprung an sich: bei
einer Schleife geht der Compiler normalerweise davon aus, dass der
Rücksprung genommen wird und instruiert den Branch-Prediktor
entsprechend. Bei goto weiß man das nicht.
Absolute Sprünge sind doch ideal!
Da wird gar keine Verzweigungsvorhersage benötigt.
Desweiteren kann danach pauschal Padding stehen.
Der Compiler kann doch nicht die Branch prediction instruieren.
Natürlich kann er das. Wenn der Befehlssatz dafür keine Bits vorsieht
(manche tun das, manche nicht), dann über solche Hinweise wie die
Anordnung des Codes ("Rücksprünge werden standardmäßig als 'taken'
vorhergesagt").
Post by Helmut Schellong
Post by Stefan Reuther
Zum anderen ist der Speicherzugriff. Das braucht Speicher und vernichtet
teuren L1-Cache. Es braucht extra Zugriffszyklen. Es braucht ggf. extra
Code für positionsunabhängige Adressierung (teuer auf i386). Es braucht
ggf. extra Adressregister.
Du machst das irgendwie alles 'sehr schlimm'.
Ich habe von Intel developer-manuals, mit bis über 4600 Seiten,
in denen das alles nicht so schlimm aussieht.
Natürlich schreibt Intel nicht in ihre Manuals, wo ihre Chips schlecht
sind. Das muss man sich dann schon aus mehreren Kapiteln selber
zusammenrechnen.

Für positionsunabhängige Adressierung braucht man ein 'call 1F; 1: pop
ebx' Päärchen, was den Return-Cache durcheinanderbringt; zusätzlich aber
natürlich noch entsprechende Adresstabellen.

Um Tabellen aus dem RAM in den Cache zu laden, muss man aus dem
schnellen Prozessorkern in langsamen Speicher. Hier [1] meint einer was
von knapp 200 Zyklen für einen vollständigen Cache-Miss. Da geht eine
Menge Multiplikation rein. Freilich zahlt man das nicht am Stück, aber
irgendwann ist halt der Punkt erreicht, wo der Cache-Footprint des
Programms selbiges langsamer macht.


Stefan

[1]
http://stackoverflow.com/questions/1126529/what-is-the-cost-of-an-l1-cache-miss
Rainer Weikusat
2016-08-29 21:52:37 UTC
Permalink
Post by Stefan Reuther
Post by Helmut Schellong
Post by Stefan Reuther
Es gibt auch keine Garantie, dass der Compiler für die goto-Wüste
effizienten Code generiert. Da ist zum einen der Sprung an sich: bei
einer Schleife geht der Compiler normalerweise davon aus, dass der
Rücksprung genommen wird und instruiert den Branch-Prediktor
entsprechend. Bei goto weiß man das nicht.
Absolute Sprünge sind doch ideal!
Da wird gar keine Verzweigungsvorhersage benötigt.
Desweiteren kann danach pauschal Padding stehen.
Der Compiler kann doch nicht die Branch prediction instruieren.
Natürlich kann er das. Wenn der Befehlssatz dafür keine Bits vorsieht
(manche tun das, manche nicht), dann über solche Hinweise wie die
Anordnung des Codes ("Rücksprünge werden standardmäßig als 'taken'
vorhergesagt").
Dann instruiert er 'die Branchprediction' aber gerade nicht. Sondern er
erzeugt Code, der zu ihren 'Vorurteilen' passt, weil diese feststehen.
Thomas Koenig
2016-08-28 17:51:04 UTC
Permalink
Post by Rainer Weikusat
Multiplikationen sind teuer
Für Multiplikationen mit kleinen Konstanten sind gerade im
Integer-Bereich ein paar nette Tricks möglich. Beispiel,
da das Diskussionsthema atoi war:

int m10(int a)
{
return a * 10;
}

wird mit einem neuen gcc übersetzt zu

leal (%rdi,%rdi,4), %eax
addl %eax, %eax
ret

was schon mal deutlich schneller geht als eine Multipilikation.
Helmut Schellong
2016-08-28 18:15:03 UTC
Permalink
Post by Thomas Koenig
Post by Rainer Weikusat
Multiplikationen sind teuer
Für Multiplikationen mit kleinen Konstanten sind gerade im
Integer-Bereich ein paar nette Tricks möglich. Beispiel,
int m10(int a)
{
return a * 10;
}
wird mit einem neuen gcc übersetzt zu
leal (%rdi,%rdi,4), %eax
addl %eax, %eax
ret
was schon mal deutlich schneller geht als eine Multipilikation.
Ja, das postete ich gestern:
leal (%rax,%rax,4), %eax
leal -48(%rdx,%rax,2), %eax
Damit übersetzte der gcc5:
i=i*10+(*a-'0');
den gesamten Schleifenkörper:
eax = eax+4*eax
eax =(edx+2*eax)-'0'

clang tat das nicht, weshalb die Funktion statt über 7
sogleich über 9 Sekunden dauerte.
Vor langer Zeit dauerte IMUL 19 Takte.
Kann sein, daß IMUL inzwischen deutlich schneller ist.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
G.B.
2016-08-25 07:49:59 UTC
Permalink
Post by Claus Reibenstein
Wer ein Werkzeug benutzen möchte, sollte
wissen, wie er damit umzugehen hat.
Sagt der Schelm.

Wer ein Rührei mit einem Messer schlägt, verdient,
bewundert zu werden. Und wer das nicht mindestens so
gut kann wie ich, der versteht eben nichts vom Kochen!

(Moral: Es kommt meistens aufs Rührei an, kaum auf
die kunstvolle Verwendung bestimmten Rührwerkzeugs.)

Algol 68, Common Lisp, Swift, Julia, Ada, Haskell ... mit
unzweideutig schlichten Literalen, alles eben Werkzeuge für
unbegabte Handwerker, nicht wahr.

https://www.rosettacode.org/wiki/Literals/Integer#Common_Lisp
Post by Claus Reibenstein
Für mich ist das systematisch genug, und für andere auch.
Für andere wiederum nicht. Und wiederum andere instrumentalisieren
diese historischen Spezialismen für fortgesetzte Unentbehrlichkeit
von Spezialwissen im korrekten Umgang mit Ziffernfolgen aus
einem korrekt hergenommenen formal-sprachlichen Kontext, in welchem
sie sich zu Hause fühlen dürfen und sich nie vergreifen.
Komme da jemand auf die Idee, das mühsam aber gern erworbene
kulturelle Kapital: die Fähigkeit zur kontextuell korrekten
Interpretation von mit '0' beginnenden Ziffernfolgen bestimmter
Längen weniger verkäuflich zu machen. Beruhigend, dass diese Gefahr
nicht besteht, solange Alt-Programme nicht syntaktisch transformiert
werden können oder sollen, auch wenn die C-Norm das technisch
möglich machen sollte.

Die Gefahr des menschlichen Verlustes von impliziten Zahlenbasen oder
der Entwertung des besonderen Vorstellungsvermögens bei der Umsetzung
von 0xabcd in die richtige Bitfolge, nebst Adressierung, ist auch
dann etwas gebannt, wenn die Definition neuerer Sprachen bequem auf
die Implemetierungssprache zurückfällt. Noch ist das aus historischen
Gründen häufig das Unix-universitäre C gewesen. Die Mode, freilich,
scheint sich mit der Popularität von 0b1010 zu ändern.

Auch nett:

$ perldoc -f oct

Denn wer die scheinbar abwegige Assoziation von "8" angesichts
von "oct" imaginiert, der weiß eben nicht, wie man dieses Werkzeug
richtig benutzt. Nicht wahr.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Hermann Riemann
2016-08-24 14:11:02 UTC
Permalink
Post by Helmut Schellong
Hallo,
0o37745 für Oktal
0d10011 für Dual
oder 0b100.. für binär
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
Lässt sich wegen vieler alter Quellen nicht so einfach ändern.
Eine neue compiler option wäre erforderlich.
Allerdings wäre das wieder eine Fehlerquelle
weil kein compiler erkennen kan,
was für die jeweilige source passend wäre.

Hermann
der die Sünden von C bei den
integer.. Datentypen für schlimmer hält.
--
www.hermann-riemann.de
Helmut Schellong
2016-08-24 14:42:07 UTC
Permalink
Post by Hermann Riemann
Post by Helmut Schellong
Hallo,
0o37745 für Oktal
0d10011 für Dual
oder 0b100.. für binär
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle.
Lässt sich wegen vieler alter Quellen nicht so einfach ändern.
Die alte Form muß bleiben!

Aber es würde sicher viele freuen, eine neue, bessere Form
auch nutzen zu können.

Binär gehört zu einer anderen Bedeutungsgruppe
als die Wörter oktal, dual, ...
Nämlich: binär, unär, ternär, monadisch, dyadisch, triadisch.
Logarithmus Dualis = Logarithmus zur Basis 2.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
David Seppi
2016-08-24 14:43:18 UTC
Permalink
Post by Hermann Riemann
Hermann
der die Sünden von C bei den
integer.. Datentypen für schlimmer hält.
Welche z.B.?
--
David Seppi
1220 Wien
Hermann Riemann
2016-08-24 15:06:18 UTC
Permalink
Post by David Seppi
Post by Hermann Riemann
Hermann
der die Sünden von C bei den
integer.. Datentypen für schlimmer hält.
Welche z.B.?
Das sie nicht von Anfang an wie bei FORTRAN
integer*1 integer*2 integer *4
als int.1 int.2 int.4 verwendet haben.
So Produkte wie QT und SDL haben da häßliche #define
Umgehungen.

Dann macht die gleiche Bezeichnung
int.1 und char Probleme,
sowohl beim debuggen als auch wenn man selber
z.B. per printf Werte ausgeben will,
weil man da nicht mehr weiß, ist das Buchstabe oder Zahl.
( oder bool)

Und vielleicht aktuell:

Warum nicht bool.1 bool.2 bool.4 bool:1 ( bit)
char.1 char.2 char.4 char.utf ( letztere systemabhängig)
enum.1 enum.2 ..

..

Hermann
der bei Rechner wie Arduino
auch ab bit-masken denkt um z.B. status-Register
gut lesbar über struct zu hantieren.
--
www.hermann-riemann.de
Rainer Weikusat
2016-08-24 20:51:24 UTC
Permalink
Hermann Riemann <***@hermann-riemann.de> writes:

[...]
Post by Hermann Riemann
Warum nicht bool.1 bool.2 bool.4 bool:1 ( bit)
'Bool' sollte es als Typ ueberhaupt nicht geben.
Hermann Riemann
2016-08-25 06:28:21 UTC
Permalink
Post by Rainer Weikusat
Post by Hermann Riemann
Warum nicht bool.1 bool.2 bool.4 bool:1 ( bit)
'Bool' sollte es als Typ ueberhaupt nicht geben.
Zum debuggen ist es schon nützlich,
ebenso wie getrenntes char in int.

Und es erhöht die Lesbarkeit von Programmen

Hermann
der in seiner privaten Standdardbibliothek
seit Jahrzehnten die Zeilen
#define bool unsigned char
#define true 1
#define fals0 0
enthält.
--
www.hermann-riemann.de
Thomas Jahns
2016-08-25 08:45:50 UTC
Permalink
Post by Rainer Weikusat
'Bool' sollte es als Typ ueberhaupt nicht geben.
also ich habe schon festgestellt, dass z.B. xlC daraus zu den nachfolgenden
Berechnungen passende Masken kompiliert, um nachfolgende Ausdruecke
verzweigungsfrei zu berechnen. Das stelle ich mir auf Compiler-Seite auch
einfacher vor als mit int. Entsprechend kann ich _Bool so unnuetz nicht finden.

Thomas
Juergen Ilse
2016-08-25 09:12:33 UTC
Permalink
Hallo,
Post by Thomas Jahns
Post by Rainer Weikusat
'Bool' sollte es als Typ ueberhaupt nicht geben.
also ich habe schon festgestellt, dass z.B. xlC daraus zu den nachfolgenden
Berechnungen passende Masken kompiliert, um nachfolgende Ausdruecke
verzweigungsfrei zu berechnen. Das stelle ich mir auf Compiler-Seite auch
einfacher vor als mit int. Entsprechend kann ich _Bool so unnuetz nicht finden.
Bei xlC werden boese Erinnerungen wach ... Das war doch der Compiler, bei
dem man tunlichst die locale-Einstellungen (zumindest aber LC_NUMERIC) auf
POSIX stehen lassen sollte, weil der compiler ansonsten ggfs. Zahlenwerte
im Quelltext fehlinterpretiert ...

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.
Stefan Reuther
2016-08-25 10:51:59 UTC
Permalink
Post by Thomas Jahns
Post by Rainer Weikusat
'Bool' sollte es als Typ ueberhaupt nicht geben.
also ich habe schon festgestellt, dass z.B. xlC daraus zu den
nachfolgenden Berechnungen passende Masken kompiliert, um nachfolgende
Ausdruecke verzweigungsfrei zu berechnen. Das stelle ich mir auf
Compiler-Seite auch einfacher vor als mit int. Entsprechend kann ich
_Bool so unnuetz nicht finden.
Die Aversion gegenüber '_Bool' kann ich auch nicht nachvollziehen. Das
Compilieren von Masken dürfte allerdings auch einfach über eine
Wertebereichsanalyse funktionieren ("diese Variable hat den Wert 0 oder
1; eine Maske '0x0000 oder 0xFF00' erhalte ich also durch Multiplikation
mit 0xFF00").


Stefan
Rainer Weikusat
2016-08-26 19:54:35 UTC
Permalink
Post by Stefan Reuther
Post by Thomas Jahns
Post by Rainer Weikusat
'Bool' sollte es als Typ ueberhaupt nicht geben.
also ich habe schon festgestellt, dass z.B. xlC daraus zu den
nachfolgenden Berechnungen passende Masken kompiliert, um nachfolgende
Ausdruecke verzweigungsfrei zu berechnen. Das stelle ich mir auf
Compiler-Seite auch einfacher vor als mit int. Entsprechend kann ich
_Bool so unnuetz nicht finden.
Die Aversion gegenüber '_Bool' kann ich auch nicht nachvollziehen.
Fuer sich genommen hat eine Zahl keine Bedeutung. Die ergibt sich erst
dadurch, dass sie in einem bestimmten Kontext interpretiert
wird. Genauso sieht das auch in C aus: Die Sprache definiert
verschiedene Operanden, die irgendwelche Berechnungen repraesentieren,

a + b

addiert a und b und gibt das Resultat zurueck,

a > b

vergleicht a und b und das Ergebnis ist 1 oder 0, je nachdem ob a
groesser als b war oder nicht. C definiert auch eine Menge von
Kontrollstrukturen, zb

if (<expr>) <statement0>; else <statement1>;

Falls die Auswertung von <expr> einen Wert ungleich 0 ergab, wird
<statement0> ausgefuehrt, andernfalls <statement1>. Und <expr> kann
sowohl a + b als auch a > b sein. Auch

a + (a > b)

ist ein gueltiger C-Ausdruck. Das folgt offensichtlich daraus, dass alle
diese Ausdruecke Zahlenresultate haben.

Ich halte das fuer eine sinnvolle Verallgemeinerung weil man mit
Computern nicht 'Mathematik', dh, Wahr- oder Falschheit von
(formalen) Aussagen aus Axiomen herzuleiten versucht, sondern 'Rechnen'
betreibt, 'in irgendeinem Sinne praktische nuetzliche Operationen mit
Zahlen'. Solange man sich darauf beschraenkt, Vergleichausdruecke als
Praedikate zu benutzen, kann man den Unterschied ignorieren aber
manchmal kann es sehr praktisch sein, sie als komplexe Operatoren zu
benutzen.
Stefan Reuther
2016-08-27 09:05:20 UTC
Permalink
Post by Rainer Weikusat
Post by Stefan Reuther
Post by Thomas Jahns
Post by Rainer Weikusat
'Bool' sollte es als Typ ueberhaupt nicht geben.
also ich habe schon festgestellt, dass z.B. xlC daraus zu den
nachfolgenden Berechnungen passende Masken kompiliert, um nachfolgende
Ausdruecke verzweigungsfrei zu berechnen. Das stelle ich mir auf
Compiler-Seite auch einfacher vor als mit int. Entsprechend kann ich
_Bool so unnuetz nicht finden.
Die Aversion gegenüber '_Bool' kann ich auch nicht nachvollziehen.
Fuer sich genommen hat eine Zahl keine Bedeutung. Die ergibt sich erst
dadurch, dass sie in einem bestimmten Kontext interpretiert
wird. Genauso sieht das auch in C aus: Die Sprache definiert
verschiedene Operanden, die irgendwelche Berechnungen repraesentieren,
[...]
Auch
a + (a > b)
ist ein gueltiger C-Ausdruck. Das folgt offensichtlich daraus, dass alle
diese Ausdruecke Zahlenresultate haben.
Daran ändert ja '_Bool' nichts, das ist halt einfach eine Variable, die
eben nur die Werte 0 und 1 speichern kann. Es ist halt immer gut, dem
Compiler möglichst genau zu sagen, was man will.

Zugegeben darf ein Compiler einer C-oiden Sprache da nicht allzuviel
Gewinn draus ziehen, und z.B. mehrere _Bool in eine einzelne
Speicherzelle packen, aber wenn es wenigstens an einigen Stellen dazu
führt, dass der Compiler besseren Code oder bessere Warnungen generieren
kann, wär's mir das wert.


Stefan
Thomas Jahns
2016-08-25 08:42:29 UTC
Permalink
Post by Hermann Riemann
Das sie nicht von Anfang an wie bei FORTRAN
integer*1 integer*2 integer *4
als int.1 int.2 int.4 verwendet haben.
Das ist mitnichten Fortran (oder meinetwegen auch FORTRAN) sondern eine
weitverbreitete Erweiterung von IBM fuer die S/360 WIMRE (habe nie an einer
derartigen Maschine gearbeitet, ist einfach vor meiner Zeit), die den Weg in
fast alle Implementierungen gefunden hat, aber nie standardisiert wurde. Seit
Fortran 90 gibt es auch noch einen ueberlegenen Mechanismus (type-kinds) der nix
mit der *-Notation gemein hat.

Thomas
Stefan Reuther
2016-08-25 08:37:13 UTC
Permalink
Post by Hermann Riemann
Post by David Seppi
Post by Hermann Riemann
Hermann
der die Sünden von C bei den
integer.. Datentypen für schlimmer hält.
Welche z.B.?
Das sie nicht von Anfang an wie bei FORTRAN
integer*1 integer*2 integer *4
als int.1 int.2 int.4 verwendet haben.
Welchen Wertebereich hätte denn 'integer*1' bzw. 'int.1' auf einem
Prozessor mit CHAR_BIT=24?
Post by Hermann Riemann
So Produkte wie QT und SDL haben da häßliche #define
Umgehungen.
Die verwenden 'typedef'. 'typedef' gibt es jetzt schon seit mindestens
28 Jahren, es gibt keinen Grund, da noch #define zu verwenden. Mit
standardisierten Namen gibt es solche typedefs unter <stdint.h> seit
mindestens 17 Jahren. Auch die sollte man verwenden.


Stefan
Thomas Koenig
2016-08-27 11:31:38 UTC
Permalink
Post by Hermann Riemann
Das sie nicht von Anfang an wie bei FORTRAN
integer*1 integer*2 integer *4
Das war nie normgerechtes Fortran, sondern eine IBM-Erweiterung.

Modernes Fortran hat ein anderes Konzept, in dem man die minimale
Anzahl von Stellen einer Integer-Zahl angibt, die man benötigt. Es
gibt auch Entsprechungen zu den C-Typen int8_t etc.
Stephan Lahl
2016-08-29 17:34:40 UTC
Permalink
Post by Helmut Schellong
Hallo,
0o37745 für Oktal 0d10011 für Dual
Bei d erwartet man Dezimal. Besser b.
Post by Helmut Schellong
Oktal per führender 0 ist für viele Programmierer eine Falle. Und es ist
nicht systematisch, wie es gemeinsam mit 0xFFA und 0o377 sein könnte.
Wen interessiert bei C noch Systematik?
Post by Helmut Schellong
Solch eine Einführung wäre konfliktfrei.
Es gibt keine konfliktfreie Einführung. Nicht bei Programmiersprachen.
Helmut Schellong
2016-08-30 10:19:23 UTC
Permalink
Post by Stephan Lahl
Post by Helmut Schellong
Solch eine Einführung wäre konfliktfrei.
Es gibt keine konfliktfreie Einführung. Nicht bei Programmiersprachen.
Welche Konflikte würden denn auftreten, wenn der nächste C-Standard
zusätzlich 0b10011 und 0o377 einführte?

Die diversen C-Standards haben viel Neues eingeführt.
Auch Dinge, die 100-fach komplexer sind als 0o377.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Loading...