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,__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类型检查。关于如何做到这一点的任何想法?

解决方法

生成的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检查的开销稍大,但是如果需要的话,应该计时一下。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...