Guten Abend, schön dich zu treffen. (゜ ∀ ゜) o 彡 ° Pyston! Pyston! !!
Pyston ist ein Python 2.7-kompatibles Verarbeitungssystem, das von Dropbox entwickelt wurde. Es wird erwartet, dass die JIT-Kompilierung mit LLVM Python beschleunigt, und sein Rivale ist Pypy. Es scheint, dass jetzt nur x86_64 unterstützt wird, und ubuntu14 wird empfohlen, wenn Sie es versuchen möchten.
Klicken Sie hier, um Details zum Erstellen zu erhalten. http://qiita.com/Masahito/items/edd028ebc17c9e6b22b0
Pyston hat v0.2 am 2014/09 veröffentlicht und scheint an der Entwicklung von v0.3 zu arbeiten.
Mit 0,3 wird die Leistung für tatsächliche Benchmarks verbessert.
Das Pyston-Repository enthält repräsentative Benchmarks Wenn es bereits erstellt wurde, konnte ich den Benchmark mit make run_TESTNAME ausführen.
minibenchmarks
allgroup.py fannkuch.py go.py interp2.py nbody_med.py raytrace.py
chaos.py fannkuch_med.py interp.py nbody.py nq.py spectral_norm.py
microbenchmarks
attribute_lookup.py fib2.py listcomp_bench.py repatching.py vecf_add.py
attrs.py function_calls.py nested.py simple_sum.py vecf_dot.py
closures.py gcj_2014_2_b.py polymorphism.py sort.py
empty_loop.py gcj_2014_3_b.py prime_summing.cpp thread_contention.py
fib.py iteration.py prime_summing.py thread_uncontended.py
fib.pyc lcg.py pydigits.py unwinding.py
Ich habe die Funktionen des JIT-Compilers auf verschiedene Weise untersucht, während ich mir Pystons README angesehen habe.
https://github.com/dropbox/pyston
Ich denke, das Highlight von Pyston ist die JIT-Kompilierung mit LLVM. Es verwendet LLVM als JIT-Compiler, und ich denke, der bekannteste ist FTL JIT von JavaScriptCore.
Die Erklärung von FTL JIT hier ist hilfreich. http://blog.llvm.org/2014/07/ftl-webkits-llvm-based-jit.html
JSC führt eine 4-Layer-JIT-Kompilierung durch.
Pyston führt auch eine 4-Layer-JIT-Kompilierung durch. Es scheint Pypas Parser und AST von Pyston 0.3 zu verwenden, die dem JSBytecode von JSC entsprechen.
Die JIT-Kompilierung durch LLVM wird in der 2-3-4. Schicht durchgeführt. In der zweiten Ebene wird der Code eingebettet, der den Typ zur Laufzeit erfasst, ohne ihn mit LLVM zu optimieren. In der 4. Schicht wird TypeSpeculation basierend auf dem zur Laufzeit erfassten Typ durchgeführt, und die Optimierung wird mit LLVM durchgeführt. Generieren Sie schnellen Code.
Das Ziel der 4. Schicht ist eine Schleife, die 10.000 Mal oder mehr ausgeführt wird, oder eine Funktion, die 10.000 Mal oder mehr aufgerufen wird.
In Zukunft wird die dritte Ebene gelöscht. Es scheint, dass ich den LLVM-IR-Interpreter in der ersten Schicht durch meine eigene Implementierung ersetzen möchte.
Patchpoint scheint die LLVM-Eigenschaften zu verwenden. Ist Stackmaps eine originelle Implementierung?
Inlining
Bei der JIT-Kompilierung scheinen Python-Methoden zeitnah eingebunden zu sein.
Außerdem sind die grundlegenden Operationen (Boxen / Entpacken) und Sammlungen (Liste / Diktat / Tupel / XRange), die zur Laufzeit häufig erforderlich sind, Es scheint, dass Bitcode generiert wird, wenn Pyston kompiliert wird, und Inlining auf Bitcode-Ebene ausgeführt wird, wenn JIT kompiliert wird.
Dieser Bereich ist ein wenig charakteristisch, und Inliner scheint Pystons eigenen Pass erstellt zu haben, während er den von LLVM modifiziert hat.
Weitere Informationen finden Sie unter codegen / opt / inliner und runtime / inline (dies ist die vom Bitcode generierte Sammlung).
inline cache
RuntimeIC(void*addr, int num_slots, int slot_size) Verwalten Sie Ihr Wörterbuch mit. Der Hauptteil des Wörterbuchs ist ICInfo
Der Aufruf stammt von einer Klasse, die RuntimeIC erbt. Call ()
Der Anruf selbst wurde zu einer Vorlage.
:lang:src/runtime/ics.cpp
template <class... Args> uint64_t call_int(Args... args) {
return reinterpret_cast<uint64_t (*)(Args...)>(this->addr)(args...);
}
template <class... Args> bool call_bool(Args... args) {
return reinterpret_cast<bool (*)(Args...)>(this->addr)(args...);
}
template <class... Args> void* call_ptr(Args... args) {
return reinterpret_cast<void* (*)(Args...)>(this->addr)(args...);
}
template <class... Args> double call_double(Args... args) {
return reinterpret_cast<double (*)(Args...)>(this->addr)(args...);
}
Siehe unten für Details src/runtime/ics src/asm_writing/icinfo
hidden class
Entspricht es der versteckten Klasse von V8?
Aus irgendeinem Grund erbt es ConservativeGCObject und viele Methoden sind für GC. Es ist ein Mysterium
Benötigen wir für Python eine versteckte Klasse, um die Unterschiede in den Attributen auszugleichen? Ich bin mir bei den Python-Spezifikationen nicht sicher. Ist der Unterschied in den Attributen ein Problem?
Siehe unten für Details src/runtime/objmodel
Type feedback
Betten Sie Code ein, der Informationen zum Laufzeittyp beim Kompilieren einer 2-3-Layer-JIT sammelt.
Grundsätzlich rufen wir zur Laufzeit das Cls-Feld von BoxedClass und ab Geben Sie den Asm aus, der im Recorder aufgezeichnet werden soll, wenn Sie die JIT in der 2-3. Ebene kompilieren. Es scheint, dass derjenige, dessen Anzahl von Datensätzen zum Zeitpunkt der JIT-Kompilierung 100 oder mehr beträgt, als Ergebnis der Typvorhersage übernommen wird.
Das Vorhersageergebnis des Typs ist auf CompileType festgelegt und zum Zeitpunkt der JIT-Kompilierung vom dynamischen Typ auf CompileType spezialisiert. Zu diesem Zeitpunkt scheinen wir aktiv zu versuchen, die Box von der Boxed Class zum Compile Type zu entpacken.
Spekulation ist src / analysis / type_analysis Der Rekorder ist src / codegen / type_recording Die Datensatzverarbeitung zur Laufzeit lautet src / runtime / objmodel
Object representation
Alle von Pyston behandelten Instanzen scheinen sich in einem Boxzustand zu befinden. Daher wird das Feld cls am Anfang ausgefüllt, und BoxeInt speichert den Wert von int64_t als Beispiel.
Die Liste der Boxed Classes sieht wahrscheinlich so aus.
:lang:
BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_
*none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls,
*member_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *unicode_cls, *
*staticmethod_cls, *classmethod_cls;
Es scheint, dass nur Boxobjekte in verschiedenen Sammlungen (Liste und Diktat) und Argumenten gespeichert werden können. Der Prozess des Extrahierens des tatsächlichen Werts scheint so spezialisiert wie möglich zu sein.
Basierend auf dem Ergebnis der Typrückmeldung wird der Laufzeittyp daher aus dem Typ der Argumente der gesammelten Funktion abgeleitet. Es scheint Boxed-Objekte so weit wie möglich zu eliminieren und Unboxed-Conversions rechtzeitig einzufügen.
Informationen zur Typenspekulation finden Sie unter src / analysis und für Box unter src / runtime / classobj und den abgeleiteten Klassen.
Optimize
Die LLVM-Optimierung scheint schnellen Code zu generieren.
:lang:src/codegen/irgen.cpp
doCompile()
CompiledFunction()
if (ENABLE_SPECULATION && effort >= EffortLevel::MODERATE)
doTypeAnalysis()
BasicBlockTypePropagator::propagate()
optimizeIR() /*Stellen Sie die LLVM-Optimierung mit LLVM PassManager ein*/
makeFPInliner() /*Pystons eigener My Inlining Pass*/
EscapeAnalysis() /*Escape Analysis, eine proprietäre Implementierung von Pyston*/
createPystonAAPass() /*Aktualisieren Sie die AA-Ergebnisse mit Bezug auf die Ergebnisse der Escape-Analyse*/
createMallocsNonNullPass() /* (malloced != NULL)Scheint zu entfernen*/
createConstClassesPass()
createDeadAllocsPass() /*Entfernen Sie die Zuordnung, die nicht entweicht*/
Die Hauptsteuerung ist src / codegen / irgen.cpp Spekulationssystem ist Analyse Siehe codegen / opt für den proprietären LLVM-Optimierungspfad
Ich fragte mich, ob EscapeAnalysis die Zuweisung-> Stapelzuweisung ersetzen würde. Es schien nur eine NoEscape-Referenz als NoModRef für die ModRef-Analyse von LLVM zurückzugeben.
Beziehen sich die ScalarReplAggregates von LLVM auf NoModRef und ersetzen es durch Alloca?
DeadAllocsPass analysiert Lade- / Speicherreferenzen anhand von AA-Ergebnissen und entfernt unnötige Ladevorgänge. * / Danach kann der Befehl, der der Zuweisung entspricht, durch dce von LLVM entwurzelt werden.
http://blog.pyston.org/2014/11/06/frame-introspection-in-pyston/ Im Blog scheinen lokale Variablen dem Stapel zugewiesen zu sein.
C API native extension
Ab Version 0.2 scheint es die Erweiterung von C_API zu unterstützen. Als Beispielcode befand es sich in test / test_extension. Siehe src / capi
:lang:test/basic_test.c
static PyObject *
test_load(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
assert(stored);
Py_INCREF(stored);
return stored;
}
static PyMethodDef TestMethods[] = {
{"store", test_store, METH_VARARGS, "Store."},
{"load", test_load, METH_VARARGS, "Load."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
initbasic_test(void)
{
PyObject *m;
m = Py_InitModule("basic_test", TestMethods);
if (m == NULL)
return;
}
Das Material wird in diesem IBM Python JIT-Compiler detailliert beschrieben. Ich habe versucht herauszufinden, welcher Teil in Python langsam ist.
http://www.cl.cam.ac.uk/research/srg/netos/vee_2012/slides/vee18-ishizaki-presentation.pdf
Es ging nicht voran, also war es nur ein Memo. Ich hoffe, Sie können ein Gefühl dafür bekommen, wie es sich im Vergleich zu anderen Python-Verarbeitungssystemen und JavaScript-JIT-Verarbeitungssystemen (V8, FTL-JIT usw.) anfühlt, auf die sich Pyston möglicherweise bezieht.
Es scheint, dass Pyston plant, Pypy-Benchmarks einzubeziehen, während PyPy und Cpython verglichen werden. Im Vergleich zum aktuellen Pyston ist PyPy zu schnell und der Mechanismus unterscheidet sich grundlegend. Ich habe hohe Erwartungen an Pyston in der Zukunft.