Cython 浮点除法 PyExc_ZeroDivisionError 检查

12 投票
2 回答
5627 浏览
提问于 2025-04-16 10:05

我正在进行一些循环密集型的计算,所以把代码转换成了Cython。
我使用了cython -a这个选项进行性能分析,并查看了生成的.html文件。结果发现,每当我进行浮点数除法时,那里就会出现一条黄色的线,类似于下面的内容:

if (unlikely(__pyx_t_37 == 0)) {
        PyErr_Format(PyExc_ZeroDivisionError, "float division");
        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
      }

我猜这可能是为了处理除数为0的情况。我使用的是一个常量,除数为0的可能性几乎没有。我在想有没有什么办法可以让它运行得更快。

2 个回答

1

如果除数是一个固定不变的数,你可以用 1/除数 来代替除法运算。

22

你需要加上 @cython.cdivision(True) 这个代码,来避免出现异常检查。

import cython

cdef double pydivision():
  cdef int i
  cdef double k, j
  k = 2.0
  j = 0.0
  for i in range(10):
    j += i/k
  # Generated code: Python exception checking
  # /* "checksum.pyx":9
  # *   j = 0.0
  # *   for i in range(10):
  # *     j += i/k             # <<<<<<<<<<<<<<
  # *   return j
  # *
  # */
  #    if (unlikely(__pyx_v_k == 0)) {
  #      PyErr_Format(PyExc_ZeroDivisionError, "float division");
  #      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  #    }
  #    __pyx_v_j = (__pyx_v_j + (__pyx_v_i / __pyx_v_k));
  #  }
  return j

#This decorator works wonders
@cython.cdivision(True)
cdef double cdivision():
  cdef int i
  cdef double k, j
  k = 2.0
  j = 0.0
  for i in range(10):
    j += i/k
  # Generated code: no exception checking
  # /* "checksum.pyx":20
  # *   j = 0.0
  # *   for i in range(10):
  # *     j += i/k             # <<<<<<<<<<<<<<
  # *   return j
  # *
  # */
  #    __pyx_v_j = (__pyx_v_j + (__pyx_v_i / __pyx_v_k));
  #  }
  return j

撰写回答