如何减少Cython编译代码';s与Python的交互

如何减少Cython编译代码';s与Python的交互,python,cython,Python,Cython,我试图通过使用Cython编译为C来减少一段计算量特别大的Python代码。令人惊讶的是,我几乎没有成功地加快速度。对于原始Python模块,代码运行时间约为45秒,对于Cython编译模块,代码运行时间约为45秒 使用annotate=True编译时,我留下了大量黄色(ish)行,这表明仍然存在大量Python交互 对此,我关闭了boundscheck(False)和cdivision(True)。这没有效果。下面的代码片段是此模块的摘录,它坚持与Python交互。为什么会这样?这里没有任何东

我试图通过使用Cython编译为C来减少一段计算量特别大的Python代码。令人惊讶的是,我几乎没有成功地加快速度。对于原始Python模块,代码运行时间约为45秒,对于Cython编译模块,代码运行时间约为45秒

使用
annotate=True
编译时,我留下了大量黄色(ish)行,这表明仍然存在大量Python交互

对此,我关闭了
boundscheck(False)
cdivision(True)
。这没有效果。下面的代码片段是此模块的摘录,它坚持与Python交互。为什么会这样?这里没有任何东西需要与任何预先存在的Python模块交互,它都是非常简单的算术模块

cpdef float __distance_between(point1, point2)  except? -2:
    return ((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2) ** (1/2)
point1
point2
是Python列表,每个列表都包含2个
double
s,例如:
[611811.997,-871083.372]
Cython为代码段中的
返回
行生成的
C
-代码如下:

+05: cpdef float __distance_between(point1, point2)  except? -2:
+06:     return ((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2)**(1/2)
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_point1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_point2, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyNumber_Subtract(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyNumber_Power(__pyx_t_3, __pyx_int_2, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_point1, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_point2, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = PyNumber_Subtract(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = PyNumber_Power(__pyx_t_4, __pyx_int_2, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = PyNumber_Add(__pyx_t_2, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyInt_From_long((1 / 2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyNumber_Power(__pyx_t_4, __pyx_t_1, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_5 = __pyx_PyFloat_AsFloat(__pyx_t_2); if (unlikely((__pyx_t_5 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_r = __pyx_t_5;
  goto __pyx_L0;
如何更好地优化代码或编译,使此代码段独立于Python


本模块中有许多其他行都呈现为黄色,但从这个问题开始,可能会让我更好地理解如何处理其余部分。

您没有
cdef
编辑任何变量;你知道它们是浮动的,Cython不知道。说出来

cpdef float __distance_between((double, double)point1, (double, double)point2)  except? -2:
    return ((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2) ** (1/2)

旁注:确保编译时使用了
-3
以选择Python 3语法,否则
1/2
将被解释为
0
;或者,只需将其更改为literal
0.5
(或
1./2.
或诸如此类),无论您使用哪种语法(Py2与Py3),它都会工作。是的,这就是问题所在。感谢您在
1/2
上的指针。但是,如果这些点是真正的python浮点数列表,那么没有一个Cython数据类型可以有效地表达这一点。您刚刚将工作转移到函数调用中的一些转换中。@DavidW:这仍然会有意义地提高性能。当然,您需要提前进行转换,但它会将一堆
PyNumber
通用API调用转换为原始C操作。四个解包和一个重新打包并不好,但在这两者之间都是原始的C
double
操作,比六个通用的
PyNumber
操作要好得多(每个操作都必须解包两个操作数,执行数学运算,并将结果重新打包到Python
float
).@ShadowRanger是的,公平点-我认为你是对的,它会有所帮助,我认为这是在不知道OP如何使用函数的情况下进行优化所能做到的。