我想加快在 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))
要优化和加速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
# 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)的共享库文件。
subset_quick.so
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并进行性能测试,看看是否有所改善。根据需要,您还可以进一步优化和调整代码。