2016-04-06 29 views
1

kullanarak benim durumumda yavaştır. Burada bir test_array, sample-size ve weight_array beyan ve for döngü kullanarak, bir res_array içine her ağırlıklı sonucu kaydedin. Hem test_array ve weight_array, Cython'da C-bitişik diziler olarak tanımlanır. aşağıdaki gibi test.pyx ve setup.py dosyalar listelenmiştir:Neden atama değerler Ben Cython kullanarak bir dizi geçici sonuçlarını atama bir sorun var 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/") 

Ve piton test.py geçerli:

# 1. when saving dot_result into 'res_array': 
    res_array[ii] = dot_result 

hızı:

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)) 

Yani iki senaryoları test test gösterimleri: Elapse time :: 0.821084 sec

# 2. when saving a random value ran(10000,20000) into 'res_array': 
    res_array[ii] = ran(10000,20000) 

hız testi gösterir: Elapse time :: 0.214591 sec. Ben kodlarını sınamak için ran(*,*) kullanmak

nedeni ben orijinal kodları hem res_array[ii] = dot_result ve res_array[ii] = ran(10000,20000) dışarı yorum yaparsanız, hız neredeyse 30-100 kat (Elapse time :: 0.00633394 sec) artacak bulundu olmasıdır. (Yukarıda gösterildiği gibi neredeyse 4 kat daha hızlı) Sonra konu res_array için rastgele oluşturulmuş çift değerini ran(10000,20000) atama hızı gibi gerçek olamayacak kadar açmak, hangi res_array için dot_result değer atama yalan sandım oldukça hızlı.

bu sorunu çözmek için herhangi bir yolu var mı? Teşekkür

cevap

3

Eğer dot_result değerini kullanmak do't ise derleyici döngü kaldıracaktır: çoğu zaman

dot_result = 0.0 
for jj in range(sample_size): 
    dot_result += tmp_sample[jj]*weight_array[jj] 

iç döngü maliyetleri.

Sen correlate() gibi görünse kod Cython, kullanmakta fft bunu hızlandırabilir: Not için

from scipy import signal 
res = signal.fftconvolve(c_contig_store_array, c_contig_weigh_array[::-1], mode="valid") 
+0

Teşekkür! İlk nokta oldukça havalı ve buna katılıyorum. signal.fftconvolve için, benim Cython veya piton kodlarında denemek ve pek hızlandırabilir (nedense yavaşlatmak) ve biz defalarca iç çarpım işlemlerini yapıyoruz kadar iç çarpım en basit çözümü gibi görünüyor bir haddeleme penceresi. Cython'da iç ürünü hızlandırmanın daha iyi bir yolu olduğunu mu düşünüyorsun? Teşekkürler – Alvin

+0

'signal.fftconvolve()' için örnek kodum, 'cython_sample()' işleviyle aynı sonucu döndürür. Cython'da aramanıza gerek yok. Fft yöntemini kullanırsanız iç döngü yoktur. – HYRY

+0

Evet, anladım! belirtildiği üzere *** çift ddot "cblas_ddot" (int, double *, int, double *, int): Parlak çözüm, hatta 17 kat daha hızlı "cblas.h" dan *** cdef extern kullanmak yerine, gerçekten hızlı http://maldun.lima-city.de/introduction_to_python/Cython.html. Senin yolun güzel bir fikir! – Alvin