Gibt es eine schnelle Produktoperation für PackedArrays?

8

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

ausgepackt werden

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.

    
Mr.Wizard 14.03.2011, 04:12
quelle

3 Antworten

9

Ich habe mich auch gefragt, ob es ein multiplikatives Äquivalent zu Total gibt.

A wirklich nicht so schlecht Lösung ist

%Vor%

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 :

%Vor%

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

%Vor%

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:

%Vor%

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] .

    
Simon 14.03.2011, 05:05
quelle
4

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:

%Vor%     
Andrew Moylan 14.03.2011 05:30
quelle
3

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.

Funktion

%Vor%

Testen

%Vor% %Vor%     
Mr.Wizard 15.03.2011 06:53
quelle