Python 2.7 使用cython加速数千个set操作

Python 2.7 使用cython加速数千个set操作,python-2.7,optimization,cython,Python 2.7,Optimization,Cython,我一直在努力克服对Cython的恐惧(恐惧是因为我对c或c++一无所知) 我有一个函数,它有两个参数,一个集合(我们称之为testSet)和一个集合列表(我们称之为targetset)。然后,该函数遍历targetSets,并计算与testSet相交的长度,将该值添加到列表中,然后返回该列表 现在,这本身并没有那么慢,但问题是我需要对测试集进行模拟(当时有大量的测试集,~10000),而目标集大约有10000集长 因此,对于少量要测试的模拟,纯python实现大约需要50秒 我试着做了一个cyt

我一直在努力克服对Cython的恐惧(恐惧是因为我对c或c++一无所知)

我有一个函数,它有两个参数,一个集合(我们称之为
testSet
)和一个集合列表(我们称之为
targetset
)。然后,该函数遍历
targetSets
,并计算与
testSet
相交的长度,将该值添加到列表中,然后返回该列表

现在,这本身并没有那么慢,但问题是我需要对测试集进行模拟(当时有大量的测试集,~10000),而目标集大约有10000集长

因此,对于少量要测试的模拟,纯python实现大约需要50秒

我试着做了一个cython函数,它成功了,现在运行速度约为16秒

如果我能对cython函数做任何其他任何人都能想到的事情,那将是非常棒的(Python2.7 btw)

下面是我在overlapFunc.pyx中的Cython实现

def computeOverlap(set testSet, list targetSets):
    cdef list obsOverlaps  = []
    cdef int i, N
    cdef set overlap
    N = len(targetSets)
    for i in range(N):
        overlap = testSet & targetSets[i]
        if len(overlap) <= 1:
            obsOverlaps.append(0)
        else:
            obsOverlaps.append(len(overlap))
    return obsOverlaps
和一些代码,以建立一些随机集进行测试和时间的功能test.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("overlapFunc", 
                         ["overlapFunc.pyx"])]

setup(
      name = 'computeOverlap function',
      cmdclass = {'build_ext': build_ext},
      ext_modules = ext_modules
      )
import numpy as np
from overlapFunc import computeOverlap
import time

def simRandomSet(n):
    for i in range(n):
        simSet= set(np.random.randint(low=1, high=100, size=50))
        yield simSet


if __name__ == '__main__':
    np.random.seed(23032014)
    targetSet = [set(np.random.randint(low=1, high=100, size=50)) for i in range(10000)]

    simulatedTestSets = simRandomSet(200)
    start = time.time()
    for i in simulatedTestSets:
        obsOverlaps = computeOverlap(i, targetSet)
    print time.time()-start
我尝试在computerOverlap功能开始时更改def,如下所示:

cdef list computeOverlap(set testSet, list targetSets):
但是,当我运行
setup.py
脚本时,会收到以下警告消息:

'__pyx_f_11overlapFunc_computeOverlap' defined but not used [-Wunused-function]
然后,当我运行某个试图使用该函数的程序时,会出现一个导入错误:

    from overlapFunc import computeOverlap
ImportError: cannot import name computeOverlap
提前感谢您的帮助

干杯


Davy

在下一行中,扩展模块名称和文件名与实际文件名不匹配

ext_modules = [Extension("computeOverlapWithGeneList", 
                         ["computeOverlapWithGeneList.pyx"])]
替换为:

ext_modules = [Extension("overlapFunc",
                         ["overlapFunc.pyx"])]

旁白:您的
computeOverlap
函数似乎有一个bug;你在
p
上循环,但是使用
i
进行索引,你不增加它。你的
if
测试是多余的。整个函数可以写成
return[len(testSet&target)for target in targetset]
。我相信它也会运行得更快,虽然我对Cython的了解还不够,所以不能完全确定。很抱歉,示例代码不好。时间很晚了,在我开始写问题后,我开始玩弄东西。草率的!等等,那应该是说
吗?它肯定应该是说
<1
。正如我所说,他很累,而且很邋遢。抱歉。我试着跟随asciinema的东西(很酷,之前没见过),我改变了
ext\u modules
行,但没有产生任何不同的结果。我编辑了这个问题,因为有很多错误。很晚了。抱歉,谢谢。@DavyKavanagh,它是否产生了
overlapFunc.so
?是的,一切运行正常,但仍然像以前一样慢。Cython在这里没有什么可优化的。大部分工作是在testSet&targetSet[i]调用中完成的,这由Python负责(实际上是用C实现的)。Cython可以从Python解释器中节省开销,这已经很小了。一个好主意是首先评测代码。它会告诉你瓶颈在哪里。Cython无法使Python中的任何东西运行得更快。Cython可以将Python代码与C集成,C有时(但并非总是)比Python快得多。但如果在Cython代码中不使用任何C,ypu将很难从Cython中获得任何好处。Cython实际上非常难,因为您必须了解Python和C,并且能够在类似Python的语言中同时使用C和Python。Cython一开始似乎很容易,但除非你正确地了解C,否则你只会朝自己的脚开枪。Cython不是一个能够神奇地加速Python代码的静态Python编译器。