Python: JIT für bekannte Engpässe

8

Gibt es irgendeinen Weg, irgendwie pypy zu benutzen, nur um eine Funktion zu kompilieren und nicht für den Rest meines Python-Programms?

Ich habe einen bekannten Engpass, in dem ich 99% meiner CPU-Zeit verbringe (hauptsächlich mit Integer-Shifts und XORs) und diese so weit wie möglich in Python optimiert habe. Ich möchte C-Bibliotheken nicht schreiben und pflegen müssen, es sei denn, es ist unbedingt notwendig.

Im Moment benutze ich Anaconda Python, das ist der normale Python mit einer Reihe von Bibliotheken. Ich würde Pypy verwenden, außer dass ich nicht sicherstellen muss, dass der Rest meines Programms mit pypy funktioniert.

Gibt es eine Möglichkeit, ein JIT explizit nur für eine Python-Funktion auszuführen?

edit: Die Funktion ist ein modularer Multiplikationsschritt in GF2 (Galois-Feld)

Ссылка

speziell:

%Vor%

Es muss für Bigints funktionieren, daher bin ich mir nicht sicher, wie ich Cython-kompatibel umschreiben soll.

Ich habe gerade @bojit von Numba ausprobiert und es ist fehlgeschlagen, weil es nicht wusste, welche Variablentypen verwendet werden sollen und kleine Ganzzahlen angenommen haben. Ich kann mir nicht vorstellen, wie ich sagen soll, dass ich Standard-Python-Bigints verwenden soll.

%Vor%     
Jason S 13.10.2013, 21:17
quelle

3 Antworten

6

Was ist mit der Verwendung von Cython ? Sie könnten nur diese eine Funktion in Cython-Syntax konvertieren, die dann direkt in C kompiliert wird. Die Syntax sollte nah genug an Python selbst sein, wahrscheinlich nur ein paar Deklarationen der richtigen Typen hinzufügen.

    
Bas Swinckels 13.10.2013, 21:36
quelle
6

Nein, Sie können keinen Teil eines Python-Programms in PyPy und anderen Teilen in einem anderen Python ausführen. Es ist mehr als nur ein JIT, es hat eine völlig andere Darstellung von Objekten und vielen anderen Interna.

Wenn Sie nicht nur sicherstellen wollen, dass der Rest des Programms mit PyPy funktioniert, können Sie sicher sein: Praktisch der gesamte reine Python-Code funktioniert mit PyPy, mit der einzigen Ausnahme von CPython-Implementierungsdetails. Diese sind obskur, es ist ziemlich schwer, versehentlich Code zu schreiben, der auf den meisten von ihnen beruht, und die anderen (z.B. Dateien, die nicht automatisch so schnell geschlossen werden) werden die meisten Programme nicht brechen. Versuchen Sie einfach, Ihr gesamtes Programm mit PyPy auszuführen.

Wenn es andere Probleme mit PyPy gibt, möchten Sie vielleicht nur diese Funktion in C übersetzen und sie mit ctypes oder cffi aufrufen. Der nervige Teil wäre es mit Python (z. B. über ein Erweiterungsmodul) zu verbinden, was ctypes und cffi für Sie tun. Sie benötigen keine vollständige Arbitrary-Precision-Integer-Bibliothek, Sie benötigen nur ein Array von Bits mit ein paar sehr einfachen Operationen: Testen des niedrigstwertigen Bits, Links / Rechts-Verschiebung, Kleiner-als- und Bit-XOR. Jeder von diesen ist nur eine triviale Schleife. Und wenn die naive C-Implementierung immer noch ein Engpass ist, können Sie wahrscheinlich alle diese Schleifen vektorisieren. Sie könnten wahrscheinlich auch die Verschiebungen optimieren, um überhaupt nichts zu kopieren.

    
delnan 13.10.2013 21:33
quelle
4

Cython wurde bereits einige Male erwähnt, aber ich möchte auf eine andere Alternative für diejenigen hinweisen, die diese Frage bei ihrer Suche finden , die möglicherweise keine ganzzahlige Ganzzahlgenauigkeitsanforderung haben: ShedSkin . Es übersetzt Python über Typinferenz in C ++. Mit anderen Worten, im Gegensatz zu Cython fügen Sie keine Typdeklarationen zu Python hinzu; du schreibst einfach Python. Sie müssen jedoch sicherstellen, dass Ihre Variablen den Typ in Ihrem Programm nicht ändern, da der Typ sonst nicht abgeleitet werden kann. Bestimmte andere der dynamischeren Features von Python werden ebenfalls nicht unterstützt, aber dies ist normalerweise kein Problem für rechenintensiven Code.

Wie bei der Integer-Anforderung mit beliebiger Genauigkeit: Sie werden wahrscheinlich viel, viel größere Geschwindigkeitsverbesserungen als die 2.5x, die Sie in Ihrem Kommentar notiert haben, für Integer erhalten, die in "native" (feste Größe) ganze Zahlen passen. Die Verbesserung ist so drastisch, dass es, wenn ein guter Teil Ihrer Berechnungen mit nativen ganzen Zahlen gemacht werden kann, wahrscheinlich eine (blitzschnelle) native-integer Version Ihrer Funktion nur für diesen Fall und Verwenden Sie nur die allgemeine Version Ihrer Funktion für Werte, die nicht passen. (Nicht alle Probleme können in separate Fälle wie diese aufgeteilt werden, aber für diejenigen, die es können, lohnt es sich, zumindest diesen Ansatz auszuprobieren.)

    
John Y 17.10.2013 16:10
quelle

Tags und Links