6

Ich möchte ein Mathematica-Modul kompilieren, weil ich nach Geschwindigkeit bin.Mathematica - Wie BitShiftRight (oder Links) zu kompilieren?

testC = Compile[{{inputInt, _Integer}}, 
     Module[{outputInt, bitShift = 5}, 
     outputInt = BitShiftRight[inputInt, bitShift] 
     ] 
     , CompilationTarget -> "C", RuntimeOptions -> "Speed" 
     , CompilationOptions -> {"ExpressionOptimization" -> True, 
     "InlineCompiledFunctions" -> True, 
     "InlineExternalDefinitions" -> True} 
    ]; 

Meine eigentliche Funktion ist länger, aber hat eine sehr einfache Struktur verwendet Listen und enthält folgende Funktion: Gesamt, Tisch, BitAnd, If. Alle Kompilierungs- und Laufzeitoptionen sind (vielleicht) in meiner echten Funktion nützlich, nicht in diesem Ein-Zeilen-Extrakt.

Ich habe gesetzt

SetSystemOptions [ "CompileOptions" -> "CompileReportExternal" -> True];

um sicherzustellen, dass ich sehen kann, was passiert, und

CompilePrint [TestC]

ergibt folgendes Ergebnis

1 argument 
    3 Integer registers 
Underflow checking off 
Overflow checking off 
Integer overflow checking off 
RuntimeAttributes -> {} 

    I0 = A1 
    I1 = 5 
    Result = I2 

    1 I2 = MainEvaluate[ Hold[BitShiftRight][ I0, I1]] 
    2 Return 

As/aus diesem Thread befürchteten erwartet https://mathematica.stackexchange.com/a/1101/1403 BitShiftRight ist nicht kompilierbar, und dieser Aufruf von MainEvaluate ist eine ernsthafte Beeinträchtigung meiner Funktion Ion. Ich bin extrem überrascht, dass diese Art von sehr niedriger Ebene, gemeinsame Funktion nicht kompilierbar ist, während BitAnd, BitNot, BitOr, BitXor sind! Kennt jemand einen (schnellen) Workaround? Ich kann einen MathLink-Aufruf für eine C-Sprachenfunktion verwenden, aber mein Ziel ist es, diese Funktion in einem Manipulate [] zu verwenden und es als eigenständige cdf-Datei bereitzustellen. Und ich verstehe, dass ich in diesem Zusammenhang MathLink nicht verwenden kann, richtig? Übrigens, gibt es da eine handliche Abhilfe?

Antwort

3

Wenn Sie durch 32 dividieren, wird der Compiler wahrscheinlich dies als eine Verschiebung umschreiben. Sie sollten auch versuchen, in Mathematica direkt durch 32 zu dividieren, indem Sie sicherstellen, dass Ihre Daten gepackt sind (Developer`ToPackedArray []). Der Aufwand für das Hin- und Herschicken der Daten ist wahrscheinlich nicht den Nutzen der Berechnung in C wert.

+0

Nur zur Bestätigung (und geringfügigen Änderung), wenn Sie Quotient verwenden, kompiliert es keine externen Evaluator-Aufrufe. In dem einfachen Beispiel wäre die entsprechende Zeile outputInt = Quotient [inputInt, 2^bitShift]]. Wenn Ihre Schichtlänge eine feste Konstante ist, sollte das Einschalten zur Kompilierungszeit erfolgen (wahrscheinlich wussten Sie beide, dass ...). –

+0

@Daniel: Deine Lösung löst meinen Pb. Danke! Dann lautet der kompilierte Code "I3 = Quotient [I0, I2]". Wenn ich nur durch 2^5 dividiere, muss ich [] mit dem Ergebnis runden, um es in einen Integer umzuwandeln. Dann lautet der Kompiliercode "R1 = Wechselseitig [R0] " 'R0 = I0'' R0 = R0 * R1 ''I3 = Runde [R0]' (länger, weniger effizient). – Oscar6E