简体   繁体   English

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

[英]How to reduce Cython compiled code's interaction with Python

I am trying to reduce a particularly computational heavy piece of Python code through compiling as C with Cython.我试图通过使用 Cython 编译为 C 来减少计算量特别大的 Python 代码。 Surprisingly I have virtually no success in speeding it up.令人惊讶的是,我在加速它方面几乎没有成功。 With the original Python module the code runs in about 45sec and with the Cython compiled module it runs in about 45secs.使用原始 Python 模块,代码运行大约 45 秒,使用 Cython 编译模块运行大约 45 秒。

Compiling with annotate=True , I am left with a sea of yellow(ish) lines suggesting there is still a huge amount of Python interaction.使用annotate=True编译,我留下了一大堆黄色(ish)线,表明仍然存在大量的 Python 交互。

I have responded to this by switching off both boundscheck (False) and cdivision (True) .我通过关闭boundscheck (False)cdivision (True)对此做出了回应。 This had no effect.这没有效果。 The following snippet of code is an extract from this module and it insists on interacting with Python.以下代码片段是从这个模块中提取的,它坚持与 Python 交互。 Why is this?为什么是这样? Nothing here need to interact with any pre-existing Python module, it is all very simple arithmatic?这里不需要与任何预先存在的 Python 模块进行交互,这一切都是非常简单的算术?

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

point1 and point2 are Python lists each containing 2 double s eg: [611811.997, -871083.372] The resulting C -code that is generated by Cython for the return line in the snippet is as follows: point1point2是 Python 列表,每个列表都包含 2 个double s 例如: [611811.997, -871083.372]生成的C -代码由 Cython 为代码段中的return行生成如下:

+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;

How can I better optimise the code or the compilation to make this snippet independent of Python?如何更好地优化代码或编译以使此代码段独立于 Python?

There are many other lines in this module that are all rendered pretty yellow, but starting with this question may provide me with a better understanding of how to tackle the rest.此模块中还有许多其他行都呈现为黄色,但从这个问题开始可能会让我更好地了解如何处理 rest。

You haven't cdef ed any of your variables;您还没有cdef编辑任何变量; you know they're float , Cython doesn't.知道它们是float的,Cython 不是。 Tell it.告诉它。

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM