Forum: PC-Programmierung Lua: Bitoperationen mit Bit32 oder Multiplikation


von Jürgen W. (lovos)


Lesenswert?

Hallo,
wenn ich aus zwei words ein dword machen will, kann ich ja schreiben
1
dwo = lowo + 0x10000 * hiwo

das modul 'bit32' bietet aber direkte Bit-Ops an (bei 5.2 schon fest 
dabei)
1
dwo = bit32.bor(lowo, bit32.lshift(hiwo,16))

Wie ist das in Sachen Lesbarkeit und Rechengeschwindigkeit zu 
vergleichen?
Mir persönlich gefällt die erste Variante besser.

Ok, beim Aufteilen müsste man schreiben
1
hiwo= math.floor( dwo / 0x10000)
2
lowo= dwo - 0x10000*hiwo

von Karl H. (kbuchegg)


Lesenswert?

Jürgen W. schrieb:

> Wie ist das in Sachen Lesbarkeit und Rechengeschwindigkeit zu
> vergleichen?

Sieh zu, dass du einen Blick auf den erzeugten Code kriegst.

Für einen ordentlichen Compiler ist es ein leichtes, für beide Versionen 
den gleichen Code zu erzeugen. Das Vereinfachen derartiger 
Multiplikationen zu Bitoperationen bzw. zu einfacheren Versionen, die 
dasselbe Ergebnis haben, machen übliche Compiler seit mehr als 40 Jahren 
standardmässig. Ist ja auch kein wirkliches Problem.

von Jürgen W. (lovos)


Lesenswert?

> du einen Blick auf den erzeugten Code

Lua wird interpretiert.
D.h. ich müsste in den Lua-Interpreter schauen, wie er 
Multiplitkationen/Divisionen mit 2er-Potenzen händelt.
Ich glaube nicht, dass er diese Zahlen erkennt und statt 
Multiplikationen/Div. die shift-Operation aufruft. Denn der Interpreter 
ist sehr klein (ca. 40 kB)

von Andreas B. (andreasb)


Lesenswert?

Jürgen W. schrieb:
> Wie ist das in Sachen Lesbarkeit und Rechengeschwindigkeit zu
> vergleichen?
> Mir persönlich gefällt die erste Variante besser.

Dann ist ja schon gewählt, oder?

Oder hast du Performance Probleme? z.B. CHDK lässt ja Lua auf den Canon 
Digicams laufen, die sind nicht besonders schnell...

Wenn du die Performance messen willst: Mach eine Schliefe, 10'000 
durchläufe und miss die Zeit...


mfg Andreas

von Karl H. (kbuchegg)


Lesenswert?

Jürgen W. schrieb:

> Lua wird interpretiert.

Das alleine ist noch kein Hindernisgrund.
1
Lua programs are not interpreted directly from the textual Lua file,
2
but are compiled into bytecode which is then run on the Lua virtual machine.

Und eine derartige Ersetzung ist ja jetzt nicht gerade kompliziert.

von Salewski, Stefan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das alleine ist noch kein Hindernisgrund.

Eher doch, und Deine obige Bemerkung

>Sieh zu, dass du einen Blick auf den erzeugten Code kriegst.

hat mich schon etwas erschreckt.

Lua wird, wie auch andere Scriptsprachen wie Python und Ruby, kein 
Assemblerlisting erzeugen können, dass man sich ansehen kann. Auch wenn 
intern Bytecode erzeugt wird -- erstens wird man den nicht zu Gesicht 
bekommen, und zweitens würde man damit wohl nicht viel anfangen können, 
soferm man keine entsprechende Virtuelle Maschiene ist.

Und da die erwähnten Sprachen eher jung sind, kann sich bezüglich 
Performance mit jeder neuen Version viel ändern. So macht es eher wenig 
Sinn, überhaupt nach Performance zu fragen, solange man nicht ein 
Problem damit hat. Bleibt also das Kriterium der Lesbarkeit.

