Es ist ein Hinweis, weil ich festgestellt habe, dass ich Cython mit Jupyter Notebook (iPython Notebook) einfacher als erwartet ausprobieren kann. Cython beschleunigt die Verarbeitung, indem es vor der Ausführung kompiliert und statisch eingegeben wird.
(Die .ipynb-Datei für diesen Artikel wurde auf Github [hier] hochgeladen (https://github.com/matsuken92/Qiita_Contents/blob/master/General/Cython_test.ipynb).)
Die Umgebung, die ich ausprobiert habe, ist wie folgt. Ich versuche es auf Mac und Anaconda. Wenn Sie Anaconda installiert haben, ist keine besondere Vorbereitung erforderlich.
Python 3.5.1 |Anaconda custom (x86_64)| (default, Jun 15 2016, 16:14:02)
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin
IPython 5.0.0
#Ermöglichen das Kompilieren von Cython-Dateien auf Jupyter Notebook
%load_ext Cython
Schreiben Sie den Cython-Code mit "%% Cython" am Anfang. Das Beispiel wird aus Cython Tutorial Basics verwendet.
# ↓ -n <Dateiname>Durch Hinzufügen wird es einfacher, die Datei später zu überprüfen.
%%cython -n test_cython_code
def fib(int n):
cdef int i
cdef double a=0.0, b=1.0
for i in range(n):
a, b = a+b, a
return a
def primes(int kmax):
cdef int n, k, i
cdef int p[1000]
result = []
if kmax > 1000:
kmax = 1000
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i += 1
if i == k:
p[k] = n
k += 1
result.append(n)
n += 1
return result
print(fib(90))
print(primes(20))
out
2.880067194370816e+18
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
erledigt!
Schreiben wir den gleichen Prozess in rohem Python und vergleichen die Ausführungszeiten.
import numpy as np
#Python-Funktion zum Leistungsvergleich
def pyfib(n):
a, b = 0.0, 1.0
for i in range(n):
a, b = a+b, a
return a
def pyprimes(kmax):
p = np.zeros(1000)
result = []
#Die maximale Anzahl beträgt 1000
if kmax > 1000:
kmax = 1000
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i += 1
if i == k:
p[k] = n
k += 1
result.append(n)
n += 1
return result
#Generieren und messen Sie wiederholt die 1000. Fibonacci-Zahl
%timeit fib(1000)
%timeit pyfib(1000)
Cython ist ungefähr 50 mal schneller!
out
1000000 loops, best of 3: 786 ns per loop
10000 loops, best of 3: 42.5 µs per loop
%timeit primes(1000)
%timeit pyprimes(1000)
out
100 loops, best of 3: 2.12 ms per loop
1 loop, best of 3: 218 ms per loop
Diese Berechnung ist ungefähr 100 mal schneller!
1000 ganze Zahlen
df = pd.DataFrame(np.arange(1, 10**4), columns=['num'] )
Sie können es einfach verwenden, indem Sie die Funktion in der Apply-Funktion angeben: erröten:
%timeit df['fib'] = df.num.apply(fib)
%timeit df['pyfib'] = df.num.apply(pyfib)
out
10 loops, best of 3: 39.2 ms per loop
1 loop, best of 3: 2.02 s per loop
print(df.head())
out
num fib pyfib
0 1 1.0 1.0
1 2 1.0 1.0
2 3 2.0 2.0
3 4 3.0 3.0
4 5 5.0 5.0
Die kompilierte Cython-Datei wird in ~ / .ipython / cython
gespeichert.
Wenn beim Kompilieren ein Dateiname mit %% cython -n
#Daten erstellen
rd.seed(71)
n_data = 10**5
X = pd.DataFrame(rd.normal(size=3*n_data).reshape((n_data,3)), columns=["a", "b", "c"])
print(X.shape)
print(X.head())
out
(100000, 3)
a b c
0 -0.430603 -1.193928 -0.444299
1 0.489412 -0.451557 0.585696
2 1.177320 -0.965009 0.218278
3 -0.866144 -0.323006 1.412919
4 -0.712651 -1.362191 -1.705966
Schreiben Sie Cython-Code, der ndarray als Argument verwendet
%%cython -n sample_calc
import numpy as np
cimport numpy as np
cpdef np.ndarray[double] sample_calc(np.ndarray col_a, np.ndarray col_b, np.ndarray col_c):
#Typprüfung für jede Spalte
assert (col_a.dtype == np.float and col_b.dtype == np.float and col_c.dtype == np.float)
#Überprüfen Sie, ob die Größe jeder Spalte gleich ist
cdef Py_ssize_t n = len(col_c)
assert (len(col_a) == len(col_b) == n)
cdef np.ndarray[double] res = np.empty(n)
# (a-b)/Berechnen Sie c
for i in range(n):
res[i] = (col_a[i] - col_b[i])/col_c[i]
return res
Anruf von Python Seite
sample_calc(X.a.values, X.b.values, X.c.values)
out
array([-1.71804336, 1.60658332, 9.81468496, ..., -0.44683095,
0.46970409, -0.28352272])
#Zum Vergleich
def pysample_calc(col_a, col_b, col_c):
#Typprüfung für jede Spalte
assert (col_a.dtype == np.float and col_b.dtype == np.float and col_c.dtype == np.float)
#Überprüfen Sie, ob die Größe jeder Spalte gleich ist
n = len(col_c)
assert (len(col_a) == len(col_b) == n)
res = np.empty(n)
# (a-b)/Berechnen Sie c
for i in range(n):
res[i] = (col_a[i] - col_b[i])/col_c[i]
return res
%timeit sample_calc(X.a.values, X.b.values, X.c.values)
%timeit pysample_calc(X.a.values, X.b.values, X.c.values)
out
100 loops, best of 3: 16.7 ms per loop
10 loops, best of 3: 37.2 ms per loop
#Datengenerierung
rd.seed(71)
n_data = 10**7
X2 = rd.random(size=(n_data,2)).astype(np.float)
X2.dtype
Definition der Cython-Funktion
%%cython -n calc_pi
import numpy as np
cimport numpy as np
cpdef np.ndarray[long] calc_pi(np.ndarray[double, ndim=2] data):
cdef Py_ssize_t n = len(data)
cdef np.ndarray[long] res = np.empty(n, dtype=np.int)
for i in range(n):
res[i] = 1 if (data[i,0]**2 + data[i,1]**2) < 1 else 0
return res
Python-Funktion zum Vergleich
#Python-Funktion zum Vergleich
def pycalc_pi(data):
n = len(data)
res = [1 if (data[i,0]**2 + data[i,1]**2) < 1 else 0 for i in range(n)]
return res
Ich werde es messen.
%time calc_pi(X2)
%time pycalc_pi(X2)
out
CPU times: user 25.2 ms, sys: 5.98 ms, total: 31.2 ms
Wall time: 31.1 ms
CPU times: user 7.7 s, sys: 46.1 ms, total: 7.75 s
Wall time: 7.75 s
Cython ist viel schneller!
#Überprüfen Sie, ob die Ergebnisse identisch sind
np.all(res == respy)
richtig!
out
True
#Berechnung des Umfangsverhältnisses
np.sum(res)/n_data*4
out
3.1413555999999998
Versuchen Sie zu zeichnen.
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
from matplotlib.colors import LinearSegmentedColormap
sns.set(style="darkgrid", palette="muted", color_codes=True)
#zeichnen
n_plot = 10**4 #Anzahl der zu ziehenden Punkte
plt.figure(figsize=(8,8))
plt.scatter(X2[:n_plot,0], X2[:n_plot,1], c=res[:n_plot], s=10)
Sie beurteilen das Innere und Äußere des Kreises richtig.
Grundlagen des Cython-Tutorials http://omake.accense.com/static/doc-ja/cython/src/userguide/tutorial.html
O'Reilly "Cython" https://www.oreilly.co.jp/books/9784873117270/
pandas 0.18.1 documentation Enhancing Performance http://pandas.pydata.org/pandas-docs/stable/enhancingperf.html
Recommended Posts