2014-04-14 45 views
9

Grubumuza Python performansını artırmak için Cython'un erdemlerini göstermeye çalışıyorum. Sadece bu hıza ulaşmak için birkaç kriter gösterdim:Dizeleri Cython'da Optimize Etme

  1. Mevcut Python kodunu derlemek.
  2. Statik tip değişkenlere cdef kullanarak, özellikle iç döngülerde.

Bununla birlikte, kodlarımızın çoğunda dize manipülasyonu vardır ve Python dizeleri yazarak kodun en iyi duruma getirilmesiyle ilgili iyi örnekler veremedim.

denedim bir örnek:

cdef str a 
cdef int i,j 
for j in range(1000000): 
    a = str([chr(i) for i in range(127)]) 

ama yazarak 'a' bir dize aslında kod çalıştırmak yavaşlatır olarak. 'Unicode ve geçen dizeler' ile ilgili belgeleri okudum, ancak gösterdiğim durumda bunun nasıl uygulanacağı konusunda kafam karıştı. Unicode kullanmıyoruz - her şey saf ASCII. Python 2.7.2'yi kullanıyoruz. Herhangi bir öneriyi takdir ediyoruz.

+0

Bu Python 2 mi? Eğer öyleyse, neden 'range' kullanıyorsunuz? –

+0

Yani, xrange kullan? –

+0

Gerçekten, kodun son satırı için kastettiğim şey: '' .join ([i (i) için menzil (127)]) –

cevap

12

cpython.array.array s işlemlerinizi yapmanızı öneririz. En iyi dokümantasyon C API ve link için çok tembel olduğum Cython kaynağıdır.

from cpython cimport array 

def cfuncA(): 
    cdef str a 
    cdef int i,j 
    for j in range(1000): 
     a = ''.join([chr(i) for i in range(127)]) 

def cfuncB(): 
    cdef: 
     str a 
     array.array[char] arr, template = array.array('c') 
     int i, j 

    for j in range(1000): 
     arr = array.clone(template, 127, False) 

     for i in range(127): 
      arr[i] = i 

     a = arr.tostring() 

Gereken işlemler, dizelerinizde yaptığınız işlemlere göre çok farklı olduğunu unutmayın.

>>> python2 -m timeit -s "import pyximport; pyximport.install(); import cyytn" "cyytn.cfuncA()" 
100 loops, best of 3: 14.3 msec per loop 

>>> python2 -m timeit -s "import pyximport; pyximport.install(); import cyytn" "cyytn.cfuncB()" 
1000 loops, best of 3: 512 usec per loop 

Yani bu durumda bir 30x hız kalmış.


Ayrıca FWIW, sen arr.data.as_chars[:len(arr)] ile arr.tostring() değiştirilmesi ve bytes olarak a yazarak başka adil birkaç us çıkarabilirsin.

+0

Mükemmel! Teşekkür ederim Veedrac –