von Jürgen W. (lovos)


Lesenswert?

>Dann ist ja schon gewählt, oder?
Nicht ganz. In einigen Fällen zB bit setzen oder löschen ist bit32 schon 
angenehmer. Die Frage ist eher ob man überhaupt noch diese 
bit-Konstrukte nimmt. Ich bin halt von C geprägt.
Auch ist zu bedenken, dass man zu Lua 5.1 kompatibel sein möchte.

>Und da die erwähnten Sprachen eher jung
Trifft bei Lua nicht zu

von Karl H. (kbuchegg)


Lesenswert?

Salewski, Stefan schrieb:

> Eher doch, und Deine obige Bemerkung
>
>>Sieh zu, dass du einen Blick auf den erzeugten Code kriegst.
>
> hat mich schon etwas erschreckt.

Da wusste ich noch nicht, dass Lua 'interpretiert' wird.
Aber wie alle ernst zu nehmende Interpreter-Ansätze, wird der 
Programmtext ja zumindest in einen Zwischencode übersetzt. Und genau da 
ist dann der Punkt an dem man derartige Optimierungen unterbringt.

Ob der Lua Compiler das macht oder nicht, weiß ich nicht.

> Bleibt also das Kriterium der Lesbarkeit.
Ganz genau.

von Salewski, Stefan (Gast)


Lesenswert?

Jürgen W. schrieb:
>>Und da die erwähnten Sprachen eher jung
> Trifft bei Lua nicht zu

Nun ja, was ist jung?

Ruby ist gerade 20 geworden, Python ist etwas älter -- Teenager halt, 
noch keine ausgereiften Persönlichkeiten. Lua würde ich auch so um die 
20 schätzen. Ruby ist "jung", weil es eine sehr komplexe Sprache ist und 
die Entwicklung langsam voranschreitet. Von Version 1.8.x nach 1.9/2.0 
hat sich viel getan, insbesondere ist durch den Bytecode-Interpreter die 
Performance stark gestiegen und hat nahezu zu Python aufgeschlossen. 
Wichtig ist ja  noch, dass es meist verschiedene Interpreter gibt -- 
etwa JRuby oder das experimentelle Topaz, und für Python etwa PyPy, was 
wohl schon eher ein Compiler ist. Daher macht die allgemeine Frage nach 
Performance wenig Sinn.

Und nun habe ich doch nachgesehen -- Lua ist auch gerade 20 geworden

http://de.wikipedia.org/wiki/Lua

von Jürgen W. (lovos)


Lesenswert?

Mit jung hätte ich Sprachen wie angelscript eingestuft. 20 Jahren sind 
ja schon eine Menge.
Als ich mit C Mitte der 80er anfing, war diese gerade 15 Jahren alt, und 
mir erschien das nicht "jung".
Von Lua habe erst vor ein paar Jahren gehört, als ein Ex-Kollege davon 
schwärmte (Spiele-Programmierer)
Die Bit-Operationen sind nicht das einzige Problem, andere Sachen 
(Array-Indizierweise) machen mir auch zu schaffen. Aber die Einfachheit, 
Erweiterbarkeit und Stabilität der Sprache überzeugt.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Bei Interpretern (auch Bytecode-Interpretern) spielt die Zeit für die
Ausführung primitiver Rechenoperationen kaum eine Rolle, zumal auf einem
PC Addition, Multiplikation, Bit-Or und Bit-Shift sowieso ungefähr
gleich lang dauern.

Wesentlich mehr Zeit brauchen i.Allg. die Dekodierung der Befehle, das
Auffinden von Variablen und die Verwaltung des internen Interpreter-
zustands.

Hier sind die Disassemblies des vom Compiler generierten Bytecodes für
die beiden Anweisungen (du erhältst sie mit luac -l test.lua):

1
  dwo = lowo + 0x10000 * hiwo
