Appeler C depuis Python avec DragonFFI

Il semble que le projet LLVM ait publié un FFI appelé Dragon FFI. Blog montre un exemple d'appel du langage C à partir de Python.

À propos, FFI est une abréviation de Foreign Function Interface, qui est un mécanisme qui vous permet d'utiliser des fonctions définies dans un langage de programmation dans un autre. Par exemple, Rust, qui a été créé pour remplacer C, a implémenté FFI pour appeler C.

J'ai joué avec pydffi, le Python Wrapper de DragonFFI.

Configuration environnementale

Pour Python, j'ai utilisé "Python 3.6.3 :: Anaconda, Inc." installé par pyenv. La bibliothèque était facile à installer avec pip.

pip install pydffi

Je vais l'essayer avec Fibonacci pour le moment

Je ne voulais vraiment rien faire, j'ai donc implémenté une fonction de séquence de Fibonacci en Python et C. L'idée est qu'une fonction écrite en C devrait avoir une vitesse d'exécution rapide, il serait donc intéressant de voir la valeur numérique.

Fonctions Python

def f(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return f(n-1)+f(n-2)

print(f(30))

pydffi

Fonction C

Définissez une fonction f comme celle-ci.

int f(int n) {
  if (n == 0) {
    return 0;
  } else if (n == 1) {
    return 1;
  } else {
    return f(n-1) + f(n-2);
  }
}

Appeler C avec pydffi depuis Python

Appelez la fonction f définie en C depuis Python. Avec pydffi, c'était très simple à écrire!

import pydffi

with open("cfunc/fibonacci_opt.c") as f:
    c_src = "".join(f.readlines())

F = pydffi.FFI()
CU = F.compile(c_src)
print(int(CU.funcs.f(30)))

résultat

Exécuté à N = 30. C'est une fonction qui n'a pas du tout été optimisée, il est donc naturel que le langage C soit plus rapide.

Fonctions Python Fonction C(pydffi)
0.3381[sec] 0.0496[sec]

Essayez d'optimiser un peu

Au fait, si vous optimisez Python en prenant des notes, cela ressemble à ceci. (vite!) L'algorithme est important.

Python(Note)
0.00005[sec]
memo = [0] * 1000

def f(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1

    if memo[n]:
        return memo[n]

    m = f(n-1)+f(n-2)
    memo[n] = m
    return m

print(f(30))

Je l'ai aussi essayé avec MatMul

Je voulais un autre échantillon, j'ai donc implémenté la multiplication matricielle, appelée matmul. Cette fois, numpy est également une cible de comparaison.

Fonctions Python

A = [random.random() for _ in range(N) for _ in range(N)]
B = [random.random() for _ in range(N) for _ in range(N)]
C = [0.0 for _ in range(N) for _ in range(N)]

for i in range(N):
    for j in range(N):
        for k in range(N):
            C[i * N + j] += A[i * N + k] * B[k * N + j]

pydffi

Fonction C

void matmul(double *A, double *B, double *C, int N) {
  int i, j, k;
  for (i = 0; i < N; i++) {
    for (j = 0; j < N; j++) {
      for (k = 0; k < N; k++) {
        C[i * N + j] += A[i * N + k] * B[k * N + j];
      }
    }
  }
}

Appeler C depuis Python

# read c source
with open("cfunc/matmul.c") as f:
    c_src = "".join(f.readlines())

# initialize
FFI = pydffi.FFI()
CU = FFI.compile(c_src)

# create array objects & set values
arr_A = pydffi.CArrayObj(FFI.arrayType(FFI.DoubleTy, N*N))
arr_B = pydffi.CArrayObj(FFI.arrayType(FFI.DoubleTy, N*N))
arr_C = pydffi.CArrayObj(FFI.arrayType(FFI.DoubleTy, N*N))
for i in range(N*N):
    arr_A.set(i, A[i])
    arr_B.set(i, B[i])
    arr_C.set(i, 0.0)

# execute c matmul
start = time.time()
CU.funcs.matmul(arr_A, arr_B, arr_C, N)
print("C(FFI):{:.5f}[sec]".format(time.time() - start))

numpy

np_A = np.array(A).reshape(N, N)
np_B = np.array(B).reshape(N, N)
np_C = np.matmul(np_A, np_B)

résultat

N=256 Après tout, la fonction C est rapide. Et numpy est le plus rapide, comme prévu. Eh bien, C n'est qu'une triple boucle, il y a donc de la place pour plus d'optimisation. (⇒ Pour ceux qui sont intéressés par l'optimisation de matmul, ici sera utile)

Fonctions Python Fonction C(pydffi) numpy
7.1067[sec] 0.0329[sec] 0.0281[sec]

N=1024

Fonctions Python Fonction C(pydffi) numpy
Aucune mesure 7.4422[sec] 0.0769[sec]

Conclusion finale

Recommended Posts

Appeler C depuis Python avec DragonFFI
Appeler popcount depuis Ruby / Python / C #
Appelez python de nim avec Nimpy
Appeler C / C ++ depuis Python sur Mac
Appeler le langage C depuis Python (python.h)
Utilisation des fonctions C ++ de python avec pybind11
Envelopper C avec Cython pour une utilisation à partir de Python
Appel de scripts Python à partir de Python intégré en C ++ / C ++
Envelopper C ++ avec Cython pour une utilisation à partir de Python
Appeler CPLEX depuis Python (DO cplex)
Appelez l'API avec python3.
Avec skype, notifiez avec skype de python!
Appelons votre propre bibliothèque C ++ avec Python (Préférences)
[Python] Comment appeler une fonction de c depuis python (édition ctypes)
Appelez Matlab depuis Python pour optimiser
Appeler des fonctions du langage C depuis Python pour échanger des tableaux multidimensionnels
Résoudre ABC163 A ~ C avec Python
Créer Awaitable avec l'API Python / C
Utilisation de Rstan de Python avec PypeR
Installez Python à partir des sources avec Ansible
Résoudre ABC168 A ~ C avec Python
Exécutez Aprili depuis Python sur Orange
Conseils pour appeler Python à partir de C
Exécuter du code Python à partir de l'interface graphique C #
Résolu AtCoder ABC 114 C-755 avec Python3
Résoudre ABC162 A ~ C avec Python
Exécutez des scripts Python de manière synchrone à partir de C #
Résoudre ABC167 A ~ C avec Python
Résoudre ABC158 A ~ C avec Python
Charger fbx depuis python avec cinema4d
Manipulation des données Kintone avec le pilote ODBC Python & C Data d'AWS Lambda
Passer la liste de Python vers C ++ par référence dans pybind11
Appelez votre propre bibliothèque partagée en langage C à partir de Python à l'aide de ctypes
Collecter des informations sur Twitter avec Python (API Twitter)
Recevoir des données textuelles de mysql avec python
Obtenir le code HTML de l'élément avec du sélénium Python
[Note] Obtenir des données de PostgreSQL avec Python
Lire un fichier audio à partir de Python avec interruption
Créez wordcloud à partir de votre tweet avec python3
Tweet de python avec Twitter Developer + Tweepy
[C] [python] Lire avec AquesTalk sous Linux
Efficacité commerciale à partir de zéro avec Python
Décrypter les fichiers cryptés avec openssl depuis python avec openssl
Manipulation d'Azure CosmosDB à partir de Python Part.2
Acquisition d'images depuis une caméra avec Python + OpenCV
Premiers pas avec Dynamo de Python boto
Essayez d'appeler Python depuis Ruby avec une économie
Scraping depuis un site authentifié avec python
Générer un langage C à partir d'une expression S avec Python
Appelez APIGateWay avec APIKey dans les requêtes python
Appeler des commandes depuis Python (édition Windows)
RaspberryPi L Chika avec Python et C #
[C, C ++, Python, JavaScript] L Chika avec Edison
FizzBuzz en Python3
Grattage avec Python
Statistiques avec python