[PYTHON] Concernant Pyston 0.3

introduction

Bonsoir, ravi de vous rencontrer. (゜ ∀ ゜) o 彡 ° pyston! pyston! !!

Présentation de Pyston

Pyston est un système de traitement compatible Python 2.7 développé par Dropbox. La compilation JIT utilisant LLVM devrait accélérer python, et son rival est pypy. Il semble que seul x86_64 soit pris en charge maintenant, et ubuntu14 est recommandé si vous voulez l'essayer.

Cliquez ici pour plus de détails sur la façon de construire. http://qiita.com/Masahito/items/edd028ebc17c9e6b22b0

Pyston a publié la v0.2 en 2014/09 et semble travailler sur le développement de la v0.3.

À 0,3, les performances sont améliorées pour les benchmarks réels.

Le référentiel pyston contient des benchmarks représentatifs S'il était déjà construit, j'ai pu exécuter le benchmark avec make run_TESTNAME.

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

Faits saillants de Pyston

J'ai étudié les fonctionnalités du compilateur JIT de différentes manières tout en regardant le README de Pyston.

https://github.com/dropbox/pyston

Je pense que le point fort de Pyston est la compilation JIT utilisant LLVM. Il utilise LLVM comme compilateur JIT, et je pense que le plus célèbre est FTL JIT de JavaScriptCore.

L'explication de FTL JIT ici sera utile. http://blog.llvm.org/2014/07/ftl-webkits-llvm-based-jit.html

JSC effectue une compilation JIT à 4 couches.

  1. low-level interpreter (LLInt)
  2. baseline JIT
  3. DFG JIT
  4. FTL JIT (c'est le seul qui utilise LLVM)

Pyston fait également la compilation JIT 4 couches. Il semble utiliser l'analyseur de Pypa et AST de Pyston 0.3 correspondant au JSBytecode de JSC.

  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)

La compilation JIT par LLVM est effectuée dans la couche 2-3-4. Dans la deuxième couche, nous intégrons le code qui collecte le Type au moment de l'exécution sans optimisation avec LLVM. Dans la 4ème couche, la spécification de type est effectuée en fonction du type collecté au moment de l'exécution et l'optimisation est effectuée avec LLVM. Générez du code rapide.

La cible de la 4ème couche est une boucle exécutée 10 000 fois ou plus ou une fonction appelée 10 000 fois ou plus.

À l'avenir, la troisième couche sera supprimée. Il semble que je veuille remplacer l'interpréteur LLVM-IR de la première couche par ma propre implémentation.

patchpoint semble utiliser les intrinsèques de LLVM, Les stackmaps sont-ils une implémentation originale?

Inlining

Lors de la compilation JIT, les méthodes python semblent être intégrées en temps opportun.

En outre, les opérations de base (boxing / unboxing) et les collections (list / dict / tuple / xrange) qui sont fréquemment nécessaires à l'exécution sont Il semble que le bitcode est généré lorsque Pyston est compilé et que l'inlining est effectué au niveau du bitcode lorsque JIT est compilé.

Cette zone est un peu caractéristique, et Inliner semble avoir créé le propre Pass de Pyston en modifiant celui de LLVM.

Pour plus de détails, voir codegen / opt / inliner et runtime / inline (il s'agit de la collection générée par bitcode).

inline cache

RuntimeIC(void*addr, int num_slots, int slot_size) Gérez votre dictionnaire avec. Le corps principal du dictionnaire est ICInfo

L'appel provient d'une classe qui hérite de RuntimeIC, call ()

L'appel lui-même est devenu un modèle.

: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...);
}

Voir ci-dessous pour plus de détails src/runtime/ics src/asm_writing/icinfo

hidden class

Est-ce équivalent à la classe cachée du V8?

Pour une raison quelconque, il hérite de ConservativeGCObject, et de nombreuses méthodes sont pour GC. C'est un mystère

Pour Python, avons-nous besoin d'une classe cachée pour absorber les différences d'attributs? Je ne suis pas sûr des spécifications Python, la différence d'attributs est-elle un problème?

Voir ci-dessous pour plus de détails src/runtime/objmodel

Type feedback

Code intégré qui collecte les informations de type à l'exécution lors de la compilation d'un JIT de 2-3 couches.

Fondamentalement, au moment de l'exécution, nous récupérons le champ Cls de BoxedClass et Émettez l'asm à enregistrer dans l'enregistreur lors de la compilation du JIT dans la 2-3ème couche. Il semble que celui dont le nombre d'enregistrements est de 100 ou plus au moment de la compilation JIT soit adopté comme résultat de la prédiction de type.

