2017-02-21 49 views
1

的大小当我尝试编译下面的代码,我得到的错误用Cython让吉尔走的时候,我需要numpy的阵列

return sign_match.sum()/y_true.shape[0] 
            ^

转换为Python对象不得擅自吉尔

有没有简单的方法来克服这一点?我能想到的最可行的解决方案是将数组的长度作为另一个参数传递。我正在使用python 3.3.5。

​​

回答

3

y_truey_pred是数组,因而Python对象。因此,任何使用它们的操作都需要gil,而不仅仅是形状。

尝试编译没有nogil,并看看-a html。哪些行是深黄色的,有很多Python对象引用?

+11:  return -(err * err).sum()/y_true.shape[0] 
    __pyx_t_7 = PyNumber_Multiply(((PyObject *)__pyx_v_err), ((PyObject *)__pyx_v_err)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 11, __pyx_L1_error) 
    __Pyx_GOTREF(__pyx_t_7); 
    __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_sum); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 11, __pyx_L1_error) 
    __Pyx_GOTREF(__pyx_t_8); 
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; 
    .... 

只是您的文件的扩展C代码的一部分。查看所有Pyx..调用。他们都需要gil

http://docs.cython.org/en/latest/src/userguide/memoryviews.html表明您可以在numpy数组的内存视图上使用nogil

从memoryview指南绘制我写了这个替代功能

cpdef double neg_mse_view(double[:] y_true, double[:] y_pred): 
    cdef double x, res 
    cdef int I 
    I = y_true.shape[0] 
    res = 0 
    for i in range(I): 
     x = y_true[i]-y_pred[i] 
     res += -(x*x) 
    res = res/I 
    return res 

这可以用同样的方法被调用。这些时间表现出2x加速。 nogil工程,但没有区别。

In [10]: a=np.arange(1000000.) 
In [11]: timeit negmse.negative_mse(a,a-10) 
10 loops, best of 3: 16.9 ms per loop 
In [12]: timeit negmse.neg_mse_view(a,a-10) 
100 loops, best of 3: 7.17 ms per loop 
In [13]: timeit negmse.neg_mse_nogil(a,a-10) 
100 loops, best of 3: 7.19 ms per loop 

对于函数这个简单的,纯粹的numpy的版本基本上是一样好:

In [20]: timeit ((a-(a-10))**2).sum()/a.shape[0] 
100 loops, best of 3: 16.8 ms per loop 
+0

TY TY!哈哈我会认为numpy会一样快。我想在循环中使用nogil函数(一个更大的进程的一小部分)。我只是想要一个简单的例子来开始。这非常有帮助。 – itzjustricky