2
        10      [7]     GETTABUP        4 0 -5  ; _ENV "lowo"
3
        11      [7]     GETTABUP        5 0 -3  ; _ENV "hiwo"
4
        12      [7]     MUL             5 -10 5 ; 65536 -
5
        13      [7]     ADD             4 4 5
6
        14      [7]     SETTABUP        0 -9 4  ; _ENV "dwo"

1
  dwo = bit32.bor(lowo, bit32.lshift(hiwo,16))
2
        10      [8]     GETTABUP        4 0 -2  ; _ENV "bit32"
3
        11      [8]     GETTABLE        4 4 -10 ; "bor"
4
        12      [8]     GETTABUP        5 0 -5  ; _ENV "lowo"
5
        13      [8]     GETTABUP        6 0 -2  ; _ENV "bit32"
6
        14      [8]     GETTABLE        6 6 -11 ; "lshift"
7
        15      [8]     GETTABUP        7 0 -3  ; _ENV "hiwo"
8
        16      [8]     LOADK           8 -12   ; 16
9
        17      [8]     CALL            6 3 0
10
        18      [8]     CALL            4 0 2
11
        19      [8]     SETTABUP        0 -9 4  ; _ENV "dwo"

Der Code sollte dank der vom Compiler eingefügten Kommentare weitgehend 
selbsterklärend sein.

Die erste Variante braucht auf meinem Pentium 4 mit 3,2 GHz 143 ns. Die
zweite Variante ist länger, macht mehr zeitaufwendige Symbol-Lookups und
braucht deswegen mit 533 ns deutlich länger.

Zwei Lookups kann man in der zweiten Variante einsparen, indem man
bit32.bor und bit32.shift am Programmanfang Variablen zuweist, so dass
bei der eigentlichen Rechenoperation bit32 nicht mehr nachgeschlagen
werden muss. Dann dauert diese Variante nur noch 462 ns, ist aber immer
noch deutlich langsamer als die erste Variante.

von Jürgen W. (lovos)


Lesenswert?

Wow. So einen Unterschied hätte ich nie vermutet.

von Stefan Salewski (Gast)


Lesenswert?

Yalu X. schrieb:
> Hier sind die Disassemblies des vom Compiler generierten Bytecodes für
> die beiden Anweisungen

Puh -- da habe ich echt mal was gelernt hier im Forum.

Das hätte ich nun echt nicht erwartet, dass man fur Lua den 
kommentierten Bytecode ansehen kann.
Ich denke mal für Ruby geht das nicht, jedenfalls habe ich da noch nie 
von gehört -- ich werde aber demnächst mal danach suchen, auch für 
Python.

Aber meine anderen Argumente entkräftet das nicht wirklich -- mit jeder 
neuen Interpreterversion oder mit einem anderen Interpreter/Compiler 
kann das ganz anders aussehen, und wenn man Sprachen wie Lua/Python/Ruby 
nutzt steht die Ausführungsgeschwindigkeit meist nicht im Vordergrund. 
Die Lesbarkeit/Verstehbarkeit ist dann wichtiger.

von Rolf M. (rmagnus)


Lesenswert?

Salewski, Stefan schrieb:
> Lua wird, wie auch andere Scriptsprachen wie Python und Ruby, kein
> Assemblerlisting erzeugen können, dass man sich ansehen kann.

Zumindest Python kann das. Lua ja anscheinend auch.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Auch die Compiler-Entwickler brauchen ja irgendwelche Tools, mit denen
der vom Compiler erzeugte Bytecode in lesbarer Form angezeigt werden
kann. Deswegen muss entweder der Compiler selbst die Möglichkeit bieten,
Assembler-Quellcode zu erzeugen, oder es gibt einen Disassembler, oder
beides. Da diese Tools sowieso schon existieren, sind sie in Opensource-
und oft auch in Closedsource-Toolchains auch für den Compiler-Anwender
verfügbar.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.