Cython

2013-07-23 19 views
8

ile paralel olarak bir liste üzerinde yineleme Cython'da bir (Python) listesi üzerinde nasıl paralel yineler? görünüşte GiL olmadan paralel bir bölümü herhangi bir Python nesne ile çalışamaz, çünkü bu derleyici hataları bir sürü verirCython

def sumList(): 
    cdef int n = 1000 
    cdef int sum = 0 

    ls = [i for i in range(n)] 

    cdef Py_ssize_t i 
    for i in prange(n, nogil=True): 
     sum += ls[i] 

    return sum 

:

Error compiling Cython file: 
------------------------------------------------------------ 
... 

    ls = [i for i in range(n)] 

    cdef Py_ssize_t i 
    for i in prange(n, nogil=True): 
     sum += ls[i] 
    ^
------------------------------------------------------------ 

src/parallel.pyx:42:6: Coercion from Python not allowed without the GIL 

Error compiling Cython file: 
------------------------------------------------------------ 
... 

    ls = [i for i in range(n)] 

    cdef Py_ssize_t i 
    for i in prange(n, nogil=True): 
     sum += ls[i] 
    ^
------------------------------------------------------------ 

src/parallel.pyx:42:6: Operation not allowed without gil 

Error compiling Cython file: 
------------------------------------------------------------ 
... 

    ls = [i for i in range(n)] 

    cdef Py_ssize_t i 
    for i in prange(n, nogil=True): 
     sum += ls[i] 
    ^
------------------------------------------------------------ 

src/parallel.pyx:42:6: Converting to Python object not allowed without gil 

Error compiling Cython file: 
------------------------------------------------------------ 
... 

    ls = [i for i in range(n)] 

    cdef Py_ssize_t i 
    for i in prange(n, nogil=True): 
     sum += ls[i] 
     ^
------------------------------------------------------------ 

src/parallel.pyx:42:11: Indexing Python object not allowed without gil 
+1

Bu hemen kullanışlı olmayabilir uint8_t

ctypedef unsigned char ama hiç D denediniz mi? C sözdizimi ve listeler üzerinde paralel yineleme gibi şeyler (D dizileri veya aralıkları) aşinaysanız MATLAB içinde yapmak kadar kolay. Buradaki örneğe bir bakın: [std.parallelism] (http://dlang.org/phobos/std_parallelism). Bir Python arka planından gelmeyi çok kolay buldum. –

+0

@mattyTpain Asla denemedim D, bir göz atacaklar. – clstaudt

+0

@mattyTpain D ile deney yapıldı, pythonic sözdizimini beğendi. Ama burada karşılaştığım bir konu: http://stackoverflow.com/questions/17837098/parallel-iterators-in-the-d-language – clstaudt

cevap

6

değilim

Aşağıdaki basit işlevi düşünün Bunu yapmanın herhangi bir yolunun farkında. Liste bir Python nesnesidir, bu yüzden __getitem__ yöntemini kullanmak GIL gerektirir. Bu durumda bir NumPy dizisini kullanabiliyorsanız, çalışır. Eğer çift hassasiyetli kayar nokta değer dizisi A üzerinde yineleme istiyorsa Örneğin, böyle bir şey yapabileceğini: my makinede

cimport cython 
from numpy cimport ndarray as ar 
from cython.parallel import prange 
@cython.boundscheck(False) 
@cython.wraparound(False) 
cpdef cysumpar(ar[double] A): 
    cdef double tot=0. 
    cdef int i, n=A.size 
    for i in prange(n, nogil=True): 
     tot += A[i] 
    return tot 

, bu özel durum için, Prange daha hızlı daha yapmaz Normal bir döngü, ancak diğer durumlarda daha iyi çalışabilir. Prange kullanımı hakkında daha fazla bilgi için bkz. http://docs.cython.org/src/userguide/parallelism.html

Bir diziyi kullanıp kullanamayacağınız, dizinin boyutunu ne kadar değiştirdiğinize bağlıdır. Boyutla çok fazla esnekliğe ihtiyacınız varsa, dizi çalışmayacaktır. C++ 'da vector sınıfıyla arayüz yapmayı deneyebilirsiniz. Bunu kendim yapmadım, ama burada nasıl yapılacağına dair kısa bir açıklama var: http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#nested-class-declarations

+0

Öte yandan, sadece bir toplamı ihtiyacınız varsa, sadece NumPy dizilerinin 'sum' yöntemini kullanın. – IanH

+0

İpuçları için teşekkürler. Toplam sadece basit bir örnektir, paralel olarak uygulanan daha karmaşık işlemlere ihtiyacım var. – clstaudt

+0

Evet, sorun değil. – IanH

0

Herhangi bir sayısal değere ihtiyacınız varsa veya 0 ile 255 arasında değerler sınırlanmışsa, listeniz bir diziye dönüştürülür. Sayısal değerlerden başka bir şey depolarsanız, numpy kullanmayı deneyin veya doğrudan doğruya dtypes kullanın.

cdef int[::1] gen = array.array('i',[1, 2, 3, 4]) 

Ve C türlerini kullanmak istiyorsanız: bayt ile Örneğin