Unicode字符串Cython上的快速迭代

时间:2020-08-27 20:44:44

标签: unicode cython

我具有以下cython功能。

 01: 
+02: cdef int count_char_in_x(unicode x,Py_UCS4  c):
 03:     cdef:
+04:         int count = 0
 05:         Py_UCS4 x_k
 06: 
+07:     for x_k in x: ## Yellow
+08:         if x_k == c:
+09:             count+=1
 10: 
+11:     return count

第7行没有正确优化。

带注释的HTML代码被扩展为:

+07:     for x_k in x: ## Yellow
  if (unlikely(__pyx_v_x == Py_None)) {
    PyErr_SetString(PyExc_TypeError, "'NoneType' is not iterable");
    __PYX_ERR(0, 8, __pyx_L1_error)
  }
  __Pyx_INCREF(__pyx_v_x);
  __pyx_t_1 = __pyx_v_x;
  __pyx_t_6 = __Pyx_init_unicode_iteration(__pyx_t_1, (&__pyx_t_3), (&__pyx_t_4), (&__pyx_t_5)); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(0, 8, __pyx_L1_error)
  for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_3; __pyx_t_7++) {
    __pyx_t_2 = __pyx_t_7;
    __pyx_v_x_k = __Pyx_PyUnicode_READ(__pyx_t_5, __pyx_t_4, __pyx_t_2);
  • 有关如何改善此问题的任何提示?

  • 我认为可以编写一个cdef / cpdef函数,在运行时完全避免Python None类型检查。关于如何做到这一点的任何想法?

1 个答案:

答案 0 :(得分:1)

生成的C代码对我来说看起来不错。整个循环是一个完整的for循环(即,它不依赖于调用Python方法__iter____next__)。

__Pyx_PyUnicode_READ is translated pretty directly to PyUnicode_READ(略微取决于您使用的Python版本)。 PyUnicode_READ是一个C语言宏,它是as close to a direct array access as you can get

这可能和所获得的一样好。使用bytes而不是unicode可能会有所改善(前提是您要处理ASCII字符)。您可能只是考虑是否真的值得重新实现unicode.count

如果它是常规的def函数,则可以将x声明为unicode not None,以在循环之前删除None检查。那可能会有所不同。但是,正如@ead指出的,cdef函数不支持。 def函数调用的开销可能会比None检查的开销稍大,但是如果需要的话,应该计时一下。

相关问题