2016-11-04 110 views
0

我不確定這是否已被解決以前,我試過搜索,但沒有找到我正在尋找什麼。我想獲得下面的代碼工作(文件是some_CD.pyx名)與Openmp的Cython numpy陣列(沒有GIL)

import numpy as np 
cimport numpy as np 
cimport cython 
from cython.parallel import * 

ctypedef np.float64_t DTYPE 

cdef DTYPE evaluate_objective(np.ndarray[DTYPE, ndim=2] A,np.ndarray[DTYPE, ndim=1] b,np.ndarray[DTYPE, ndim=1] x): 
    return x.dot(A.dot(x) - b.dot(x)) 

cpdef DTYPE coordinate_descent(np.ndarray[DTYPE, ndim=2] A,np.ndarray[DTYPE, ndim=1] b,int nDim, int nIter): 
    cdef int i, iter 
    cdef np.ndarray[DTYPE, 
        ndim=1] x = \ 
        np.zeros(nDim,) 
    cdef DTYPE temp 
    for iter in prange(nIter,nogil=True): 
     i = (iter%nDim) 
     temp = (b[i]-(A[:,i].dot(x)*x[i]) + (A[i,i]*x[i]*x[i]))/A[i,i] 
     x[i] = np.max([0,np.min([temp,1])]) 
    return evaluate_objective(A,b,x) 

我setup.py看起來如下

from distutils.core import setup, Extension 
from Cython.Build import cythonize 
import numpy 

ext_modules = [ 
    Extension(
     "some_CD", 
     ["some_CD.pyx"], 
     extra_compile_args=['-fopenmp'], 
     extra_link_args=['-fopenmp'], 
    ) 
] 

setup(
    name='some_parallel', 
    ext_modules=cythonize(ext_modules), 
    include_dirs=[numpy.get_include()] 
) 

有很多事情我不知道這個代碼。首先,我是否以正確的方式使用numpy數組?是否在prange中使用float64,np.int類型的變量?

+0

不幸的是,你不能在nogil上下文中使用numpy數組,因爲它們本身就是python對象。這個問題也困擾了我一段時間,雖然我沒有寫出自己解決問題的東西,但是我正在瀏覽sklearn的sourcode,看起來他們在進入nogil環境之前會將其數據記錄到他們的ndarrays中。這應該讓你進入一個純粹的C語境,你可以用prange來使用nogil。 – Erotemic

+0

複製整個陣列特別是在大尺寸時是不是很費時間?有沒有什麼有效的方法?如果可能,你可以修改代碼作爲答案嗎?花費相當長的時間才能瞭解正確的語法和所有! – user52705

回答

0

此循環無法並行化,因爲它是迭代算法。換句話說,後面的迭代取決於前面迭代的結果。

忽略這個問題,這裏是你將如何改變的代碼..

沒有GIL你只能使用基本的索引(無切片)和極少數通過用Cython套管Python函數特殊(主要是那些listed here )。所以你只需要讓prange更清晰明確。

for iter in prange(nIter, nogil=True): 
    i = iter % nDim 

    Ai_dot_x = 0 
    for j in range(x.shape[0]): 
     Ai_dot_x += A[j,i] * x[j] 

    temp = (b[i] - Ai_dot_x*x[i] + A[i,i]*x[i]*x[i])/A[i,i] 
    x[i] = max(0, min(temp, 1)) 

Ai_dot_x是,你必須cdef額外的臨時變量。

+0

不知道Cython的細節,但不會將'prange(nIter):'分割爲'range(nIter/nDim):'和'prange(nDim,nogil = True):'解決數據依賴性問題?我確實沒有看到爲什麼這些合併在一起的問題。 – Zulan

+0

@ user6758673在進行更改後,我在問題中添加了回溯。請檢查以上。 – user52705

+0

@Zulan你提到的可能是一種不同的算法,也許它叫做平行座標下降(部分異步)。我想要做的是真正的異步更新,其中每個座標有時可能不止一次更新。 – user52705