Le résultat de la prédiction de type est défini sur CompileType et il est spécialisé du type dynamique à CompileType au moment de la compilation JIT. À ce moment-là, il semble que nous essaierons activement de déballer de la classe en boîte au type de compilation.

la spéculation est src / analysis / type_analysis l'enregistreur est src / codegen / type_recording Le traitement des enregistrements à l'exécution est src / runtime / objmodel

Object representation

Toutes les instances gérées par Pyston semblent être dans un état encadré. Par conséquent, le champ cls est rempli au début et BoxeInt stocke la valeur de int64_t à titre d'exemple.

La liste des classes encadrées ressemble probablement à ceci.

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

Il semble que seuls les objets boxed peuvent être stockés dans diverses collections (list et dict) et args, Le processus d'extraction de la valeur réelle de celui-ci semble être aussi spécialisé que possible.

Par conséquent, en fonction du résultat du retour de type, le type d'exécution est déduit du type d'arguments de la fonction collectée. Il semble éliminer autant que possible les objets en boîte et insérer des conversions sans boîte en temps opportun.

Pour la spéculation de type, reportez-vous à src / analysis, et pour Box, reportez-vous à src / runtime / classobj et ses classes dérivées.

Optimize

L'optimisation LLVM semble générer du code rapide.

:lang:src/codegen/irgen.cpp


  doCompile()
    CompiledFunction()
    if (ENABLE_SPECULATION && effort >= EffortLevel::MODERATE)
      doTypeAnalysis()
        BasicBlockTypePropagator::propagate()
    optimizeIR() /*Définir l'optimisation LLVM avec LLVM PassManager*/
      makeFPInliner() /*My Inlining Pass de pyston*/

      EscapeAnalysis() /*Escape Analysis, une implémentation propriétaire de pyston*/
      createPystonAAPass() /*Mettre à jour les résultats AA en référence aux résultats de l'analyse Escape*/

      createMallocsNonNullPass() /* (malloced != NULL)Semble supprimer*/

      createConstClassesPass()
      createDeadAllocsPass() /*Supprimer l'allocation qui ne s'échappe pas*/

Le contrôle principal est src / codegen / irgen.cpp Le système de spéculation est l'analyse Voir codegen / opt pour le chemin d'optimisation propriétaire LLVM

Je me suis demandé si EscapeAnalysis remplacerait alloc-> allocation de pile, Il semblait simplement renvoyer une référence NoEscape en tant que NoModRef pour l'analyse ModRef de LLVM.

Est-ce que ScalarReplAggregates de LLVM fait référence à NoModRef et le remplace par Alloca?

DeadAllocsPass analyse les références de chargement / stockage en référence aux résultats AA et supprime les charges inutiles. * / Après cela, l'instruction équivalente à alloca peut être déracinée par dce de LLVM.

http://blog.pyston.org/2014/11/06/frame-introspection-in-pyston/ Dans le blog, il semble que des variables locales soient assignées à stack.

C API native extension

Depuis la v0.2, il semble prendre en charge l'extension de C_API. En tant qu'exemple de code, il se trouvait dans test / test_extension. Voir 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;
}

Point d'optimisation du système de traitement python

Le matériel est détaillé dans ce compilateur IBM Python JIT, veuillez donc vous y référer. J'ai essayé de savoir quelle partie est lente en python.

http://www.cl.cam.ac.uk/research/srg/netos/vee_2012/slides/vee18-ishizaki-presentation.pdf

  1. Recherchez le hachage lors de l'accès au champ / * Voir ics? L'accélération de la référence de champ est inconnue * /
  2. vérifier l'instance d'une classe / * Toutes les classes de base sont encadrées * /
  3. recherchez le dictionnaire lorsque vous appelez hasattr / * Je ne comprends pas attr * /
  4. vérification des exceptions sans fractionnement des BB / * Existe-t-il des conventions pour les exceptions python * /
  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 */

Résumé

Cela ne progressait pas, donc c'était juste un mémo. J'espère que vous pouvez avoir une idée de ce que cela fait par rapport aux autres systèmes de traitement Python et aux systèmes de traitement JavaScript JIT (V8, FTL JIT, etc.) auxquels Pyston peut faire référence.

Il semble que Pyston envisage d'incorporer des benchmarks pypy tout en comparant PyPy et Cpython. Par rapport au Pyston actuel, PyPy est trop rapide et le mécanisme est fondamentalement différent. J'ai de grandes attentes pour Pyston à l'avenir.

Recommended Posts

Concernant Pyston 0.3
[Note] À propos de Tensorflow
Concernant Pyston 0.3
[Note] À propos de Tensorflow
Concernant l'API VirusTotal
Concernant l'API VirusTotal
Essayez d'exécuter Pyston 0.1