Cython:具有 2 个列表的简单函数,最快的方法是什么?

Cython: simple function with 2 lists, what is the fastest way?

我想做的 - 将我的纯 Python 代码转换为 Cython。

纯Python代码:

def conflicts(list1,list2):
    numIt = 10
    for i in list1:
        for j in list2:
            if i == j and i < numIt:
                return True
    return False
conflicts([1,2,3], [6,9,8])

到目前为止我的 Cython 代码:

cdef char conflicts(int [] list1,int [] list2):
    cdef int numIt = 10
        for i in list1:
            for j in list2:
                if i == j and i < numIt:
                    return True
    return False
conflicts([1,2,3], [6,9,8])

由于我是 Cython 的新手(在 Python 方面并不是真正的专家),所以我想获得一些关于我的转换的反馈。我做对了吗?为了使功能更快,我还应该做些什么吗?

更新:

有谁知道如何在输入(list1、list2)函数的 header 中添加类型?我尝试了 "int [:]" 编译没有错误但是当我尝试用两个列表调用函数时我得到消息 "TypeError: 'list' does not have the buffer interface"。

可以声明

"i" 和 "j" 以优化您的代码。使用 cython 的第一次优化是使用显式声明完成的。

您可以使用

cython -a yourcode.py

并查看一些可能更改的自动建议,以使用 cython(黄线)优化您的 python 代码。您可以使用生成的 c 模块(工作完美!)。

部分手写cython优化:
+ 对 list1 和 list2 使用类型 list
+ bint type for conflicts functions because that return boolean value.
+ 获取列表的长度,因为 for 循环需要结束索引。
+ 在 int 数组中映射列表(因为列表只有整数值)。

cdef bint conflicts(list list1, list list2):
    cdef int numIt = 10
    cdef int i, j
    cdef int end_index = len(list1)
    cdef int[:] my_list1 = list1
    cdef int[:] my_list2 = list2

    for i in range(end_index):
        for j in range(end_index):
            if my_list1[i] == my_list2[j] and my_list1[i] < numIt:
                return True
    return False
conflicts([1,2,3], [6,9,8])

正如我评论的那样,您应该能够通过更改算法获得相当大的改进,而根本不会弄乱 cython。您当前的代码是 O(len(list1)*len(list2)),但您可以使用 set 将其缩减为 O(len(list1)+len(list2))。您还可以使用内置的 any 函数来简化代码:

def conflicts(list1,list2):
    numIt = 10
    s1 = set(list1)
    return any(x in s1 and x < numIt for x in list2)

根据每个列表中您希望小于 10 的数字的数量,您可以尝试稍微移动 x < numIt 测试以查看最快的(在您转向之前过滤 list1例如,将其放入 set,或者在 any 内的生成器表达式中将 if x < numIt 放在 for 之后。