Ich habe ein Problem bei der Zuweisung von temporären Ergebnissen zu einem Array mit Cython. Hier erkläre ich eine test_array
, und weight_array
, und unter Verwendung for
Schleife, ich speichern jedes gewichtete Ergebnis in eine res_array
. Sowohl test_array
als auch weight_array
sind in Cython als C-zusammenhängende Arrays definiert. Die test.pyx und setup.py Dateien sind wie folgt aufgeführt:Warum Werte zuweisen C-zusammenhängende Array ist langsam in meinem Fall mit Cython
# test.pyx
import numpy as np
cimport numpy as np
import random
cimport cython
from cython cimport boundscheck, wraparound
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
@cython.cdivision(True)
@cython.profile(True)
def cython_sample(int res_size, int sample_size, double[::1] all_data, double[::1] weight_array):
# using c-contiguous array can speed up a little bit
cdef int ii, jj
cdef double tmp_res, dot_result
cdef double[::1] tmp_sample = np.ones(sample_size, dtype=np.double)
cdef double[::1] res_array = np.ones(res_size, dtype=np.double)
ran = random.normalvariate # generate random value as a test
for ii in range(res_size):
tmp_sample = all_data[ii:(ii + sample_size)]
# inner product operation
dot_result = 0.0
for jj in range(sample_size):
dot_result += tmp_sample[jj]*weight_array[jj]
# save inner product result into array
res_array[ii] = dot_result
#res_array[ii] = ran(10000,20000)
return res_array
# setup.py
from setuptools import setup,find_packages
from distutils.extension import Extension
from Cython.Build import cythonize
import numpy as np
ext = Extension("mycython.test", sources=["mycython/test.pyx"])
setup(ext_modules=cythonize(ext),
include_dirs=[np.get_include()],
name="mycython",
version="0.1",
packages=find_packages(),
author="me",
author_email="[email protected]",
url="http://example.com/")
Und der Python test.py ist:
import time
import random
import numpy as np
from strategy1 import __cyn__
sample_size = 3000
test_array = [random.random() for _ in range(300000)]
res_size = len(test_array) - sample_size + 1
weight_array = [random.random() for _ in range(sample_size)]
c_contig_store_array = np.ascontiguousarray(test_array, dtype=np.double)
c_contig_weigh_array = np.ascontiguousarray(weight_array, dtype=np.double)
replay = 100
start_time = time.time()
for ii in range(int(replay)):
__cyn__.cython_sample(res_size, sample_size, c_contig_store_array, c_contig_weigh_array)
per_elapsed_time = (time.time() - start_time)/replay
print('Elapse time :: %g sec' % (per_elapsed_time))
So teste ich zwei Szenarien:
# 1. when saving dot_result into 'res_array':
res_array[ii] = dot_result
Geschwindigkeit Test zeigt: Elapse time :: 0.821084 sec
# 2. when saving a random value ran(10000,20000) into 'res_array':
res_array[ii] = ran(10000,20000)
Geschwindigkeitstest zeigt: Elapse time :: 0.214591 sec
.
Der Grund, dass ich ran(*,*)
verwenden, um die Codes zu testen ist, dass ich gefunden, wenn ich beide res_array[ii] = dot_result
und res_array[ii] = ran(10000,20000)
in dem ursprünglichen Codes auf Kommentar, wird die Geschwindigkeit fast 30-100 mal erhöhen (Elapse time :: 0.00633394 sec
). Dann dachte ich, das Problem könnte darin liegen, Wert zu res_array
zuzuweisen, was wahr wird, da die Geschwindigkeit der Zuordnung eines zufällig generierten Doppelwerts ran(10000,20000)
zu res_array
ziemlich schnell ist (fast 4 mal schneller, wie oben gezeigt).
Gibt es eine Möglichkeit, dieses Problem zu lösen? Dank
Danke für den Hinweis! Der erste Punkt ist ziemlich cool, und ich stimme dem zu. Für das signal.fftconvolve versuche ich es in meinen Cython- oder Python-Codes, und es kann kaum beschleunigen (aus irgendeinem Grund wird es langsamer) und das innere Produkt scheint die einfachste Lösung zu sein, da wir viele Male innere Produktoperationen ausführen ein rollendes Fenster. Glaubst du, gibt es einen besseren Weg, um das Produkt in Cython zu beschleunigen? Danke – Alvin
mein Beispielcode für 'signal.fftconvolve()' gibt das gleiche Ergebnis wie die 'cython_sample()' Funktion zurück. Sie müssen es nicht in Cython aufrufen. Es gibt keine innere Schleife, wenn Sie die fft-Methode verwenden. – HYRY
Ja, ich habe es! Brilliante Lösung, es ist wirklich schnell, sogar 17 mal schneller als mit *** cdef extern von "cblas.h": doppelter ddot "cblas_ddot" (int, double *, int, double *, int) *** wie in http://maldun.lima-city.de/introduction_to_python/Cython.html. Dein Weg ist eine ziemlich coole Idee! – Alvin