mschnell hat geschrieben:
Das hört sich ganz schlecht an !
Hinsichtlich der Addition ist es klar, dass der Übertrag in Hardware schneller geregelt werden kann als in Software, dies gilt gewiss auch für die Multiplikation - an dieser Stelle besteht, wie wir schon feststellten, Optimierungsbedarf.
In diesem Fall dienen die if-Abzweigungen der Optimierung des Codes, sie sind also durchaus sinnvoll. In sehr vielen Fällen ist die Geschwindigkeit einer Routine stärker von dem verwendeten Algorithmus abhängig denn von den Hardware-Optimierungen. Hinsichlich der Multiplikation ist z.B. die Schulmethode der schriftlichen Multiplikation für kleine Zahlen unschlagbar schnell. Da hier aber der Rechanaufwand quadratisch mit der Stellenanzahl zunimmt, wird sie für große Zahlen zu langsam. Daher verwendet die GNURZ-Artihmetik ab einer Stellenanzahl von 44 den sogenannten Karazuba-Algorithmus, der mit n^1,6 im Aufwand zunimmt. Dieser wiederum ist besonders für Zahlen mit ähnlicher Stellenanzahl effektiv, d.h. hier muss erneut eine Fallunterscheidung eingeführt werden.
Hier habe ich Messungen durchgeführt, die die Vorteile zeigten. Die Multiplikation zweier hunderttausendstelliger Zahlen wäre nicht im Hundertstelsekundenbereich möglich ohne Karazuba. Ohne Zweifel können weitere Optimierungen auf Hardware-Seite die Berechnung in den ein- bis zweistelligen Millisekundenbereich drücken.
Theoretisch gibt es für sehr große Zahlen eine Methode, die die schnelle Fourier-Transformation benutzt und welche schneller ist als der Karazuba-Algorithmus. Diese wurde noch nicht implementiert.
Wie bereits früher angedeutet: Abweichungen vom linearen Fluss des Codes sind bei modernen Prozessoren fürchrterlich langsame Operationen. Für ein "if" kann dar Prozessor bestimmt zehn Multiplikationen und Addition ausführen.
Naja, bedingte Sprünge brauchen bei heutigen Prozessoren nicht mehr sonderlich viele Zyklen. Aber ich stimme dir zu, dass es dem Prozessor erschwert wird, parallel Befehle abzuarbeiten (was moderne Prozessoren tun), wenn der Code viele Sprünge enthält.
Zusätzlich wird die (Instruction-) Cache-Ausnutzung mit größer werdendem Code schlechter.
Das ist wahr. Bei allen im Laden befindlichen Prozessoren und bei den meisten der aktuell verwendeten Prozessoren dürfte der Instructions-Cache die 64 KB überschreiten. Hier dürften die aktiven Teile des Multiplikationsalgorithmus reinpassen. Man muss bedenken, dass sich die Multiplikation z.B. _nach_ der Entscheidung, per Schulmethode zu multiplizieren, auf einen relativ kleinen iterativen Bereich beschränkt.
Probleme macht der Karazuba-Algorithmus insofern, da mir nur ein rekursiver Algorithmus bekannt ist. Ein iterativer Algorithmus wäre hier effektiver, ich konnte jedoch weder einen finden noch einen herleiten.
Hast Du getestet, ob eine "Pennäler"-mäßige Multiplikationsroutine (eine Dezimalstelle entspricht 32 oder 64-Bit Wert) nicht vielleicht doch schneller ist ?
Ich bin mir nicht sicher, ob ich hier verstanden habe, was du meinst: Aber durch die Setzung der GlobZahlenbasis im Constructor Create wird mit 32bit-Werten pro Stelle gerechnet. Das gilt für alle Routinen.
Das könnte vor allem sein wenn die Addition zweier Langzahlen und die Multiplikation einer Langzahl mit einem 32 (oder 64-Bit) Wert mit ASM optimiert ist, um die Behandlung des Übertrags "hardwaremäßig" zu realisieren.
Zustimmung: Das wären ganz sicher lohnenswerte Optimierungen.
Viele Grüße, Euklid