首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Cythonize两个小numpy函数,需要帮助

Cythonize两个小numpy函数,需要帮助
EN

Stack Overflow用户
提问于 2013-11-19 22:54:54
回答 1查看 584关注 0票数 5

问题所在

我正在尝试对两个小函数进行Cython化,这两个小函数主要是为了一些科学目的而处理numpy ndarray。这两个小函数在遗传算法中被调用了数百万次,占算法所用时间的大部分。

我自己取得了一些进步,两者都工作得很好,但速度只有很小的提高(10%)。更重要的是,cython --annotate表明大部分代码仍在使用Python。

代码

第一个函数:

这个函数的目的是取回数据切片,它在一个内部嵌套循环中被调用了数百万次。根据data1中的布尔值,我们可以按正向或反向顺序获取切片。

代码语言:javascript
复制
#Ipython notebook magic for cython
%%cython --annotate
import numpy as np
from scipy import signal as scisignal

cimport cython
cimport numpy as np
def get_signal(data):
    #data[0] contains the data structure containing the numpy arrays
    #data[1][0] contains the position to slice
    #data[1][1] contains the orientation to slice, forward = 0, reverse = 1

    cdef int halfwinwidth = 100
    cdef int midpoint = data[1][0]
    cdef int strand = data[1][1]
    cdef int start = midpoint - halfwinwidth
    cdef int end = midpoint + halfwinwidth
    #the arrays we want to slice
    cdef np.ndarray r0 = data[0]['normals_forward']
    cdef np.ndarray r1 = data[0]['normals_reverse']
    cdef np.ndarray r2 = data[0]['normals_combined']
    if strand == 0:
        normals_forward = r0[start:end]
        normals_reverse = r1[start:end]
        normals_combined = r2[start:end]
    else:
        normals_forward = r1[end - 1:start - 1: -1]
        normals_reverse = r0[end - 1:start - 1: -1]
        normals_combined = r2[end - 1:start - 1: -1]
    #return the result as a tuple
    row = (normals_forward,
           normals_reverse,
           normals_combined)
    return row

第二个函数

这个函数得到了numpy数组的元组列表,我们想要将数组元素相加,然后对它们进行归一化,并得到交集的积分。

代码语言:javascript
复制
def calculate_signal(list signal):
    cdef int halfwinwidth = 100
    cdef np.ndarray profile_normals_forward = np.zeros(halfwinwidth * 2, dtype='f')
    cdef np.ndarray profile_normals_reverse = np.zeros(halfwinwidth * 2, dtype='f')
    cdef np.ndarray profile_normals_combined = np.zeros(halfwinwidth * 2, dtype='f')
    #b is a tuple of 3 np.ndarrays containing 200 floats
    #here we add them up elementwise
    for b in signal:
        profile_normals_forward += b[0]
        profile_normals_reverse += b[1]
        profile_normals_combined += b[2]
    #normalize the arrays
    cdef int count = len(signal)

    #print "Normalizing to number of elements"
    profile_normals_forward /= count
    profile_normals_reverse /= count
    profile_normals_combined /= count
    intersection_signal = scisignal.detrend(np.fmin(profile_normals_forward, profile_normals_reverse))
    intersection_signal[intersection_signal < 0] = 0
    intersection = np.sum(intersection_signal)

    results = {"intersection": intersection,
               "profile_normals_forward": profile_normals_forward,
               "profile_normals_reverse": profile_normals_reverse,
               "profile_normals_combined": profile_normals_combined,
               }
    return results

感谢任何帮助-我尝试使用内存视图,但由于某些原因,代码变得非常、非常慢。

EN

回答 1

Stack Overflow用户

发布于 2015-03-12 18:20:09

修复数组cdef之后(如前所述,使用指定的dtype ),您可能应该将例程放在cdef函数中(该函数只能由同一脚本中的def函数调用)。

在函数的声明中,您需要提供类型(如果是数组numpy,还需要提供维度):

代码语言:javascript
复制
cdef get_signal(numpy.ndarray[DTYPE_t, ndim=3] data):

不过,我不确定使用字典是不是一个好主意。您可以使用numpy的列或行切片,如data:,0。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20074780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档