当参数和 returns 是矩阵而不是标量时使用 cython

Using cython when arguments and returns are matrices, not scalars

我是 cython 的新手,我想更快地对 pandas DataFrames 进行计算。这是此类计算的一个典型的简化示例。在此示例中,参数是向量,return 是标量,但在其他情况下,参数和 return 都可以是 DataFrame/arrays。我有很多这样的功能,它们有时是嵌套的。

import pandas as pd
import numpy as np

def f(x,y,z):
  return np.dot(x,np.exp(x*y/(1-np.power(z,3))))

df = pd.DataFrame({'a': np.random.randn(1000), 'b': 
np.random.randn(1000),'c': np.random.randint(100, 1000, (1000))})

print(f(df.a,df.b,df.c))

在我看到的教程和文档中,cython 用于优化标量的计算,而不是matrices/arrays(例如http://pandas.pydata.org/pandas-docs/stable/enhancingperf.html)。因此,该过程通常涉及向标量添加类型(int、float、double 等)。在函数使用 DataFrames 或数组作为参数和 returns 而不是标量的情况下,使用 cython 的正确过程是什么?

我尝试了以下方法,但没有看到任何明显的改进(尽管没有抛出错误):

@cython.locals(x=cython.float,y=cython.float,z=cython.float)   
@cython.returns(cython.float)  
def f(x,y,z):
  return np.dot(x,np.exp(x*y/(1-np.power(z,3))))

提前致谢

查看您的函数内部:您只调用了 numpy 函数,也就是说,您为 Cython 转换为 C 代码留了一小部分(如果有的话)余量。

可能 如果你输入你的变量如数组的 double[:] 来提高速度(老实说,我不知道在哪里,但编译器的优化通常更聪明比自己)。但是你的函数仍然主要是 numpy 函数的包装器:Cython 不会改进它们的内部工作。

不过,您可以尝试实现自己的外部乘积函数,并在那里获得一些速度(我不知道 numpy 的效率如何,但您可能会比它稍胜一筹)。另外,使用 C 的 expmath.h 中的 pow 可能会进一步改进。

Cython 没有 'type-definign' 个变量,但您必须确保在调用 cython 的编译器时,它能够将尽可能多的代码转换为 C 语言。 (顺便说一句,你正在编译你的代码,对吧?只有当你编译你的源代码并导入生成的模块时才会看到速度提升;运行 它在 pure-python 模式下只是 Python).