小能豆

如何对 numpy 数组进行 cynthonize 以提高性能?

py

我想加快在 for 循环内迭代的 isSubsetQuick 函数之外的外部 for 循环(由于其巨大而不共享)。

目标是将 python numpy 数组转换为 cython numpy 数组,以便能够将 numpy 函数用作 np.isin,并加快那些不共享 for 循环内的数据分配速度。

如何对数组和函数进行 cynthonize 以优化和加速 for 循环和函数?

(这只是代码的一部分,因为除了数组数据分配之外还有更多的 for 循环,而且速度很慢,这就是我想要优化的原因)。

谢谢你!

def isSubsetquick(arr_3d: np.ndarray, arr_1d: np.ndarray, limit_elemets: int):

    common_elements = np.isin(arr_3d, arr_1d[:limit_elemets])
    quantity_common_elements = np.sum(common_elements, axis=-1)

    counter = np.count_nonzero(quantity_common_elements == limit_elemets)

    return counter 


array_3 = np.array([[[1, 2, 3, 7], [4, 5, 6, 8]], [[7, 8, 9, 4], [10, 11, 12, 5]]])
array_1 = np.array([1, 2, 6])

cdef int limit=3
cdef int size= 100000
cdef int result

#for x in range (size):
    print(result = isSubsetquick(array_3, array_1, limit))

阅读 127

收藏
2023-07-10

共1个答案

小能豆

要优化和加速Python代码,特别是涉及循环和NumPy数组操作的部分,您可以考虑使用Cython进行优化。Cython是一个将Python代码转换为C代码的编译器,它可以生成高效的扩展模块,以提供更快的执行速度。

首先,您需要安装Cython。可以使用以下命令通过pip安装Cython:

pip install cython

接下来,您需要创建一个Cython扩展模块,将您想要优化的函数从Python转换为Cython。以下是一个示例:

# subset_quick.pyx

import numpy as np
cimport numpy as np

def isSubsetquick(np.ndarray[np.int32_t, ndim=3] arr_3d, np.ndarray[np.int32_t] arr_1d, int limit_elements):
    cdef np.ndarray[np.int32_t, ndim=3] common_elements = np.isin(arr_3d, arr_1d[:limit_elements])
    cdef np.ndarray[np.int32_t, ndim=2] quantity_common_elements = np.sum(common_elements, axis=-1)

    cdef int counter = np.count_nonzero(quantity_common_elements == limit_elements)

    return counter

注意,在Cython代码中,我们使用了Cython的类型声明来指定输入参数和返回值的类型,以便获得更好的性能。

然后,您需要创建一个名为setup.py的构建脚本,以便将Cython代码编译为扩展模块。以下是一个示例:

# setup.py

from setuptools import setup
from Cython.Build import cythonize
import numpy as np

setup(
    ext_modules = cythonize("subset_quick.pyx"),
    include_dirs=[np.get_include()]
)

接下来,运行以下命令来构建和编译Cython模块:

python setup.py build_ext --inplace

这将生成一个名为subset_quick.so(在Windows上是subset_quick.pyd)的共享库文件。

最后,您可以在Python代码中导入并使用这个优化过的函数:

import numpy as np
from subset_quick import isSubsetquick

array_3 = np.array([[[1, 2, 3, 7], [4, 5, 6, 8]], [[7, 8, 9, 4], [10, 11, 12, 5]]])
array_1 = np.array([1, 2, 6])

limit = 3
result = isSubsetquick(array_3, array_1, limit)
print(result)

使用Cython进行优化可以提供比纯Python更高的执行速度,特别是对于涉及循环和数组操作的部分。尝试将您的函数转换为Cython并进行性能测试,看看是否有所改善。根据需要,您还可以进一步优化和调整代码。

2023-07-10