[PYTHON] In Bezug auf Pyston 0.3

Einführung

Guten Abend, schön dich zu treffen. (゜ ∀ ゜) o 彡 ° Pyston! Pyston! !!

Pyston Übersicht

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

Höhepunkte von Pyston

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.

  1. low-level interpreter (LLInt)
  2. baseline JIT
  3. DFG JIT
  4. FTL JIT (Dies ist die einzige, die LLVM verwendet)

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.

  1. LLVM-IR interpreter (EffortLevel::INTERPRETED)
  2. Baseline LLVM compilation (EffortLevel::MINIMAL)
  3. Improved LLVM compilation (EffortLevel::MODERATE)
  4. Full LLVM optimization + compilation (EffortLevel::MAXIMAL)

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;
}

Optimierungspunkt des Python-Verarbeitungssystems

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

  1. Hash beim Zugriffsfeld nachschlagen / * Siehe ics? Die Beschleunigung der Feldreferenz ist unbekannt * /
  2. Instanz einer Klasse prüfen / * Alle Basisklassen sind eingerahmt * /
  3. Wörterbuch suchen, wenn hasattr / * aufgerufen wird Ich verstehe attr nicht * /
  4. Ausnahmeprüfung ohne Aufteilung von BBs / * Gibt es Konventionen für Python-Ausnahmen * /
  5. specialize runtime type information /* type feedback and type speculation */
  6. speculatively builtin-functions /* bitcode inlining */
  7. reference counting without branch /* ??? */
  8. map to stack-allocated variables /* escape analysis and deadalloc */

Zusammenfassung

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.

Recommended Posts

In Bezug auf Pyston 0.3
[Hinweis] In Bezug auf Tensorflow
In Bezug auf Pyston 0.3
[Hinweis] In Bezug auf Tensorflow
In Bezug auf die VirusTotal-API
In Bezug auf die VirusTotal-API
Versuchen Sie, Pyston 0.1 auszuführen