Maison  >  Article  >  développement back-end  >  Introduction à la façon d'utiliser les ctypes pour améliorer la vitesse d'exécution de Python

Introduction à la façon d'utiliser les ctypes pour améliorer la vitesse d'exécution de Python

高洛峰
高洛峰original
2017-03-28 14:59:281273parcourir

Cet article explique comment utiliser les ctypes pour améliorer la vitesse d'exécution de Python et a une certaine valeur de référence pour que tout le monde puisse apprendre à utiliser Python. Des amis dans le besoin viennent jeter un œil.

">

Préface

ctypes est une bibliothèque de fonctions externe pour Python. Elle fournit des types de données compatibles C et permet d'appeler des bibliothèques de liens dynamiques/bibliothèques partagées. Fonction. Il peut envelopper ces bibliothèques pour une utilisation en Python. Cette interface introduite dans le langage C peut nous aider à faire beaucoup de choses, comme certains petits problèmes qui nécessitent d'appeler du code C pour améliorer les performances. Grâce à elle, vous pouvez accéder au système Windows32. dll et msvcrt.dll et la bibliothèque libc.so.6 sur les systèmes Linux. Bien sûr, vous pouvez également utiliser vos propres bibliothèques partagées compilées

Regardons d'abord un exemple simple pour utiliser Python. trouvez les nombres premiers inférieurs à 1 000 000, répétez ce processus 10 fois et calculez le temps d'exécution

import math
from timeit import timeit
def check_prime(x):
values ​​​​= xrange. (2 , int(math.sqrt(x)) + 1)
pour i en valeurs :
si x % i == 0 :
return False
return True
def get_prime( n) :
return [x for x in xrange(2, n) if check_prime(x)]
print timeit(stmt='get_prime(1000000)', setup='from __main__ import get_prime',
number =10)

Sortie

42.8259568214

Écrivez une fonction check_prime en langage C ci-dessous, puis importez-la en tant que bibliothèque partagée (bibliothèque de liens dynamiques)

#include
#include
int check_prime(int a)
{
int c;
for ( c = 2 ; c <= sqrt(a) ; c++ ) {
if ( a%c == 0 )
renvoie 0;
}
renvoie 1;
}

utiliser La commande suivante génère un fichier .so (objet partagé)

gcc -shared -o prime.so -fPIC prime.c
import ctypes
import math
from timeit import timeit
check_prime_in_c = ctypes.CDLL('./prime.so').check_prime
def check_prime_in_py(x):
values ​​​​= xrange(2, int(math.sqrt(x)) + 1)
pour i en valeurs :
if x % i == 0 :
return False
return True
def get_prime_in_c(n):
return [x for x in xrange(2 , n) if check_prime_in_c (x)]
def get_prime_in_py(n):
return [x for x in xrange(2, n) if check_prime_in_py(x)]
py_time = timeit(stmt='get_prime_in_py (1000000)', setup='from __main__ import get_prime_in_py',
    number=10)
c_time = timeit(stmt='get_prime_in_c(1000000)', setup='from __main__ import get_prime_in_c',
    numéro =10)
imprimer "Version Python : {} secondes".format(py_time)
imprimer "Version C : {} secondes".format(c_time)

Sortie

Version Python : 43,4539749622 secondes
Version C : 8,56250786781 secondes

Nous pouvons voir l'écart de performances évident. Voici d'autres façons de déterminer si un nombre est premier

Regardons un problème plus complexe. exemple trier rapidement

mylib.c

#include
typedef struct _Range {
 int start, end;
} Range;
Range new_Range(int s, int e) {
 Range r ;
 r.start = s;
 r.end = e;
 return r;
>
void swap(int *x, int *y) {
 int t = *x;
 *x = *y;
 *y = t;
}
void quick_sort(int arr[], const int len) {
 if (len <= 0 )
   return;
 Range r[len];
 int p = 0;
 r[p++] = new_Range(0, len - 1);
 while (p) {
   Range range = r[--p];
   if (range.start >= range.end)
     continue;
   int mid = arr[range.end];
   int left = range.start, right = range.end - 1;
   pendant que (gauche < droite) {
     pendant que (arr[gauche] < milieu && gauche < droite)
       gauche++;
     pendant (arr[right] >= milieu && gauche < droite)
       droite--;
     swap(&arr[gauche], &arr[droite]);
   }
   si (arr[gauche ] >= arr[range.end])
     swap(&arr[left], &arr[range.end]);
   else
     left++;
   r[p++] = new_Range(range. start, left - 1);
   r[p++] = new_Range(left + 1, range.end);
 }
>
gcc -shared -o mylib.so -fPIC mylib.c

Les ctypes sont des exemples de Python. Il s'agit d'un tableau de type Python.所以我们需要进行转换

test.py

import ctypes
import time
import random
quick_sort = ctypes.CDLL('./mylib.so'). quick_sort
nums = []
for _ in range(100):
 r = [random.randrange(1, 100000000) for x in xrange(100000)]
 arr = (ctypes.c_int * len(r))(*r)
 nums.append((arr, len(r)))
init = time.clock()
pour i in range(100):
quick_sort(nums[i][0], nums[i][1])
print "%s" % (time.clock() - init)

输出

1.874907

与Python list 的 sort 方法进行对比

import ctypes
import time
import random
quick_sort = ctypes.CDLL('./mylib.so'). quick_sort
nums = []
for _ in range(100):
 nums.append([random.randrange(1, 100000000) for x in xrange(100000)])
init = time .clock()
for i in range(100):
 nums[i].sort()
print "%s" % (time.clock() - init)

输出

2.501257

至于结构体,需要定义一个类,包含相应的字段和类型

class Point(ctypes. Structure) :
 _fields_ = [( 'x', ctypes.c_double)导入系统提供的库文件,比如linux下c标准库的实现 glibc

import time

import random

from ctypes import cdll

libc = cdll.LoadLibrary('libc.so.6') # Linux系统
# libc = cdll.msvcrt # Windows系统
init = time.clock()
randoms = [random.randrange(1, 100) for x in xrange(1000000)]
print "Version Python : %s secondes" % (time.clock() - init)
init = time.clock()
randoms = [(libc.rand() % 100) pour x dans xrange(1000000)]
imprimer "Version C : %s secondes" % (time.clock() - init)

输出

Version Python : 0,850172 secondes

Version C : 0,27645 secondes

总结

以上就是这篇文章的全部内容,希望对大家学习或使用Python能有一定的帮助,如果有疑问大家可以留言交流。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn