This article introduces how to use ctypes to improve the execution speed of Python, which has some reference value for us to learn to use Python. Let's have a look at the friends who need them.
">
Objective
cTYPES is the external library of functions for Python. It provides a C-compatible data type and allows you to invoke functions in a dynamic-link library/shared library. It can wrap these libraries up for Python use. The introduction of the C language interface can help us do a lot of things, such as the need to call C code to improve performance of some small problems. It allows you to access the Kernel32.dll and Msvcrt.dll dynamic link libraries on Windows systems, as well as the Libc.so.6 libraries on Linux systems. Of course you can also use your own compiled shared library
Let's start with a simple example where we use Python for 1000000 primes, repeat the process 10 times, and calculate the elapsed time.
Import Math
From Timeit import Timeit
def check_prime (x):
Values = xrange (2, int (math.sqrt (x)) + 1)
For I in Values:
If 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)
Output
42.8259568214
Below, write a check_prime function in C and import it as a shared library (dynamic link library)
#include <stdio.h>
#include <math.h>
int check_prime (int a)
{
int C;
for (c = 2; c <= sqrt (a); C + +) {
if (a%c = = 0)
return 0;
}
return 1;
}
Use the following command to generate a. So (Shared object) file
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)
For I in Values:
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 ',
NUMBER=10)
Print "Python version: {} seconds". Format (Py_time)
Print "C version: {} seconds". Format (C_time)
Output
Python version:43.4539749622 seconds
C version:8.56250786781 seconds
We can see the obvious performance gap there are more ways to determine if a number is a prime
Take a look at a more complicated example. Quick Sort
Mylib.c
#include <stdio.h>
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;
while (left < right) {
while (Arr[left] < mid && left < right)
left++;
while (Arr[right] >= mid && left < right)
right--;
Swap (&arr[left], &arr[right]);
}
if (Arr[left] >= 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
The trouble with using ctypes is that the type used by native C code may not correspond explicitly to Python. Like here, what is an array in Python? List? or an array in the array module. So we need to convert.
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 ()
For I in range (100):
Quick_sort (Nums[i][0], nums[i][1])
Print "%s"% (Time.clock ()-init)
Output
1.874907
Compare to the sort method of the Python list
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)
Output
2.501257
As for structs, you need to define a class that contains the corresponding fields and types
Class Point (ctypes. Structure):
_fields_ = [(' x ', ctypes.c_double),
(' Y ', ctypes.c_double)]
In addition to importing our own written C language extension files, we can also directly import the system-provided library files, such as the implementation of the C standard library under Linux glibc
Import time
Import Random
From ctypes import Cdll
libc = Cdll. LoadLibrary (' libc.so.6 ') # Linux system
# libc = cdll.msvcrt # Windows system
init = Time.clock ()
Randoms = [Random.randrange (1, +) for x in Xrange (1000000)]
Print "Python version:%s seconds"% (Time.clock ()-init)
init = Time.clock ()
Randoms = [(Libc.rand ()%) for x in Xrange (1000000)]
Print "C version:%s seconds"% (Time.clock ()-init)
Output
Python version:0.850172 seconds
C version:0.27645 seconds
Summarize
The above is the entire content of this article, I hope to learn from you or use Python can have a certain help, if there are questions you can message exchange.