In Mathematica kann ein Vektor (oder ein rechteckiges Array), der alle Integer oder Floats der Maschinengröße enthält, in einem gepackten Array gespeichert werden. Diese Objekte benötigen weniger Arbeitsspeicher und einige Operationen sind viel schneller.
RandomReal
erzeugt wenn möglich ein gepacktes Array. Ein gepacktes Array kann mit der Funktion Developer
function FromPackedArray
Betrachten Sie diese Zeitvorgaben
%Vor% Daher ist Total
im Falle eines gepackten Arrays um ein Vielfaches schneller als Plus @@
, aber ungefähr gleich für ein nicht gepacktes Array. Beachten Sie, dass Plus @@
im gepackten Array tatsächlich etwas langsamer ist.
Betrachten Sie nun
%Vor% Schließlich meine Frage: Gibt es in Mathematica eine schnelle Methode für das Listenprodukt eines gepackten Arrays, analog zu Total
?
Ich vermute, dass dies wegen der Art und Weise, in der sich numerische Fehler mit der Multiplikation verbinden, nicht möglich ist. Außerdem muss die Funktion in der Lage sein, Nicht-Maschinen-Floats als nützlich zurückzugeben.
Ich habe mich auch gefragt, ob es ein multiplikatives Äquivalent zu Total
gibt.
A wirklich nicht so schlecht Lösung ist
Solange die Zahlen positiv sind und nicht zu groß oder klein sind,
dann sind die Rundungsfehler nicht zu schlecht.
Eine Vermutung, was während der Auswertung passieren könnte, ist: (1) Vorausgesetzt, die Zahlen sind positive Gleitkommazahlen, kann die Operation Log
schnell auf das gepackte Array angewendet werden. (2) Die Zahlen können dann schnell mit der gepackten Array-Methode Total
hinzugefügt werden. (3) Dann ist es nur der letzte Schritt, in dem ein nicht-maschinengroßer Schwimmer entstehen muss.
Siehe diese SO-Antwort für eine Lösung, die sowohl für positive als auch negative Floats funktioniert.
Lassen Sie uns schnell überprüfen, ob diese Lösung mit Floats funktioniert, die eine Antwort ohne Maschinengröße liefern. Vergleichen Sie mit Andrew (viel schneller) compiledListProduct
:
Wenn Sie größere ( >1
) Reale wählen, wird compiledListProduct
die Warnung ausgeben
CompiledFunction::cfne: Numerical error encountered; proceeding with uncompiled evaluation.
und es wird einige Zeit dauern, um ein Ergebnis zu erhalten ...
Eine Kuriosität ist, dass sowohl Sum
als auch Product
beliebige Listen annehmen können. Sum
funktioniert gut
aber für lange PackedArray
s, wie die Testbeispiele hier, schlägt Product
fehl, da der automatisch kompilierte Code (in Version 8.0) Unterläufe / Überläufe nicht richtig erfasst:
Die vom hilfreichen WRI-Tech-Support zur Verfügung gestellte Arbeit besteht darin, die Produktkompilierung mit SetSystemOptions["CompileOptions" -> {"ProductCompileLength" -> Infinity}]
auszuschalten. Eine andere Option ist die Verwendung von lst=Developer'FromPackedArray[lst]
.
Um Verwirrung zu vermeiden, sehen Sie sich zunächst ein Beispiel an, dessen Ergebnisse alle als Hardwaremaschinen-Präzisionszahlen dargestellt werden können, die alle kleiner als
sein müssen %Vor%Ihr Gesamtbeispiel hatte bereits diese nette (und schnelle) Eigenschaft. Hier ist eine Variante Ihres Times-Beispiels mit Maschinennummern:
%Vor%Jetzt können wir Kompilieren verwenden, um eine kompilierte Funktion zu erstellen, um diese Operation effizient durchzuführen:
> %Vor%Es ist viel schneller:
%Vor%Angenommen, Sie haben einen C-Compiler und Mathematica 8, können Sie auch automatisch den kompletten Weg zum C-Code kompilieren. Eine temporäre DLL wird zur Laufzeit in Mathematica erstellt und zurückverknüpft.
%Vor%Dies ergibt eine Leistung, die nicht viel anders ist als bei einer eingebauten Mathematica-Funktion:
%Vor% Beachten Sie, dass, wenn Ihr Produkt wirklich über $ MaxMachineNumber hinausgeht (oder $MinMachineNumber ), dann sind Sie besser dran mit Apply[Times, list]
. Der gleiche Kommentar gilt für Total, wenn Ihre Ergebnisse so groß werden können:
Simons Methode ist schnell, aber sie schlägt bei negativen Werten fehl. Kombiniert mit seine Antwort auf meine andere Frage , hier ist eine schnelle Lösung, die Negative behandelt. Danke, Simon.
Tags und Links wolfram-mathematica list numeric packed